diff options
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.patch | 160 |
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]); |