Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b43cd6f authored by Sekhar Nori's avatar Sekhar Nori Committed by Kevin Hilman
Browse files

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: default avatarSekhar Nori <nsekhar@ti.com>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 00642f66
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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,
+8 −1
Original line number Diff line number Diff line
@@ -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);