summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorAmit Nischal <anischal@codeaurora.org>2016-09-26 10:58:14 +0530
committerAmit Nischal <anischal@codeaurora.org>2016-09-29 19:10:25 +0530
commitac987c7a71dcd839261c8c2aaf60d860a14168aa (patch)
tree51e8f1ecebbd53249cf25a38600f361b88a4e79e /drivers/clk
parent626caf4e54864d90e8d104277f9a1446e487c7e1 (diff)
clk: qcom: Add support to force enable/disable the RCG
Some RCGs would be expected to be enabled/disabled using the root enable bit of the RCGR. These RCGs would have to indicate the force enable using the FORCE_ENABLE_RCGR flag. Change-Id: Ia1eaba2728d06066612739ff48f7e5e44322e96b Signed-off-by: Amit Nischal <anischal@codeaurora.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/qcom/clk-rcg.h7
-rw-r--r--drivers/clk/qcom/clk-rcg2.c57
2 files changed, 62 insertions, 2 deletions
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index b904c335cda4..e3760969848d 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -158,6 +158,8 @@ extern const struct clk_ops clk_dyn_rcg_ops;
* @freq_tbl: frequency table
* @current_freq: last cached frequency when using branches with shared RCGs
* @clkr: regmap clock handle
+ * @flags: set if RCG needs to be force enabled/disabled during
+ * power sequence.
*
*/
struct clk_rcg2 {
@@ -168,6 +170,9 @@ struct clk_rcg2 {
const struct freq_tbl *freq_tbl;
unsigned long current_freq;
struct clk_regmap clkr;
+
+#define FORCE_ENABLE_RCGR BIT(0)
+ u8 flags;
};
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index a071bba8018c..4d5081c2b6d1 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -60,6 +60,57 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw)
return (cmd & CMD_ROOT_OFF) == 0;
}
+static int clk_rcg_set_force_enable(struct clk_hw *hw)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ const char *name = clk_hw_get_name(hw);
+ int ret = 0, count;
+
+ /* force enable RCG */
+ ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+ CMD_ROOT_EN, CMD_ROOT_EN);
+ if (ret)
+ return ret;
+
+ /* wait for RCG to turn ON */
+ for (count = 500; count > 0; count--) {
+ ret = clk_rcg2_is_enabled(hw);
+ if (ret) {
+ ret = 0;
+ break;
+ }
+ udelay(1);
+ }
+ if (!count)
+ pr_err("%s: RCG did not turn on after force enable\n", name);
+
+ return ret;
+}
+
+static int clk_rcg2_enable(struct clk_hw *hw)
+{
+ int ret = 0;
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ if (rcg->flags & FORCE_ENABLE_RCGR)
+ ret = clk_rcg_set_force_enable(hw);
+
+ return ret;
+}
+
+static void clk_rcg2_disable(struct clk_hw *hw)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ if (rcg->flags & FORCE_ENABLE_RCGR) {
+ /* force disable RCG - clear CMD_ROOT_EN bit */
+ regmap_update_bits(rcg->clkr.regmap,
+ rcg->cmd_rcgr + CMD_REG, CMD_ROOT_EN, 0);
+ /* Add a delay to disable the RCG */
+ udelay(100);
+ }
+}
+
static u8 clk_rcg2_get_parent(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -290,6 +341,8 @@ static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
}
const struct clk_ops clk_rcg2_ops = {
+ .enable = clk_rcg2_enable,
+ .disable = clk_rcg2_disable,
.is_enabled = clk_rcg2_is_enabled,
.get_parent = clk_rcg2_get_parent,
.set_parent = clk_rcg2_set_parent,
@@ -801,6 +854,8 @@ static int clk_gfx3d_set_rate(struct clk_hw *hw, unsigned long rate,
}
const struct clk_ops clk_gfx3d_ops = {
+ .enable = clk_rcg2_enable,
+ .disable = clk_rcg2_disable,
.is_enabled = clk_rcg2_is_enabled,
.get_parent = clk_rcg2_get_parent,
.set_parent = clk_rcg2_set_parent,