diff options
| author | Sekhar Nori <nsekhar@ti.com> | 2010-01-12 08:25:35 -0500 |
|---|---|---|
| committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-02-04 16:30:08 -0500 |
| commit | 3b43cd6f2dcbf871b8cabe16ae4ac8c036c959ac (patch) | |
| tree | 064252da18333283fc12e088f37b94fc6c74e24e | |
| parent | 00642f6616a0d1893ab1dcfec4d833210f310e95 (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>
| -rw-r--r-- | arch/arm/mach-davinci/cdce949.c | 10 | ||||
| -rw-r--r-- | 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 6af3289e0527..aec375690543 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 | ||
| 25 | static struct i2c_client *cdce_i2c_client; | 25 | static struct i2c_client *cdce_i2c_client; |
| 26 | static DEFINE_MUTEX(cdce_mutex); | ||
| 26 | 27 | ||
| 27 | /* CDCE register descriptor */ | 28 | /* CDCE register descriptor */ |
| 28 | struct cdce_reg { | 29 | struct 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 | ||
| 246 | static int cdce_probe(struct i2c_client *client, | 250 | 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 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) | |||
| 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 | } |
| 421 | EXPORT_SYMBOL(davinci_set_pllrate); | 428 | EXPORT_SYMBOL(davinci_set_pllrate); |
