clk: ti: add a usecount for autoidle
Multiple users might deny autoidle on a clock. So we should have some counting here, also according to the comment in _setup_iclk_autoidle(). Also setting autoidle regs is not atomic, so there is another reason for locking. Signed-off-by: Andreas Kemnade <andreas@kemnade.info> Acked-by: Tony Lindgren <tony@atomide.com> Tested-by: Keerthy <j-keerthy@ti.com> Signed-off-by: Tero Kristo <t-kristo@ti.com>
This commit is contained in:
parent
ead478250b
commit
d277ce2d3a
|
@ -36,17 +36,41 @@ struct clk_ti_autoidle {
|
||||||
|
|
||||||
static LIST_HEAD(autoidle_clks);
|
static LIST_HEAD(autoidle_clks);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we have some non-atomic read/write
|
||||||
|
* operations behind it, so lets
|
||||||
|
* take one lock for handling autoidle
|
||||||
|
* of all clocks
|
||||||
|
*/
|
||||||
|
static DEFINE_SPINLOCK(autoidle_spinlock);
|
||||||
|
|
||||||
static int _omap2_clk_deny_idle(struct clk_hw_omap *clk)
|
static int _omap2_clk_deny_idle(struct clk_hw_omap *clk)
|
||||||
{
|
{
|
||||||
if (clk->ops && clk->ops->deny_idle)
|
if (clk->ops && clk->ops->deny_idle) {
|
||||||
clk->ops->deny_idle(clk);
|
unsigned long irqflags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&autoidle_spinlock, irqflags);
|
||||||
|
clk->autoidle_count++;
|
||||||
|
if (clk->autoidle_count == 1)
|
||||||
|
clk->ops->deny_idle(clk);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&autoidle_spinlock, irqflags);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _omap2_clk_allow_idle(struct clk_hw_omap *clk)
|
static int _omap2_clk_allow_idle(struct clk_hw_omap *clk)
|
||||||
{
|
{
|
||||||
if (clk->ops && clk->ops->allow_idle)
|
if (clk->ops && clk->ops->allow_idle) {
|
||||||
clk->ops->allow_idle(clk);
|
unsigned long irqflags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&autoidle_spinlock, irqflags);
|
||||||
|
clk->autoidle_count--;
|
||||||
|
if (clk->autoidle_count == 0)
|
||||||
|
clk->ops->allow_idle(clk);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&autoidle_spinlock, irqflags);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ struct clk_hw_omap {
|
||||||
struct clockdomain *clkdm;
|
struct clockdomain *clkdm;
|
||||||
const struct clk_hw_omap_ops *ops;
|
const struct clk_hw_omap_ops *ops;
|
||||||
u32 context;
|
u32 context;
|
||||||
|
int autoidle_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue