aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorSekhar Nori <nsekhar@ti.com>2010-01-12 08:25:35 -0500
committerKevin Hilman <khilman@deeprootsystems.com>2010-02-04 16:30:08 -0500
commit3b43cd6f2dcbf871b8cabe16ae4ac8c036c959ac (patch)
tree064252da18333283fc12e088f37b94fc6c74e24e /arch/arm
parent00642f6616a0d1893ab1dcfec4d833210f310e95 (diff)
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')
-rw-r--r--arch/arm/mach-davinci/cdce949.c10
-rw-r--r--arch/arm/mach-davinci/clock.c9
2 files changed, 15 insertions, 4 deletions
diff --git a/arch/arm/mach-davinci/cdce949.c b/arch/arm/mach-davinci/cdce949.c
index 6af3289e052..aec37569054 100644
--- a/arch/arm/mach-davinci/cdce949.c
+++ b/arch/arm/mach-davinci/cdce949.c
@@ -23,6 +23,7 @@
23#include "clock.h" 23#include "clock.h"
24 24
25static struct i2c_client *cdce_i2c_client; 25static struct i2c_client *cdce_i2c_client;
26static DEFINE_MUTEX(cdce_mutex);
26 27
27/* CDCE register descriptor */ 28/* CDCE register descriptor */
28struct cdce_reg { 29struct cdce_reg {
@@ -231,16 +232,19 @@ int cdce_set_rate(struct clk *clk, unsigned long rate)
231 if (!regs) 232 if (!regs)
232 return -EINVAL; 233 return -EINVAL;
233 234
235 mutex_lock(&cdce_mutex);
234 for (i = 0; regs[i].addr; i++) { 236 for (i = 0; regs[i].addr; i++) {
235 ret = i2c_smbus_write_byte_data(cdce_i2c_client, 237 ret = i2c_smbus_write_byte_data(cdce_i2c_client,
236 regs[i].addr | 0x80, regs[i].val); 238 regs[i].addr | 0x80, regs[i].val);
237 if (ret) 239 if (ret)
238 return ret; 240 break;
239 } 241 }
242 mutex_unlock(&cdce_mutex);
240 243
241 clk->rate = rate; 244 if (!ret)
245 clk->rate = rate;
242 246
243 return 0; 247 return ret;
244} 248}
245 249
246static int cdce_probe(struct i2c_client *client, 250static int cdce_probe(struct i2c_client *client,
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 123839332d5..0fc63f93a22 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)
125 if (clk == NULL || IS_ERR(clk)) 125 if (clk == NULL || IS_ERR(clk))
126 return ret; 126 return ret;
127 127
128 spin_lock_irqsave(&clockfw_lock, flags);
129 if (clk->set_rate) 128 if (clk->set_rate)
130 ret = clk->set_rate(clk, rate); 129 ret = clk->set_rate(clk, rate);
130
131 spin_lock_irqsave(&clockfw_lock, flags);
131 if (ret == 0) { 132 if (ret == 0) {
132 if (clk->recalc) 133 if (clk->recalc)
133 clk->rate = clk->recalc(clk); 134 clk->rate = clk->recalc(clk);
@@ -364,6 +365,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
364{ 365{
365 u32 ctrl; 366 u32 ctrl;
366 unsigned int locktime; 367 unsigned int locktime;
368 unsigned long flags;
367 369
368 if (pll->base == NULL) 370 if (pll->base == NULL)
369 return -EINVAL; 371 return -EINVAL;
@@ -384,6 +386,9 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
384 if (mult) 386 if (mult)
385 mult = mult - 1; 387 mult = mult - 1;
386 388
389 /* Protect against simultaneous calls to PLL setting seqeunce */
390 spin_lock_irqsave(&clockfw_lock, flags);
391
387 ctrl = __raw_readl(pll->base + PLLCTL); 392 ctrl = __raw_readl(pll->base + PLLCTL);
388 393
389 /* Switch the PLL to bypass mode */ 394 /* Switch the PLL to bypass mode */
@@ -416,6 +421,8 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
416 ctrl |= PLLCTL_PLLEN; 421 ctrl |= PLLCTL_PLLEN;
417 __raw_writel(ctrl, pll->base + PLLCTL); 422 __raw_writel(ctrl, pll->base + PLLCTL);
418 423
424 spin_unlock_irqrestore(&clockfw_lock, flags);
425
419 return 0; 426 return 0;
420} 427}
421EXPORT_SYMBOL(davinci_set_pllrate); 428EXPORT_SYMBOL(davinci_set_pllrate);