aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-4.14/0044-clk-Add-safe-switch-hook.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches-4.14/0044-clk-Add-safe-switch-hook.patch')
-rw-r--r--target/linux/ipq806x/patches-4.14/0044-clk-Add-safe-switch-hook.patch160
1 files changed, 160 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-4.14/0044-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.14/0044-clk-Add-safe-switch-hook.patch
new file mode 100644
index 0000000000..b2468a9609
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.14/0044-clk-Add-safe-switch-hook.patch
@@ -0,0 +1,160 @@
+From patchwork Fri Dec 8 09:42:28 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,10/12] clk: qcom: Add safe switch hook for krait mux clocks
+From: Sricharan R <sricharan@codeaurora.org>
+X-Patchwork-Id: 10102057
+Message-Id: <1512726150-7204-11-git-send-email-sricharan@codeaurora.org>
+To: mturquette@baylibre.com, sboyd@codeaurora.org,
+ devicetree@vger.kernel.org, linux-pm@vger.kernel.org,
+ linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
+ viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org
+Cc: sricharan@codeaurora.org
+Date: Fri, 8 Dec 2017 15:12:28 +0530
+
+When the Hfplls are reprogrammed during the rate change,
+the primary muxes which are sourced from the same hfpll
+for higher frequencies, needs to be switched to the 'safe
+secondary mux' as the parent for that small window. This
+is done by registering a clk notifier for the muxes and
+switching to the safe parent in the PRE_RATE_CHANGE notifier
+and back to the original parent in the POST_RATE_CHANGE notifier.
+
+Signed-off-by: Sricharan R <sricharan@codeaurora.org>
+---
+ drivers/clk/qcom/clk-krait.c | 2 ++
+ drivers/clk/qcom/clk-krait.h | 3 +++
+ drivers/clk/qcom/krait-cc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 61 insertions(+)
+
+--- a/drivers/clk/qcom/clk-krait.c
++++ b/drivers/clk/qcom/clk-krait.c
+@@ -60,6 +60,8 @@ static int krait_mux_set_parent(struct c
+ if (__clk_is_enabled(hw->clk))
+ __krait_mux_set_sel(mux, sel);
+
++ mux->reparent = true;
++
+ return 0;
+ }
+
+--- a/drivers/clk/qcom/clk-krait.h
++++ b/drivers/clk/qcom/clk-krait.h
+@@ -23,6 +23,9 @@ struct krait_mux_clk {
+ u32 shift;
+ u32 en_mask;
+ bool lpl;
++ u8 safe_sel;
++ u8 old_index;
++ bool reparent;
+
+ struct clk_hw hw;
+ struct notifier_block clk_nb;
+--- a/drivers/clk/qcom/krait-cc.c
++++ b/drivers/clk/qcom/krait-cc.c
+@@ -35,6 +35,49 @@ static unsigned int pri_mux_map[] = {
+ 0,
+ };
+
++/*
++ * Notifier function for switching the muxes to safe parent
++ * while the hfpll is getting reprogrammed.
++ */
++static int krait_notifier_cb(struct notifier_block *nb,
++ unsigned long event,
++ void *data)
++{
++ int ret = 0;
++ struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk,
++ clk_nb);
++ /* Switch to safe parent */
++ if (event == PRE_RATE_CHANGE) {
++ mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw);
++ ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel);
++ mux->reparent = false;
++ /*
++ * By the time POST_RATE_CHANGE notifier is called,
++ * clk framework itself would have changed the parent for the new rate.
++ * Only otherwise, put back to the old parent.
++ */
++ } else if (event == POST_RATE_CHANGE) {
++ if (!mux->reparent)
++ ret = krait_mux_clk_ops.set_parent(&mux->hw,
++ mux->old_index);
++ }
++
++ return notifier_from_errno(ret);
++}
++
++static int krait_notifier_register(struct device *dev, struct clk *clk,
++ struct krait_mux_clk *mux)
++{
++ int ret = 0;
++
++ mux->clk_nb.notifier_call = krait_notifier_cb;
++ ret = clk_notifier_register(clk, &mux->clk_nb);
++ if (ret)
++ dev_err(dev, "failed to register clock notifier: %d\n", ret);
++
++ return ret;
++}
++
+ static int
+ krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
+ {
+@@ -79,6 +122,7 @@ static int
+ krait_add_sec_mux(struct device *dev, int id, const char *s,
+ unsigned int offset, bool unique_aux)
+ {
++ int ret;
+ struct krait_mux_clk *mux;
+ static const char *sec_mux_list[] = {
+ "acpu_aux",
+@@ -102,6 +146,7 @@ krait_add_sec_mux(struct device *dev, in
+ mux->shift = 2;
+ mux->parent_map = sec_mux_map;
+ mux->hw.init = &init;
++ mux->safe_sel = 0;
+
+ init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
+ if (!init.name)
+@@ -117,6 +162,11 @@ krait_add_sec_mux(struct device *dev, in
+
+ clk = devm_clk_register(dev, &mux->hw);
+
++ ret = krait_notifier_register(dev, clk, mux);
++ if (ret)
++ goto unique_aux;
++
++unique_aux:
+ if (unique_aux)
+ kfree(sec_mux_list[0]);
+ err_aux:
+@@ -128,6 +178,7 @@ static struct clk *
+ krait_add_pri_mux(struct device *dev, int id, const char *s,
+ unsigned int offset)
+ {
++ int ret;
+ struct krait_mux_clk *mux;
+ const char *p_names[3];
+ struct clk_init_data init = {
+@@ -148,6 +199,7 @@ krait_add_pri_mux(struct device *dev, in
+ mux->lpl = id >= 0;
+ mux->parent_map = pri_mux_map;
+ mux->hw.init = &init;
++ mux->safe_sel = 2;
+
+ init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
+ if (!init.name)
+@@ -173,6 +225,10 @@ krait_add_pri_mux(struct device *dev, in
+
+ clk = devm_clk_register(dev, &mux->hw);
+
++ ret = krait_notifier_register(dev, clk, mux);
++ if (ret)
++ goto err_p3;
++err_p3:
+ kfree(p_names[2]);
+ err_p2:
+ kfree(p_names[1]);