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