From 7947c04641d8dc96eaf84fa9a4c6e1097181abb0 Mon Sep 17 00:00:00 2001 From: Deepak Katragadda Date: Tue, 23 Feb 2016 15:21:59 -0800 Subject: clk: msm: clock-local2: Set RCG root_enable bit prior to changing rate Firmware running on HW blocks could be powering down the branch clock or the RCG whilst software is doing frequency changes. If this happens, the RCG behavior is undefined and may cause issues with its functioning. To work around this, use the RCG root_en bit and force turn it on while scaling the rate. In addition, make the polling timeouts configurable. CRs-Fixed: 971305 Change-Id: If2db14c70614c47d673fc735f5f4bac276d4a3d9 Signed-off-by: Deepak Katragadda --- drivers/clk/msm/clock-local2.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'drivers/clk/msm') 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 -- cgit v1.2.3