diff options
author | Sekhar Nori <nsekhar@ti.com> | 2010-01-12 18:55:35 +0530 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-02-04 13:30:08 -0800 |
commit | 3b43cd6f2dcbf871b8cabe16ae4ac8c036c959ac (patch) | |
tree | 064252da18333283fc12e088f37b94fc6c74e24e /arch/arm/mach-davinci/clock.c | |
parent | 00642f6616a0d1893ab1dcfec4d833210f310e95 (diff) | |
download | kernel-common-3b43cd6f2dcbf871b8cabe16ae4ac8c036c959ac.tar.gz kernel-common-3b43cd6f2dcbf871b8cabe16ae4ac8c036c959ac.tar.bz2 kernel-common-3b43cd6f2dcbf871b8cabe16ae4ac8c036c959ac.zip |
davinci: clock: let clk->set_rate function sleep
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 <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r-- | arch/arm/mach-davinci/clock.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 123839332d50..0fc63f93a222 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); |