From d277ce2d3a75c6c116a6119c3745694f5941eff5 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Wed, 16 Jan 2019 23:04:27 +0100 Subject: 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 Acked-by: Tony Lindgren Tested-by: Keerthy Signed-off-by: Tero Kristo --- drivers/clk/ti/autoidle.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers/clk/ti') diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c index a129b4b36ea3..964e97b5478a 100644 --- a/drivers/clk/ti/autoidle.c +++ b/drivers/clk/ti/autoidle.c @@ -36,17 +36,41 @@ struct clk_ti_autoidle { 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) { - if (clk->ops && clk->ops->deny_idle) - clk->ops->deny_idle(clk); + if (clk->ops && clk->ops->deny_idle) { + 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; } static int _omap2_clk_allow_idle(struct clk_hw_omap *clk) { - if (clk->ops && clk->ops->allow_idle) - clk->ops->allow_idle(clk); + if (clk->ops && clk->ops->allow_idle) { + 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; } -- cgit v1.2.3