summaryrefslogtreecommitdiff
path: root/drivers/clk/msm/clock-local2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/msm/clock-local2.c')
-rw-r--r--drivers/clk/msm/clock-local2.c40
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