From: Pavel Kubelun <be.dissent@gmail.com> Date: Sat, 9 Dec 2017 17:15:05 +0000 (+0300) Subject: ipq806x: update clk and cpufreq drivers X-Git-Tag: v18.06.0-rc1~1236 X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=7903a9219c7eb5d14c62f79d4a70f5cab1c6294f;p=openwrt%2Fstaging%2Fpepe2k.git ipq806x: update clk and cpufreq drivers A newer clk and cpufreq drivers for ipq806x platform had been sent upstream. A change that i have noticed is that now it's possible to set min, cur and max frequencies from sysfs (previously it was bugged and caused nothing). Following patches are removed: - 0036-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch - seems it was dropped from the patchset by current committer. - 0044-clk-qcom-krait-Remove-CLK_IS_ROOT.patch - already applied to the driver itself in the corresponding patch. - 0057-clk-qcom-Add-regmap-mux-div-clocks-support.patch - seem to be irrelevant to ipq806x. Signed-off-by: Pavel Kubelun <be.dissent@gmail.com> --- diff --git a/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch b/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch index 8c69b97cc4..019170b6dc 100644 --- a/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch +++ b/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch @@ -1,7 +1,21 @@ -From 1d6b12f73c98ecf252743936a53242356cc50a34 Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:19 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,01/12] ARM: Add Krait L2 register accessor functions +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102101 +Message-Id: <1512726150-7204-2-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, Mark Rutland <mark.rutland@arm.com>, + Russell King <linux@arm.linux.org.uk>, + Courtney Cavin <courtney.cavin@sonymobile.com> +Date: Fri, 8 Dec 2017 15:12:19 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:20 -0700 -Subject: [PATCH 34/69] ARM: Add Krait L2 register accessor functions Krait CPUs have a handful of L2 cache controller registers that live behind a cp15 based indirection register. First you program diff --git a/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch b/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch index 426cabd4e4..5a64e6c56e 100644 --- a/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch +++ b/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch @@ -1,7 +1,19 @@ -From 9d381d65eae163d8f50d97a3ad9033bba176f62b Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:20 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,02/12] clk: mux: Split out register accessors for reuse +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102103 +Message-Id: <1512726150-7204-3-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:20 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:21 -0700 -Subject: [PATCH 35/69] clk: mux: Split out register accessors for reuse We want to reuse the logic in clk-mux.c for other clock drivers that don't use readl as register accessors. Fortunately, there @@ -12,28 +24,25 @@ that operate on an optional table and some flags so that other drivers can use the same logic. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> -Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> --- - drivers/clk/clk-mux.c | 76 ++++++++++++++++++++++++++++---------------- - include/linux/clk-provider.h | 11 +++++-- - 2 files changed, 57 insertions(+), 30 deletions(-) + drivers/clk/clk-mux.c | 75 +++++++++++++++++++++++++++----------------- + include/linux/clk-provider.h | 9 ++++-- + 2 files changed, 54 insertions(+), 30 deletions(-) --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c -@@ -26,35 +26,27 @@ +@@ -26,35 +26,24 @@ * parent - parent is adjustable through clk_set_parent */ -static u8 clk_mux_get_parent(struct clk_hw *hw) -+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) -+ +unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val, + unsigned int *table, unsigned long flags) { - struct clk_mux *mux = to_clk_mux(hw); +- struct clk_mux *mux = to_clk_mux(hw); int num_parents = clk_hw_get_num_parents(hw); - u32 val; - +- - /* - * FIXME need a mux-specific flag to determine if val is bitwise or numeric - * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 @@ -43,7 +52,7 @@ Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> - */ - val = clk_readl(mux->reg) >> mux->shift; - val &= mux->mask; -- + - if (mux->table) { + if (table) { int i; @@ -64,7 +73,7 @@ Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> val--; if (val >= num_parents) -@@ -62,23 +54,53 @@ static u8 clk_mux_get_parent(struct clk_ +@@ -62,23 +51,53 @@ static u8 clk_mux_get_parent(struct clk_ return val; } @@ -80,9 +89,9 @@ Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> - if (mux->table) { - index = mux->table[index]; + /* -+ * FIXME need a mux-specific flag to determine if val is bitwise or numeric -+ * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 -+ * to 0x7 (index starts at one) ++ * FIXME need a mux-specific flag to determine if val is bitwise or ++ * numeric e.g. sys_clkin_ck's clksel field is 3 bits wide, ++ * but ranges from 0x1 to 0x7 (index starts at one) + * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so + * val = 0x4 really means "bit 2, index starts at bit 0" + */ @@ -126,7 +135,7 @@ Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> if (mux->lock) spin_lock_irqsave(mux->lock, flags); else -@@ -102,14 +124,14 @@ static int clk_mux_set_parent(struct clk +@@ -102,14 +121,14 @@ static int clk_mux_set_parent(struct clk } const struct clk_ops clk_mux_ops = { @@ -143,7 +152,7 @@ Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> }; EXPORT_SYMBOL_GPL(clk_mux_ro_ops); -@@ -117,7 +139,7 @@ struct clk_hw *clk_hw_register_mux_table +@@ -117,7 +136,7 @@ struct clk_hw *clk_hw_register_mux_table const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, @@ -175,13 +184,7 @@ Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> struct clk *clk_register_mux(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned long flags, -@@ -499,12 +504,12 @@ struct clk *clk_register_mux_table(struc - const char * const *parent_names, u8 num_parents, - unsigned long flags, - void __iomem *reg, u8 shift, u32 mask, -- u8 clk_mux_flags, u32 *table, spinlock_t *lock); -+ u8 clk_mux_flags, unsigned int *table, spinlock_t *lock); - struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, +@@ -504,7 +509,7 @@ struct clk_hw *clk_hw_register_mux_table const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, diff --git a/target/linux/ipq806x/patches-4.9/0036-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch b/target/linux/ipq806x/patches-4.9/0036-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch deleted file mode 100644 index f4a47c7ba3..0000000000 --- a/target/linux/ipq806x/patches-4.9/0036-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 88e1d6d9c113fe50810d1b03eb1fdbf015e5d1bd Mon Sep 17 00:00:00 2001 -From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:22 -0700 -Subject: [PATCH 36/69] clk: Avoid sending high rates to downstream clocks - during set_rate - -If a clock is on and we call clk_set_rate() on it we may get into -a situation where the clock temporarily increases in rate -dramatically while we walk the tree and call .set_rate() ops. For -example, consider a case where a PLL feeds into a divider. -Initially the divider is set to divide by 1 and the PLL is -running fairly slow (100MHz). The downstream consumer of the -divider output can only handle rates =< 400 MHz, but the divider -can only choose between divisors of 1 and 4. - - +-----+ +----------------+ - | PLL |-->| div 1 or div 4 |---> consumer device - +-----+ +----------------+ - -To achieve a rate of 400MHz on the output of the divider, we -would have to set the rate of the PLL to 1.6 GHz and then divide -it by 4. The current code would set the PLL to 1.6GHz first while -the divider is still set to 1, thus causing the downstream -consumer of the clock to receive a few clock cycles of 1.6GHz -clock (far beyond it's maximum acceptable rate). We should be -changing the divider first before increasing the PLL rate to -avoid this problem. - -Therefore, set the rate of any child clocks that are increasing -in rate from their current rate so that they can increase their -dividers if necessary. We assume that there isn't such a thing as -minimum rate requirements. - -Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> - -Conflicts: - drivers/clk/clk.c ---- - drivers/clk/clk.c | 22 +++++++++++++++------- - 1 file changed, 15 insertions(+), 7 deletions(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -1466,12 +1466,12 @@ static struct clk_core *clk_propagate_ra - * walk down a subtree and set the new rates notifying the rate - * change on the way - */ --static void clk_change_rate(struct clk_core *core) -+static void -+clk_change_rate(struct clk_core *core, unsigned long best_parent_rate) - { - struct clk_core *child; - struct hlist_node *tmp; - unsigned long old_rate; -- unsigned long best_parent_rate = 0; - bool skip_set_rate = false; - struct clk_core *old_parent; - struct clk_core *parent = NULL; -@@ -1523,6 +1523,7 @@ static void clk_change_rate(struct clk_c - trace_clk_set_rate_complete(core, core->new_rate); - - core->rate = clk_recalc(core, best_parent_rate); -+ core->rate = core->new_rate; - - if (core->flags & CLK_SET_RATE_UNGATE) { - unsigned long flags; -@@ -1550,12 +1551,13 @@ static void clk_change_rate(struct clk_c - /* Skip children who will be reparented to another clock */ - if (child->new_parent && child->new_parent != core) - continue; -- clk_change_rate(child); -+ if (child->new_rate != child->rate) -+ clk_change_rate(child, core->new_rate); - } - -- /* handle the new child who might not be in core->children yet */ -- if (core->new_child) -- clk_change_rate(core->new_child); -+ /* handle the new child who might not be in clk->children yet */ -+ if (core->new_child && core->new_child->new_rate != core->new_child->rate) -+ clk_change_rate(core->new_child, core->new_rate); - } - - static int clk_core_set_rate_nolock(struct clk_core *core, -@@ -1563,6 +1565,7 @@ static int clk_core_set_rate_nolock(stru - { - struct clk_core *top, *fail_clk; - unsigned long rate = req_rate; -+ unsigned long parent_rate; - - if (!core) - return 0; -@@ -1588,8 +1591,13 @@ static int clk_core_set_rate_nolock(stru - return -EBUSY; - } - -+ if (top->parent) -+ parent_rate = top->parent->rate; -+ else -+ parent_rate = 0; -+ - /* change the rates */ -- clk_change_rate(top); -+ clk_change_rate(top, parent_rate); - - core->req_rate = req_rate; - diff --git a/target/linux/ipq806x/patches-4.9/0037-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.9/0037-clk-Add-safe-switch-hook.patch deleted file mode 100644 index bff605f8de..0000000000 --- a/target/linux/ipq806x/patches-4.9/0037-clk-Add-safe-switch-hook.patch +++ /dev/null @@ -1,158 +0,0 @@ -From a1adfb782789ae9b25c928dfe3d639288563a86c Mon Sep 17 00:00:00 2001 -From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:23 -0700 -Subject: [PATCH 37/69] clk: Add safe switch hook - -Sometimes clocks can't accept their parent source turning off -while the source is reprogrammed to a different rate. Most -notably CPU clocks require a way to switch away from the current -PLL they're running on, reprogram that PLL to a new rate, and -then switch back to the PLL with the new rate once they're done. -Add a hook that drivers can implement allowing them to return a -'safe parent' and 'safe frequency' that they can switch their -parent to while the upstream source is reprogrammed to support -this. - -Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> -Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> ---- - drivers/clk/clk.c | 73 +++++++++++++++++++++++++++++++++++++++++--- - include/linux/clk-provider.h | 2 ++ - 2 files changed, 70 insertions(+), 5 deletions(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -51,9 +51,13 @@ struct clk_core { - struct clk_core **parents; - u8 num_parents; - u8 new_parent_index; -+ u8 safe_parent_index; - unsigned long rate; - unsigned long req_rate; -+ unsigned long old_rate; - unsigned long new_rate; -+ unsigned long safe_freq; -+ struct clk_core *safe_parent; - struct clk_core *new_parent; - struct clk_core *new_child; - unsigned long flags; -@@ -1310,7 +1314,9 @@ out: - static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate, - struct clk_core *new_parent, u8 p_index) - { -- struct clk_core *child; -+ struct clk_core *child, *parent; -+ struct clk_hw *parent_hw; -+ unsigned long safe_freq = 0; - - core->new_rate = new_rate; - core->new_parent = new_parent; -@@ -1320,6 +1326,23 @@ static void clk_calc_subtree(struct clk_ - if (new_parent && new_parent != core->parent) - new_parent->new_child = core; - -+ if (core->ops->get_safe_parent) { -+ parent_hw = core->ops->get_safe_parent(core->hw, &safe_freq); -+ if (parent_hw) { -+ parent = parent_hw->core; -+ p_index = clk_fetch_parent_index(core, parent); -+ core->safe_parent_index = p_index; -+ core->safe_parent = parent; -+ if (safe_freq) -+ core->safe_freq = safe_freq; -+ else -+ core->safe_freq = 0; -+ } -+ } else { -+ core->safe_parent = NULL; -+ core->safe_freq = 0; -+ } -+ - hlist_for_each_entry(child, &core->children, child_node) { - child->new_rate = clk_recalc(child, new_rate); - clk_calc_subtree(child, child->new_rate, NULL, 0); -@@ -1432,14 +1455,51 @@ static struct clk_core *clk_propagate_ra - unsigned long event) - { - struct clk_core *child, *tmp_clk, *fail_clk = NULL; -+ struct clk_core *old_parent; - int ret = NOTIFY_DONE; - -- if (core->rate == core->new_rate) -+ if (core->rate == core->new_rate && event != POST_RATE_CHANGE) - return NULL; - -+ switch (event) { -+ case PRE_RATE_CHANGE: -+ if (core->safe_parent) { -+ if (core->safe_freq) -+ core->ops->set_rate_and_parent(core->hw, -+ core->safe_freq, -+ core->safe_parent->rate, -+ core->safe_parent_index); -+ else -+ core->ops->set_parent(core->hw, -+ core->safe_parent_index); -+ } -+ core->old_rate = core->rate; -+ break; -+ case POST_RATE_CHANGE: -+ if (core->safe_parent) { -+ old_parent = __clk_set_parent_before(core, -+ core->new_parent); -+ if (core->ops->set_rate_and_parent) { -+ core->ops->set_rate_and_parent(core->hw, -+ core->new_rate, -+ core->new_parent ? -+ core->new_parent->rate : 0, -+ core->new_parent_index); -+ } else if (core->ops->set_parent) { -+ core->ops->set_parent(core->hw, -+ core->new_parent_index); -+ } -+ __clk_set_parent_after(core, core->new_parent, -+ old_parent); -+ } -+ break; -+ } -+ - if (core->notifier_count) { -- ret = __clk_notify(core, event, core->rate, core->new_rate); -- if (ret & NOTIFY_STOP_MASK) -+ if (event != POST_RATE_CHANGE || core->old_rate != core->rate) -+ ret = __clk_notify(core, event, core->old_rate, -+ core->new_rate); -+ if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE) - fail_clk = core; - } - -@@ -1495,7 +1555,8 @@ clk_change_rate(struct clk_core *core, u - clk_enable_unlock(flags); - } - -- if (core->new_parent && core->new_parent != core->parent) { -+ if (core->new_parent && core->new_parent != core->parent && -+ !core->safe_parent) { - old_parent = __clk_set_parent_before(core, core->new_parent); - trace_clk_set_parent(core, core->new_parent); - -@@ -1601,6 +1662,8 @@ static int clk_core_set_rate_nolock(stru - - core->req_rate = req_rate; - -+ clk_propagate_rate_change(top, POST_RATE_CHANGE); -+ - return 0; - } - ---- a/include/linux/clk-provider.h -+++ b/include/linux/clk-provider.h -@@ -206,6 +206,8 @@ struct clk_ops { - struct clk_rate_request *req); - int (*set_parent)(struct clk_hw *hw, u8 index); - u8 (*get_parent)(struct clk_hw *hw); -+ struct clk_hw *(*get_safe_parent)(struct clk_hw *hw, -+ unsigned long *safe_freq); - int (*set_rate)(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); - int (*set_rate_and_parent)(struct clk_hw *hw, diff --git a/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch b/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch index e3797cfb71..70926143ec 100644 --- a/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch +++ b/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch @@ -1,7 +1,19 @@ -From f044ffe2d612dcaa2de36c918aaab79c8db1482e Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:21 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,03/12] clk: qcom: Add support for High-Frequency PLLs (HFPLLs) +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102083 +Message-Id: <1512726150-7204-4-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:21 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:24 -0700 -Subject: [PATCH 38/69] clk: qcom: Add support for High-Frequency PLLs (HFPLLs) HFPLLs are the main frequency source for Krait CPU clocks. Add support for changing the rate of these PLLs. @@ -105,7 +117,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + * H/W requires a 5us delay between disabling the bypass and + * de-asserting the reset. Delay 10us just to be safe. + */ -+ udelay(10); ++ usleep_range(10, 100); + + /* De-assert active-low PLL reset. */ + regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N); @@ -116,7 +128,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + regmap_read(regmap, hd->status_reg, &val); + } while (!(val & BIT(hd->lock_bit))); + } else { -+ udelay(60); ++ usleep_range(60, 100); + } + + /* Enable PLL output. */ @@ -151,7 +163,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + * and assert the reset. + */ + regmap_update_bits(regmap, hd->mode_reg, -+ PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0); ++ PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0); +} + +static void clk_hfpll_disable(struct clk_hw *hw) @@ -252,7 +264,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + regmap_read(regmap, hd->status_reg, &status); + if (!(status & BIT(hd->lock_bit))) { + WARN(1, "HFPLL %s is ON, but not locked!\n", -+ __clk_get_name(hw->clk)); ++ __clk_get_name(hw->clk)); + clk_hfpll_disable(hw); + __clk_hfpll_init_once(hw); + } diff --git a/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch b/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch index 92266f763a..d9ad391d02 100644 --- a/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch +++ b/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch @@ -1,7 +1,19 @@ -From 23f680d03e5894f494572a5162d21328bd86890c Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:22 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,04/12] clk: qcom: Add HFPLL driver +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102079 +Message-Id: <1512726150-7204-5-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:22 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:25 -0700 -Subject: [PATCH 39/69] clk: qcom: Add HFPLL driver On some devices (MSM8974 for example), the HFPLLs are instantiated within the Krait processor subsystem as separate @@ -10,7 +22,6 @@ provide HFPLL clocks for use by the system. Cc: <devicetree@vger.kernel.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> -Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> --- .../devicetree/bindings/clock/qcom,hfpll.txt | 40 ++++++++ drivers/clk/qcom/Kconfig | 8 ++ @@ -171,7 +182,7 @@ Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> + return PTR_ERR(regmap); + + if (of_property_read_string_index(dev->of_node, "clock-output-names", -+ 0, &init.name)) ++ 0, &init.name)) + return -ENODEV; + + h->d = &hdata; diff --git a/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch b/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch index 8a51af79df..c3af0fa55c 100644 --- a/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch +++ b/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch @@ -1,14 +1,26 @@ -From 0dfdf84ee3982e88a62123b3de1c094d2c0829af Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:24 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,06/12] clk: qcom: Add IPQ806X's HFPLLs +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102047 +Message-Id: <1512726150-7204-7-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:24 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:27 -0700 -Subject: [PATCH 40/69] clk: qcom: Add IPQ806X's HFPLLs Describe the HFPLLs present on IPQ806X devices. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> --- - drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 83 insertions(+) + drivers/clk/qcom/gcc-ipq806x.c | 82 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 82 insertions(+) --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c @@ -20,7 +32,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> #include "reset.h" static struct clk_pll pll0 = { -@@ -113,6 +114,85 @@ static struct clk_regmap pll8_vote = { +@@ -113,6 +114,84 @@ static struct clk_regmap pll8_vote = { }, }; @@ -101,12 +113,11 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + }, + .lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock), +}; -+ + static struct clk_pll pll14 = { .l_reg = 0x31c4, .m_reg = 0x31c8, -@@ -2801,6 +2881,9 @@ static struct clk_regmap *gcc_ipq806x_cl +@@ -2801,6 +2880,9 @@ static struct clk_regmap *gcc_ipq806x_cl [UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr, [NSSTCM_CLK_SRC] = &nss_tcm_src.clkr, [NSSTCM_CLK] = &nss_tcm_clk.clkr, diff --git a/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch index 902e49d60c..a6d0f0d7a6 100644 --- a/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch +++ b/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch @@ -1,7 +1,19 @@ -From b9747125a8e7633ed2701a70e32dbb0442193774 Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:25 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,07/12] clk: qcom: Add support for Krait clocks +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102051 +Message-Id: <1512726150-7204-8-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:25 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:28 -0700 -Subject: [PATCH 41/69] clk: qcom: Add support for Krait clocks The Krait clocks are made up of a series of muxes and a divider that choose between a fixed rate clock and dedicated HFPLLs for @@ -13,9 +25,9 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> --- drivers/clk/qcom/Kconfig | 4 ++ drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-krait.c | 167 +++++++++++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-krait.h | 49 +++++++++++++ - 4 files changed, 221 insertions(+) + drivers/clk/qcom/clk-krait.c | 134 +++++++++++++++++++++++++++++++++++++++++++ + drivers/clk/qcom/clk-krait.h | 48 ++++++++++++++++ + 4 files changed, 187 insertions(+) create mode 100644 drivers/clk/qcom/clk-krait.c create mode 100644 drivers/clk/qcom/clk-krait.h @@ -41,7 +53,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o --- /dev/null +++ b/drivers/clk/qcom/clk-krait.c -@@ -0,0 +1,167 @@ +@@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * @@ -103,6 +115,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + /* Don't touch mux if CPU is off as it won't work */ + if (__clk_is_enabled(hw->clk)) + __krait_mux_set_sel(mux, sel); ++ + return 0; +} + @@ -119,44 +132,10 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + return clk_mux_get_parent(hw, sel, mux->parent_map, 0); +} + -+static struct clk_hw *krait_mux_get_safe_parent(struct clk_hw *hw, -+ unsigned long *safe_freq) -+{ -+ int i; -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ int num_parents = clk_hw_get_num_parents(hw); -+ -+ i = mux->safe_sel; -+ for (i = 0; i < num_parents; i++) -+ if (mux->safe_sel == mux->parent_map[i]) -+ break; -+ -+ return clk_hw_get_parent_by_index(hw, i); -+} -+ -+static int krait_mux_enable(struct clk_hw *hw) -+{ -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ -+ __krait_mux_set_sel(mux, mux->en_mask); -+ -+ return 0; -+} -+ -+static void krait_mux_disable(struct clk_hw *hw) -+{ -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ -+ __krait_mux_set_sel(mux, mux->safe_sel); -+} -+ +const struct clk_ops krait_mux_clk_ops = { -+ .enable = krait_mux_enable, -+ .disable = krait_mux_disable, + .set_parent = krait_mux_set_parent, + .get_parent = krait_mux_get_parent, + .determine_rate = __clk_mux_determine_rate_closest, -+ .get_safe_parent = krait_mux_get_safe_parent, +}; +EXPORT_SYMBOL_GPL(krait_mux_clk_ops); + @@ -169,7 +148,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +} + +static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) ++ unsigned long parent_rate) +{ + struct krait_div2_clk *d = to_krait_div2_clk(hw); + unsigned long flags; @@ -211,7 +190,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +EXPORT_SYMBOL_GPL(krait_div2_clk_ops); --- /dev/null +++ b/drivers/clk/qcom/clk-krait.h -@@ -0,0 +1,49 @@ +@@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * @@ -232,8 +211,6 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + +struct krait_mux_clk { + unsigned int *parent_map; -+ bool has_safe_parent; -+ u8 safe_sel; + u32 offset; + u32 mask; + u32 shift; @@ -241,6 +218,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + bool lpl; + + struct clk_hw hw; ++ struct notifier_block clk_nb; +}; + +#define to_krait_mux_clk(_hw) container_of(_hw, struct krait_mux_clk, hw) diff --git a/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch b/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch index c499436478..5a76fbc8b6 100644 --- a/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch +++ b/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch @@ -1,7 +1,19 @@ -From 6039eb63fabdd6871fc70940aa98102665c78eed Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:26 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,08/12] clk: qcom: Add KPSS ACC/GCC driver +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102023 +Message-Id: <1512726150-7204-9-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:26 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:29 -0700 -Subject: [PATCH 42/69] clk: qcom: Add KPSS ACC/GCC driver The ACC and GCC regions present in KPSSv1 contain registers to control clocks and power to each Krait CPU and L2. For CPUfreq @@ -15,8 +27,8 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt | 28 +++++++ drivers/clk/qcom/Kconfig | 8 ++ drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/kpss-xcc.c | 95 ++++++++++++++++++++++ - 5 files changed, 139 insertions(+) + drivers/clk/qcom/kpss-xcc.c | 96 ++++++++++++++++++++++ + 5 files changed, 140 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt create mode 100644 drivers/clk/qcom/kpss-xcc.c @@ -98,7 +110,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> obj-$(CONFIG_QCOM_HFPLL) += hfpll.o --- /dev/null +++ b/drivers/clk/qcom/kpss-xcc.c -@@ -0,0 +1,95 @@ +@@ -0,0 +1,96 @@ +/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify @@ -158,7 +170,8 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + + if (id->data) { + if (of_property_read_string_index(pdev->dev.of_node, -+ "clock-output-names", 0, &name)) ++ "clock-output-names", ++ 0, &name)) + return -ENODEV; + base += 0x14; + } else { diff --git a/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch b/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch index 7e2e41e3bb..1d32b2b05d 100644 --- a/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch +++ b/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch @@ -1,7 +1,19 @@ -From 7fb5976eb0231a06f484a6bde5e5fbfee7ee4f4a Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:27 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,09/12] clk: qcom: Add Krait clock controller driver +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102061 +Message-Id: <1512726150-7204-10-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:27 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:30 -0700 -Subject: [PATCH 43/69] clk: qcom: Add Krait clock controller driver The Krait CPU clocks are made up of a primary mux and secondary mux for each CPU and the L2, controlled via cp15 accessors. For @@ -15,8 +27,8 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> .../devicetree/bindings/clock/qcom,krait-cc.txt | 22 ++ drivers/clk/qcom/Kconfig | 8 + drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/krait-cc.c | 352 +++++++++++++++++++++ - 4 files changed, 383 insertions(+) + drivers/clk/qcom/krait-cc.c | 350 +++++++++++++++++++++ + 4 files changed, 381 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt create mode 100644 drivers/clk/qcom/krait-cc.c @@ -71,7 +83,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +obj-$(CONFIG_KRAITCC) += krait-cc.o --- /dev/null +++ b/drivers/clk/qcom/krait-cc.c -@@ -0,0 +1,352 @@ +@@ -0,0 +1,350 @@ +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify @@ -110,7 +122,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +}; + +static int -+krait_add_div(struct device *dev, int id, const char *s, unsigned offset) ++krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) +{ + struct krait_div2_clk *div; + struct clk_init_data init = { @@ -150,8 +162,8 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +} + +static int -+krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset, -+ bool unique_aux) ++krait_add_sec_mux(struct device *dev, int id, const char *s, ++ unsigned int offset, bool unique_aux) +{ + struct krait_mux_clk *mux; + static const char *sec_mux_list[] = { @@ -172,8 +184,6 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + + mux->offset = offset; + mux->lpl = id >= 0; -+ mux->has_safe_parent = true; -+ mux->safe_sel = 2; + mux->mask = 0x3; + mux->shift = 2; + mux->parent_map = sec_mux_map; @@ -201,7 +211,8 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +} + +static struct clk * -+krait_add_pri_mux(struct device *dev, int id, const char *s, unsigned offset) ++krait_add_pri_mux(struct device *dev, int id, const char *s, ++ unsigned int offset) +{ + struct krait_mux_clk *mux; + const char *p_names[3]; @@ -217,8 +228,6 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + if (!mux) + return ERR_PTR(-ENOMEM); + -+ mux->has_safe_parent = true; -+ mux->safe_sel = 0; + mux->mask = 0x3; + mux->shift = 0; + mux->offset = offset; @@ -264,7 +273,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux) +{ + int ret; -+ unsigned offset; ++ unsigned int offset; + void *p = NULL; + const char *s; + struct clk *clk; @@ -332,7 +341,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + return -ENODEV; + + /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ -+ clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1); ++ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1); + if (IS_ERR(clk)) + return PTR_ERR(clk); + @@ -370,7 +379,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + for_each_online_cpu(cpu) { + clk_prepare_enable(l2_pri_mux_clk); + WARN(clk_prepare_enable(clks[cpu]), -+ "Unable to turn on CPU%d clock", cpu); ++ "Unable to turn on CPU%d clock", cpu); + } + + /* @@ -401,6 +410,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu); + cur_rate = aux_rate; + } ++ + clk_set_rate(clk, aux_rate); + clk_set_rate(clk, 2); + clk_set_rate(clk, cur_rate); diff --git a/target/linux/ipq806x/patches-4.9/0044-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.9/0044-clk-Add-safe-switch-hook.patch new file mode 100644 index 0000000000..d0eddc64c2 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/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]); diff --git a/target/linux/ipq806x/patches-4.9/0044-clk-qcom-krait-Remove-CLK_IS_ROOT.patch b/target/linux/ipq806x/patches-4.9/0044-clk-qcom-krait-Remove-CLK_IS_ROOT.patch deleted file mode 100644 index c3761eef53..0000000000 --- a/target/linux/ipq806x/patches-4.9/0044-clk-qcom-krait-Remove-CLK_IS_ROOT.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 58f8215f1d9397f9130657cc2c15a956bd99210e Mon Sep 17 00:00:00 2001 -From: Georgi Djakov <georgi.djakov@linaro.org> -Date: Wed, 13 Jul 2016 15:22:25 +0300 -Subject: [PATCH 44/69] clk: qcom: krait: Remove CLK_IS_ROOT - -The flag CLK_IS_ROOT is no-op now. Remove it. - -Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> ---- - drivers/clk/qcom/krait-cc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/clk/qcom/krait-cc.c -+++ b/drivers/clk/qcom/krait-cc.c -@@ -258,7 +258,7 @@ static int krait_cc_probe(struct platfor - return -ENODEV; - - /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ -- clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1); -+ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1); - if (IS_ERR(clk)) - return PTR_ERR(clk); - diff --git a/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch b/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch index f5b5ea0fdb..820d13f3c9 100644 --- a/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch +++ b/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch @@ -1,7 +1,19 @@ -From 42eea6bc2858ab9649cf6931455e391e48939685 Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:29 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,11/12] cpufreq: Add module to register cpufreq on Krait CPUs +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102075 +Message-Id: <1512726150-7204-12-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:29 +0530 + From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 20 Mar 2015 23:45:31 -0700 -Subject: [PATCH 45/69] cpufreq: Add module to register cpufreq on Krait CPUs Register a cpufreq-generic device whenever we detect that a "qcom,krait" compatible CPU is present in DT. @@ -111,7 +123,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +#include <linux/platform_device.h> +#include <linux/pm_opp.h> +#include <linux/slab.h> -+#include <linux/cpufreq-dt.h> ++#include "cpufreq-dt.h" + +static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver) +{ @@ -227,7 +239,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + } + + snprintf(table_name, sizeof(table_name), -+ "qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver); ++ "qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver); + + if (!of_find_property(np, table_name, &len)) + return -EINVAL; diff --git a/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch b/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch index 8d2861ce9e..d767dbf5f0 100644 --- a/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch +++ b/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch @@ -1,25 +1,31 @@ -ipq806x: support independent core clocks with kernel 4.9+ +From patchwork Fri Dec 8 09:42:30 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,12/12] cpufreq: dt: Reintroduce independent_clocks platform data +From: Sricharan R <sricharan@codeaurora.org> +X-Patchwork-Id: 10102073 +Message-Id: <1512726150-7204-13-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:30 +0530 -Add back support for the independent_clocks definition that has been -removed between kernel 4.4 and 4.9 by upstream commits -eb96924acddc709db58221c210ca05cd9effb1df and -e86eee6bc2aaa6b3637f6497b26beee09a91bde9 +The Platform data was removed earlier by, +'commit eb96924acddc ("cpufreq: dt: Kill platform-data")' +since there were no users at that time. +Now this is required when the each of the cpu clocks +can be scaled independently, which is the case +for krait cores. So reintroduce it. -* extend the new cpufreq_dt_platform_data definition in cpufreq-dt.h -* use new cpufreq-dt.h in qcom-cpufreq.c +Signed-off-by: Sricharan R <sricharan@codeaurora.org> +--- + drivers/cpufreq/cpufreq-dt.c | 7 ++++++- + drivers/cpufreq/cpufreq-dt.h | 6 ++++++ + 2 files changed, 12 insertions(+), 1 deletion(-) -Signed-off-by: Hannu Nyman <hannu.nyman@iki.fi> - ---- a/drivers/cpufreq/cpufreq-dt.h -+++ b/drivers/cpufreq/cpufreq-dt.h -@@ -14,6 +14,7 @@ - - struct cpufreq_dt_platform_data { - bool have_governor_per_policy; -+ bool independent_clocks; - }; - - #endif /* __CPUFREQ_DT_H__ */ --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -221,7 +221,10 @@ static int cpufreq_init(struct cpufreq_p @@ -38,19 +44,23 @@ Signed-off-by: Hannu Nyman <hannu.nyman@iki.fi> if (data && data->have_governor_per_policy) dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY; -+ dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev); ++ dt_cpufreq_driver.driver_data = data; + ret = cpufreq_register_driver(&dt_cpufreq_driver); if (ret) dev_err(&pdev->dev, "failed register driver: %d\n", ret); ---- a/drivers/cpufreq/qcom-cpufreq.c -+++ b/drivers/cpufreq/qcom-cpufreq.c -@@ -20,7 +20,7 @@ - #include <linux/platform_device.h> - #include <linux/pm_opp.h> - #include <linux/slab.h> --#include <linux/cpufreq-dt.h> -+#include "cpufreq-dt.h" +--- a/drivers/cpufreq/cpufreq-dt.h ++++ b/drivers/cpufreq/cpufreq-dt.h +@@ -13,6 +13,12 @@ + #include <linux/types.h> + + struct cpufreq_dt_platform_data { ++ /* ++ * True when each CPU has its own clock to control its ++ * frequency, false when all CPUs are controlled by a single ++ * clock. ++ */ ++ bool independent_clocks; + bool have_governor_per_policy; + }; - static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver) - { diff --git a/target/linux/ipq806x/patches-4.9/0057-clk-qcom-Add-regmap-mux-div-clocks-support.patch b/target/linux/ipq806x/patches-4.9/0057-clk-qcom-Add-regmap-mux-div-clocks-support.patch deleted file mode 100644 index c5cdc79300..0000000000 --- a/target/linux/ipq806x/patches-4.9/0057-clk-qcom-Add-regmap-mux-div-clocks-support.patch +++ /dev/null @@ -1,372 +0,0 @@ -From f72c5aa18281c44945fea6181d0d816a7605505c Mon Sep 17 00:00:00 2001 -From: Georgi Djakov <georgi.djakov@linaro.org> -Date: Wed, 18 Mar 2015 17:23:29 +0200 -Subject: [PATCH 57/69] clk: qcom: Add regmap mux-div clocks support - -Add support for hardware that can switch both parent clocks and divider -at the same time. This avoids generating intermediate frequencies from -either the old parent clock and new divider or new parent clock and -old divider combinations. - -Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> ---- - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-regmap-mux-div.c | 272 ++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-regmap-mux-div.h | 65 ++++++++ - 3 files changed, 338 insertions(+) - create mode 100644 drivers/clk/qcom/clk-regmap-mux-div.c - create mode 100644 drivers/clk/qcom/clk-regmap-mux-div.h - ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -9,6 +9,7 @@ clk-qcom-y += clk-rcg2.o - clk-qcom-y += clk-branch.o - clk-qcom-y += clk-regmap-divider.o - clk-qcom-y += clk-regmap-mux.o -+clk-qcom-y += clk-regmap-mux-div.o - clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o - clk-qcom-y += clk-hfpll.o - clk-qcom-y += reset.o ---- /dev/null -+++ b/drivers/clk/qcom/clk-regmap-mux-div.c -@@ -0,0 +1,272 @@ -+/* -+ * Copyright (c) 2015, Linaro Limited -+ * Copyright (c) 2014, 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 -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/bitops.h> -+#include <linux/delay.h> -+#include <linux/export.h> -+#include <linux/kernel.h> -+#include <linux/regmap.h> -+ -+#include "clk-regmap-mux-div.h" -+ -+#define CMD_RCGR 0x0 -+#define CMD_RCGR_UPDATE BIT(0) -+#define CMD_RCGR_DIRTY_CFG BIT(4) -+#define CMD_RCGR_ROOT_OFF BIT(31) -+#define CFG_RCGR 0x4 -+ -+#define to_clk_regmap_mux_div(_hw) \ -+ container_of(to_clk_regmap(_hw), struct clk_regmap_mux_div, clkr) -+ -+int __mux_div_set_src_div(struct clk_regmap_mux_div *md, u32 src, u32 div) -+{ -+ int ret, count; -+ u32 val, mask; -+ const char *name = clk_hw_get_name(&md->clkr.hw); -+ -+ val = (div << md->hid_shift) | (src << md->src_shift); -+ mask = ((BIT(md->hid_width) - 1) << md->hid_shift) | -+ ((BIT(md->src_width) - 1) << md->src_shift); -+ -+ ret = regmap_update_bits(md->clkr.regmap, CFG_RCGR + md->reg_offset, -+ mask, val); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(md->clkr.regmap, CMD_RCGR + md->reg_offset, -+ CMD_RCGR_UPDATE, CMD_RCGR_UPDATE); -+ if (ret) -+ return ret; -+ -+ /* Wait for update to take effect */ -+ for (count = 500; count > 0; count--) { -+ ret = regmap_read(md->clkr.regmap, CMD_RCGR + md->reg_offset, -+ &val); -+ if (ret) -+ return ret; -+ if (!(val & CMD_RCGR_UPDATE)) -+ return 0; -+ udelay(1); -+ } -+ -+ pr_err("%s: RCG did not update its configuration", name); -+ return -EBUSY; -+} -+ -+static void __mux_div_get_src_div(struct clk_regmap_mux_div *md, u32 *src, -+ u32 *div) -+{ -+ u32 val, __div, __src; -+ const char *name = clk_hw_get_name(&md->clkr.hw); -+ -+ regmap_read(md->clkr.regmap, CMD_RCGR + md->reg_offset, &val); -+ -+ if (val & CMD_RCGR_DIRTY_CFG) { -+ pr_err("%s: RCG configuration is pending\n", name); -+ return; -+ } -+ -+ regmap_read(md->clkr.regmap, CFG_RCGR + md->reg_offset, &val); -+ __src = (val >> md->src_shift); -+ __src &= BIT(md->src_width) - 1; -+ *src = __src; -+ -+ __div = (val >> md->hid_shift); -+ __div &= BIT(md->hid_width) - 1; -+ *div = __div; -+} -+ -+static int mux_div_enable(struct clk_hw *hw) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_src_div(md, md->src, md->div); -+} -+ -+static inline bool is_better_rate(unsigned long req, unsigned long best, -+ unsigned long new) -+{ -+ return (req <= new && new < best) || (best < req && best < new); -+} -+ -+static int mux_div_determine_rate(struct clk_hw *hw, -+ struct clk_rate_request *req) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ unsigned int i, div, max_div; -+ unsigned long actual_rate, best_rate = 0; -+ unsigned long req_rate = req->rate; -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) { -+ struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); -+ unsigned long parent_rate = clk_hw_get_rate(parent); -+ -+ max_div = BIT(md->hid_width) - 1; -+ for (div = 1; div < max_div; div++) { -+ parent_rate = mult_frac(req_rate, div, 2); -+ parent_rate = clk_hw_round_rate(parent, parent_rate); -+ actual_rate = mult_frac(parent_rate, 2, div); -+ -+ if (is_better_rate(req_rate, best_rate, actual_rate)) { -+ best_rate = actual_rate; -+ req->rate = best_rate; -+ req->best_parent_rate = parent_rate; -+ req->best_parent_hw = parent; -+ } -+ -+ if (actual_rate < req_rate || best_rate <= req_rate) -+ break; -+ } -+ } -+ -+ if (!best_rate) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int __mux_div_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, -+ unsigned long prate, u32 src) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ int ret; -+ u32 div, max_div, best_src = 0, best_div = 0; -+ unsigned int i; -+ unsigned long actual_rate, best_rate = 0; -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) { -+ struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); -+ unsigned long parent_rate = clk_hw_get_rate(parent); -+ -+ max_div = BIT(md->hid_width) - 1; -+ for (div = 1; div < max_div; div++) { -+ parent_rate = mult_frac(rate, div, 2); -+ parent_rate = clk_hw_round_rate(parent, parent_rate); -+ actual_rate = mult_frac(parent_rate, 2, div); -+ -+ if (is_better_rate(rate, best_rate, actual_rate)) { -+ best_rate = actual_rate; -+ best_src = md->parent_map[i].cfg; -+ best_div = div - 1; -+ } -+ -+ if (actual_rate < rate || best_rate <= rate) -+ break; -+ } -+ } -+ -+ ret = __mux_div_set_src_div(md, best_src, best_div); -+ if (!ret) { -+ md->div = best_div; -+ md->src = best_src; -+ } -+ -+ return ret; -+} -+ -+static u8 mux_div_get_parent(struct clk_hw *hw) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ const char *name = clk_hw_get_name(hw); -+ u32 i, div, src = 0; -+ -+ __mux_div_get_src_div(md, &src, &div); -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) -+ if (src == md->parent_map[i].cfg) -+ return i; -+ -+ pr_err("%s: Can't find parent with src %d\n", name, src); -+ return 0; -+} -+ -+static int mux_div_set_parent(struct clk_hw *hw, u8 index) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_src_div(md, md->parent_map[index].cfg, md->div); -+} -+ -+static int mux_div_set_rate(struct clk_hw *hw, -+ unsigned long rate, unsigned long prate) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_rate_and_parent(hw, rate, prate, md->src); -+} -+ -+static int mux_div_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, -+ unsigned long prate, u8 index) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_rate_and_parent(hw, rate, prate, -+ md->parent_map[index].cfg); -+} -+ -+static unsigned long mux_div_recalc_rate(struct clk_hw *hw, unsigned long prate) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ u32 div, src; -+ int i, num_parents = clk_hw_get_num_parents(hw); -+ const char *name = clk_hw_get_name(hw); -+ -+ __mux_div_get_src_div(md, &src, &div); -+ for (i = 0; i < num_parents; i++) -+ if (src == md->parent_map[i].cfg) { -+ struct clk_hw *p = clk_hw_get_parent_by_index(hw, i); -+ unsigned long parent_rate = clk_hw_get_rate(p); -+ -+ return mult_frac(parent_rate, 2, div + 1); -+ } -+ -+ pr_err("%s: Can't find parent %d\n", name, src); -+ return 0; -+} -+ -+static struct clk_hw *mux_div_get_safe_parent(struct clk_hw *hw, -+ unsigned long *safe_freq) -+{ -+ int i; -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ if (md->safe_freq) -+ *safe_freq = md->safe_freq; -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) -+ if (md->safe_src == md->parent_map[i].cfg) -+ break; -+ -+ return clk_hw_get_parent_by_index(hw, i); -+} -+ -+static void mux_div_disable(struct clk_hw *hw) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ __mux_div_set_src_div(md, md->safe_src, md->safe_div); -+} -+ -+const struct clk_ops clk_regmap_mux_div_ops = { -+ .enable = mux_div_enable, -+ .disable = mux_div_disable, -+ .get_parent = mux_div_get_parent, -+ .set_parent = mux_div_set_parent, -+ .set_rate = mux_div_set_rate, -+ .set_rate_and_parent = mux_div_set_rate_and_parent, -+ .determine_rate = mux_div_determine_rate, -+ .recalc_rate = mux_div_recalc_rate, -+ .get_safe_parent = mux_div_get_safe_parent, -+}; -+EXPORT_SYMBOL_GPL(clk_regmap_mux_div_ops); ---- /dev/null -+++ b/drivers/clk/qcom/clk-regmap-mux-div.h -@@ -0,0 +1,65 @@ -+/* -+ * Copyright (c) 2015, Linaro Limited -+ * Copyright (c) 2014, 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 -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __QCOM_CLK_REGMAP_MUX_DIV_H__ -+#define __QCOM_CLK_REGMAP_MUX_DIV_H__ -+ -+#include <linux/clk-provider.h> -+#include "clk-rcg.h" -+#include "clk-regmap.h" -+ -+/** -+ * struct mux_div_clk - combined mux/divider clock -+ * @reg_offset: offset of the mux/divider register -+ * @hid_width: number of bits in half integer divider -+ * @hid_shift: lowest bit of hid value field -+ * @src_width: number of bits in source select -+ * @src_shift: lowest bit of source select field -+ * @div: the divider raw configuration value -+ * @src: the mux index which will be used if the clock is enabled -+ * @safe_src: the safe source mux value we switch to, while the main PLL is -+ * reconfigured -+ * @safe_div: the safe divider value that we set, while the main PLL is -+ * reconfigured -+ * @safe_freq: When switching rates from A to B, the mux div clock will -+ * instead switch from A -> safe_freq -> B. This allows the -+ * mux_div clock to change rates while enabled, even if this -+ * behavior is not supported by the parent clocks. -+ * If changing the rate of parent A also causes the rate of -+ * parent B to change, then safe_freq must be defined. -+ * safe_freq is expected to have a source clock which is always -+ * on and runs at only one rate. -+ * @parent_map: pointer to parent_map struct -+ * @clkr: handle between common and hardware-specific interfaces -+ */ -+ -+struct clk_regmap_mux_div { -+ u32 reg_offset; -+ u32 hid_width; -+ u32 hid_shift; -+ u32 src_width; -+ u32 src_shift; -+ u32 div; -+ u32 src; -+ u32 safe_src; -+ u32 safe_div; -+ unsigned long safe_freq; -+ const struct parent_map *parent_map; -+ struct clk_regmap clkr; -+}; -+ -+extern const struct clk_ops clk_regmap_mux_div_ops; -+int __mux_div_set_src_div(struct clk_regmap_mux_div *md, u32 src, u32 div); -+ -+#endif diff --git a/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch b/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch index a3e0a1dc5d..717934315a 100644 --- a/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch +++ b/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch @@ -14,7 +14,7 @@ Signed-off-by: Abhishek Sahu <absahu@codeaurora.org> --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -1234,6 +1234,8 @@ static struct clk_rcg prng_src = { +@@ -1233,6 +1233,8 @@ static struct clk_rcg prng_src = { .parent_map = gcc_pxo_pll8_map, }, .clkr = {