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>
-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
-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
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
- */
- val = clk_readl(mux->reg) >> mux->shift;
- val &= mux->mask;
--
+
- if (mux->table) {
+ if (table) {
int i;
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;
}
- 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"
+ */
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 = {
};
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,
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,
+++ /dev/null
-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;
-
+++ /dev/null
-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,
-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.
+ * 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);
+ regmap_read(regmap, hd->status_reg, &val);
+ } while (!(val & BIT(hd->lock_bit)));
+ } else {
-+ udelay(60);
++ usleep_range(60, 100);
+ }
+
+ /* Enable PLL output. */
+ * 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)
+ 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);
+ }
-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
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 ++
+ 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;
-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
#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 = {
},
};
+ },
+ .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,
-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
---
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
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.
+ *
+ /* 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;
+}
+
+ 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);
+
+}
+
+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;
+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.
+ *
+
+struct krait_mux_clk {
+ unsigned int *parent_map;
-+ bool has_safe_parent;
-+ u8 safe_sel;
+ u32 offset;
+ u32 mask;
+ u32 shift;
+ 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)
-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
.../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
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
+
+ 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 {
-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
.../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
+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
+};
+
+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 = {
+}
+
+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[] = {
+
+ 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;
+}
+
+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];
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
-+ mux->has_safe_parent = true;
-+ mux->safe_sel = 0;
+ mux->mask = 0x3;
+ mux->shift = 0;
+ mux->offset = offset;
+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;
+ 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);
+
+ 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);
+ }
+
+ /*
+ 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);
--- /dev/null
+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]);
+++ /dev/null
-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);
-
-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.
+#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)
+{
+ }
+
+ 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;
-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
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)
- {
+++ /dev/null
-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
--- 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 = {