diff options
Diffstat (limited to 'drivers/clk/msm/clock-local2.c')
-rw-r--r-- | drivers/clk/msm/clock-local2.c | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/drivers/clk/msm/clock-local2.c b/drivers/clk/msm/clock-local2.c index 56ee6d0d7c89..bfa2147ad42c 100644 --- a/drivers/clk/msm/clock-local2.c +++ b/drivers/clk/msm/clock-local2.c @@ -36,6 +36,8 @@ /* For clock without halt checking, wait this long after enables/disables. */ #define HALT_CHECK_DELAY_US 500 +#define RCG_FORCE_DISABLE_DELAY_US 100 + /* * When updating an RCG configuration, check the update bit up to this number * number of times (with a 1 us delay in between) before continuing. @@ -105,14 +107,18 @@ struct div_map { */ static void rcg_update_config(struct rcg_clk *rcg) { - u32 cmd_rcgr_regval, count; + u32 cmd_rcgr_regval; + int count = UPDATE_CHECK_MAX_LOOPS; + + if (rcg->non_local_control_timeout) + count = rcg->non_local_control_timeout; cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg)); cmd_rcgr_regval |= CMD_RCGR_CONFIG_UPDATE_BIT; writel_relaxed(cmd_rcgr_regval, CMD_RCGR_REG(rcg)); /* Wait for update to take effect */ - for (count = UPDATE_CHECK_MAX_LOOPS; count > 0; count--) { + for (; count > 0; count--) { if (!(readl_relaxed(CMD_RCGR_REG(rcg)) & CMD_RCGR_CONFIG_UPDATE_BIT)) return; @@ -124,10 +130,13 @@ static void rcg_update_config(struct rcg_clk *rcg) static void rcg_on_check(struct rcg_clk *rcg) { - int count; + int count = UPDATE_CHECK_MAX_LOOPS; + + if (rcg->non_local_control_timeout) + count = rcg->non_local_control_timeout; /* Wait for RCG to turn on */ - for (count = UPDATE_CHECK_MAX_LOOPS; count > 0; count--) { + for (; count > 0; count--) { if (!(readl_relaxed(CMD_RCGR_REG(rcg)) & CMD_RCGR_ROOT_STATUS_BIT)) return; @@ -211,6 +220,8 @@ static void rcg_clear_force_enable(struct rcg_clk *rcg) cmd_rcgr_regval &= ~CMD_RCGR_ROOT_ENABLE_BIT; writel_relaxed(cmd_rcgr_regval, CMD_RCGR_REG(rcg)); spin_unlock_irqrestore(&local_clock_reg_lock, flags); + /* Add a delay of 100usecs to let the RCG disable */ + udelay(RCG_FORCE_DISABLE_DELAY_US); } static int rcg_clk_enable(struct clk *c) @@ -291,25 +302,20 @@ static int rcg_clk_set_rate(struct clk *c, unsigned long rate) BUG_ON(!rcg->set_rate); - /* - * Perform clock-specific frequency switch operations. - * - * For RCGs with non_local_children set to true: - * If this RCG has at least one branch that is controlled by another - * execution entity, ensure that the enable/disable and mux switch - * are staggered. - */ - if (!rcg->non_local_children) { - rcg->set_rate(rcg, nf); - } else if (c->count) { + /* Perform clock-specific frequency switch operations. */ + if ((rcg->non_local_children && c->count) || + rcg->non_local_control_timeout) { /* - * Force enable the RCG here since there could be a disable - * call happening between pre_reparent and set_rate. + * Force enable the RCG here since the clock could be disabled + * between pre_reparent and set_rate. */ rcg_set_force_enable(rcg); rcg->set_rate(rcg, nf); rcg_clear_force_enable(rcg); + } else if (!rcg->non_local_children) { + rcg->set_rate(rcg, nf); } + /* * If non_local_children is set and the RCG is not enabled, * the following operations switch parent in software and cache |