Sekhar Nori <[email protected]> writes:

> When supporting I2C/SPI based on-board PLLs like CDCE949,
> it is essential that clk->set_rate be able to sleep.
>
> Currently, this is not possible because clk->set_rate is
> called from within spin-lock in clk_set_rate
>
> This patch brings clk->set_rate outside of the spin-lock
> and lets the individual set_rate implementations achieve
> serialization through appropiate means.
>
> Signed-off-by: Sekhar Nori <[email protected]>
> ---
> This patch is a replacement for an earlier patch titled
> "davinci: clock framework: remove spinlock usage"

Looks good, queueing for 2.6.34.

Kevin

>  arch/arm/mach-davinci/cdce949.c |   10 +++++++---
>  arch/arm/mach-davinci/clock.c   |    9 ++++++++-
>  2 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/cdce949.c b/arch/arm/mach-davinci/cdce949.c
> index 6af3289..aec3756 100644
> --- a/arch/arm/mach-davinci/cdce949.c
> +++ b/arch/arm/mach-davinci/cdce949.c
> @@ -23,6 +23,7 @@
>  #include "clock.h"
>  
>  static struct i2c_client *cdce_i2c_client;
> +static DEFINE_MUTEX(cdce_mutex);
>  
>  /* CDCE register descriptor */
>  struct cdce_reg {
> @@ -231,16 +232,19 @@ int cdce_set_rate(struct clk *clk, unsigned long rate)
>       if (!regs)
>               return -EINVAL;
>  
> +     mutex_lock(&cdce_mutex);
>       for (i = 0; regs[i].addr; i++) {
>               ret = i2c_smbus_write_byte_data(cdce_i2c_client,
>                                       regs[i].addr | 0x80, regs[i].val);
>               if (ret)
> -                     return ret;
> +                     break;
>       }
> +     mutex_unlock(&cdce_mutex);
>  
> -     clk->rate = rate;
> +     if (!ret)
> +             clk->rate = rate;
>  
> -     return 0;
> +     return ret;
>  }
>  
>  static int cdce_probe(struct i2c_client *client,
> diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
> index 79d6ec8..bf6218e 100644
> --- a/arch/arm/mach-davinci/clock.c
> +++ b/arch/arm/mach-davinci/clock.c
> @@ -125,9 +125,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
>       if (clk == NULL || IS_ERR(clk))
>               return ret;
>  
> -     spin_lock_irqsave(&clockfw_lock, flags);
>       if (clk->set_rate)
>               ret = clk->set_rate(clk, rate);
> +
> +     spin_lock_irqsave(&clockfw_lock, flags);
>       if (ret == 0) {
>               if (clk->recalc)
>                       clk->rate = clk->recalc(clk);
> @@ -364,6 +365,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned 
> int prediv,
>  {
>       u32 ctrl;
>       unsigned int locktime;
> +     unsigned long flags;
>  
>       if (pll->base == NULL)
>               return -EINVAL;
> @@ -384,6 +386,9 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned 
> int prediv,
>       if (mult)
>               mult = mult - 1;
>  
> +     /* Protect against simultaneous calls to PLL setting seqeunce */
> +     spin_lock_irqsave(&clockfw_lock, flags);
> +
>       ctrl = __raw_readl(pll->base + PLLCTL);
>  
>       /* Switch the PLL to bypass mode */
> @@ -416,6 +421,8 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned 
> int prediv,
>       ctrl |= PLLCTL_PLLEN;
>       __raw_writel(ctrl, pll->base + PLLCTL);
>  
> +     spin_unlock_irqrestore(&clockfw_lock, flags);
> +
>       return 0;
>  }
>  EXPORT_SYMBOL(davinci_set_pllrate);
> -- 
> 1.6.2.4
>
> _______________________________________________
> Davinci-linux-open-source mailing list
> [email protected]
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to