forked from Minki/linux
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:
parent
00642f6616
commit
3b43cd6f2d
@ -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);
|
||||
|
||||
if (!ret)
|
||||
clk->rate = rate;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cdce_probe(struct i2c_client *client,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user