aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-4.19/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches-4.19/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch')
-rw-r--r--target/linux/ipq806x/patches-4.19/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch152
1 files changed, 152 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-4.19/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch b/target/linux/ipq806x/patches-4.19/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch
new file mode 100644
index 0000000000..847b4809a3
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.19/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch
@@ -0,0 +1,152 @@
+From 77612720a2362230af726baa4149c40ec7a7fb05 Mon Sep 17 00:00:00 2001
+From: Sricharan R <sricharan@codeaurora.org>
+Date: Tue, 14 Aug 2018 17:42:31 +0530
+Subject: [PATCH 12/12] clk: qcom: Add safe switch hook for krait mux clocks
+
+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>
+Tested-by: Craig Tatlor <ctatlor97@gmail.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.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
+@@ -50,6 +50,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
+@@ -12,6 +12,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
+@@ -26,6 +26,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)
+ {
+@@ -70,6 +113,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",
+@@ -93,6 +137,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)
+@@ -108,6 +153,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:
+@@ -119,6 +169,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 = {
+@@ -139,6 +190,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)
+@@ -164,6 +216,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]);