msm: clock: Move voltage scaling to prepare/unprepare
Move the voltage calls to a sleepable context so we can avoid
spinning for hundreds of microseconds with interrupts disabled
waiting for a regulator to increase. This change also paves the
way to making the clock driver into a real regulator consumer
that uses the proper regulator APIs instead of the MSM specific
rpm_vreg API.
Doing this also requires us to make clk_set_rate() a sleeping
call so that concurrent clk_prepare() and clk_set_rate() calls
are synchronized. Making clk_set_rate() sleepable also
necessitates moving the clk_set_rate() call in clock-voter.c to a
sleepable context. Do that by having clock-voter aggregate and
update the rate in prepare/unprepare instead of enable/disable
(note that enable/disable of voter clocks implicitly calls
enable/disable on the parent via generic clock code).
Now that clk_set_rate() is sleeping, call clk_prepare() and
clk_unprepare() in the clock-local code when a rate change
requires reparenting the clock. This cleans up a problem we have
where sources may be left unprepared by a clock rate switch
(hence the default true warned flag for PLLs and crystals).
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
(cherry picked from commit d86d1f2d968f194e3db46bb683e370a9fa3a6037)
Conflicts:
arch/arm/mach-msm/clock-local2.c
Change-Id: Ie5bbb17537d5b33de92f8ea1c2da6070b18c14f1
Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index d5ee35b..0383f1d 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -141,12 +141,12 @@
rcg_update_config(rcg);
}
-static int rcg_clk_enable(struct clk *c)
+static int rcg_clk_prepare(struct clk *c)
{
struct rcg_clk *rcg = to_rcg_clk(c);
WARN(rcg->current_freq == &rcg_dummy_freq,
- "Attempting to enable %s before setting its rate. "
+ "Attempting to prepare %s before setting its rate. "
"Set the rate first!\n", rcg->c.dbg_name);
return 0;
@@ -156,7 +156,7 @@
{
struct clk_freq_tbl *cf, *nf;
struct rcg_clk *rcg = to_rcg_clk(c);
- int rc = 0;
+ int rc;
unsigned long flags;
for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
@@ -168,12 +168,21 @@
cf = rcg->current_freq;
- if (rcg->c.count) {
- /* TODO: Modify to use the prepare API */
- /* Enable source clock dependency for the new freq. */
- rc = clk_enable(nf->src_clk);
+ /* Enable source clock dependency for the new freq. */
+ if (c->prepare_count) {
+ rc = clk_prepare(nf->src_clk);
if (rc)
- goto out;
+ return rc;
+ }
+
+ spin_lock_irqsave(&c->lock, flags);
+ if (c->count) {
+ rc = clk_enable(nf->src_clk);
+ if (rc) {
+ spin_unlock_irqrestore(&c->lock, flags);
+ clk_unprepare(nf->src_clk);
+ return rc;
+ }
}
BUG_ON(!rcg->set_rate);
@@ -186,12 +195,16 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
/* Release source requirements of the old freq. */
- if (rcg->c.count)
+ if (c->count)
clk_disable(cf->src_clk);
+ spin_unlock_irqrestore(&c->lock, flags);
+
+ if (c->prepare_count)
+ clk_unprepare(cf->src_clk);
rcg->current_freq = nf;
-out:
- return rc;
+
+ return 0;
}
/* Return a supported rate that's at least the specified rate. */
@@ -583,7 +596,7 @@
struct clk_ops clk_ops_empty;
struct clk_ops clk_ops_rcg = {
- .enable = rcg_clk_enable,
+ .enable = rcg_clk_prepare,
.set_rate = rcg_clk_set_rate,
.list_rate = rcg_clk_list_rate,
.round_rate = rcg_clk_round_rate,
@@ -592,7 +605,7 @@
};
struct clk_ops clk_ops_rcg_mnd = {
- .enable = rcg_clk_enable,
+ .enable = rcg_clk_prepare,
.set_rate = rcg_clk_set_rate,
.list_rate = rcg_clk_list_rate,
.round_rate = rcg_clk_round_rate,