From: Ansuel Smith Date: Fri, 28 Feb 2020 20:04:10 +0000 (+0100) Subject: ipq806x: drop upstream patch X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=eaceb85ebc01895d153a687123cf5d050d0f148b;p=openwrt%2Fstaging%2Faparcar.git ipq806x: drop upstream patch This patchset has been merged upstream. Signed-off-by: Ansuel Smith --- diff --git a/target/linux/ipq806x/patches-5.4/0034-0001-ARM-Add-Krait-L2-register-accessor-functions.patch b/target/linux/ipq806x/patches-5.4/0034-0001-ARM-Add-Krait-L2-register-accessor-functions.patch deleted file mode 100644 index 68acbeeec2..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0001-ARM-Add-Krait-L2-register-accessor-functions.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 36d68f64c411e09788687d5919886aadeb92adca Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:20 +0530 -Subject: [PATCH 01/12] 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 -the indirection register (l2cpselr) to point the L2 'window' -register (l2cpdr) at what you want to read/write. Then you -read/write the 'window' register to do what you want. The -l2cpselr register is not banked per-cpu so we must lock around -accesses to it to prevent other CPUs from re-pointing l2cpdr -underneath us. - -Cc: Mark Rutland -Cc: Russell King -Acked-by: Bjorn Andersson -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - arch/arm/common/Kconfig | 3 ++ - arch/arm/common/Makefile | 1 + - arch/arm/common/krait-l2-accessors.c | 48 +++++++++++++++++++++++ - arch/arm/include/asm/krait-l2-accessors.h | 9 +++++ - 4 files changed, 61 insertions(+) - create mode 100644 arch/arm/common/krait-l2-accessors.c - create mode 100644 arch/arm/include/asm/krait-l2-accessors.h - ---- a/arch/arm/common/Kconfig -+++ b/arch/arm/common/Kconfig -@@ -7,6 +7,9 @@ config DMABOUNCE - bool - select ZONE_DMA - -+config KRAIT_L2_ACCESSORS -+ bool -+ - config SHARP_LOCOMO - bool - ---- a/arch/arm/common/Makefile -+++ b/arch/arm/common/Makefile -@@ -7,6 +7,7 @@ obj-y += firmware.o - - obj-$(CONFIG_SA1111) += sa1111.o - obj-$(CONFIG_DMABOUNCE) += dmabounce.o -+obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o - obj-$(CONFIG_SHARP_LOCOMO) += locomo.o - obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o - obj-$(CONFIG_SHARP_SCOOP) += scoop.o ---- /dev/null -+++ b/arch/arm/common/krait-l2-accessors.c -@@ -0,0 +1,48 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ -+#include -+#include -+ -+#include -+#include -+ -+static DEFINE_RAW_SPINLOCK(krait_l2_lock); -+ -+void krait_set_l2_indirect_reg(u32 addr, u32 val) -+{ -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&krait_l2_lock, flags); -+ /* -+ * Select the L2 window by poking l2cpselr, then write to the window -+ * via l2cpdr. -+ */ -+ asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr)); -+ isb(); -+ asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val)); -+ isb(); -+ -+ raw_spin_unlock_irqrestore(&krait_l2_lock, flags); -+} -+EXPORT_SYMBOL(krait_set_l2_indirect_reg); -+ -+u32 krait_get_l2_indirect_reg(u32 addr) -+{ -+ u32 val; -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&krait_l2_lock, flags); -+ /* -+ * Select the L2 window by poking l2cpselr, then read from the window -+ * via l2cpdr. -+ */ -+ asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr)); -+ isb(); -+ asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val)); -+ -+ raw_spin_unlock_irqrestore(&krait_l2_lock, flags); -+ -+ return val; -+} -+EXPORT_SYMBOL(krait_get_l2_indirect_reg); ---- /dev/null -+++ b/arch/arm/include/asm/krait-l2-accessors.h -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H -+#define __ASMARM_KRAIT_L2_ACCESSORS_H -+ -+extern void krait_set_l2_indirect_reg(u32 addr, u32 val); -+extern u32 krait_get_l2_indirect_reg(u32 addr); -+ -+#endif diff --git a/target/linux/ipq806x/patches-5.4/0034-0002-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch b/target/linux/ipq806x/patches-5.4/0034-0002-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch deleted file mode 100644 index d43d0c89b5..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0002-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch +++ /dev/null @@ -1,324 +0,0 @@ -From b3f2f10693aadeacf83ab5be03810941a4b77612 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:21 +0530 -Subject: [PATCH 02/12] 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. - -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-hfpll.c | 244 +++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-hfpll.h | 44 +++++++ - 3 files changed, 289 insertions(+) - create mode 100644 drivers/clk/qcom/clk-hfpll.c - create mode 100644 drivers/clk/qcom/clk-hfpll.h - ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -11,6 +11,7 @@ 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-y += clk-hfpll.o - clk-qcom-y += reset.o - clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o - ---- /dev/null -+++ b/drivers/clk/qcom/clk-hfpll.c -@@ -0,0 +1,244 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-regmap.h" -+#include "clk-hfpll.h" -+ -+#define PLL_OUTCTRL BIT(0) -+#define PLL_BYPASSNL BIT(1) -+#define PLL_RESET_N BIT(2) -+ -+/* Initialize a HFPLL at a given rate and enable it. */ -+static void __clk_hfpll_init_once(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ -+ if (likely(h->init_done)) -+ return; -+ -+ /* Configure PLL parameters for integer mode. */ -+ if (hd->config_val) -+ regmap_write(regmap, hd->config_reg, hd->config_val); -+ regmap_write(regmap, hd->m_reg, 0); -+ regmap_write(regmap, hd->n_reg, 1); -+ -+ if (hd->user_reg) { -+ u32 regval = hd->user_val; -+ unsigned long rate; -+ -+ rate = clk_hw_get_rate(hw); -+ -+ /* Pick the right VCO. */ -+ if (hd->user_vco_mask && rate > hd->low_vco_max_rate) -+ regval |= hd->user_vco_mask; -+ regmap_write(regmap, hd->user_reg, regval); -+ } -+ -+ if (hd->droop_reg) -+ regmap_write(regmap, hd->droop_reg, hd->droop_val); -+ -+ h->init_done = true; -+} -+ -+static void __clk_hfpll_enable(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 val; -+ -+ __clk_hfpll_init_once(hw); -+ -+ /* Disable PLL bypass mode. */ -+ regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL); -+ -+ /* -+ * H/W requires a 5us delay between disabling the bypass and -+ * de-asserting the reset. Delay 10us just to be safe. -+ */ -+ udelay(10); -+ -+ /* De-assert active-low PLL reset. */ -+ regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N); -+ -+ /* Wait for PLL to lock. */ -+ if (hd->status_reg) { -+ do { -+ regmap_read(regmap, hd->status_reg, &val); -+ } while (!(val & BIT(hd->lock_bit))); -+ } else { -+ udelay(60); -+ } -+ -+ /* Enable PLL output. */ -+ regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL); -+} -+ -+/* Enable an already-configured HFPLL. */ -+static int clk_hfpll_enable(struct clk_hw *hw) -+{ -+ unsigned long flags; -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 mode; -+ -+ spin_lock_irqsave(&h->lock, flags); -+ regmap_read(regmap, hd->mode_reg, &mode); -+ if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL))) -+ __clk_hfpll_enable(hw); -+ spin_unlock_irqrestore(&h->lock, flags); -+ -+ return 0; -+} -+ -+static void __clk_hfpll_disable(struct clk_hfpll *h) -+{ -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ -+ /* -+ * Disable the PLL output, disable test mode, enable the bypass mode, -+ * and assert the reset. -+ */ -+ regmap_update_bits(regmap, hd->mode_reg, -+ PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0); -+} -+ -+static void clk_hfpll_disable(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&h->lock, flags); -+ __clk_hfpll_disable(h); -+ spin_unlock_irqrestore(&h->lock, flags); -+} -+ -+static long clk_hfpll_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *parent_rate) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ unsigned long rrate; -+ -+ rate = clamp(rate, hd->min_rate, hd->max_rate); -+ -+ rrate = DIV_ROUND_UP(rate, *parent_rate) * *parent_rate; -+ if (rrate > hd->max_rate) -+ rrate -= *parent_rate; -+ -+ return rrate; -+} -+ -+/* -+ * For optimization reasons, assumes no downstream clocks are actively using -+ * it. -+ */ -+static int clk_hfpll_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ unsigned long flags; -+ u32 l_val, val; -+ bool enabled; -+ -+ l_val = rate / parent_rate; -+ -+ spin_lock_irqsave(&h->lock, flags); -+ -+ enabled = __clk_is_enabled(hw->clk); -+ if (enabled) -+ __clk_hfpll_disable(h); -+ -+ /* Pick the right VCO. */ -+ if (hd->user_reg && hd->user_vco_mask) { -+ regmap_read(regmap, hd->user_reg, &val); -+ if (rate <= hd->low_vco_max_rate) -+ val &= ~hd->user_vco_mask; -+ else -+ val |= hd->user_vco_mask; -+ regmap_write(regmap, hd->user_reg, val); -+ } -+ -+ regmap_write(regmap, hd->l_reg, l_val); -+ -+ if (enabled) -+ __clk_hfpll_enable(hw); -+ -+ spin_unlock_irqrestore(&h->lock, flags); -+ -+ return 0; -+} -+ -+static unsigned long clk_hfpll_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 l_val; -+ -+ regmap_read(regmap, hd->l_reg, &l_val); -+ -+ return l_val * parent_rate; -+} -+ -+static void clk_hfpll_init(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 mode, status; -+ -+ regmap_read(regmap, hd->mode_reg, &mode); -+ if (mode != (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)) { -+ __clk_hfpll_init_once(hw); -+ return; -+ } -+ -+ if (hd->status_reg) { -+ 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_hfpll_disable(hw); -+ __clk_hfpll_init_once(hw); -+ } -+ } -+} -+ -+static int hfpll_is_enabled(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 mode; -+ -+ regmap_read(regmap, hd->mode_reg, &mode); -+ mode &= 0x7; -+ return mode == (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL); -+} -+ -+const struct clk_ops clk_ops_hfpll = { -+ .enable = clk_hfpll_enable, -+ .disable = clk_hfpll_disable, -+ .is_enabled = hfpll_is_enabled, -+ .round_rate = clk_hfpll_round_rate, -+ .set_rate = clk_hfpll_set_rate, -+ .recalc_rate = clk_hfpll_recalc_rate, -+ .init = clk_hfpll_init, -+}; -+EXPORT_SYMBOL_GPL(clk_ops_hfpll); ---- /dev/null -+++ b/drivers/clk/qcom/clk-hfpll.h -@@ -0,0 +1,44 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+#ifndef __QCOM_CLK_HFPLL_H__ -+#define __QCOM_CLK_HFPLL_H__ -+ -+#include -+#include -+#include "clk-regmap.h" -+ -+struct hfpll_data { -+ u32 mode_reg; -+ u32 l_reg; -+ u32 m_reg; -+ u32 n_reg; -+ u32 user_reg; -+ u32 droop_reg; -+ u32 config_reg; -+ u32 status_reg; -+ u8 lock_bit; -+ -+ u32 droop_val; -+ u32 config_val; -+ u32 user_val; -+ u32 user_vco_mask; -+ unsigned long low_vco_max_rate; -+ -+ unsigned long min_rate; -+ unsigned long max_rate; -+}; -+ -+struct clk_hfpll { -+ struct hfpll_data const *d; -+ int init_done; -+ -+ struct clk_regmap clkr; -+ spinlock_t lock; -+}; -+ -+#define to_clk_hfpll(_hw) \ -+ container_of(to_clk_regmap(_hw), struct clk_hfpll, clkr) -+ -+extern const struct clk_ops clk_ops_hfpll; -+ -+#endif diff --git a/target/linux/ipq806x/patches-5.4/0034-0003-clk-qcom-Add-HFPLL-driver.patch b/target/linux/ipq806x/patches-5.4/0034-0003-clk-qcom-Add-HFPLL-driver.patch deleted file mode 100644 index 292eb66d67..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0003-clk-qcom-Add-HFPLL-driver.patch +++ /dev/null @@ -1,142 +0,0 @@ -From cb546b797a0da4dbb1a0c76a2a357921887b6189 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:22 +0530 -Subject: [PATCH 03/12] clk: qcom: Add HFPLL driver - -On some devices (MSM8974 for example), the HFPLLs are -instantiated within the Krait processor subsystem as separate -register regions. Add a driver for these PLLs so that we can -provide HFPLL clocks for use by the system. - -Cc: -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 8 ++++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/hfpll.c | 96 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 105 insertions(+) - create mode 100644 drivers/clk/qcom/hfpll.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -272,3 +272,11 @@ config SPMI_PMIC_CLKDIV - Technologies, Inc. SPMI PMIC. It configures the frequency of - clkdiv outputs of the PMIC. These clocks are typically wired - through alternate functions on GPIO pins. -+ -+config QCOM_HFPLL -+ tristate "High-Frequency PLL (HFPLL) Clock Controller" -+ depends on COMMON_CLK_QCOM -+ help -+ Support for the high-frequency PLLs present on Qualcomm devices. -+ Say Y if you want to support CPU frequency scaling on devices -+ such as MSM8974, APQ8084, etc. ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -44,3 +44,4 @@ obj-$(CONFIG_SDM_DISPCC_845) += dispcc-s - obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o - obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o - obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o -+obj-$(CONFIG_QCOM_HFPLL) += hfpll.o ---- /dev/null -+++ b/drivers/clk/qcom/hfpll.c -@@ -0,0 +1,96 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-regmap.h" -+#include "clk-hfpll.h" -+ -+static const struct hfpll_data hdata = { -+ .mode_reg = 0x00, -+ .l_reg = 0x04, -+ .m_reg = 0x08, -+ .n_reg = 0x0c, -+ .user_reg = 0x10, -+ .config_reg = 0x14, -+ .config_val = 0x430405d, -+ .status_reg = 0x1c, -+ .lock_bit = 16, -+ -+ .user_val = 0x8, -+ .user_vco_mask = 0x100000, -+ .low_vco_max_rate = 1248000000, -+ .min_rate = 537600000UL, -+ .max_rate = 2900000000UL, -+}; -+ -+static const struct of_device_id qcom_hfpll_match_table[] = { -+ { .compatible = "qcom,hfpll" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table); -+ -+static const struct regmap_config hfpll_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x30, -+ .fast_io = true, -+}; -+ -+static int qcom_hfpll_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ struct device *dev = &pdev->dev; -+ void __iomem *base; -+ struct regmap *regmap; -+ struct clk_hfpll *h; -+ struct clk_init_data init = { -+ .parent_names = (const char *[]){ "xo" }, -+ .num_parents = 1, -+ .ops = &clk_ops_hfpll, -+ }; -+ -+ h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL); -+ if (!h) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ regmap = devm_regmap_init_mmio(&pdev->dev, base, &hfpll_regmap_config); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ if (of_property_read_string_index(dev->of_node, "clock-output-names", -+ 0, &init.name)) -+ return -ENODEV; -+ -+ h->d = &hdata; -+ h->clkr.hw.init = &init; -+ spin_lock_init(&h->lock); -+ -+ return devm_clk_register_regmap(&pdev->dev, &h->clkr); -+} -+ -+static struct platform_driver qcom_hfpll_driver = { -+ .probe = qcom_hfpll_probe, -+ .driver = { -+ .name = "qcom-hfpll", -+ .of_match_table = qcom_hfpll_match_table, -+ }, -+}; -+module_platform_driver(qcom_hfpll_driver); -+ -+MODULE_DESCRIPTION("QCOM HFPLL Clock Driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:qcom-hfpll"); diff --git a/target/linux/ipq806x/patches-5.4/0034-0004-dt-bindings-clock-Document-qcom-hfpll.patch b/target/linux/ipq806x/patches-5.4/0034-0004-dt-bindings-clock-Document-qcom-hfpll.patch deleted file mode 100644 index 1db989f6d9..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0004-dt-bindings-clock-Document-qcom-hfpll.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 1f924faa8b1e4789ecc06ed0dd58ca3487c89012 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:23 +0530 -Subject: [PATCH 04/12] dt-bindings: clock: Document qcom,hfpll - -Adds bindings document for qcom,hfpll instantiated within -the Krait processor subsystem as separate register region. - -Reviewed-by: Rob Herring -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - .../devicetree/bindings/clock/qcom,hfpll.txt | 60 +++++++++++++++++++ - 1 file changed, 60 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt -@@ -0,0 +1,60 @@ -+High-Frequency PLL (HFPLL) -+ -+PROPERTIES -+ -+- compatible: -+ Usage: required -+ Value type: : -+ shall contain only one of the following. The generic -+ compatible "qcom,hfpll" should be also included. -+ -+ "qcom,hfpll-ipq8064", "qcom,hfpll" -+ "qcom,hfpll-apq8064", "qcom,hfpll" -+ "qcom,hfpll-msm8974", "qcom,hfpll" -+ "qcom,hfpll-msm8960", "qcom,hfpll" -+ -+- reg: -+ Usage: required -+ Value type: -+ Definition: address and size of HPLL registers. An optional second -+ element specifies the address and size of the alias -+ register region. -+ -+- clocks: -+ Usage: required -+ Value type: -+ Definition: reference to the xo clock. -+ -+- clock-names: -+ Usage: required -+ Value type: -+ Definition: must be "xo". -+ -+- clock-output-names: -+ Usage: required -+ Value type: -+ Definition: Name of the PLL. Typically hfpllX where X is a CPU number -+ starting at 0. Otherwise hfpll_Y where Y is more specific -+ such as "l2". -+ -+Example: -+ -+1) An HFPLL for the L2 cache. -+ -+ clock-controller@f9016000 { -+ compatible = "qcom,hfpll-ipq8064", "qcom,hfpll"; -+ reg = <0xf9016000 0x30>; -+ clocks = <&xo_board>; -+ clock-names = "xo"; -+ clock-output-names = "hfpll_l2"; -+ }; -+ -+2) An HFPLL for CPU0. This HFPLL has the alias register region. -+ -+ clock-controller@f908a000 { -+ compatible = "qcom,hfpll-ipq8064", "qcom,hfpll"; -+ reg = <0xf908a000 0x30>, <0xf900a000 0x30>; -+ clocks = <&xo_board>; -+ clock-names = "xo"; -+ clock-output-names = "hfpll0"; -+ }; diff --git a/target/linux/ipq806x/patches-5.4/0034-0005-clk-qcom-Add-MSM8960-APQ8064-s-HFPLLs.patch b/target/linux/ipq806x/patches-5.4/0034-0005-clk-qcom-Add-MSM8960-APQ8064-s-HFPLLs.patch deleted file mode 100644 index 5ed5625f2e..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0005-clk-qcom-Add-MSM8960-APQ8064-s-HFPLLs.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 72ad7207954dd622a662ba884dc6c30a820123f2 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:24 +0530 -Subject: [PATCH 05/12] clk: qcom: Add MSM8960/APQ8064's HFPLLs - -Describe the HFPLLs present on MSM8960 and APQ8064 devices. - -Acked-by: Rob Herring (bindings) -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/gcc-msm8960.c | 172 +++++++++++++++++++ - include/dt-bindings/clock/qcom,gcc-msm8960.h | 2 + - 2 files changed, 174 insertions(+) - ---- a/drivers/clk/qcom/gcc-msm8960.c -+++ b/drivers/clk/qcom/gcc-msm8960.c -@@ -30,6 +30,7 @@ - #include "clk-pll.h" - #include "clk-rcg.h" - #include "clk-branch.h" -+#include "clk-hfpll.h" - #include "reset.h" - - static struct clk_pll pll3 = { -@@ -86,6 +87,164 @@ static struct clk_regmap pll8_vote = { - }, - }; - -+static struct hfpll_data hfpll0_data = { -+ .mode_reg = 0x3200, -+ .l_reg = 0x3208, -+ .m_reg = 0x320c, -+ .n_reg = 0x3210, -+ .config_reg = 0x3204, -+ .status_reg = 0x321c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3214, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll0 = { -+ .d = &hfpll0_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll0", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock), -+}; -+ -+static struct hfpll_data hfpll1_8064_data = { -+ .mode_reg = 0x3240, -+ .l_reg = 0x3248, -+ .m_reg = 0x324c, -+ .n_reg = 0x3250, -+ .config_reg = 0x3244, -+ .status_reg = 0x325c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3254, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct hfpll_data hfpll1_data = { -+ .mode_reg = 0x3300, -+ .l_reg = 0x3308, -+ .m_reg = 0x330c, -+ .n_reg = 0x3310, -+ .config_reg = 0x3304, -+ .status_reg = 0x331c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3314, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll1 = { -+ .d = &hfpll1_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll1", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock), -+}; -+ -+static struct hfpll_data hfpll2_data = { -+ .mode_reg = 0x3280, -+ .l_reg = 0x3288, -+ .m_reg = 0x328c, -+ .n_reg = 0x3290, -+ .config_reg = 0x3284, -+ .status_reg = 0x329c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3294, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll2 = { -+ .d = &hfpll2_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll2", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll2.lock), -+}; -+ -+static struct hfpll_data hfpll3_data = { -+ .mode_reg = 0x32c0, -+ .l_reg = 0x32c8, -+ .m_reg = 0x32cc, -+ .n_reg = 0x32d0, -+ .config_reg = 0x32c4, -+ .status_reg = 0x32dc, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x32d4, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll3 = { -+ .d = &hfpll3_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll3", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll3.lock), -+}; -+ -+static struct hfpll_data hfpll_l2_8064_data = { -+ .mode_reg = 0x3300, -+ .l_reg = 0x3308, -+ .m_reg = 0x330c, -+ .n_reg = 0x3310, -+ .config_reg = 0x3304, -+ .status_reg = 0x331c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3314, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct hfpll_data hfpll_l2_data = { -+ .mode_reg = 0x3400, -+ .l_reg = 0x3408, -+ .m_reg = 0x340c, -+ .n_reg = 0x3410, -+ .config_reg = 0x3404, -+ .status_reg = 0x341c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3414, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll_l2 = { -+ .d = &hfpll_l2_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll_l2", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock), -+}; -+ - static struct clk_pll pll14 = { - .l_reg = 0x31c4, - .m_reg = 0x31c8, -@@ -3107,6 +3266,9 @@ static struct clk_regmap *gcc_msm8960_cl - [PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr, - [PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr, - [RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr, -+ [PLL9] = &hfpll0.clkr, -+ [PLL10] = &hfpll1.clkr, -+ [PLL12] = &hfpll_l2.clkr, - }; - - static const struct qcom_reset_map gcc_msm8960_resets[] = { -@@ -3318,6 +3480,11 @@ static struct clk_regmap *gcc_apq8064_cl - [PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr, - [PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr, - [RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr, -+ [PLL9] = &hfpll0.clkr, -+ [PLL10] = &hfpll1.clkr, -+ [PLL12] = &hfpll_l2.clkr, -+ [PLL16] = &hfpll2.clkr, -+ [PLL17] = &hfpll3.clkr, - }; - - static const struct qcom_reset_map gcc_apq8064_resets[] = { -@@ -3477,6 +3644,11 @@ static int gcc_msm8960_probe(struct plat - if (ret) - return ret; - -+ if (match->data == &gcc_apq8064_desc) { -+ hfpll1.d = &hfpll1_8064_data; -+ hfpll_l2.d = &hfpll_l2_8064_data; -+ } -+ - tsens = platform_device_register_data(&pdev->dev, "qcom-tsens", -1, - NULL, 0); - if (IS_ERR(tsens)) ---- a/include/dt-bindings/clock/qcom,gcc-msm8960.h -+++ b/include/dt-bindings/clock/qcom,gcc-msm8960.h -@@ -319,5 +319,7 @@ - #define CE3_SRC 303 - #define CE3_CORE_CLK 304 - #define CE3_H_CLK 305 -+#define PLL16 306 -+#define PLL17 307 - - #endif diff --git a/target/linux/ipq806x/patches-5.4/0034-0006-clk-qcom-Add-IPQ806X-s-HFPLLs.patch b/target/linux/ipq806x/patches-5.4/0034-0006-clk-qcom-Add-IPQ806X-s-HFPLLs.patch deleted file mode 100644 index 74c66178a8..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0006-clk-qcom-Add-IPQ806X-s-HFPLLs.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 1f79131bfd512f322c16b58dca581ce39beafab9 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:25 +0530 -Subject: [PATCH 06/12] clk: qcom: Add IPQ806X's HFPLLs - -Describe the HFPLLs present on IPQ806X devices. - -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - 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 -@@ -30,6 +30,7 @@ - #include "clk-pll.h" - #include "clk-rcg.h" - #include "clk-branch.h" -+#include "clk-hfpll.h" - #include "reset.h" - - static struct clk_pll pll0 = { -@@ -113,6 +114,84 @@ static struct clk_regmap pll8_vote = { - }, - }; - -+static struct hfpll_data hfpll0_data = { -+ .mode_reg = 0x3200, -+ .l_reg = 0x3208, -+ .m_reg = 0x320c, -+ .n_reg = 0x3210, -+ .config_reg = 0x3204, -+ .status_reg = 0x321c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3214, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll0 = { -+ .d = &hfpll0_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll0", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock), -+}; -+ -+static struct hfpll_data hfpll1_data = { -+ .mode_reg = 0x3240, -+ .l_reg = 0x3248, -+ .m_reg = 0x324c, -+ .n_reg = 0x3250, -+ .config_reg = 0x3244, -+ .status_reg = 0x325c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3314, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll1 = { -+ .d = &hfpll1_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll1", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock), -+}; -+ -+static struct hfpll_data hfpll_l2_data = { -+ .mode_reg = 0x3300, -+ .l_reg = 0x3308, -+ .m_reg = 0x330c, -+ .n_reg = 0x3310, -+ .config_reg = 0x3304, -+ .status_reg = 0x331c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3314, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll_l2 = { -+ .d = &hfpll_l2_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll_l2", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock), -+}; -+ - static struct clk_pll pll14 = { - .l_reg = 0x31c4, - .m_reg = 0x31c8, -@@ -2798,6 +2877,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, -+ [PLL9] = &hfpll0.clkr, -+ [PLL10] = &hfpll1.clkr, -+ [PLL12] = &hfpll_l2.clkr, - }; - - static const struct qcom_reset_map gcc_ipq806x_resets[] = { diff --git a/target/linux/ipq806x/patches-5.4/0034-0007-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches-5.4/0034-0007-clk-qcom-Add-support-for-Krait-clocks.patch deleted file mode 100644 index 181b91f6eb..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0007-clk-qcom-Add-support-for-Krait-clocks.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 4d7dc77babfef1d6cb8fd825e2f17dc3384c3272 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:26 +0530 -Subject: [PATCH 07/12] 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 -each CPU. Instead of using mmio accesses to remux parents, the -Krait implementation exposes the remux control via cp15 -registers. Support these clocks. - -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -[sboyd@kernel.org: Move hidden config to top outside of the visible qcom -config zone so that menuconfig looks nice] -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 4 ++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-krait.c | 124 +++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-krait.h | 37 +++++++++++ - 4 files changed, 166 insertions(+) - create mode 100644 drivers/clk/qcom/clk-krait.c - create mode 100644 drivers/clk/qcom/clk-krait.h - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -1,3 +1,7 @@ -+config KRAIT_CLOCKS -+ bool -+ select KRAIT_L2_ACCESSORS -+ - config QCOM_GDSC - bool - select PM_GENERIC_DOMAINS if PM ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -11,6 +11,7 @@ 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 - clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o ---- /dev/null -+++ b/drivers/clk/qcom/clk-krait.c -@@ -0,0 +1,124 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "clk-krait.h" -+ -+/* Secondary and primary muxes share the same cp15 register */ -+static DEFINE_SPINLOCK(krait_clock_reg_lock); -+ -+#define LPL_SHIFT 8 -+static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel) -+{ -+ unsigned long flags; -+ u32 regval; -+ -+ spin_lock_irqsave(&krait_clock_reg_lock, flags); -+ regval = krait_get_l2_indirect_reg(mux->offset); -+ regval &= ~(mux->mask << mux->shift); -+ regval |= (sel & mux->mask) << mux->shift; -+ if (mux->lpl) { -+ regval &= ~(mux->mask << (mux->shift + LPL_SHIFT)); -+ regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT); -+ } -+ krait_set_l2_indirect_reg(mux->offset, regval); -+ spin_unlock_irqrestore(&krait_clock_reg_lock, flags); -+ -+ /* Wait for switch to complete. */ -+ mb(); -+ udelay(1); -+} -+ -+static int krait_mux_set_parent(struct clk_hw *hw, u8 index) -+{ -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ u32 sel; -+ -+ sel = clk_mux_reindex(index, mux->parent_map, 0); -+ mux->en_mask = sel; -+ /* 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; -+} -+ -+static u8 krait_mux_get_parent(struct clk_hw *hw) -+{ -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ u32 sel; -+ -+ sel = krait_get_l2_indirect_reg(mux->offset); -+ sel >>= mux->shift; -+ sel &= mux->mask; -+ mux->en_mask = sel; -+ -+ return clk_mux_get_parent(hw, sel, mux->parent_map, 0); -+} -+ -+const struct clk_ops krait_mux_clk_ops = { -+ .set_parent = krait_mux_set_parent, -+ .get_parent = krait_mux_get_parent, -+ .determine_rate = __clk_mux_determine_rate_closest, -+}; -+EXPORT_SYMBOL_GPL(krait_mux_clk_ops); -+ -+/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */ -+static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *parent_rate) -+{ -+ *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * 2); -+ return DIV_ROUND_UP(*parent_rate, 2); -+} -+ -+static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct krait_div2_clk *d = to_krait_div2_clk(hw); -+ unsigned long flags; -+ u32 val; -+ u32 mask = BIT(d->width) - 1; -+ -+ if (d->lpl) -+ mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift; -+ -+ spin_lock_irqsave(&krait_clock_reg_lock, flags); -+ val = krait_get_l2_indirect_reg(d->offset); -+ val &= ~mask; -+ krait_set_l2_indirect_reg(d->offset, val); -+ spin_unlock_irqrestore(&krait_clock_reg_lock, flags); -+ -+ return 0; -+} -+ -+static unsigned long -+krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -+{ -+ struct krait_div2_clk *d = to_krait_div2_clk(hw); -+ u32 mask = BIT(d->width) - 1; -+ u32 div; -+ -+ div = krait_get_l2_indirect_reg(d->offset); -+ div >>= d->shift; -+ div &= mask; -+ div = (div + 1) * 2; -+ -+ return DIV_ROUND_UP(parent_rate, div); -+} -+ -+const struct clk_ops krait_div2_clk_ops = { -+ .round_rate = krait_div2_round_rate, -+ .set_rate = krait_div2_set_rate, -+ .recalc_rate = krait_div2_recalc_rate, -+}; -+EXPORT_SYMBOL_GPL(krait_div2_clk_ops); ---- /dev/null -+++ b/drivers/clk/qcom/clk-krait.h -@@ -0,0 +1,37 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+#ifndef __QCOM_CLK_KRAIT_H -+#define __QCOM_CLK_KRAIT_H -+ -+#include -+ -+struct krait_mux_clk { -+ unsigned int *parent_map; -+ u32 offset; -+ u32 mask; -+ u32 shift; -+ u32 en_mask; -+ 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) -+ -+extern const struct clk_ops krait_mux_clk_ops; -+ -+struct krait_div2_clk { -+ u32 offset; -+ u8 width; -+ u32 shift; -+ bool lpl; -+ -+ struct clk_hw hw; -+}; -+ -+#define to_krait_div2_clk(_hw) container_of(_hw, struct krait_div2_clk, hw) -+ -+extern const struct clk_ops krait_div2_clk_ops; -+ -+#endif diff --git a/target/linux/ipq806x/patches-5.4/0034-0008-clk-qcom-Add-KPSS-ACC-GCC-driver.patch b/target/linux/ipq806x/patches-5.4/0034-0008-clk-qcom-Add-KPSS-ACC-GCC-driver.patch deleted file mode 100644 index aa19ea2e3f..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0008-clk-qcom-Add-KPSS-ACC-GCC-driver.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 3ddc3564d3c9f097986bd4ccbe34152413811335 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:27 +0530 -Subject: [PATCH 08/12] 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 -purposes probe these devices and expose a mux clock that chooses -between PXO and PLL8. - -Cc: -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 8 ++++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/kpss-xcc.c | 87 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 96 insertions(+) - create mode 100644 drivers/clk/qcom/kpss-xcc.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -284,3 +284,11 @@ config QCOM_HFPLL - Support for the high-frequency PLLs present on Qualcomm devices. - Say Y if you want to support CPU frequency scaling on devices - such as MSM8974, APQ8084, etc. -+ -+config KPSS_XCC -+ tristate "KPSS Clock Controller" -+ depends on COMMON_CLK_QCOM -+ help -+ Support for the Krait ACC and GCC clock controllers. Say Y -+ if you want to support CPU frequency scaling on devices such -+ as MSM8960, APQ8064, etc. ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -45,4 +45,5 @@ obj-$(CONFIG_SDM_DISPCC_845) += dispcc-s - obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o - obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o - obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o -+obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o - obj-$(CONFIG_QCOM_HFPLL) += hfpll.o ---- /dev/null -+++ b/drivers/clk/qcom/kpss-xcc.c -@@ -0,0 +1,87 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static const char *aux_parents[] = { -+ "pll8_vote", -+ "pxo", -+}; -+ -+static unsigned int aux_parent_map[] = { -+ 3, -+ 0, -+}; -+ -+static const struct of_device_id kpss_xcc_match_table[] = { -+ { .compatible = "qcom,kpss-acc-v1", .data = (void *)1UL }, -+ { .compatible = "qcom,kpss-gcc" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, kpss_xcc_match_table); -+ -+static int kpss_xcc_driver_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *id; -+ struct clk *clk; -+ struct resource *res; -+ void __iomem *base; -+ const char *name; -+ -+ id = of_match_device(kpss_xcc_match_table, &pdev->dev); -+ if (!id) -+ return -ENODEV; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ if (id->data) { -+ if (of_property_read_string_index(pdev->dev.of_node, -+ "clock-output-names", -+ 0, &name)) -+ return -ENODEV; -+ base += 0x14; -+ } else { -+ name = "acpu_l2_aux"; -+ base += 0x28; -+ } -+ -+ clk = clk_register_mux_table(&pdev->dev, name, aux_parents, -+ ARRAY_SIZE(aux_parents), 0, base, 0, 0x3, -+ 0, aux_parent_map, NULL); -+ -+ platform_set_drvdata(pdev, clk); -+ -+ return PTR_ERR_OR_ZERO(clk); -+} -+ -+static int kpss_xcc_driver_remove(struct platform_device *pdev) -+{ -+ clk_unregister_mux(platform_get_drvdata(pdev)); -+ return 0; -+} -+ -+static struct platform_driver kpss_xcc_driver = { -+ .probe = kpss_xcc_driver_probe, -+ .remove = kpss_xcc_driver_remove, -+ .driver = { -+ .name = "kpss-xcc", -+ .of_match_table = kpss_xcc_match_table, -+ }, -+}; -+module_platform_driver(kpss_xcc_driver); -+ -+MODULE_DESCRIPTION("Krait Processor Sub System (KPSS) Clock Driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:kpss-xcc"); diff --git a/target/linux/ipq806x/patches-5.4/0034-0009-dt-bindings-arm-Document-qcom-kpss-gcc.patch b/target/linux/ipq806x/patches-5.4/0034-0009-dt-bindings-arm-Document-qcom-kpss-gcc.patch deleted file mode 100644 index 6af40895bc..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0009-dt-bindings-arm-Document-qcom-kpss-gcc.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 40e5ddf4f84869815129551f4a8cfc2c223ebeae Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:28 +0530 -Subject: [PATCH 09/12] dt-bindings: arm: Document qcom,kpss-gcc - -The ACC and GCC regions present in KPSSv1 contain registers to -control clocks and power to each Krait CPU and L2. Documenting -the bindings here. - -Reviewed-by: Rob Herring -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - .../bindings/arm/msm/qcom,kpss-acc.txt | 19 ++++++++ - .../bindings/arm/msm/qcom,kpss-gcc.txt | 44 +++++++++++++++++++ - 2 files changed, 63 insertions(+) - create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt - ---- a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt -+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt -@@ -21,10 +21,29 @@ PROPERTIES - the register region. An optional second element specifies - the base address and size of the alias register region. - -+- clocks: -+ Usage: required -+ Value type: -+ Definition: reference to the pll parents. -+ -+- clock-names: -+ Usage: required -+ Value type: -+ Definition: must be "pll8_vote", "pxo". -+ -+- clock-output-names: -+ Usage: optional -+ Value type: -+ Definition: Name of the output clock. Typically acpuX_aux where X is a -+ CPU number starting at 0. -+ - Example: - - clock-controller@2088000 { - compatible = "qcom,kpss-acc-v2"; - reg = <0x02088000 0x1000>, - <0x02008000 0x1000>; -+ clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>; -+ clock-names = "pll8_vote", "pxo"; -+ clock-output-names = "acpu0_aux"; - }; ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt -@@ -0,0 +1,44 @@ -+Krait Processor Sub-system (KPSS) Global Clock Controller (GCC) -+ -+PROPERTIES -+ -+- compatible: -+ Usage: required -+ Value type: -+ Definition: should be one of the following. The generic compatible -+ "qcom,kpss-gcc" should also be included. -+ "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc" -+ "qcom,kpss-gcc-apq8064", "qcom,kpss-gcc" -+ "qcom,kpss-gcc-msm8974", "qcom,kpss-gcc" -+ "qcom,kpss-gcc-msm8960", "qcom,kpss-gcc" -+ -+- reg: -+ Usage: required -+ Value type: -+ Definition: base address and size of the register region -+ -+- clocks: -+ Usage: required -+ Value type: -+ Definition: reference to the pll parents. -+ -+- clock-names: -+ Usage: required -+ Value type: -+ Definition: must be "pll8_vote", "pxo". -+ -+- clock-output-names: -+ Usage: required -+ Value type: -+ Definition: Name of the output clock. Typically acpu_l2_aux indicating -+ an L2 cache auxiliary clock. -+ -+Example: -+ -+ l2cc: clock-controller@2011000 { -+ compatible = "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc"; -+ reg = <0x2011000 0x1000>; -+ clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>; -+ clock-names = "pll8_vote", "pxo"; -+ clock-output-names = "acpu_l2_aux"; -+ }; diff --git a/target/linux/ipq806x/patches-5.4/0034-0010-clk-qcom-Add-Krait-clock-controller-driver.patch b/target/linux/ipq806x/patches-5.4/0034-0010-clk-qcom-Add-Krait-clock-controller-driver.patch deleted file mode 100644 index 7ee1f50f41..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0010-clk-qcom-Add-Krait-clock-controller-driver.patch +++ /dev/null @@ -1,409 +0,0 @@ -From bb5c4a85051e5e0be39c775b6df85521f2ae807d Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:29 +0530 -Subject: [PATCH 10/12] 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 -Kraits within KPSSv1 each secondary mux accepts a different aux -source, but on KPSSv2 each secondary mux accepts the same aux -source. - -Cc: -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 8 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-krait.c | 4 +- - drivers/clk/qcom/krait-cc.c | 341 +++++++++++++++++++++++++++++++++++ - 4 files changed, 352 insertions(+), 2 deletions(-) - create mode 100644 drivers/clk/qcom/krait-cc.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -292,3 +292,11 @@ config KPSS_XCC - Support for the Krait ACC and GCC clock controllers. Say Y - if you want to support CPU frequency scaling on devices such - as MSM8960, APQ8064, etc. -+ -+config KRAITCC -+ tristate "Krait Clock Controller" -+ depends on COMMON_CLK_QCOM && ARM -+ select KRAIT_CLOCKS -+ help -+ Support for the Krait CPU clocks on Qualcomm devices. -+ Say Y if you want to support CPU frequency scaling. ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -47,3 +47,4 @@ obj-$(CONFIG_SDM_VIDEOCC_845) += videocc - obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o - obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o - obj-$(CONFIG_QCOM_HFPLL) += hfpll.o -+obj-$(CONFIG_KRAITCC) += krait-cc.o ---- a/drivers/clk/qcom/clk-krait.c -+++ b/drivers/clk/qcom/clk-krait.c -@@ -44,7 +44,7 @@ static int krait_mux_set_parent(struct c - struct krait_mux_clk *mux = to_krait_mux_clk(hw); - u32 sel; - -- sel = clk_mux_reindex(index, mux->parent_map, 0); -+ sel = clk_mux_index_to_val(mux->parent_map, 0, index); - mux->en_mask = sel; - /* Don't touch mux if CPU is off as it won't work */ - if (__clk_is_enabled(hw->clk)) -@@ -63,7 +63,7 @@ static u8 krait_mux_get_parent(struct cl - sel &= mux->mask; - mux->en_mask = sel; - -- return clk_mux_get_parent(hw, sel, mux->parent_map, 0); -+ return clk_mux_val_to_index(hw, mux->parent_map, 0, sel); - } - - const struct clk_ops krait_mux_clk_ops = { ---- /dev/null -+++ b/drivers/clk/qcom/krait-cc.c -@@ -0,0 +1,341 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-krait.h" -+ -+static unsigned int sec_mux_map[] = { -+ 2, -+ 0, -+}; -+ -+static unsigned int pri_mux_map[] = { -+ 1, -+ 2, -+ 0, -+}; -+ -+static int -+krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) -+{ -+ struct krait_div2_clk *div; -+ struct clk_init_data init = { -+ .num_parents = 1, -+ .ops = &krait_div2_clk_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }; -+ const char *p_names[1]; -+ struct clk *clk; -+ -+ div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); -+ if (!div) -+ return -ENOMEM; -+ -+ div->width = 2; -+ div->shift = 6; -+ div->lpl = id >= 0; -+ div->offset = offset; -+ div->hw.init = &init; -+ -+ init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s); -+ if (!init.name) -+ return -ENOMEM; -+ -+ init.parent_names = p_names; -+ p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s); -+ if (!p_names[0]) { -+ kfree(init.name); -+ return -ENOMEM; -+ } -+ -+ clk = devm_clk_register(dev, &div->hw); -+ kfree(p_names[0]); -+ kfree(init.name); -+ -+ return PTR_ERR_OR_ZERO(clk); -+} -+ -+static int -+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[] = { -+ "acpu_aux", -+ "qsb", -+ }; -+ struct clk_init_data init = { -+ .parent_names = sec_mux_list, -+ .num_parents = ARRAY_SIZE(sec_mux_list), -+ .ops = &krait_mux_clk_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }; -+ struct clk *clk; -+ -+ mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); -+ if (!mux) -+ return -ENOMEM; -+ -+ mux->offset = offset; -+ mux->lpl = id >= 0; -+ mux->mask = 0x3; -+ mux->shift = 2; -+ mux->parent_map = sec_mux_map; -+ mux->hw.init = &init; -+ -+ init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); -+ if (!init.name) -+ return -ENOMEM; -+ -+ if (unique_aux) { -+ sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s); -+ if (!sec_mux_list[0]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_aux; -+ } -+ } -+ -+ clk = devm_clk_register(dev, &mux->hw); -+ -+ if (unique_aux) -+ kfree(sec_mux_list[0]); -+err_aux: -+ kfree(init.name); -+ return PTR_ERR_OR_ZERO(clk); -+} -+ -+static struct clk * -+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]; -+ struct clk_init_data init = { -+ .parent_names = p_names, -+ .num_parents = ARRAY_SIZE(p_names), -+ .ops = &krait_mux_clk_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }; -+ struct clk *clk; -+ -+ mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); -+ if (!mux) -+ return ERR_PTR(-ENOMEM); -+ -+ mux->mask = 0x3; -+ mux->shift = 0; -+ mux->offset = offset; -+ mux->lpl = id >= 0; -+ mux->parent_map = pri_mux_map; -+ mux->hw.init = &init; -+ -+ init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s); -+ if (!init.name) -+ return ERR_PTR(-ENOMEM); -+ -+ p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s); -+ if (!p_names[0]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_p0; -+ } -+ -+ p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s); -+ if (!p_names[1]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_p1; -+ } -+ -+ p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); -+ if (!p_names[2]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_p2; -+ } -+ -+ clk = devm_clk_register(dev, &mux->hw); -+ -+ kfree(p_names[2]); -+err_p2: -+ kfree(p_names[1]); -+err_p1: -+ kfree(p_names[0]); -+err_p0: -+ kfree(init.name); -+ return clk; -+} -+ -+/* id < 0 for L2, otherwise id == physical CPU number */ -+static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux) -+{ -+ int ret; -+ unsigned int offset; -+ void *p = NULL; -+ const char *s; -+ struct clk *clk; -+ -+ if (id >= 0) { -+ offset = 0x4501 + (0x1000 * id); -+ s = p = kasprintf(GFP_KERNEL, "%d", id); -+ if (!s) -+ return ERR_PTR(-ENOMEM); -+ } else { -+ offset = 0x500; -+ s = "_l2"; -+ } -+ -+ ret = krait_add_div(dev, id, s, offset); -+ if (ret) { -+ clk = ERR_PTR(ret); -+ goto err; -+ } -+ -+ ret = krait_add_sec_mux(dev, id, s, offset, unique_aux); -+ if (ret) { -+ clk = ERR_PTR(ret); -+ goto err; -+ } -+ -+ clk = krait_add_pri_mux(dev, id, s, offset); -+err: -+ kfree(p); -+ return clk; -+} -+ -+static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data) -+{ -+ unsigned int idx = clkspec->args[0]; -+ struct clk **clks = data; -+ -+ if (idx >= 5) { -+ pr_err("%s: invalid clock index %d\n", __func__, idx); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ return clks[idx] ? : ERR_PTR(-ENODEV); -+} -+ -+static const struct of_device_id krait_cc_match_table[] = { -+ { .compatible = "qcom,krait-cc-v1", (void *)1UL }, -+ { .compatible = "qcom,krait-cc-v2" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, krait_cc_match_table); -+ -+static int krait_cc_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ const struct of_device_id *id; -+ unsigned long cur_rate, aux_rate; -+ int cpu; -+ struct clk *clk; -+ struct clk **clks; -+ struct clk *l2_pri_mux_clk; -+ -+ id = of_match_device(krait_cc_match_table, dev); -+ if (!id) -+ return -ENODEV; -+ -+ /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ -+ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ if (!id->data) { -+ clk = clk_register_fixed_factor(dev, "acpu_aux", -+ "gpll0_vote", 0, 1, 2); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ } -+ -+ /* Krait configurations have at most 4 CPUs and one L2 */ -+ clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL); -+ if (!clks) -+ return -ENOMEM; -+ -+ for_each_possible_cpu(cpu) { -+ clk = krait_add_clks(dev, cpu, id->data); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ clks[cpu] = clk; -+ } -+ -+ l2_pri_mux_clk = krait_add_clks(dev, -1, id->data); -+ if (IS_ERR(l2_pri_mux_clk)) -+ return PTR_ERR(l2_pri_mux_clk); -+ clks[4] = l2_pri_mux_clk; -+ -+ /* -+ * We don't want the CPU or L2 clocks to be turned off at late init -+ * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the -+ * refcount of these clocks. Any cpufreq/hotplug manager can assume -+ * that the clocks have already been prepared and enabled by the time -+ * they take over. -+ */ -+ 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); -+ } -+ -+ /* -+ * Force reinit of HFPLLs and muxes to overwrite any potential -+ * incorrect configuration of HFPLLs and muxes by the bootloader. -+ * While at it, also make sure the cores are running at known rates -+ * and print the current rate. -+ * -+ * The clocks are set to aux clock rate first to make sure the -+ * secondary mux is not sourcing off of QSB. The rate is then set to -+ * two different rates to force a HFPLL reinit under all -+ * circumstances. -+ */ -+ cur_rate = clk_get_rate(l2_pri_mux_clk); -+ aux_rate = 384000000; -+ if (cur_rate == 1) { -+ pr_info("L2 @ QSB rate. Forcing new rate.\n"); -+ cur_rate = aux_rate; -+ } -+ clk_set_rate(l2_pri_mux_clk, aux_rate); -+ clk_set_rate(l2_pri_mux_clk, 2); -+ clk_set_rate(l2_pri_mux_clk, cur_rate); -+ pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000); -+ for_each_possible_cpu(cpu) { -+ clk = clks[cpu]; -+ cur_rate = clk_get_rate(clk); -+ if (cur_rate == 1) { -+ 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); -+ pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000); -+ } -+ -+ of_clk_add_provider(dev->of_node, krait_of_get, clks); -+ -+ return 0; -+} -+ -+static struct platform_driver krait_cc_driver = { -+ .probe = krait_cc_probe, -+ .driver = { -+ .name = "krait-cc", -+ .of_match_table = krait_cc_match_table, -+ }, -+}; -+module_platform_driver(krait_cc_driver); -+ -+MODULE_DESCRIPTION("Krait CPU Clock Driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:krait-cc"); diff --git a/target/linux/ipq806x/patches-5.4/0034-0011-dt-bindings-clock-Document-qcom-krait-cc.patch b/target/linux/ipq806x/patches-5.4/0034-0011-dt-bindings-clock-Document-qcom-krait-cc.patch deleted file mode 100644 index 13e05c425a..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0011-dt-bindings-clock-Document-qcom-krait-cc.patch +++ /dev/null @@ -1,55 +0,0 @@ -From bf4503ccf321811192cb07f9711556237c3cf668 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Aug 2018 17:42:30 +0530 -Subject: [PATCH 11/12] dt-bindings: clock: Document qcom,krait-cc - -The Krait clock controller controls the krait CPU and the L2 clocks -consisting a primary mux and secondary mux. Add document for that. - -Reviewed-by: Rob Herring -Signed-off-by: Stephen Boyd -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - .../bindings/clock/qcom,krait-cc.txt | 34 +++++++++++++++++++ - 1 file changed, 34 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt -@@ -0,0 +1,34 @@ -+Krait Clock Controller -+ -+PROPERTIES -+ -+- compatible: -+ Usage: required -+ Value type: -+ Definition: must be one of: -+ "qcom,krait-cc-v1" -+ "qcom,krait-cc-v2" -+ -+- #clock-cells: -+ Usage: required -+ Value type: -+ Definition: must be 1 -+ -+- clocks: -+ Usage: required -+ Value type: -+ Definition: reference to the clock parents of hfpll, secondary muxes. -+ -+- clock-names: -+ Usage: required -+ Value type: -+ Definition: must be "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb". -+ -+Example: -+ -+ kraitcc: clock-controller { -+ compatible = "qcom,krait-cc-v1"; -+ clocks = <&hfpll0>, <&hfpll1>, <&acpu0_aux>, <&acpu1_aux>, ; -+ clock-names = "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb"; -+ #clock-cells = <1>; -+ }; diff --git a/target/linux/ipq806x/patches-5.4/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch b/target/linux/ipq806x/patches-5.4/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch deleted file mode 100644 index 847b4809a3..0000000000 --- a/target/linux/ipq806x/patches-5.4/0034-0012-clk-qcom-Add-safe-switch-hook-for-krait-mux-clocks.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 77612720a2362230af726baa4149c40ec7a7fb05 Mon Sep 17 00:00:00 2001 -From: Sricharan R -Date: Tue, 14 Aug 2018 17:42:31 +0530 -Subject: [PATCH 12/12] clk: qcom: Add safe switch hook for krait mux clocks - -When the Hfplls are reprogrammed during the rate change, -the primary muxes which are sourced from the same hfpll -for higher frequencies, needs to be switched to the 'safe -secondary mux' as the parent for that small window. This -is done by registering a clk notifier for the muxes and -switching to the safe parent in the PRE_RATE_CHANGE notifier -and back to the original parent in the POST_RATE_CHANGE notifier. - -Signed-off-by: Sricharan R -Tested-by: Craig Tatlor -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/clk-krait.c | 2 ++ - drivers/clk/qcom/clk-krait.h | 3 ++ - drivers/clk/qcom/krait-cc.c | 56 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 61 insertions(+) - ---- a/drivers/clk/qcom/clk-krait.c -+++ b/drivers/clk/qcom/clk-krait.c -@@ -50,6 +50,8 @@ static int krait_mux_set_parent(struct c - if (__clk_is_enabled(hw->clk)) - __krait_mux_set_sel(mux, sel); - -+ mux->reparent = true; -+ - return 0; - } - ---- a/drivers/clk/qcom/clk-krait.h -+++ b/drivers/clk/qcom/clk-krait.h -@@ -12,6 +12,9 @@ struct krait_mux_clk { - u32 shift; - u32 en_mask; - bool lpl; -+ u8 safe_sel; -+ u8 old_index; -+ bool reparent; - - struct clk_hw hw; - struct notifier_block clk_nb; ---- a/drivers/clk/qcom/krait-cc.c -+++ b/drivers/clk/qcom/krait-cc.c -@@ -26,6 +26,49 @@ static unsigned int pri_mux_map[] = { - 0, - }; - -+/* -+ * Notifier function for switching the muxes to safe parent -+ * while the hfpll is getting reprogrammed. -+ */ -+static int krait_notifier_cb(struct notifier_block *nb, -+ unsigned long event, -+ void *data) -+{ -+ int ret = 0; -+ struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk, -+ clk_nb); -+ /* Switch to safe parent */ -+ if (event == PRE_RATE_CHANGE) { -+ mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw); -+ ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel); -+ mux->reparent = false; -+ /* -+ * By the time POST_RATE_CHANGE notifier is called, -+ * clk framework itself would have changed the parent for the new rate. -+ * Only otherwise, put back to the old parent. -+ */ -+ } else if (event == POST_RATE_CHANGE) { -+ if (!mux->reparent) -+ ret = krait_mux_clk_ops.set_parent(&mux->hw, -+ mux->old_index); -+ } -+ -+ return notifier_from_errno(ret); -+} -+ -+static int krait_notifier_register(struct device *dev, struct clk *clk, -+ struct krait_mux_clk *mux) -+{ -+ int ret = 0; -+ -+ mux->clk_nb.notifier_call = krait_notifier_cb; -+ ret = clk_notifier_register(clk, &mux->clk_nb); -+ if (ret) -+ dev_err(dev, "failed to register clock notifier: %d\n", ret); -+ -+ return ret; -+} -+ - static int - krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) - { -@@ -70,6 +113,7 @@ static int - krait_add_sec_mux(struct device *dev, int id, const char *s, - unsigned int offset, bool unique_aux) - { -+ int ret; - struct krait_mux_clk *mux; - static const char *sec_mux_list[] = { - "acpu_aux", -@@ -93,6 +137,7 @@ krait_add_sec_mux(struct device *dev, in - mux->shift = 2; - mux->parent_map = sec_mux_map; - mux->hw.init = &init; -+ mux->safe_sel = 0; - - init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); - if (!init.name) -@@ -108,6 +153,11 @@ krait_add_sec_mux(struct device *dev, in - - clk = devm_clk_register(dev, &mux->hw); - -+ ret = krait_notifier_register(dev, clk, mux); -+ if (ret) -+ goto unique_aux; -+ -+unique_aux: - if (unique_aux) - kfree(sec_mux_list[0]); - err_aux: -@@ -119,6 +169,7 @@ static struct clk * - krait_add_pri_mux(struct device *dev, int id, const char *s, - unsigned int offset) - { -+ int ret; - struct krait_mux_clk *mux; - const char *p_names[3]; - struct clk_init_data init = { -@@ -139,6 +190,7 @@ krait_add_pri_mux(struct device *dev, in - mux->lpl = id >= 0; - mux->parent_map = pri_mux_map; - mux->hw.init = &init; -+ mux->safe_sel = 2; - - init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s); - if (!init.name) -@@ -164,6 +216,10 @@ krait_add_pri_mux(struct device *dev, in - - clk = devm_clk_register(dev, &mux->hw); - -+ ret = krait_notifier_register(dev, clk, mux); -+ if (ret) -+ goto err_p3; -+err_p3: - kfree(p_names[2]); - err_p2: - kfree(p_names[1]); diff --git a/target/linux/ipq806x/patches-5.4/0035-qcom-cpufreq-nvmem-qcm-kyrp_make_Some_variables_static.patch b/target/linux/ipq806x/patches-5.4/0035-qcom-cpufreq-nvmem-qcm-kyrp_make_Some_variables_static.patch deleted file mode 100644 index a51153b2aa..0000000000 --- a/target/linux/ipq806x/patches-5.4/0035-qcom-cpufreq-nvmem-qcm-kyrp_make_Some_variables_static.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 50c0b12f098fb3cfac7abcc0f2b5409f6bac5fa2 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Mon, 4 Feb 2019 01:13:10 -0500 -Subject: [PATCH] cpufreq: qcom-kryo: make some variables static - -The variables are local to the source and do not -need to be in global scope, so make them static. - -Signed-off-by: Yangtao Li -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/qcom-cpufreq-kryo.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/cpufreq/qcom-cpufreq-kryo.c -+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c -@@ -42,7 +42,7 @@ enum _msm8996_version { - NUM_OF_MSM8996_VERSIONS, - }; - --struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; -+static struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; - - static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void) - { diff --git a/target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch b/target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch deleted file mode 100644 index c7e4569616..0000000000 --- a/target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 7d12709544b8b3fb9727a34a664b8380e1e3493a Mon Sep 17 00:00:00 2001 -From: Sricharan R -Date: Thu, 25 Jul 2019 12:41:31 +0200 -Subject: [PATCH] cpufreq: qcom: Re-organise kryo cpufreq to use it for other - nvmem based qcom socs - -The kryo cpufreq driver reads the nvmem cell and uses that data to -populate the opps. There are other qcom cpufreq socs like krait which -does similar thing. Except for the interpretation of the read data, -rest of the driver is same for both the cases. So pull the common things -out for reuse. - -Signed-off-by: Sricharan R -[niklas.cassel@linaro.org: split dt-binding into a separate patch and -do not rename the compatible string. Update MAINTAINERS file.] -Signed-off-by: Niklas Cassel -Reviewed-by: Ilia Lin -Reviewed-by: Stephen Boyd -Signed-off-by: Viresh Kumar ---- - MAINTAINERS | 4 +- - drivers/cpufreq/Kconfig.arm | 4 +- - drivers/cpufreq/Makefile | 2 +- - ...om-cpufreq-kryo.c => qcom-cpufreq-nvmem.c} | 122 +++++++++++------- - 4 files changed, 78 insertions(+), 54 deletions(-) - rename drivers/cpufreq/{qcom-cpufreq-kryo.c => qcom-cpufreq-nvmem.c} (69%) - ---- a/drivers/cpufreq/Kconfig.arm -+++ b/drivers/cpufreq/Kconfig.arm -@@ -110,8 +110,8 @@ config ARM_OMAP2PLUS_CPUFREQ - depends on ARCH_OMAP2PLUS - default ARCH_OMAP2PLUS - --config ARM_QCOM_CPUFREQ_KRYO -- tristate "Qualcomm Kryo based CPUFreq" -+config ARM_QCOM_CPUFREQ_NVMEM -+ tristate "Qualcomm nvmem based CPUFreq" - depends on ARM64 - depends on QCOM_QFPROM - depends on QCOM_SMEM ---- a/drivers/cpufreq/Makefile -+++ b/drivers/cpufreq/Makefile -@@ -64,7 +64,7 @@ obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cp - obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o - obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o - obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o --obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o -+obj-$(CONFIG_ARM_QCOM_CPUFREQ_NVMEM) += qcom-cpufreq-nvmem.o - obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o - obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o - obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o ---- a/drivers/cpufreq/qcom-cpufreq-kryo.c -+++ /dev/null -@@ -1,249 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * Copyright (c) 2018, The Linux Foundation. All rights reserved. -- */ -- --/* -- * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors, -- * the CPU frequency subset and voltage value of each OPP varies -- * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables -- * defines the voltage and frequency value based on the msm-id in SMEM -- * and speedbin blown in the efuse combination. -- * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC -- * to provide the OPP framework with required information. -- * This is used to determine the voltage and frequency value for each OPP of -- * operating-points-v2 table when it is parsed by the OPP framework. -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define MSM_ID_SMEM 137 -- --enum _msm_id { -- MSM8996V3 = 0xF6ul, -- APQ8096V3 = 0x123ul, -- MSM8996SG = 0x131ul, -- APQ8096SG = 0x138ul, --}; -- --enum _msm8996_version { -- MSM8996_V3, -- MSM8996_SG, -- NUM_OF_MSM8996_VERSIONS, --}; -- --static struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; -- --static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void) --{ -- size_t len; -- u32 *msm_id; -- enum _msm8996_version version; -- -- msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); -- if (IS_ERR(msm_id)) -- return NUM_OF_MSM8996_VERSIONS; -- -- /* The first 4 bytes are format, next to them is the actual msm-id */ -- msm_id++; -- -- switch ((enum _msm_id)*msm_id) { -- case MSM8996V3: -- case APQ8096V3: -- version = MSM8996_V3; -- break; -- case MSM8996SG: -- case APQ8096SG: -- version = MSM8996_SG; -- break; -- default: -- version = NUM_OF_MSM8996_VERSIONS; -- } -- -- return version; --} -- --static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) --{ -- struct opp_table **opp_tables; -- enum _msm8996_version msm8996_version; -- struct nvmem_cell *speedbin_nvmem; -- struct device_node *np; -- struct device *cpu_dev; -- unsigned cpu; -- u8 *speedbin; -- u32 versions; -- size_t len; -- int ret; -- -- cpu_dev = get_cpu_device(0); -- if (!cpu_dev) -- return -ENODEV; -- -- msm8996_version = qcom_cpufreq_kryo_get_msm_id(); -- if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { -- dev_err(cpu_dev, "Not Snapdragon 820/821!"); -- return -ENODEV; -- } -- -- np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); -- if (!np) -- return -ENOENT; -- -- ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); -- if (!ret) { -- of_node_put(np); -- return -ENOENT; -- } -- -- speedbin_nvmem = of_nvmem_cell_get(np, NULL); -- of_node_put(np); -- if (IS_ERR(speedbin_nvmem)) { -- if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) -- dev_err(cpu_dev, "Could not get nvmem cell: %ld\n", -- PTR_ERR(speedbin_nvmem)); -- return PTR_ERR(speedbin_nvmem); -- } -- -- speedbin = nvmem_cell_read(speedbin_nvmem, &len); -- nvmem_cell_put(speedbin_nvmem); -- if (IS_ERR(speedbin)) -- return PTR_ERR(speedbin); -- -- switch (msm8996_version) { -- case MSM8996_V3: -- versions = 1 << (unsigned int)(*speedbin); -- break; -- case MSM8996_SG: -- versions = 1 << ((unsigned int)(*speedbin) + 4); -- break; -- default: -- BUG(); -- break; -- } -- kfree(speedbin); -- -- opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); -- if (!opp_tables) -- return -ENOMEM; -- -- for_each_possible_cpu(cpu) { -- cpu_dev = get_cpu_device(cpu); -- if (NULL == cpu_dev) { -- ret = -ENODEV; -- goto free_opp; -- } -- -- opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, -- &versions, 1); -- if (IS_ERR(opp_tables[cpu])) { -- ret = PTR_ERR(opp_tables[cpu]); -- dev_err(cpu_dev, "Failed to set supported hardware\n"); -- goto free_opp; -- } -- } -- -- cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, -- NULL, 0); -- if (!IS_ERR(cpufreq_dt_pdev)) { -- platform_set_drvdata(pdev, opp_tables); -- return 0; -- } -- -- ret = PTR_ERR(cpufreq_dt_pdev); -- dev_err(cpu_dev, "Failed to register platform device\n"); -- --free_opp: -- for_each_possible_cpu(cpu) { -- if (IS_ERR_OR_NULL(opp_tables[cpu])) -- break; -- dev_pm_opp_put_supported_hw(opp_tables[cpu]); -- } -- kfree(opp_tables); -- -- return ret; --} -- --static int qcom_cpufreq_kryo_remove(struct platform_device *pdev) --{ -- struct opp_table **opp_tables = platform_get_drvdata(pdev); -- unsigned int cpu; -- -- platform_device_unregister(cpufreq_dt_pdev); -- -- for_each_possible_cpu(cpu) -- dev_pm_opp_put_supported_hw(opp_tables[cpu]); -- -- kfree(opp_tables); -- -- return 0; --} -- --static struct platform_driver qcom_cpufreq_kryo_driver = { -- .probe = qcom_cpufreq_kryo_probe, -- .remove = qcom_cpufreq_kryo_remove, -- .driver = { -- .name = "qcom-cpufreq-kryo", -- }, --}; -- --static const struct of_device_id qcom_cpufreq_kryo_match_list[] __initconst = { -- { .compatible = "qcom,apq8096", }, -- { .compatible = "qcom,msm8996", }, -- {} --}; -- --/* -- * Since the driver depends on smem and nvmem drivers, which may -- * return EPROBE_DEFER, all the real activity is done in the probe, -- * which may be defered as well. The init here is only registering -- * the driver and the platform device. -- */ --static int __init qcom_cpufreq_kryo_init(void) --{ -- struct device_node *np = of_find_node_by_path("/"); -- const struct of_device_id *match; -- int ret; -- -- if (!np) -- return -ENODEV; -- -- match = of_match_node(qcom_cpufreq_kryo_match_list, np); -- of_node_put(np); -- if (!match) -- return -ENODEV; -- -- ret = platform_driver_register(&qcom_cpufreq_kryo_driver); -- if (unlikely(ret < 0)) -- return ret; -- -- kryo_cpufreq_pdev = platform_device_register_simple( -- "qcom-cpufreq-kryo", -1, NULL, 0); -- ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev); -- if (0 == ret) -- return 0; -- -- platform_driver_unregister(&qcom_cpufreq_kryo_driver); -- return ret; --} --module_init(qcom_cpufreq_kryo_init); -- --static void __exit qcom_cpufreq_kryo_exit(void) --{ -- platform_device_unregister(kryo_cpufreq_pdev); -- platform_driver_unregister(&qcom_cpufreq_kryo_driver); --} --module_exit(qcom_cpufreq_kryo_exit); -- --MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver"); --MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -0,0 +1,273 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ */ -+ -+/* -+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors, -+ * the CPU frequency subset and voltage value of each OPP varies -+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables -+ * defines the voltage and frequency value based on the msm-id in SMEM -+ * and speedbin blown in the efuse combination. -+ * The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC -+ * to provide the OPP framework with required information. -+ * This is used to determine the voltage and frequency value for each OPP of -+ * operating-points-v2 table when it is parsed by the OPP framework. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MSM_ID_SMEM 137 -+ -+enum _msm_id { -+ MSM8996V3 = 0xF6ul, -+ APQ8096V3 = 0x123ul, -+ MSM8996SG = 0x131ul, -+ APQ8096SG = 0x138ul, -+}; -+ -+enum _msm8996_version { -+ MSM8996_V3, -+ MSM8996_SG, -+ NUM_OF_MSM8996_VERSIONS, -+}; -+ -+static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev; -+ -+static enum _msm8996_version qcom_cpufreq_get_msm_id(void) -+{ -+ size_t len; -+ u32 *msm_id; -+ enum _msm8996_version version; -+ -+ msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); -+ if (IS_ERR(msm_id)) -+ return NUM_OF_MSM8996_VERSIONS; -+ -+ /* The first 4 bytes are format, next to them is the actual msm-id */ -+ msm_id++; -+ -+ switch ((enum _msm_id)*msm_id) { -+ case MSM8996V3: -+ case APQ8096V3: -+ version = MSM8996_V3; -+ break; -+ case MSM8996SG: -+ case APQ8096SG: -+ version = MSM8996_SG; -+ break; -+ default: -+ version = NUM_OF_MSM8996_VERSIONS; -+ } -+ -+ return version; -+} -+ -+static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, -+ struct nvmem_cell *speedbin_nvmem, -+ u32 *versions) -+{ -+ size_t len; -+ u8 *speedbin; -+ enum _msm8996_version msm8996_version; -+ -+ msm8996_version = qcom_cpufreq_get_msm_id(); -+ if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { -+ dev_err(cpu_dev, "Not Snapdragon 820/821!"); -+ return -ENODEV; -+ } -+ -+ speedbin = nvmem_cell_read(speedbin_nvmem, &len); -+ if (IS_ERR(speedbin)) -+ return PTR_ERR(speedbin); -+ -+ switch (msm8996_version) { -+ case MSM8996_V3: -+ *versions = 1 << (unsigned int)(*speedbin); -+ break; -+ case MSM8996_SG: -+ *versions = 1 << ((unsigned int)(*speedbin) + 4); -+ break; -+ default: -+ BUG(); -+ break; -+ } -+ -+ kfree(speedbin); -+ return 0; -+} -+ -+static int qcom_cpufreq_probe(struct platform_device *pdev) -+{ -+ struct opp_table **opp_tables; -+ int (*get_version)(struct device *cpu_dev, -+ struct nvmem_cell *speedbin_nvmem, -+ u32 *versions); -+ struct nvmem_cell *speedbin_nvmem; -+ struct device_node *np; -+ struct device *cpu_dev; -+ unsigned cpu; -+ u32 versions; -+ const struct of_device_id *match; -+ int ret; -+ -+ cpu_dev = get_cpu_device(0); -+ if (!cpu_dev) -+ return -ENODEV; -+ -+ match = pdev->dev.platform_data; -+ get_version = match->data; -+ if (!get_version) -+ return -ENODEV; -+ -+ np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); -+ if (!np) -+ return -ENOENT; -+ -+ ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); -+ if (!ret) { -+ of_node_put(np); -+ return -ENOENT; -+ } -+ -+ speedbin_nvmem = of_nvmem_cell_get(np, NULL); -+ of_node_put(np); -+ if (IS_ERR(speedbin_nvmem)) { -+ if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) -+ dev_err(cpu_dev, "Could not get nvmem cell: %ld\n", -+ PTR_ERR(speedbin_nvmem)); -+ return PTR_ERR(speedbin_nvmem); -+ } -+ -+ ret = get_version(cpu_dev, speedbin_nvmem, &versions); -+ nvmem_cell_put(speedbin_nvmem); -+ if (ret) -+ return ret; -+ -+ opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); -+ if (!opp_tables) -+ return -ENOMEM; -+ -+ for_each_possible_cpu(cpu) { -+ cpu_dev = get_cpu_device(cpu); -+ if (NULL == cpu_dev) { -+ ret = -ENODEV; -+ goto free_opp; -+ } -+ -+ opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, -+ &versions, 1); -+ if (IS_ERR(opp_tables[cpu])) { -+ ret = PTR_ERR(opp_tables[cpu]); -+ dev_err(cpu_dev, "Failed to set supported hardware\n"); -+ goto free_opp; -+ } -+ } -+ -+ cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, -+ NULL, 0); -+ if (!IS_ERR(cpufreq_dt_pdev)) { -+ platform_set_drvdata(pdev, opp_tables); -+ return 0; -+ } -+ -+ ret = PTR_ERR(cpufreq_dt_pdev); -+ dev_err(cpu_dev, "Failed to register platform device\n"); -+ -+free_opp: -+ for_each_possible_cpu(cpu) { -+ if (IS_ERR_OR_NULL(opp_tables[cpu])) -+ break; -+ dev_pm_opp_put_supported_hw(opp_tables[cpu]); -+ } -+ kfree(opp_tables); -+ -+ return ret; -+} -+ -+static int qcom_cpufreq_remove(struct platform_device *pdev) -+{ -+ struct opp_table **opp_tables = platform_get_drvdata(pdev); -+ unsigned int cpu; -+ -+ platform_device_unregister(cpufreq_dt_pdev); -+ -+ for_each_possible_cpu(cpu) -+ dev_pm_opp_put_supported_hw(opp_tables[cpu]); -+ -+ kfree(opp_tables); -+ -+ return 0; -+} -+ -+static struct platform_driver qcom_cpufreq_driver = { -+ .probe = qcom_cpufreq_probe, -+ .remove = qcom_cpufreq_remove, -+ .driver = { -+ .name = "qcom-cpufreq-nvmem", -+ }, -+}; -+ -+static const struct of_device_id qcom_cpufreq_match_list[] __initconst = { -+ { .compatible = "qcom,apq8096", -+ .data = qcom_cpufreq_kryo_name_version }, -+ { .compatible = "qcom,msm8996", -+ .data = qcom_cpufreq_kryo_name_version }, -+ {}, -+}; -+ -+/* -+ * Since the driver depends on smem and nvmem drivers, which may -+ * return EPROBE_DEFER, all the real activity is done in the probe, -+ * which may be defered as well. The init here is only registering -+ * the driver and the platform device. -+ */ -+static int __init qcom_cpufreq_init(void) -+{ -+ struct device_node *np = of_find_node_by_path("/"); -+ const struct of_device_id *match; -+ int ret; -+ -+ if (!np) -+ return -ENODEV; -+ -+ match = of_match_node(qcom_cpufreq_match_list, np); -+ of_node_put(np); -+ if (!match) -+ return -ENODEV; -+ -+ ret = platform_driver_register(&qcom_cpufreq_driver); -+ if (unlikely(ret < 0)) -+ return ret; -+ -+ cpufreq_pdev = platform_device_register_data(NULL, "qcom-cpufreq-nvmem", -+ -1, match, sizeof(*match)); -+ ret = PTR_ERR_OR_ZERO(cpufreq_pdev); -+ if (0 == ret) -+ return 0; -+ -+ platform_driver_unregister(&qcom_cpufreq_driver); -+ return ret; -+} -+module_init(qcom_cpufreq_init); -+ -+static void __exit qcom_cpufreq_exit(void) -+{ -+ platform_device_unregister(cpufreq_pdev); -+ platform_driver_unregister(&qcom_cpufreq_driver); -+} -+module_exit(qcom_cpufreq_exit); -+ -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. CPUfreq driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches-5.4/0037-qcom-cpufreq-nvmem-Refactor-the-driver.patch b/target/linux/ipq806x/patches-5.4/0037-qcom-cpufreq-nvmem-Refactor-the-driver.patch deleted file mode 100644 index d00b2ccfcb..0000000000 --- a/target/linux/ipq806x/patches-5.4/0037-qcom-cpufreq-nvmem-Refactor-the-driver.patch +++ /dev/null @@ -1,241 +0,0 @@ -From 57f2f8b4aa0c6b41a284da82bfa40dc3b2abe9a5 Mon Sep 17 00:00:00 2001 -From: Niklas Cassel -Date: Thu, 25 Jul 2019 12:41:33 +0200 -Subject: [PATCH] cpufreq: qcom: Refactor the driver to make it easier to - extend - -Refactor the driver to make it easier to extend in a later commit. - -Create a driver struct to collect all common resources, in order to make -it easier to free up all common resources. -Create a driver match_data struct to make it easier to extend the driver -with support for new features that might only be supported on certain SoCs. - -Co-developed-by: Jorge Ramirez-Ortiz -Signed-off-by: Jorge Ramirez-Ortiz -Signed-off-by: Niklas Cassel -Reviewed-by: Ilia Lin -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/qcom-cpufreq-nvmem.c | 123 +++++++++++++++++---------- - 1 file changed, 79 insertions(+), 44 deletions(-) - ---- a/drivers/cpufreq/qcom-cpufreq-nvmem.c -+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -43,6 +43,20 @@ enum _msm8996_version { - NUM_OF_MSM8996_VERSIONS, - }; - -+struct qcom_cpufreq_drv; -+ -+struct qcom_cpufreq_match_data { -+ int (*get_version)(struct device *cpu_dev, -+ struct nvmem_cell *speedbin_nvmem, -+ struct qcom_cpufreq_drv *drv); -+}; -+ -+struct qcom_cpufreq_drv { -+ struct opp_table **opp_tables; -+ u32 versions; -+ const struct qcom_cpufreq_match_data *data; -+}; -+ - static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev; - - static enum _msm8996_version qcom_cpufreq_get_msm_id(void) -@@ -76,7 +90,7 @@ static enum _msm8996_version qcom_cpufre - - static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, - struct nvmem_cell *speedbin_nvmem, -- u32 *versions) -+ struct qcom_cpufreq_drv *drv) - { - size_t len; - u8 *speedbin; -@@ -94,10 +108,10 @@ static int qcom_cpufreq_kryo_name_versio - - switch (msm8996_version) { - case MSM8996_V3: -- *versions = 1 << (unsigned int)(*speedbin); -+ drv->versions = 1 << (unsigned int)(*speedbin); - break; - case MSM8996_SG: -- *versions = 1 << ((unsigned int)(*speedbin) + 4); -+ drv->versions = 1 << ((unsigned int)(*speedbin) + 4); - break; - default: - BUG(); -@@ -108,17 +122,17 @@ static int qcom_cpufreq_kryo_name_versio - return 0; - } - -+static const struct qcom_cpufreq_match_data match_data_kryo = { -+ .get_version = qcom_cpufreq_kryo_name_version, -+}; -+ - static int qcom_cpufreq_probe(struct platform_device *pdev) - { -- struct opp_table **opp_tables; -- int (*get_version)(struct device *cpu_dev, -- struct nvmem_cell *speedbin_nvmem, -- u32 *versions); -+ struct qcom_cpufreq_drv *drv; - struct nvmem_cell *speedbin_nvmem; - struct device_node *np; - struct device *cpu_dev; - unsigned cpu; -- u32 versions; - const struct of_device_id *match; - int ret; - -@@ -126,11 +140,6 @@ static int qcom_cpufreq_probe(struct pla - if (!cpu_dev) - return -ENODEV; - -- match = pdev->dev.platform_data; -- get_version = match->data; -- if (!get_version) -- return -ENODEV; -- - np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); - if (!np) - return -ENOENT; -@@ -141,23 +150,43 @@ static int qcom_cpufreq_probe(struct pla - return -ENOENT; - } - -- speedbin_nvmem = of_nvmem_cell_get(np, NULL); -- of_node_put(np); -- if (IS_ERR(speedbin_nvmem)) { -- if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) -- dev_err(cpu_dev, "Could not get nvmem cell: %ld\n", -- PTR_ERR(speedbin_nvmem)); -- return PTR_ERR(speedbin_nvmem); -+ drv = kzalloc(sizeof(*drv), GFP_KERNEL); -+ if (!drv) -+ return -ENOMEM; -+ -+ match = pdev->dev.platform_data; -+ drv->data = match->data; -+ if (!drv->data) { -+ ret = -ENODEV; -+ goto free_drv; - } - -- ret = get_version(cpu_dev, speedbin_nvmem, &versions); -- nvmem_cell_put(speedbin_nvmem); -- if (ret) -- return ret; -+ if (drv->data->get_version) { -+ speedbin_nvmem = of_nvmem_cell_get(np, NULL); -+ if (IS_ERR(speedbin_nvmem)) { -+ if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) -+ dev_err(cpu_dev, -+ "Could not get nvmem cell: %ld\n", -+ PTR_ERR(speedbin_nvmem)); -+ ret = PTR_ERR(speedbin_nvmem); -+ goto free_drv; -+ } - -- opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); -- if (!opp_tables) -- return -ENOMEM; -+ ret = drv->data->get_version(cpu_dev, speedbin_nvmem, drv); -+ if (ret) { -+ nvmem_cell_put(speedbin_nvmem); -+ goto free_drv; -+ } -+ nvmem_cell_put(speedbin_nvmem); -+ } -+ of_node_put(np); -+ -+ drv->opp_tables = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tables), -+ GFP_KERNEL); -+ if (!drv->opp_tables) { -+ ret = -ENOMEM; -+ goto free_drv; -+ } - - for_each_possible_cpu(cpu) { - cpu_dev = get_cpu_device(cpu); -@@ -166,19 +195,23 @@ static int qcom_cpufreq_probe(struct pla - goto free_opp; - } - -- opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, -- &versions, 1); -- if (IS_ERR(opp_tables[cpu])) { -- ret = PTR_ERR(opp_tables[cpu]); -- dev_err(cpu_dev, "Failed to set supported hardware\n"); -- goto free_opp; -+ if (drv->data->get_version) { -+ drv->opp_tables[cpu] = -+ dev_pm_opp_set_supported_hw(cpu_dev, -+ &drv->versions, 1); -+ if (IS_ERR(drv->opp_tables[cpu])) { -+ ret = PTR_ERR(drv->opp_tables[cpu]); -+ dev_err(cpu_dev, -+ "Failed to set supported hardware\n"); -+ goto free_opp; -+ } - } - } - - cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, - NULL, 0); - if (!IS_ERR(cpufreq_dt_pdev)) { -- platform_set_drvdata(pdev, opp_tables); -+ platform_set_drvdata(pdev, drv); - return 0; - } - -@@ -187,26 +220,30 @@ static int qcom_cpufreq_probe(struct pla - - free_opp: - for_each_possible_cpu(cpu) { -- if (IS_ERR_OR_NULL(opp_tables[cpu])) -+ if (IS_ERR_OR_NULL(drv->opp_tables[cpu])) - break; -- dev_pm_opp_put_supported_hw(opp_tables[cpu]); -+ dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]); - } -- kfree(opp_tables); -+ kfree(drv->opp_tables); -+free_drv: -+ kfree(drv); - - return ret; - } - - static int qcom_cpufreq_remove(struct platform_device *pdev) - { -- struct opp_table **opp_tables = platform_get_drvdata(pdev); -+ struct qcom_cpufreq_drv *drv = platform_get_drvdata(pdev); - unsigned int cpu; - - platform_device_unregister(cpufreq_dt_pdev); - - for_each_possible_cpu(cpu) -- dev_pm_opp_put_supported_hw(opp_tables[cpu]); -+ if (drv->opp_tables[cpu]) -+ dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]); - -- kfree(opp_tables); -+ kfree(drv->opp_tables); -+ kfree(drv); - - return 0; - } -@@ -220,10 +257,8 @@ static struct platform_driver qcom_cpufr - }; - - static const struct of_device_id qcom_cpufreq_match_list[] __initconst = { -- { .compatible = "qcom,apq8096", -- .data = qcom_cpufreq_kryo_name_version }, -- { .compatible = "qcom,msm8996", -- .data = qcom_cpufreq_kryo_name_version }, -+ { .compatible = "qcom,apq8096", .data = &match_data_kryo }, -+ { .compatible = "qcom,msm8996", .data = &match_data_kryo }, - {}, - }; - diff --git a/target/linux/ipq806x/patches-5.4/0070-qcom-spm-fix-probe-order.patch b/target/linux/ipq806x/patches-5.4/0070-qcom-spm-fix-probe-order.patch deleted file mode 100644 index febfd53398..0000000000 --- a/target/linux/ipq806x/patches-5.4/0070-qcom-spm-fix-probe-order.patch +++ /dev/null @@ -1,16 +0,0 @@ -Check for SCM availability before attempting to use SPM - -Signed-off-by: Felix Fietkau - ---- a/drivers/soc/qcom/spm.c -+++ b/drivers/soc/qcom/spm.c -@@ -214,6 +214,9 @@ static int __init qcom_cpuidle_init(stru - if (!qcom_scm_is_available()) - return -EPROBE_DEFER; - -+ if (!qcom_scm_is_available()) -+ return -EPROBE_DEFER; -+ - for (i = 0; ; i++) { - state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); - if (!state_node)