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>
This commit is contained in:
Sekhar Nori 2010-01-12 18:55:35 +05:30 committed by Kevin Hilman
parent 00642f6616
commit 3b43cd6f2d
2 changed files with 15 additions and 4 deletions

View file

@ -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,

View file

@ -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);