devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] clk: qcom: CPU clock driver for msm8996
@ 2017-12-12 12:31 Ilia Lin
  2017-12-12 12:31 ` [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver Ilia Lin
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel

This series adds support for the CPU clocks on msm8996 devices.
A previous post of RFC can be found here
https://patchwork.kernel.org/patch/9662917/

Ilia Lin (5):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: qcom: clk-cpu-8996: Prepare PLLs on probe
  clk: qcom: Add ACD path to CPU clock driver for msm8996
  DT: QCOM: Add cpufreq-dt to msm8996
  DT: QCOM: Add thermal mitigation to msm8996

Rajendra Nayak (4):
  clk: qcom: Make clk_alpha_pll_configure available to modules
  clk: qcom: Add CPU clock driver for msm8996
  clk: qcom: cpu-8996: Add support to switch to alternate PLL
  clk: qcom: cpu-8996: Add support to switch below 600Mhz

Taniya Das (1):
  clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update

 .../devicetree/bindings/clock/qcom,kryocc.txt      |  17 +
 arch/arm64/Kconfig.platforms                       |   7 +
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts        |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi              | 282 ++++++++++-
 drivers/clk/qcom/Kconfig                           |   8 +
 drivers/clk/qcom/Makefile                          |   1 +
 drivers/clk/qcom/clk-alpha-pll.c                   |  72 ++-
 drivers/clk/qcom/clk-alpha-pll.h                   |   5 +
 drivers/clk/qcom/clk-cpu-8996.c                    | 542 +++++++++++++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c               |   3 +
 drivers/perf/qcom_l2_pmu.c                         |  48 +-
 drivers/soc/qcom/Makefile                          |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c               |  64 +++
 include/soc/qcom/kryo-l2-accessors.h               |  27 +
 14 files changed, 1009 insertions(+), 70 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation

-- 
1.9.1

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
@ 2017-12-12 12:31 ` Ilia Lin
  2017-12-12 14:03   ` Mark Rutland
  2017-12-12 12:31 ` [PATCH 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update Ilia Lin
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel

The driver provides kernel level API for other drivers
to access the MSM8996 L2 cache registers.
Separating the L2 access code from the PMU driver and
making it public to allow other drivers use it.
The accesses must be separated with a single spinlock,
maintained in this driver.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 arch/arm64/Kconfig.platforms         |  7 ++++
 drivers/perf/qcom_l2_pmu.c           | 48 +--------------------------
 drivers/soc/qcom/Makefile            |  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 64 ++++++++++++++++++++++++++++++++++++
 include/soc/qcom/kryo-l2-accessors.h | 27 +++++++++++++++
 5 files changed, 100 insertions(+), 47 deletions(-)
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2401373..a6a6504 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -144,6 +144,13 @@ config ARCH_REALTEK
 	  This enables support for the ARMv8 based Realtek chipsets,
 	  like the RTD1295.
 
+config ARCH_MSM8996
+    bool "Enable Support for Qualcomm Technologies, Inc. MSM8996"
+	depends on ARCH_QCOM
+	help
+	This enables support for the MSM8996 chipset. If you do not
+	wish to build a kernel that runs on this chipset, say 'N' here.
+
 config ARCH_ROCKCHIP
 	bool "Rockchip Platforms"
 	select ARCH_HAS_RESET_CONTROLLER
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 4fdc848..ba5f241 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -30,7 +30,7 @@
 
 #include <asm/barrier.h>
 #include <asm/local64.h>
-#include <asm/sysreg.h>
+#include <soc/qcom/kryo-l2-accessors.h>
 
 #define MAX_L2_CTRS             9
 
@@ -87,9 +87,6 @@
 #define L2_COUNTER_RELOAD       BIT_ULL(31)
 #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
 
-#define L2CPUSRSELR_EL1         sys_reg(3, 3, 15, 0, 6)
-#define L2CPUSRDR_EL1           sys_reg(3, 3, 15, 0, 7)
-
 #define reg_idx(reg, i)         (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
 
 /*
@@ -107,49 +104,6 @@
 #define L2_EVENT_STREX                     0x421
 #define L2_EVENT_CLREX                     0x422
 
-static DEFINE_RAW_SPINLOCK(l2_access_lock);
-
-/**
- * set_l2_indirect_reg: write value to an L2 register
- * @reg: Address of L2 register.
- * @value: Value to be written to register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static void set_l2_indirect_reg(u64 reg, u64 val)
-{
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&l2_access_lock, flags);
-	write_sysreg_s(reg, L2CPUSRSELR_EL1);
-	isb();
-	write_sysreg_s(val, L2CPUSRDR_EL1);
-	isb();
-	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-}
-
-/**
- * get_l2_indirect_reg: read an L2 register value
- * @reg: Address of L2 register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static u64 get_l2_indirect_reg(u64 reg)
-{
-	u64 val;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&l2_access_lock, flags);
-	write_sysreg_s(reg, L2CPUSRSELR_EL1);
-	isb();
-	val = read_sysreg_s(L2CPUSRDR_EL1);
-	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-
-	return val;
-}
-
 struct cluster_pmu;
 
 /*
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 40c56f6..2bf8d93 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o
 obj-$(CONFIG_QCOM_SMSM)	+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_ARCH_MSM8996) +=	kryo-l2-accessors.o
diff --git a/drivers/soc/qcom/kryo-l2-accessors.c b/drivers/soc/qcom/kryo-l2-accessors.c
new file mode 100644
index 0000000..6be57e6
--- /dev/null
+++ b/drivers/soc/qcom/kryo-l2-accessors.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/spinlock.h>
+#include <asm/sysreg.h>
+#include <soc/qcom/kryo-l2-accessors.h>
+
+#define L2CPUSRSELR_EL1         sys_reg(3, 3, 15, 0, 6)
+#define L2CPUSRDR_EL1           sys_reg(3, 3, 15, 0, 7)
+
+static DEFINE_RAW_SPINLOCK(l2_access_lock);
+
+/**
+ * set_l2_indirect_reg: write value to an L2 register
+ * @reg: Address of L2 register.
+ * @value: Value to be written to register.
+ *
+ * Use architecturally required barriers for ordering between system register
+ * accesses, and system registers with respect to device memory
+ */
+void set_l2_indirect_reg(u64 reg, u64 val)
+{
+	unsigned long flags;
+	mb();
+	raw_spin_lock_irqsave(&l2_access_lock, flags);
+	write_sysreg_s(reg, L2CPUSRSELR_EL1);
+	isb();
+	write_sysreg_s(val, L2CPUSRDR_EL1);
+	isb();
+	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
+}
+EXPORT_SYMBOL(set_l2_indirect_reg);
+
+/**
+ * get_l2_indirect_reg: read an L2 register value
+ * @reg: Address of L2 register.
+ *
+ * Use architecturally required barriers for ordering between system register
+ * accesses, and system registers with respect to device memory
+ */
+u64 get_l2_indirect_reg(u64 reg)
+{
+	u64 val;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&l2_access_lock, flags);
+	write_sysreg_s(reg, L2CPUSRSELR_EL1);
+	isb();
+	val = read_sysreg_s(L2CPUSRDR_EL1);
+	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
+
+	return val;
+}
+EXPORT_SYMBOL(get_l2_indirect_reg);
diff --git a/include/soc/qcom/kryo-l2-accessors.h b/include/soc/qcom/kryo-l2-accessors.h
new file mode 100644
index 0000000..2bebce1
--- /dev/null
+++ b/include/soc/qcom/kryo-l2-accessors.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 __ASM_ARCH_MSM_MSM_KRYO_L2_ACCESSORS_H
+#define __ASM_ARCH_MSM_MSM_KRYO_L2_ACCESSORS_H
+
+#ifdef CONFIG_ARCH_QCOM
+void set_l2_indirect_reg(u64 reg_addr, u64 val);
+u64 get_l2_indirect_reg(u64 reg_addr);
+#else
+static inline void set_l2_indirect_reg(u32 reg_addr, u32 val) {}
+static inline u32 get_l2_indirect_reg(u32 reg_addr)
+{
+	return 0;
+}
+#endif
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update
  2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
  2017-12-12 12:31 ` [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver Ilia Lin
@ 2017-12-12 12:31 ` Ilia Lin
       [not found]   ` <1513081897-31612-3-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2017-12-12 12:31 ` [PATCH 03/10] clk: qcom: Make clk_alpha_pll_configure available to modules Ilia Lin
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel, Taniya Das

From: Taniya Das <tdas@codeaurora.org>

From: Taniya Das <tdas@codeaurora.org>

Alpha PLLs which do not support dynamic update feature
need to be explicitly disabled before a rate change.
The ones which do support dynamic update do so within a
single vco range, so add a min/max freq check for such
PLLs so they fall in the vco range.

Signed-off-by: Taniya Das <tdas@codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 71 +++++++++++++++++++++++++++++++++-------
 drivers/clk/qcom/clk-alpha-pll.h |  5 +++
 2 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 47a1da3..ecb9e7f 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -376,19 +376,46 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
 	return alpha_pll_calc_rate(prate, l, a);
 }
 
-static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
-				  unsigned long prate)
+static int alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long prate,
+			      int (*enable)(struct clk_hw *hw),
+			      void (*disable)(struct clk_hw *hw))
 {
+	bool enabled;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
 	const struct pll_vco *vco;
 	u32 l, off = pll->offset;
 	u64 a;
 
 	rate = alpha_pll_round_rate(rate, prate, &l, &a);
-	vco = alpha_pll_find_vco(pll, rate);
-	if (!vco) {
-		pr_err("alpha pll not in a valid vco range\n");
-		return -EINVAL;
+	enabled = clk_hw_is_enabled(hw);
+
+	if (pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
+		/*
+		 * PLLs which support dynamic updates support one single
+		 * vco range, between min_rate and max_rate supported
+		 */
+		if (rate < pll->min_rate || rate > pll->max_rate) {
+			pr_err("alpha pll rate outside supported min/max range\n");
+			return -EINVAL;
+		}
+	} else {
+		/*
+		 * All alpha PLLs which do not support dynamic update,
+		 * should be disabled before a vco update.
+		 */
+		if (enabled)
+			disable(hw);
+
+		vco = alpha_pll_find_vco(pll, rate);
+		if (!vco) {
+			pr_err("alpha pll not in a valid vco range\n");
+			return -EINVAL;
+		}
+
+		regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
+				   PLL_VCO_MASK << PLL_VCO_SHIFT,
+				   vco->val << PLL_VCO_SHIFT);
 	}
 
 	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
@@ -401,16 +428,29 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
 	}
 
-	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
-			   PLL_VCO_MASK << PLL_VCO_SHIFT,
-			   vco->val << PLL_VCO_SHIFT);
-
 	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
 			   PLL_ALPHA_EN);
 
+	if (!(pll->flags & SUPPORTS_DYNAMIC_UPDATE) && enabled)
+		enable(hw);
+
 	return 0;
 }
 
+static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long prate)
+{
+	return alpha_pll_set_rate(hw, rate, prate, clk_alpha_pll_enable,
+				  clk_alpha_pll_disable);
+}
+
+static int clk_alpha_pll_hwfsm_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long prate)
+{
+	return alpha_pll_set_rate(hw, rate, prate, clk_alpha_pll_hwfsm_enable,
+				  clk_alpha_pll_hwfsm_disable);
+}
+
 static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 				     unsigned long *prate)
 {
@@ -420,6 +460,15 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long min_freq, max_freq;
 
 	rate = alpha_pll_round_rate(rate, *prate, &l, &a);
+
+	if (pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
+		if (rate < pll->min_rate)
+			rate = pll->min_rate;
+		else if (rate > pll->max_rate)
+			rate = pll->max_rate;
+		return rate;
+	}
+
 	if (alpha_pll_find_vco(pll, rate))
 		return rate;
 
@@ -445,7 +494,7 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 	.is_enabled = clk_alpha_pll_hwfsm_is_enabled,
 	.recalc_rate = clk_alpha_pll_recalc_rate,
 	.round_rate = clk_alpha_pll_round_rate,
-	.set_rate = clk_alpha_pll_set_rate,
+	.set_rate = clk_alpha_pll_hwfsm_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
 
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index d6e1ee2..7aaa11c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -27,6 +27,8 @@ struct pll_vco {
  * struct clk_alpha_pll - phase locked loop (PLL)
  * @offset: base address of registers
  * @vco_table: array of VCO settings
+ * @min_rate: Minimim rate for PLLs with single VCO range
+ * @max_rate: Maximun rate for PLLs with single VCO range
  * @clkr: regmap clock handle
  */
 struct clk_alpha_pll {
@@ -37,8 +39,11 @@ struct clk_alpha_pll {
 #define SUPPORTS_OFFLINE_REQ	BIT(0)
 #define SUPPORTS_16BIT_ALPHA	BIT(1)
 #define SUPPORTS_FSM_MODE	BIT(2)
+#define SUPPORTS_DYNAMIC_UPDATE	BIT(3)
 	u8 flags;
 
+	unsigned long min_rate;
+	unsigned long max_rate;
 	struct clk_regmap clkr;
 };
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/10] clk: qcom: Make clk_alpha_pll_configure available to modules
  2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
  2017-12-12 12:31 ` [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver Ilia Lin
  2017-12-12 12:31 ` [PATCH 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update Ilia Lin
@ 2017-12-12 12:31 ` Ilia Lin
  2017-12-12 12:31 ` [PATCH 04/10] clk: qcom: Add CPU clock driver for msm8996 Ilia Lin
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel

From: Rajendra Nayak <rnayak@codeaurora.org>

Allow clk_alpha_pll_configure to be called from loadable
kernel modules.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index ecb9e7f..7b06e21 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -141,6 +141,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 	if (pll->flags & SUPPORTS_FSM_MODE)
 		qcom_pll_set_fsm_mode(regmap, off + PLL_MODE, 6, 0);
 }
+EXPORT_SYMBOL_GPL(clk_alpha_pll_configure);
 
 static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
 {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 04/10] clk: qcom: Add CPU clock driver for msm8996
  2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
                   ` (2 preceding siblings ...)
  2017-12-12 12:31 ` [PATCH 03/10] clk: qcom: Make clk_alpha_pll_configure available to modules Ilia Lin
@ 2017-12-12 12:31 ` Ilia Lin
  2017-12-15 22:35   ` Rob Herring
       [not found] ` <1513081897-31612-1-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel

From: Rajendra Nayak <rnayak@codeaurora.org>

Each of the CPU clusters (Power and Perf) on msm8996 are
clocked via 2 PLLs, a primary and alternate. There are also
2 Mux'es, a primary and secondary all connected together
as shown below

                             +-------+
              XO             |       |
          +------------------>0      |
                             |       |
                   PLL/2     | SMUX  +----+
                     +------->1      |    |
                     |       |       |    |
                     |       +-------+    |    +-------+
                     |                    +---->0      |
                     |                         |       |
+---------------+    |             +----------->1      | CPU clk
|Primary PLL    +----+ PLL_EARLY   |           |       +------>
|               +------+-----------+    +------>2 PMUX |
+---------------+      |                |      |       |
                       |   +------+     |   +-->3      |
                       +--^+  ACD +-----+   |  +-------+
+---------------+          +------+         |
|Alt PLL        |                           |
|               +---------------------------+
+---------------+         PLL_EARLY

The primary PLL is what drives the CPU clk, except for times
when we are reprogramming the PLL itself (for rate changes) when
we temporarily switch to an alternate PLL. A subsequent patch adds
support to switch between primary and alternate PLL during rate
changes.

The primary PLL operates on a single VCO range, between 600Mhz
and 3Ghz. However the CPUs do support OPPs with frequencies
between 300Mhz and 600Mhz. In order to support running the CPUs
at those frequencies we end up having to lock the PLL at twice
the rate and drive the CPU clk via the PLL/2 output and SMUX.

So for frequencies above 600Mhz we follow the following path
 Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk
and for frequencies between 300Mhz and 600Mhz we follow
 Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk
Support for this is added in a subsequent patch as well.

ACD stands for Adaptive Clock Distribution and is used to
detect voltage droops. We do not add support for ACD as yet.
This can be added at a later point as needed.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 .../devicetree/bindings/clock/qcom,kryocc.txt      |  17 +
 drivers/clk/qcom/Kconfig                           |   8 +
 drivers/clk/qcom/Makefile                          |   1 +
 drivers/clk/qcom/clk-cpu-8996.c                    | 388 +++++++++++++++++++++
 4 files changed, 414 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index 0000000..c45de03
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
@@ -0,0 +1,17 @@
+Qualcomm CPUSS clock controller for Kryo CPUs
+----------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+			"qcom,apcc-msm8996"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+	kryocc: clock-controller@6400000 {
+		compatible = "qcom,apcc-msm8996";
+		reg = <0x6400000 0x90000>;
+		#clock-cells = <1>;
+	};
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 9f6c278..124fb9a4 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -196,3 +196,11 @@ config MSM_MMCC_8996
 	  Support for the multimedia clock controller on msm8996 devices.
 	  Say Y if you want to support multimedia devices such as display,
 	  graphics, video encode/decode, camera, etc.
+
+config MSM_APCC_8996
+	tristate "MSM8996 CPU Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the CPU clock controller on msm8996 devices.
+	  Say Y if you want to support CPU clock scaling using CPUfreq
+	  drivers for dyanmic power management.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 26410d3..b964f43 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -32,5 +32,6 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
 obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
+obj-$(CONFIG_MSM_APCC_8996) += clk-cpu-8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
new file mode 100644
index 0000000..bc60111
--- /dev/null
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "clk-alpha-pll.h"
+
+#define VCO(a, b, c) { \
+	.val = a,\
+	.min_freq = b,\
+	.max_freq = c,\
+}
+
+#define DIV_2_INDEX		0
+#define PLL_INDEX		1
+#define ACD_INDEX		2
+#define ALT_INDEX		3
+
+/* PLLs */
+
+static const struct alpha_pll_config hfpll_config = {
+	.l = 60,
+	.config_ctl_val = 0x200d4828,
+	.config_ctl_hi_val = 0x006,
+	.pre_div_mask = BIT(12),
+	.post_div_mask = 0x3 << 8,
+	.main_output_mask = BIT(0),
+	.early_output_mask = BIT(3),
+};
+
+static struct clk_alpha_pll perfcl_pll = {
+	.offset = 0x80000,
+	.min_rate = 600000000,
+	.max_rate = 3000000000,
+	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_16BIT_ALPHA
+			| SUPPORTS_FSM_MODE,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "perfcl_pll",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_hwfsm_ops,
+	},
+};
+
+static struct clk_alpha_pll pwrcl_pll = {
+	.offset = 0x0,
+	.min_rate = 600000000,
+	.max_rate = 3000000000,
+	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_16BIT_ALPHA
+			| SUPPORTS_FSM_MODE,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pwrcl_pll",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_hwfsm_ops,
+	},
+};
+
+static const struct pll_vco alt_pll_vco_modes[] = {
+	VCO(3,  250000000,  500000000),
+	VCO(2,  500000000,  750000000),
+	VCO(1,  750000000, 1000000000),
+	VCO(0, 1000000000, 2150400000),
+};
+
+static const struct alpha_pll_config altpll_config = {
+	.l = 16,
+	.vco_val = 0x3 << 20,
+	.vco_mask = 0x3 << 20,
+	.config_ctl_val = 0x4001051b,
+	.post_div_mask = 0x3 << 8,
+	.post_div_val = 0x1,
+	.main_output_mask = BIT(0),
+	.early_output_mask = BIT(3),
+};
+
+static struct clk_alpha_pll perfcl_alt_pll = {
+	.offset = 0x80100,
+	.vco_table = alt_pll_vco_modes,
+	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
+	.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "perfcl_alt_pll",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_hwfsm_ops,
+	},
+};
+
+static struct clk_alpha_pll pwrcl_alt_pll = {
+	.offset = 0x100,
+	.vco_table = alt_pll_vco_modes,
+	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
+	.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "pwrcl_alt_pll",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_hwfsm_ops,
+	},
+};
+
+/* Mux'es */
+
+struct clk_cpu_8996_mux {
+	u32	reg;
+	u32	shift;
+	u32	width;
+	struct clk_hw	*pll;
+	struct clk_regmap clkr;
+};
+
+static inline
+struct clk_cpu_8996_mux *to_clk_cpu_8996_mux_hw(struct clk_hw *hw)
+{
+	return container_of(to_clk_regmap(hw), struct clk_cpu_8996_mux, clkr);
+}
+
+static u8 clk_cpu_8996_mux_get_parent(struct clk_hw *hw)
+{
+	unsigned int val;
+	struct clk_regmap *clkr = to_clk_regmap(hw);
+	struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
+	unsigned int mask = GENMASK(cpuclk->width - 1, 0);
+
+	regmap_read(clkr->regmap, cpuclk->reg, &val);
+
+	val >>= cpuclk->shift;
+	val &= mask;
+
+	return val;
+}
+
+static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	unsigned int val;
+	struct clk_regmap *clkr = to_clk_regmap(hw);
+	struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
+	unsigned int mask = GENMASK(cpuclk->width + cpuclk->shift - 1,
+				    cpuclk->shift);
+
+	val = index;
+	val = cpuclk->shift;
+
+	return regmap_update_bits(clkr->regmap, cpuclk->reg, mask, val);
+}
+
+static int
+clk_cpu_8996_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+	struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
+	struct clk_hw *parent = cpuclk->pll;
+
+	if (!cpuclk->pll)
+		return -EINVAL;
+
+	req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
+	req->best_parent_hw = parent;
+
+	return 0;
+}
+
+const struct clk_ops clk_cpu_8996_mux_ops = {
+	.set_parent = clk_cpu_8996_mux_set_parent,
+	.get_parent = clk_cpu_8996_mux_get_parent,
+	.determine_rate = clk_cpu_8996_mux_determine_rate,
+};
+
+static struct clk_cpu_8996_mux pwrcl_smux = {
+	.reg = 0x40,
+	.shift = 2,
+	.width = 2,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "pwrcl_smux",
+		.parent_names = (const char *[]){
+			"xo",
+			"pwrcl_pll_main",
+		},
+		.num_parents = 2,
+		.ops = &clk_cpu_8996_mux_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_cpu_8996_mux perfcl_smux = {
+	.reg = 0x80040,
+	.shift = 2,
+	.width = 2,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "perfcl_smux",
+		.parent_names = (const char *[]){
+			"xo",
+			"perfcl_pll_main",
+		},
+		.num_parents = 2,
+		.ops = &clk_cpu_8996_mux_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_cpu_8996_mux pwrcl_pmux = {
+	.reg = 0x40,
+	.shift = 0,
+	.width = 2,
+	.pll = &pwrcl_pll.clkr.hw,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "pwrcl_pmux",
+		.parent_names = (const char *[]){
+			"pwrcl_smux",
+			"pwrcl_pll",
+			"pwrcl_pll_acd",
+			"pwrcl_alt_pll",
+		},
+		.num_parents = 4,
+		.ops = &clk_cpu_8996_mux_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_cpu_8996_mux perfcl_pmux = {
+	.reg = 0x80040,
+	.shift = 0,
+	.width = 2,
+	.pll = &perfcl_pll.clkr.hw,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "perfcl_pmux",
+		.parent_names = (const char *[]){
+			"perfcl_smux",
+			"perfcl_pll",
+			"pwrcl_pll_acd",
+			"perfcl_alt_pll",
+		},
+		.num_parents = 4,
+		.ops = &clk_cpu_8996_mux_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct regmap_config cpu_msm8996_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= 0x80210,
+	.fast_io		= true,
+	.val_format_endian	= REGMAP_ENDIAN_LITTLE,
+};
+
+static const struct of_device_id match_table[] = {
+	{ .compatible = "qcom,apcc-msm8996" },
+	{}
+};
+
+struct clk_regmap *clks[] = {
+	/* PLLs */
+	&perfcl_pll.clkr,
+	&pwrcl_pll.clkr,
+	&perfcl_alt_pll.clkr,
+	&pwrcl_alt_pll.clkr,
+	/* MUXs */
+	&perfcl_smux.clkr,
+	&pwrcl_smux.clkr,
+	&perfcl_pmux.clkr,
+	&pwrcl_pmux.clkr,
+};
+
+struct clk_hw_clks {
+	unsigned int num;
+	struct clk_hw *hws[];
+};
+
+static int
+qcom_cpu_clk_msm8996_register_clks(struct device *dev, struct clk_hw_clks *hws,
+				   struct regmap *regmap)
+{
+	int i, ret;
+
+	hws->hws[0] = clk_hw_register_fixed_factor(dev, "perfcl_pll_main",
+						   "perfcl_pll",
+						   CLK_SET_RATE_PARENT, 1, 2);
+	perfcl_smux.pll = hws->hws[0];
+
+	hws->hws[1] = clk_hw_register_fixed_factor(dev, "pwrcl_pll_main",
+						   "pwrcl_pll",
+						   CLK_SET_RATE_PARENT, 1, 2);
+	pwrcl_smux.pll = hws->hws[1];
+
+	hws->num = 2;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++) {
+		ret = devm_clk_register_regmap(dev, clks[i]);
+		if (ret)
+			return ret;
+	}
+
+	clk_alpha_pll_configure(&perfcl_pll, regmap, &hfpll_config);
+	clk_alpha_pll_configure(&pwrcl_pll, regmap, &hfpll_config);
+	clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
+	clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
+
+	return ret;
+}
+
+static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
+{
+	int ret;
+	void __iomem *base;
+	struct resource *res;
+	struct regmap *regmap_cpu;
+	struct clk_hw_clks *hws;
+	struct clk_hw_onecell_data *data;
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+
+	data = devm_kzalloc(dev, sizeof(*data) + 2 * sizeof(struct clk_hw *),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	hws = devm_kzalloc(dev, sizeof(*hws) + 2 * sizeof(struct clk_hw *),
+			   GFP_KERNEL);
+	if (!hws)
+		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_cpu = devm_regmap_init_mmio(dev, base,
+					   &cpu_msm8996_regmap_config);
+	if (IS_ERR(regmap_cpu))
+		return PTR_ERR(regmap_cpu);
+
+	ret = qcom_cpu_clk_msm8996_register_clks(dev, hws, regmap_cpu);
+	if (ret)
+		return ret;
+
+	data->hws[0] = &pwrcl_pmux.clkr.hw;
+	data->hws[1] = &perfcl_pmux.clkr.hw;
+
+	data->num = 2;
+
+	platform_set_drvdata(pdev, hws);
+
+	return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data);
+}
+
+static int qcom_cpu_clk_msm8996_driver_remove(struct platform_device *pdev)
+{
+	int i;
+	struct device *dev = &pdev->dev;
+	struct clk_hw_clks *hws = platform_get_drvdata(pdev);
+
+	for (i = 0; i < hws->num; i++)
+		clk_hw_unregister_fixed_rate(hws->hws[i]);
+
+	of_clk_del_provider(dev->of_node);
+
+	return 0;
+}
+
+static struct platform_driver qcom_cpu_clk_msm8996_driver = {
+	.probe = qcom_cpu_clk_msm8996_driver_probe,
+	.remove = qcom_cpu_clk_msm8996_driver_remove,
+	.driver = {
+		.name = "qcom-apcc-msm8996",
+		.of_match_table = match_table,
+	},
+};
+
+module_platform_driver(qcom_cpu_clk_msm8996_driver);
+
+MODULE_ALIAS("platform:apcc-msm8996");
+MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
       [not found] ` <1513081897-31612-1-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2017-12-12 12:31   ` Ilia Lin
  2017-12-12 12:31   ` [PATCH 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz Ilia Lin
  2017-12-12 12:31   ` [PATCH 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996 Ilia Lin
  2 siblings, 0 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
	qualcomm-lt-cunTk1MwBs8s++Sfvej+rw,
	ilialin-sgV2jX0FEOL9JmXXK+q4OQ, celster-sgV2jX0FEOL9JmXXK+q4OQ,
	tfinkel-sgV2jX0FEOL9JmXXK+q4OQ

From: Rajendra Nayak <rnayak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Each of the CPU clusters on msm8996 and powered via a primary
PLL and a secondary PLL. The primary PLL is what drivers the
CPU clk, except for times when we are reprogramming the PLL
itself, when we temporarily switch to an alternate PLL.
Use clock rate change notifiers to support this.

Signed-off-by: Rajendra Nayak <rnayak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Ilia Lin <ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index bc60111..9bb25be 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -119,10 +119,14 @@ struct clk_cpu_8996_mux {
 	u32	reg;
 	u32	shift;
 	u32	width;
+	struct notifier_block nb;
 	struct clk_hw	*pll;
 	struct clk_regmap clkr;
 };
 
+#define to_clk_cpu_8996_mux_nb(_nb) \
+	container_of(_nb, struct clk_cpu_8996_mux, nb)
+
 static inline
 struct clk_cpu_8996_mux *to_clk_cpu_8996_mux_hw(struct clk_hw *hw)
 {
@@ -173,6 +177,27 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
 	return 0;
 }
 
+int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
+			void *data)
+{
+	int ret;
+	struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_nb(nb);
+
+	switch (event) {
+	case PRE_RATE_CHANGE:
+		ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, ALT_INDEX);
+		break;
+	case POST_RATE_CHANGE:
+		ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, PLL_INDEX);
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	return notifier_from_errno(ret);
+};
+
 const struct clk_ops clk_cpu_8996_mux_ops = {
 	.set_parent = clk_cpu_8996_mux_set_parent,
 	.get_parent = clk_cpu_8996_mux_get_parent,
@@ -216,6 +241,7 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
 	.shift = 0,
 	.width = 2,
 	.pll = &pwrcl_pll.clkr.hw,
+	.nb.notifier_call = cpu_clk_notifier_cb,
 	.clkr.hw.init = &(struct clk_init_data) {
 		.name = "pwrcl_pmux",
 		.parent_names = (const char *[]){
@@ -235,6 +261,7 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
 	.shift = 0,
 	.width = 2,
 	.pll = &perfcl_pll.clkr.hw,
+	.nb.notifier_call = cpu_clk_notifier_cb,
 	.clkr.hw.init = &(struct clk_init_data) {
 		.name = "perfcl_pmux",
 		.parent_names = (const char *[]){
@@ -310,6 +337,14 @@ struct clk_hw_clks {
 	clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
 	clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
 
+	ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
+	if (ret)
+		return ret;
+
+	ret = clk_notifier_register(perfcl_pmux.clkr.hw.clk, &perfcl_pmux.nb);
+	if (ret)
+		return ret;
+
 	return ret;
 }
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz
       [not found] ` <1513081897-31612-1-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2017-12-12 12:31   ` [PATCH 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL Ilia Lin
@ 2017-12-12 12:31   ` Ilia Lin
  2017-12-12 12:31   ` [PATCH 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996 Ilia Lin
  2 siblings, 0 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
	qualcomm-lt-cunTk1MwBs8s++Sfvej+rw,
	ilialin-sgV2jX0FEOL9JmXXK+q4OQ, celster-sgV2jX0FEOL9JmXXK+q4OQ,
	tfinkel-sgV2jX0FEOL9JmXXK+q4OQ

From: Rajendra Nayak <rnayak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

The CPU clock controllers primary PLL operates on a single VCO range,
between 600Mhz and 3Ghz. However the CPUs do support OPPs with
frequencies between 300Mhz and 600Mhz. In order to support running the
CPUs at those frequencies we end up having to lock the PLL at twice the
rate and drive the CPU clk via the PLL/2 output and SMUX.

So for frequencies above 600Mhz we follow the following path
 Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk
and for frequencies between 300Mhz and 600Mhz we follow
 Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk

Signed-off-by: Rajendra Nayak <rnayak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Ilia Lin <ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 9bb25be..79db4e8 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -28,6 +28,7 @@
 #define PLL_INDEX		1
 #define ACD_INDEX		2
 #define ALT_INDEX		3
+#define DIV_2_THRESHOLD		600000000
 
 /* PLLs */
 
@@ -121,6 +122,7 @@ struct clk_cpu_8996_mux {
 	u32	width;
 	struct notifier_block nb;
 	struct clk_hw	*pll;
+	struct clk_hw	*pll_div_2;
 	struct clk_regmap clkr;
 };
 
@@ -171,6 +173,13 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (!cpuclk->pll)
 		return -EINVAL;
 
+	if (cpuclk->pll_div_2 && req->rate < DIV_2_THRESHOLD) {
+		if (req->rate < (DIV_2_THRESHOLD / 2))
+			return -EINVAL;
+
+		parent = cpuclk->pll_div_2;
+	}
+
 	req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
 	req->best_parent_hw = parent;
 
@@ -182,13 +191,19 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 {
 	int ret;
 	struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_nb(nb);
+	struct clk_notifier_data *cnd = data;
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
 		ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, ALT_INDEX);
 		break;
 	case POST_RATE_CHANGE:
-		ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, PLL_INDEX);
+		if (cnd->new_rate < DIV_2_THRESHOLD)
+			ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
+							  DIV_2_INDEX);
+		else
+			ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
+							  PLL_INDEX);
 		break;
 	default:
 		ret = 0;
@@ -241,6 +256,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 	.shift = 0,
 	.width = 2,
 	.pll = &pwrcl_pll.clkr.hw,
+	.pll_div_2 = &pwrcl_smux.clkr.hw,
 	.nb.notifier_call = cpu_clk_notifier_cb,
 	.clkr.hw.init = &(struct clk_init_data) {
 		.name = "pwrcl_pmux",
@@ -261,6 +277,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 	.shift = 0,
 	.width = 2,
 	.pll = &perfcl_pll.clkr.hw,
+	.pll_div_2 = &perfcl_smux.clkr.hw,
 	.nb.notifier_call = cpu_clk_notifier_cb,
 	.clkr.hw.init = &(struct clk_init_data) {
 		.name = "perfcl_pmux",
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
  2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
                   ` (4 preceding siblings ...)
       [not found] ` <1513081897-31612-1-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2017-12-12 12:31 ` Ilia Lin
  2017-12-12 12:31 ` [PATCH 09/10] DT: QCOM: Add cpufreq-dt to msm8996 Ilia Lin
  2017-12-12 12:31 ` [PATCH 10/10] DT: QCOM: Add thermal mitigation " Ilia Lin
  7 siblings, 0 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel

The PLLs must be prepared enabled during the probe to be
accessible by the OPPs. Otherwise an OPP may switch
to non-enabled clock.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 79db4e8..0d41fa9 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
-
+#include <linux/clk-provider.h>
 #include "clk-alpha-pll.h"
 
 #define VCO(a, b, c) { \
@@ -159,7 +159,7 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
 				    cpuclk->shift);
 
 	val = index;
-	val = cpuclk->shift;
+	val <<= cpuclk->shift;
 
 	return regmap_update_bits(clkr->regmap, cpuclk->reg, mask, val);
 }
@@ -268,7 +268,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 		},
 		.num_parents = 4,
 		.ops = &clk_cpu_8996_mux_ops,
-		.flags = CLK_SET_RATE_PARENT,
+		.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 	},
 };
 
@@ -284,12 +284,12 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 		.parent_names = (const char *[]){
 			"perfcl_smux",
 			"perfcl_pll",
-			"pwrcl_pll_acd",
+			"perfcl_pll_acd",
 			"perfcl_alt_pll",
 		},
 		.num_parents = 4,
 		.ops = &clk_cpu_8996_mux_ops,
-		.flags = CLK_SET_RATE_PARENT,
+		.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 	},
 };
 
@@ -354,6 +354,18 @@ struct clk_hw_clks {
 	clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
 	clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
 
+	/* Enable all PLLs and alt PLLs */
+	clk_prepare_enable(pwrcl_alt_pll.clkr.hw.clk);
+	clk_prepare_enable(perfcl_alt_pll.clkr.hw.clk);
+	clk_prepare_enable(pwrcl_pll.clkr.hw.clk);
+	clk_prepare_enable(perfcl_pll.clkr.hw.clk);
+
+	/* Set initial boot frequencies for power/perf PLLs */
+	clk_set_rate(pwrcl_alt_pll.clkr.hw.clk, 652800000);
+	clk_set_rate(perfcl_alt_pll.clkr.hw.clk, 652800000);
+	clk_set_rate(pwrcl_pll.clkr.hw.clk, 652800000);
+	clk_set_rate(perfcl_pll.clkr.hw.clk, 652800000);
+
 	ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
 	if (ret)
 		return ret;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
       [not found] ` <1513081897-31612-1-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2017-12-12 12:31   ` [PATCH 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL Ilia Lin
  2017-12-12 12:31   ` [PATCH 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz Ilia Lin
@ 2017-12-12 12:31   ` Ilia Lin
  2 siblings, 0 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
	qualcomm-lt-cunTk1MwBs8s++Sfvej+rw,
	ilialin-sgV2jX0FEOL9JmXXK+q4OQ, celster-sgV2jX0FEOL9JmXXK+q4OQ,
	tfinkel-sgV2jX0FEOL9JmXXK+q4OQ

The PMUX for each duplex allows for selection of ACD clock source.
The DVM (Dynamic Variation Monitor) will flag an error
when a voltage droop event is detected. This flagged error
enables ACD to provide a div-by-2 clock, sourced from the primary PLL.
The duplex will be provided the divided clock
until a pre-programmed delay has expired.

This change configures ACD during the probe and switches
the PMUXes to the ACD clock source.

Signed-off-by: Ilia Lin <ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 122 ++++++++++++++++++++++++++++++++++------
 1 file changed, 106 insertions(+), 16 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 0d41fa9..6f89471 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -17,6 +17,7 @@
 #include <linux/regmap.h>
 #include <linux/clk-provider.h>
 #include "clk-alpha-pll.h"
+#include <soc/qcom/kryo-l2-accessors.h>
 
 #define VCO(a, b, c) { \
 	.val = a,\
@@ -29,6 +30,27 @@
 #define ACD_INDEX		2
 #define ALT_INDEX		3
 #define DIV_2_THRESHOLD		600000000
+#define PWRCL_REG_OFFSET 0x0
+#define PERFCL_REG_OFFSET 0x80000
+#define MUX_OFFSET	0x40
+#define ALT_PLL_OFFSET	0x100
+#define SSSCTL_OFFSET 0x160
+/*
+APCy_QLL_SSSCTL value:
+SACDRCLEN=1
+SSWEN=1
+SSTRTEN=1
+SSTPAPMSWEN=1
+*/
+#define SSSCTL_VAL 0xF
+
+enum {
+	APC_BASE,
+	EFUSE_BASE,
+	NUM_BASES
+};
+
+static void __iomem *vbases[NUM_BASES];
 
 /* PLLs */
 
@@ -43,7 +65,7 @@
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-	.offset = 0x80000,
+	.offset = PERFCL_REG_OFFSET,
 	.min_rate = 600000000,
 	.max_rate = 3000000000,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_16BIT_ALPHA
@@ -57,7 +79,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_pll = {
-	.offset = 0x0,
+	.offset = PWRCL_REG_OFFSET,
 	.min_rate = 600000000,
 	.max_rate = 3000000000,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_16BIT_ALPHA
@@ -89,7 +111,7 @@
 };
 
 static struct clk_alpha_pll perfcl_alt_pll = {
-	.offset = 0x80100,
+	.offset = PERFCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
 	.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
@@ -102,7 +124,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_alt_pll = {
-	.offset = 0x100,
+	.offset = PWRCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
 	.flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
@@ -113,6 +135,7 @@
 		.ops = &clk_alpha_pll_hwfsm_ops,
 	},
 };
+static void qcom_cpu_clk_msm8996_acd_init(void);
 
 /* Mux'es */
 
@@ -196,6 +219,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 	switch (event) {
 	case PRE_RATE_CHANGE:
 		ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, ALT_INDEX);
+		qcom_cpu_clk_msm8996_acd_init();
 		break;
 	case POST_RATE_CHANGE:
 		if (cnd->new_rate < DIV_2_THRESHOLD)
@@ -203,7 +227,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 							  DIV_2_INDEX);
 		else
 			ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
-							  PLL_INDEX);
+							  ACD_INDEX);
 		break;
 	default:
 		ret = 0;
@@ -220,7 +244,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux pwrcl_smux = {
-	.reg = 0x40,
+	.reg = PWRCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 2,
 	.width = 2,
 	.clkr.hw.init = &(struct clk_init_data) {
@@ -236,7 +260,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux perfcl_smux = {
-	.reg = 0x80040,
+	.reg = PERFCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 2,
 	.width = 2,
 	.clkr.hw.init = &(struct clk_init_data) {
@@ -252,7 +276,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux pwrcl_pmux = {
-	.reg = 0x40,
+	.reg = PWRCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 0,
 	.width = 2,
 	.pll = &pwrcl_pll.clkr.hw,
@@ -273,7 +297,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 };
 
 static struct clk_cpu_8996_mux perfcl_pmux = {
-	.reg = 0x80040,
+	.reg = PERFCL_REG_OFFSET + MUX_OFFSET,
 	.shift = 0,
 	.width = 2,
 	.pll = &perfcl_pll.clkr.hw,
@@ -341,7 +365,17 @@ struct clk_hw_clks {
 						   CLK_SET_RATE_PARENT, 1, 2);
 	pwrcl_smux.pll = hws->hws[1];
 
-	hws->num = 2;
+	hws->hws[2] = clk_hw_register_fixed_factor(dev, "perfcl_pll_acd",
+						   "perfcl_pll",
+						   CLK_SET_RATE_PARENT, 1, 1);
+	perfcl_pmux.pll = hws->hws[2];
+
+	hws->hws[3] = clk_hw_register_fixed_factor(dev, "pwrcl_pll_acd",
+						   "pwrcl_pll",
+						   CLK_SET_RATE_PARENT, 1, 1);
+	pwrcl_pmux.pll = hws->hws[3];
+
+	hws->num = 4;
 
 	for (i = 0; i < ARRAY_SIZE(clks); i++) {
 		ret = devm_clk_register_regmap(dev, clks[i]);
@@ -377,10 +411,65 @@ struct clk_hw_clks {
 	return ret;
 }
 
+#define CPU_AFINITY_MASK 0xFFF
+#define PWRCL_CPU_REG_MASK 0x3
+#define PERFCL_CPU_REG_MASK 0x103
+
+/* ACD static settings (HMSS HPG 7.2.2) */
+#define L2ACDCR_REG 0x580ULL
+#define L2ACDTD_REG 0x581ULL
+#define L2ACDDVMRC_REG 0x584ULL
+#define L2ACDSSCR_REG 0x589ULL
+#define ACDTD_VAL 0x00006A11
+#define ACDCR_VAL 0x002C5FFD
+#define ACDSSCR_VAL 0x00000601
+#define ACDDVMRC_VAL 0x000E0F0F
+
+static DEFINE_SPINLOCK(acd_lock);
+
+static void qcom_cpu_clk_msm8996_acd_init(void)
+{
+	u64 hwid;
+	unsigned long flags;
+
+	spin_lock_irqsave(&acd_lock, flags);
+
+	hwid = read_cpuid_mpidr() & CPU_AFINITY_MASK;
+
+	/* Program ACD Tunable-Length Delay (TLD) */
+	set_l2_indirect_reg(L2ACDTD_REG, ACDTD_VAL);
+	/* Initial ACD for *this* cluster */
+	set_l2_indirect_reg(L2ACDDVMRC_REG, ACDDVMRC_VAL);
+	/* Program ACD soft start control bits. */
+	set_l2_indirect_reg(L2ACDSSCR_REG, ACDSSCR_VAL);
+
+	if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
+		/* Enable Soft Stop/Start */
+		if (vbases[APC_BASE])
+			writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
+					PWRCL_REG_OFFSET + SSSCTL_OFFSET);
+		/* Ensure SSSCTL config goes through before enabling ACD. */
+		mb();
+		/* Program ACD control bits */
+		set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
+	}
+	if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) { //else {
+		/* Program ACD control bits */
+		set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
+		/* Enable Soft Stop/Start */
+		if (vbases[APC_BASE])
+			writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
+					PERFCL_REG_OFFSET + SSSCTL_OFFSET);
+		/* Ensure SSSCTL config goes through before enabling ACD. */
+		mb();
+	}
+
+	spin_unlock_irqrestore(&acd_lock, flags);
+}
+
 static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 {
 	int ret;
-	void __iomem *base;
 	struct resource *res;
 	struct regmap *regmap_cpu;
 	struct clk_hw_clks *hws;
@@ -393,17 +482,17 @@ static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 	if (!data)
 		return -ENOMEM;
 
-	hws = devm_kzalloc(dev, sizeof(*hws) + 2 * sizeof(struct clk_hw *),
+	hws = devm_kzalloc(dev, sizeof(*hws) + 4 * sizeof(struct clk_hw *),
 			   GFP_KERNEL);
 	if (!hws)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+	vbases[APC_BASE] = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vbases[APC_BASE]))
+		return PTR_ERR(vbases[APC_BASE]);
 
-	regmap_cpu = devm_regmap_init_mmio(dev, base,
+	regmap_cpu = devm_regmap_init_mmio(dev, vbases[APC_BASE],
 					   &cpu_msm8996_regmap_config);
 	if (IS_ERR(regmap_cpu))
 		return PTR_ERR(regmap_cpu);
@@ -411,6 +500,7 @@ static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 	ret = qcom_cpu_clk_msm8996_register_clks(dev, hws, regmap_cpu);
 	if (ret)
 		return ret;
+	qcom_cpu_clk_msm8996_acd_init();
 
 	data->hws[0] = &pwrcl_pmux.clkr.hw;
 	data->hws[1] = &perfcl_pmux.clkr.hw;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 09/10] DT: QCOM: Add cpufreq-dt to msm8996
  2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
                   ` (5 preceding siblings ...)
  2017-12-12 12:31 ` [PATCH 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe Ilia Lin
@ 2017-12-12 12:31 ` Ilia Lin
  2017-12-12 12:31 ` [PATCH 10/10] DT: QCOM: Add thermal mitigation " Ilia Lin
  7 siblings, 0 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel

Add device tree frequency table for the MSM8996 to be
used by the upstream cpufreq-dt driver with the clk-cpu-8996
driver as infrastructure.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi       | 184 ++++++++++++++++++++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c        |   3 +
 3 files changed, 188 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..da23bda 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -17,5 +17,5 @@
 
 / {
 	model = "Qualcomm Technologies, Inc. DB820c";
-	compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc";
+	compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096";
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 4b2afcc..8beea7e 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -86,6 +86,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x0>;
 			enable-method = "psci";
+			clocks = <&kryocc 0>;
+			operating-points-v2 = <&cluster0_opp>;
 			next-level-cache = <&L2_0>;
 			L2_0: l2-cache {
 			      compatible = "cache";
@@ -98,6 +100,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x1>;
 			enable-method = "psci";
+			clocks = <&kryocc 0>;
+			operating-points-v2 = <&cluster0_opp>;
 			next-level-cache = <&L2_0>;
 		};
 
@@ -106,6 +110,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x100>;
 			enable-method = "psci";
+			clocks = <&kryocc 1>;
+			operating-points-v2 = <&cluster1_opp>;
 			next-level-cache = <&L2_1>;
 			L2_1: l2-cache {
 			      compatible = "cache";
@@ -118,6 +124,8 @@
 			compatible = "qcom,kryo";
 			reg = <0x0 0x101>;
 			enable-method = "psci";
+			clocks = <&kryocc 1>;
+			operating-points-v2 = <&cluster1_opp>;
 			next-level-cache = <&L2_1>;
 		};
 
@@ -144,6 +152,182 @@
 		};
 	};
 
+	cluster0_opp: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@307200000 {
+			opp-hz = /bits/ 64 <  307200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@422400000 {
+			opp-hz = /bits/ 64 <  422400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@480000000 {
+			opp-hz = /bits/ 64 <  480000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@556800000 {
+			opp-hz = /bits/ 64 <  556800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@652800000 {
+			opp-hz = /bits/ 64 <  652800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@729600000 {
+			opp-hz = /bits/ 64 <  729600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@844800000 {
+			opp-hz = /bits/ 64 <  844800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@960000000 {
+			opp-hz = /bits/ 64 <  960000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1036800000 {
+			opp-hz = /bits/ 64 < 1036800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1113600000 {
+			opp-hz = /bits/ 64 < 1113600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1190400000 {
+			opp-hz = /bits/ 64 < 1190400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1228800000 {
+			opp-hz = /bits/ 64 < 1228800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1324800000 {
+			opp-hz = /bits/ 64 < 1324800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1401600000 {
+			opp-hz = /bits/ 64 < 1401600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1478400000 {
+			opp-hz = /bits/ 64 < 1478400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1593600000 {
+			opp-hz = /bits/ 64 < 1593600000 >;
+			clock-latency-ns = <200000>;
+		};
+	};
+
+	cluster1_opp: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@307200000 {
+			opp-hz = /bits/ 64 <  307200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@403200000 {
+			opp-hz = /bits/ 64 <  403200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@480000000 {
+			opp-hz = /bits/ 64 <  480000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@556800000 {
+			opp-hz = /bits/ 64 <  556800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@652800000 {
+			opp-hz = /bits/ 64 <  652800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@729600000 {
+			opp-hz = /bits/ 64 <  729600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@806400000 {
+			opp-hz = /bits/ 64 <  806400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@883200000 {
+			opp-hz = /bits/ 64 <  883200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@940800000 {
+			opp-hz = /bits/ 64 <  940800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1036800000 {
+			opp-hz = /bits/ 64 < 1036800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1113600000 {
+			opp-hz = /bits/ 64 < 1113600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1190400000 {
+			opp-hz = /bits/ 64 < 1190400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1248000000 {
+			opp-hz = /bits/ 64 < 1248000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1324800000 {
+			opp-hz = /bits/ 64 < 1324800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1401600000 {
+			opp-hz = /bits/ 64 < 1401600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1478400000 {
+			opp-hz = /bits/ 64 < 1478400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1552000000 {
+			opp-hz = /bits/ 64 < 1552000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1632000000 {
+			opp-hz = /bits/ 64 < 1632000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1708800000 {
+			opp-hz = /bits/ 64 < 1708800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1785600000 {
+			opp-hz = /bits/ 64 < 1785600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1824000000 {
+			opp-hz = /bits/ 64 < 1824000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1920000000 {
+			opp-hz = /bits/ 64 < 1920000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@1996800000 {
+			opp-hz = /bits/ 64 < 1996800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@2073600000 {
+			opp-hz = /bits/ 64 < 2073600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp@2150400000 {
+			opp-hz = /bits/ 64 < 2150400000 >;
+			clock-latency-ns = <200000>;
+		};
+
+	};
 	thermal-zones {
 		cpu-thermal0 {
 			polling-delay-passive = <250>;
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index ecc56e2..0feca0e 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -95,6 +95,9 @@
 	{ .compatible = "xlnx,zynq-7000", },
 	{ .compatible = "xlnx,zynqmp", },
 
+	{ .compatible = "qcom,msm8996", },
+	{ .compatible = "qcom,apq8096", },
+
 	{ }
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 10/10] DT: QCOM: Add thermal mitigation to msm8996
  2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
                   ` (6 preceding siblings ...)
  2017-12-12 12:31 ` [PATCH 09/10] DT: QCOM: Add cpufreq-dt to msm8996 Ilia Lin
@ 2017-12-12 12:31 ` Ilia Lin
  7 siblings, 0 replies; 19+ messages in thread
From: Ilia Lin @ 2017-12-12 12:31 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, mark.rutland, will.deacon, rnayak, qualcomm-lt,
	ilialin, celster, tfinkel

Add thermal mitigation configuration to msm8996.
With the cpufreq-dt OPP table the CPU frequency may be
scaled and therefore throttled by the thermal config.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 98 +++++++++++++++++++++++++++++++----
 1 file changed, 87 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 8beea7e..6fa061f 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -14,6 +14,7 @@
 #include <dt-bindings/clock/qcom,gcc-msm8996.h>
 #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
 #include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8996";
@@ -88,6 +89,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 0>;
 			operating-points-v2 = <&cluster0_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_0>;
 			L2_0: l2-cache {
 			      compatible = "cache";
@@ -102,6 +107,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 0>;
 			operating-points-v2 = <&cluster0_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_0>;
 		};
 
@@ -112,6 +121,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 1>;
 			operating-points-v2 = <&cluster1_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_1>;
 			L2_1: l2-cache {
 			      compatible = "cache";
@@ -126,6 +139,10 @@
 			enable-method = "psci";
 			clocks = <&kryocc 1>;
 			operating-points-v2 = <&cluster1_opp>;
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <15>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_1>;
 		};
 
@@ -336,18 +353,33 @@
 			thermal-sensors = <&tsens0 3>;
 
 			trips {
-				cpu_alert0: trip0 {
+				cpu_alert0: cpu_alert0 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn0: cpu_warn0 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				cpu_crit0: trip1 {
+				cpu_crit0: cpu_crit0 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device = <&CPU0 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn0>;
+					cooling-device = <&CPU0 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 
 		cpu-thermal1 {
@@ -357,18 +389,33 @@
 			thermal-sensors = <&tsens0 5>;
 
 			trips {
-				cpu_alert1: trip0 {
+				cpu_alert1: cpu_alert1 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn1: cpu_warn1 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				cpu_crit1: trip1 {
+				cpu_crit1: cpu_crit1 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert1>;
+					cooling-device = <&CPU0 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn1>;
+					cooling-device = <&CPU0 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 
 		cpu-thermal2 {
@@ -378,18 +425,32 @@
 			thermal-sensors = <&tsens0 8>;
 
 			trips {
-				cpu_alert2: trip0 {
+				cpu_alert2: cpu_alert2 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn2: cpu_warn2 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				cpu_crit2: trip1 {
+				cpu_crit2: cpu_crit2 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert2>;
+					cooling-device = <&CPU2 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn2>;
+					cooling-device = <&CPU2 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 
 		cpu-thermal3 {
@@ -399,18 +460,33 @@
 			thermal-sensors = <&tsens0 10>;
 
 			trips {
-				cpu_alert3: trip0 {
+				cpu_alert3: cpu_alert3 {
 					temperature = <75000>;
 					hysteresis = <2000>;
+					type = "active";
+				};
+				cpu_warn3: cpu_warn3 {
+					temperature = <90000>;
+					hysteresis = <2000>;
 					type = "passive";
 				};
-
 				cpu_crit3: trip1 {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert3>;
+					cooling-device = <&CPU2 THERMAL_NO_LIMIT 7>;
+				};
+				map1 {
+					trip = <&cpu_warn3>;
+					cooling-device = <&CPU2 8 THERMAL_NO_LIMIT>;
+				};
+			};
 		};
 	};
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2017-12-12 12:31 ` [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver Ilia Lin
@ 2017-12-12 14:03   ` Mark Rutland
  2017-12-22  2:06     ` Stephen Boyd
  2018-01-04 11:13     ` ilialin
  0 siblings, 2 replies; 19+ messages in thread
From: Mark Rutland @ 2017-12-12 14:03 UTC (permalink / raw)
  To: Ilia Lin
  Cc: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd, devicetree,
	will.deacon, rnayak, qualcomm-lt, celster, tfinkel

Hi,

On Tue, Dec 12, 2017 at 02:31:28PM +0200, Ilia Lin wrote:
> The driver provides kernel level API for other drivers
> to access the MSM8996 L2 cache registers.
> Separating the L2 access code from the PMU driver and
> making it public to allow other drivers use it.
> The accesses must be separated with a single spinlock,
> maintained in this driver.

> -static void set_l2_indirect_reg(u64 reg, u64 val)
> -{
> -	unsigned long flags;
> -
> -	raw_spin_lock_irqsave(&l2_access_lock, flags);
> -	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> -	isb();
> -	write_sysreg_s(val, L2CPUSRDR_EL1);
> -	isb();
> -	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> -}

> +/**
> + * set_l2_indirect_reg: write value to an L2 register
> + * @reg: Address of L2 register.
> + * @value: Value to be written to register.
> + *
> + * Use architecturally required barriers for ordering between system register
> + * accesses, and system registers with respect to device memory
> + */
> +void set_l2_indirect_reg(u64 reg, u64 val)
> +{
> +	unsigned long flags;
> +	mb();

We didn't need this for the PMU driver, so it's unfortuante that it now
has to pay the cost.

Can we please factor this mb() into the callers that need it?

> +	raw_spin_lock_irqsave(&l2_access_lock, flags);
> +	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> +	isb();
> +	write_sysreg_s(val, L2CPUSRDR_EL1);
> +	isb();
> +	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> +}
> +EXPORT_SYMBOL(set_l2_indirect_reg);

[...]

> +#ifdef CONFIG_ARCH_QCOM
> +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> +u64 get_l2_indirect_reg(u64 reg_addr);
> +#else
> +static inline void set_l2_indirect_reg(u32 reg_addr, u32 val) {}
> +static inline u32 get_l2_indirect_reg(u32 reg_addr)
> +{
> +	return 0;
> +}
> +#endif
> +#endif

Are there any drivers that will bne built for !CONFIG_ARCH_QCOM that
reference this?

It might be better to not have the stub versions, so that we get a
build-error if they are erroneously used.

Thannks,
Mark.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update
       [not found]   ` <1513081897-31612-3-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2017-12-12 15:05     ` Julien Thierry
  2018-01-04 11:14       ` ilialin
  0 siblings, 1 reply; 19+ messages in thread
From: Julien Thierry @ 2017-12-12 15:05 UTC (permalink / raw)
  To: Ilia Lin, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ, will.deacon-5wv7dgnIgG8,
	tfinkel-sgV2jX0FEOL9JmXXK+q4OQ,
	qualcomm-lt-cunTk1MwBs8s++Sfvej+rw,
	celster-sgV2jX0FEOL9JmXXK+q4OQ, Taniya Das

Hi,

On 12/12/17 12:31, Ilia Lin wrote:
> From: Taniya Das <tdas-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> 
> From: Taniya Das <tdas-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> 
> Alpha PLLs which do not support dynamic update feature
> need to be explicitly disabled before a rate change.
> The ones which do support dynamic update do so within a
> single vco range, so add a min/max freq check for such
> PLLs so they fall in the vco range.
> 
> Signed-off-by: Taniya Das <tdas-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Signed-off-by: Rajendra Nayak <rnayak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Signed-off-by: Ilia Lin <ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
>   drivers/clk/qcom/clk-alpha-pll.c | 71 +++++++++++++++++++++++++++++++++-------
>   drivers/clk/qcom/clk-alpha-pll.h |  5 +++
>   2 files changed, 65 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index 47a1da3..ecb9e7f 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -376,19 +376,46 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
>   	return alpha_pll_calc_rate(prate, l, a);
>   }
>   
> -static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> -				  unsigned long prate)
> +static int alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +			      unsigned long prate,
> +			      int (*enable)(struct clk_hw *hw),
> +			      void (*disable)(struct clk_hw *hw))
>   {
> +	bool enabled;

Some remarks about this.

>   	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>   	const struct pll_vco *vco;
>   	u32 l, off = pll->offset;
>   	u64 a;
>   
>   	rate = alpha_pll_round_rate(rate, prate, &l, &a);
> -	vco = alpha_pll_find_vco(pll, rate);
> -	if (!vco) {
> -		pr_err("alpha pll not in a valid vco range\n");
> -		return -EINVAL;
> +	enabled = clk_hw_is_enabled(hw);

This is not needed unless we go through the 'else' branch.

> +
> +	if (pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
> +		/*
> +		 * PLLs which support dynamic updates support one single
> +		 * vco range, between min_rate and max_rate supported
> +		 */
> +		if (rate < pll->min_rate || rate > pll->max_rate) {
> +			pr_err("alpha pll rate outside supported min/max range\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		/*
> +		 * All alpha PLLs which do not support dynamic update,
> +		 * should be disabled before a vco update.
> +		 */
> +		if (enabled)
> +			disable(hw);
> +
> +		vco = alpha_pll_find_vco(pll, rate);
> +		if (!vco) {
> +			pr_err("alpha pll not in a valid vco range\n");
> +			return -EINVAL;
> +		}
> +
> +		regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
> +				   PLL_VCO_MASK << PLL_VCO_SHIFT,
> +				   vco->val << PLL_VCO_SHIFT);
>   	}
>   
>   	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
> @@ -401,16 +428,29 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>   		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
>   	}
>   
> -	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
> -			   PLL_VCO_MASK << PLL_VCO_SHIFT,
> -			   vco->val << PLL_VCO_SHIFT);
> -
>   	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
>   			   PLL_ALPHA_EN);
>   
> +	if (!(pll->flags & SUPPORTS_DYNAMIC_UPDATE) && enabled)
> +		enable(hw);
> +

This condition is only "did we disable the clock and need to reenable it?".

To make it clearer, I'd suggest renaming 'enabled' to something like 
'need_reenabling' and the code look like this:

static int alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
			      unsigned long prate,
			      int (*enable)(struct clk_hw *hw),
			      void (*disable)(struct clk_hw *hw))
{
	bool need_reenabling = false;

	[...]

	if(pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
		[...]
	} else {
		if (clk_hw_is_enabled(hw)) {
			disable(hw);
			need_reenabling = true;
		}
		[...]
	}

	[...]

	if (need_reenabling)
		enable(hw);

}


Cheers,

-- 
Julien Thierry
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 04/10] clk: qcom: Add CPU clock driver for msm8996
  2017-12-12 12:31 ` [PATCH 04/10] clk: qcom: Add CPU clock driver for msm8996 Ilia Lin
@ 2017-12-15 22:35   ` Rob Herring
  2018-01-04 11:15     ` ilialin
  0 siblings, 1 reply; 19+ messages in thread
From: Rob Herring @ 2017-12-15 22:35 UTC (permalink / raw)
  To: Ilia Lin
  Cc: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd, devicetree,
	mark.rutland, will.deacon, rnayak, qualcomm-lt, celster, tfinkel

On Tue, Dec 12, 2017 at 02:31:31PM +0200, Ilia Lin wrote:
> From: Rajendra Nayak <rnayak@codeaurora.org>
> 
> Each of the CPU clusters (Power and Perf) on msm8996 are
> clocked via 2 PLLs, a primary and alternate. There are also
> 2 Mux'es, a primary and secondary all connected together
> as shown below
> 
>                              +-------+
>               XO             |       |
>           +------------------>0      |
>                              |       |
>                    PLL/2     | SMUX  +----+
>                      +------->1      |    |
>                      |       |       |    |
>                      |       +-------+    |    +-------+
>                      |                    +---->0      |
>                      |                         |       |
> +---------------+    |             +----------->1      | CPU clk
> |Primary PLL    +----+ PLL_EARLY   |           |       +------>
> |               +------+-----------+    +------>2 PMUX |
> +---------------+      |                |      |       |
>                        |   +------+     |   +-->3      |
>                        +--^+  ACD +-----+   |  +-------+
> +---------------+          +------+         |
> |Alt PLL        |                           |
> |               +---------------------------+
> +---------------+         PLL_EARLY
> 
> The primary PLL is what drives the CPU clk, except for times
> when we are reprogramming the PLL itself (for rate changes) when
> we temporarily switch to an alternate PLL. A subsequent patch adds
> support to switch between primary and alternate PLL during rate
> changes.
> 
> The primary PLL operates on a single VCO range, between 600Mhz
> and 3Ghz. However the CPUs do support OPPs with frequencies
> between 300Mhz and 600Mhz. In order to support running the CPUs
> at those frequencies we end up having to lock the PLL at twice
> the rate and drive the CPU clk via the PLL/2 output and SMUX.
> 
> So for frequencies above 600Mhz we follow the following path
>  Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk
> and for frequencies between 300Mhz and 600Mhz we follow
>  Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk
> Support for this is added in a subsequent patch as well.
> 
> ACD stands for Adaptive Clock Distribution and is used to
> detect voltage droops. We do not add support for ACD as yet.
> This can be added at a later point as needed.
> 
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  .../devicetree/bindings/clock/qcom,kryocc.txt      |  17 +

If you respin, please make bindings a separate patch. In any case,

Reviewed-by: Rob Herring <robh@kernel.org>

>  drivers/clk/qcom/Kconfig                           |   8 +
>  drivers/clk/qcom/Makefile                          |   1 +
>  drivers/clk/qcom/clk-cpu-8996.c                    | 388 +++++++++++++++++++++
>  4 files changed, 414 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
>  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2017-12-12 14:03   ` Mark Rutland
@ 2017-12-22  2:06     ` Stephen Boyd
  2018-01-04 11:15       ` ilialin
  2018-01-04 11:13     ` ilialin
  1 sibling, 1 reply; 19+ messages in thread
From: Stephen Boyd @ 2017-12-22  2:06 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Ilia Lin, linux-clk, linux-arm-kernel, linux-arm-msm, devicetree,
	will.deacon, rnayak, qualcomm-lt, celster, tfinkel

On 12/12, Mark Rutland wrote:
> On Tue, Dec 12, 2017 at 02:31:28PM +0200, Ilia Lin wrote:
> > + * accesses, and system registers with respect to device memory
> > + */
> > +void set_l2_indirect_reg(u64 reg, u64 val)
> > +{
> > +	unsigned long flags;
> > +	mb();
> 
> We didn't need this for the PMU driver, so it's unfortuante that it now
> has to pay the cost.
> 
> Can we please factor this mb() into the callers that need it?

+1

> 
> > +	raw_spin_lock_irqsave(&l2_access_lock, flags);
> > +	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > +	isb();
> > +	write_sysreg_s(val, L2CPUSRDR_EL1);
> > +	isb();
> > +	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> > +}
> > +EXPORT_SYMBOL(set_l2_indirect_reg);
> 
> [...]
> 
> > +#ifdef CONFIG_ARCH_QCOM
> > +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> > +u64 get_l2_indirect_reg(u64 reg_addr);
> > +#else
> > +static inline void set_l2_indirect_reg(u32 reg_addr, u32 val) {}
> > +static inline u32 get_l2_indirect_reg(u32 reg_addr)
> > +{
> > +	return 0;
> > +}
> > +#endif
> > +#endif
> 
> Are there any drivers that will bne built for !CONFIG_ARCH_QCOM that
> reference this?
> 
> It might be better to not have the stub versions, so that we get a
> build-error if they are erroneously used.
> 

Does that approach make COMPILE_TEST break?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2017-12-12 14:03   ` Mark Rutland
  2017-12-22  2:06     ` Stephen Boyd
@ 2018-01-04 11:13     ` ilialin
  1 sibling, 0 replies; 19+ messages in thread
From: ilialin @ 2018-01-04 11:13 UTC (permalink / raw)
  To: 'Mark Rutland'
  Cc: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd, devicetree,
	will.deacon, rnayak, qualcomm-lt, celster, tfinkel

This is address in the V2: https://patchwork.kernel.org/patch/10144473/

> -----Original Message-----
> From: Mark Rutland [mailto:mark.rutland@arm.com]
> Sent: Tuesday, December 12, 2017 4:03 PM
> To: Ilia Lin <ilialin@codeaurora.org>
> Cc: linux-clk@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
linux-
> arm-msm@vger.kernel.org; sboyd@codeaurora.org;
> devicetree@vger.kernel.org; will.deacon@arm.com;
> rnayak@codeaurora.org; qualcomm-lt@lists.linaro.org;
> celster@codeaurora.org; tfinkel@codeaurora.org
> Subject: Re: [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU
> driver
> 
> Hi,
> 
> On Tue, Dec 12, 2017 at 02:31:28PM +0200, Ilia Lin wrote:
> > The driver provides kernel level API for other drivers to access the
> > MSM8996 L2 cache registers.
> > Separating the L2 access code from the PMU driver and making it public
> > to allow other drivers use it.
> > The accesses must be separated with a single spinlock, maintained in
> > this driver.
> 
> > -static void set_l2_indirect_reg(u64 reg, u64 val) -{
> > -	unsigned long flags;
> > -
> > -	raw_spin_lock_irqsave(&l2_access_lock, flags);
> > -	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > -	isb();
> > -	write_sysreg_s(val, L2CPUSRDR_EL1);
> > -	isb();
> > -	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> > -}
> 
> > +/**
> > + * set_l2_indirect_reg: write value to an L2 register
> > + * @reg: Address of L2 register.
> > + * @value: Value to be written to register.
> > + *
> > + * Use architecturally required barriers for ordering between system
> > +register
> > + * accesses, and system registers with respect to device memory  */
> > +void set_l2_indirect_reg(u64 reg, u64 val) {
> > +	unsigned long flags;
> > +	mb();
> 
> We didn't need this for the PMU driver, so it's unfortuante that it now
has to
> pay the cost.
> 
> Can we please factor this mb() into the callers that need it?
> 
> > +	raw_spin_lock_irqsave(&l2_access_lock, flags);
> > +	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > +	isb();
> > +	write_sysreg_s(val, L2CPUSRDR_EL1);
> > +	isb();
> > +	raw_spin_unlock_irqrestore(&l2_access_lock, flags); }
> > +EXPORT_SYMBOL(set_l2_indirect_reg);
> 
> [...]
> 
> > +#ifdef CONFIG_ARCH_QCOM
> > +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> > +u64 get_l2_indirect_reg(u64 reg_addr); #else static inline void
> > +set_l2_indirect_reg(u32 reg_addr, u32 val) {} static inline u32
> > +get_l2_indirect_reg(u32 reg_addr) {
> > +	return 0;
> > +}
> > +#endif
> > +#endif
> 
> Are there any drivers that will bne built for !CONFIG_ARCH_QCOM that
> reference this?
> 
> It might be better to not have the stub versions, so that we get a
build-error
> if they are erroneously used.
> 
> Thannks,
> Mark.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update
  2017-12-12 15:05     ` Julien Thierry
@ 2018-01-04 11:14       ` ilialin
  0 siblings, 0 replies; 19+ messages in thread
From: ilialin @ 2018-01-04 11:14 UTC (permalink / raw)
  To: 'Julien Thierry',
	linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: mark.rutland, devicetree, rnayak, will.deacon, tfinkel,
	qualcomm-lt, celster, 'Taniya Das'

This is address in the V2: https://patchwork.kernel.org/patch/10144477/

> -----Original Message-----
> From: Julien Thierry [mailto:julien.thierry@arm.com]
> Sent: Tuesday, December 12, 2017 5:06 PM
> To: Ilia Lin <ilialin@codeaurora.org>; linux-clk@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; linux-arm-msm@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; will.deacon@arm.com; tfinkel@codeaurora.org;
> qualcomm-lt@lists.linaro.org; celster@codeaurora.org; Taniya Das
> <tdas@codeaurora.org>
> Subject: Re: [PATCH 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs
> w/wo dynamic update
> 
> Hi,
> 
> On 12/12/17 12:31, Ilia Lin wrote:
> > From: Taniya Das <tdas@codeaurora.org>
> >
> > From: Taniya Das <tdas@codeaurora.org>
> >
> > Alpha PLLs which do not support dynamic update feature need to be
> > explicitly disabled before a rate change.
> > The ones which do support dynamic update do so within a single vco
> > range, so add a min/max freq check for such PLLs so they fall in the
> > vco range.
> >
> > Signed-off-by: Taniya Das <tdas@codeaurora.org>
> > Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >   drivers/clk/qcom/clk-alpha-pll.c | 71
> +++++++++++++++++++++++++++++++++-------
> >   drivers/clk/qcom/clk-alpha-pll.h |  5 +++
> >   2 files changed, 65 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/clk/qcom/clk-alpha-pll.c
> > b/drivers/clk/qcom/clk-alpha-pll.c
> > index 47a1da3..ecb9e7f 100644
> > --- a/drivers/clk/qcom/clk-alpha-pll.c
> > +++ b/drivers/clk/qcom/clk-alpha-pll.c
> > @@ -376,19 +376,46 @@ static unsigned long alpha_pll_calc_rate(u64
> prate, u32 l, u32 a)
> >   	return alpha_pll_calc_rate(prate, l, a);
> >   }
> >
> > -static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> > -				  unsigned long prate)
> > +static int alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> > +			      unsigned long prate,
> > +			      int (*enable)(struct clk_hw *hw),
> > +			      void (*disable)(struct clk_hw *hw))
> >   {
> > +	bool enabled;
> 
> Some remarks about this.
> 
> >   	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> >   	const struct pll_vco *vco;
> >   	u32 l, off = pll->offset;
> >   	u64 a;
> >
> >   	rate = alpha_pll_round_rate(rate, prate, &l, &a);
> > -	vco = alpha_pll_find_vco(pll, rate);
> > -	if (!vco) {
> > -		pr_err("alpha pll not in a valid vco range\n");
> > -		return -EINVAL;
> > +	enabled = clk_hw_is_enabled(hw);
> 
> This is not needed unless we go through the 'else' branch.
> 
> > +
> > +	if (pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
> > +		/*
> > +		 * PLLs which support dynamic updates support one single
> > +		 * vco range, between min_rate and max_rate supported
> > +		 */
> > +		if (rate < pll->min_rate || rate > pll->max_rate) {
> > +			pr_err("alpha pll rate outside supported min/max
> range\n");
> > +			return -EINVAL;
> > +		}
> > +	} else {
> > +		/*
> > +		 * All alpha PLLs which do not support dynamic update,
> > +		 * should be disabled before a vco update.
> > +		 */
> > +		if (enabled)
> > +			disable(hw);
> > +
> > +		vco = alpha_pll_find_vco(pll, rate);
> > +		if (!vco) {
> > +			pr_err("alpha pll not in a valid vco range\n");
> > +			return -EINVAL;
> > +		}
> > +
> > +		regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
> > +				   PLL_VCO_MASK << PLL_VCO_SHIFT,
> > +				   vco->val << PLL_VCO_SHIFT);
> >   	}
> >
> >   	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l); @@ -401,16
> > +428,29 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned
> long rate,
> >   		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a
> >> 32);
> >   	}
> >
> > -	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
> > -			   PLL_VCO_MASK << PLL_VCO_SHIFT,
> > -			   vco->val << PLL_VCO_SHIFT);
> > -
> >   	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
> PLL_ALPHA_EN,
> >   			   PLL_ALPHA_EN);
> >
> > +	if (!(pll->flags & SUPPORTS_DYNAMIC_UPDATE) && enabled)
> > +		enable(hw);
> > +
> 
> This condition is only "did we disable the clock and need to reenable it?".
> 
> To make it clearer, I'd suggest renaming 'enabled' to something like
> 'need_reenabling' and the code look like this:
> 
> static int alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> 			      unsigned long prate,
> 			      int (*enable)(struct clk_hw *hw),
> 			      void (*disable)(struct clk_hw *hw)) {
> 	bool need_reenabling = false;
> 
> 	[...]
> 
> 	if(pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
> 		[...]
> 	} else {
> 		if (clk_hw_is_enabled(hw)) {
> 			disable(hw);
> 			need_reenabling = true;
> 		}
> 		[...]
> 	}
> 
> 	[...]
> 
> 	if (need_reenabling)
> 		enable(hw);
> 
> }
> 
> 
> Cheers,
> 
> --
> Julien Thierry

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH 04/10] clk: qcom: Add CPU clock driver for msm8996
  2017-12-15 22:35   ` Rob Herring
@ 2018-01-04 11:15     ` ilialin
  0 siblings, 0 replies; 19+ messages in thread
From: ilialin @ 2018-01-04 11:15 UTC (permalink / raw)
  To: 'Rob Herring'
  Cc: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd, devicetree,
	mark.rutland, will.deacon, rnayak, qualcomm-lt, celster, tfinkel

This is address in the V2: https://patchwork.kernel.org/patch/10144489/

> -----Original Message-----
> From: Rob Herring [mailto:robh@kernel.org]
> Sent: Saturday, December 16, 2017 12:35 AM
> To: Ilia Lin <ilialin@codeaurora.org>
> Cc: linux-clk@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
linux-
> arm-msm@vger.kernel.org; sboyd@codeaurora.org;
> devicetree@vger.kernel.org; mark.rutland@arm.com;
> will.deacon@arm.com; rnayak@codeaurora.org; qualcomm-
> lt@lists.linaro.org; celster@codeaurora.org; tfinkel@codeaurora.org
> Subject: Re: [PATCH 04/10] clk: qcom: Add CPU clock driver for msm8996
> 
> On Tue, Dec 12, 2017 at 02:31:31PM +0200, Ilia Lin wrote:
> > From: Rajendra Nayak <rnayak@codeaurora.org>
> >
> > Each of the CPU clusters (Power and Perf) on msm8996 are clocked via 2
> > PLLs, a primary and alternate. There are also
> > 2 Mux'es, a primary and secondary all connected together as shown
> > below
> >
> >                              +-------+
> >               XO             |       |
> >           +------------------>0      |
> >                              |       |
> >                    PLL/2     | SMUX  +----+
> >                      +------->1      |    |
> >                      |       |       |    |
> >                      |       +-------+    |    +-------+
> >                      |                    +---->0      |
> >                      |                         |       |
> > +---------------+    |             +----------->1      | CPU clk
> > |Primary PLL    +----+ PLL_EARLY   |           |       +------>
> > |               +------+-----------+    +------>2 PMUX |
> > +---------------+      |                |      |       |
> >                        |   +------+     |   +-->3      |
> >                        +--^+  ACD +-----+   |  +-------+
> > +---------------+          +------+         |
> > |Alt PLL        |                           |
> > |               +---------------------------+
> > +---------------+         PLL_EARLY
> >
> > The primary PLL is what drives the CPU clk, except for times when we
> > are reprogramming the PLL itself (for rate changes) when we
> > temporarily switch to an alternate PLL. A subsequent patch adds
> > support to switch between primary and alternate PLL during rate
> > changes.
> >
> > The primary PLL operates on a single VCO range, between 600Mhz and
> > 3Ghz. However the CPUs do support OPPs with frequencies between
> 300Mhz
> > and 600Mhz. In order to support running the CPUs at those frequencies
> > we end up having to lock the PLL at twice the rate and drive the CPU
> > clk via the PLL/2 output and SMUX.
> >
> > So for frequencies above 600Mhz we follow the following path  Primary
> > PLL --> PLL_EARLY --> PMUX(1) --> CPU clk and for frequencies between
> > 300Mhz and 600Mhz we follow  Primary PLL --> PLL/2 --> SMUX(1) -->
> > PMUX(0) --> CPU clk Support for this is added in a subsequent patch as
> > well.
> >
> > ACD stands for Adaptive Clock Distribution and is used to detect
> > voltage droops. We do not add support for ACD as yet.
> > This can be added at a later point as needed.
> >
> > Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >  .../devicetree/bindings/clock/qcom,kryocc.txt      |  17 +
> 
> If you respin, please make bindings a separate patch. In any case,
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> 
> >  drivers/clk/qcom/Kconfig                           |   8 +
> >  drivers/clk/qcom/Makefile                          |   1 +
> >  drivers/clk/qcom/clk-cpu-8996.c                    | 388
> +++++++++++++++++++++
> >  4 files changed, 414 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> >  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2017-12-22  2:06     ` Stephen Boyd
@ 2018-01-04 11:15       ` ilialin
  0 siblings, 0 replies; 19+ messages in thread
From: ilialin @ 2018-01-04 11:15 UTC (permalink / raw)
  To: 'Stephen Boyd', 'Mark Rutland'
  Cc: linux-clk, linux-arm-kernel, linux-arm-msm, devicetree,
	will.deacon, rnayak, qualcomm-lt, celster, tfinkel

Tested COMPILE_TEST and found OK.

> -----Original Message-----
> From: Stephen Boyd [mailto:sboyd@codeaurora.org]
> Sent: Friday, December 22, 2017 4:07 AM
> To: Mark Rutland <mark.rutland@arm.com>
> Cc: Ilia Lin <ilialin@codeaurora.org>; linux-clk@vger.kernel.org;
linux-arm-
> kernel@lists.infradead.org; linux-arm-msm@vger.kernel.org;
> devicetree@vger.kernel.org; will.deacon@arm.com;
> rnayak@codeaurora.org; qualcomm-lt@lists.linaro.org;
> celster@codeaurora.org; tfinkel@codeaurora.org
> Subject: Re: [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU
> driver
> 
> On 12/12, Mark Rutland wrote:
> > On Tue, Dec 12, 2017 at 02:31:28PM +0200, Ilia Lin wrote:
> > > + * accesses, and system registers with respect to device memory  */
> > > +void set_l2_indirect_reg(u64 reg, u64 val) {
> > > +	unsigned long flags;
> > > +	mb();
> >
> > We didn't need this for the PMU driver, so it's unfortuante that it
> > now has to pay the cost.
> >
> > Can we please factor this mb() into the callers that need it?
> 
> +1
> 
> >
> > > +	raw_spin_lock_irqsave(&l2_access_lock, flags);
> > > +	write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > > +	isb();
> > > +	write_sysreg_s(val, L2CPUSRDR_EL1);
> > > +	isb();
> > > +	raw_spin_unlock_irqrestore(&l2_access_lock, flags); }
> > > +EXPORT_SYMBOL(set_l2_indirect_reg);
> >
> > [...]
> >
> > > +#ifdef CONFIG_ARCH_QCOM
> > > +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> > > +u64 get_l2_indirect_reg(u64 reg_addr); #else static inline void
> > > +set_l2_indirect_reg(u32 reg_addr, u32 val) {} static inline u32
> > > +get_l2_indirect_reg(u32 reg_addr) {
> > > +	return 0;
> > > +}
> > > +#endif
> > > +#endif
> >
> > Are there any drivers that will bne built for !CONFIG_ARCH_QCOM that
> > reference this?
> >
> > It might be better to not have the stub versions, so that we get a
> > build-error if they are erroneously used.
> >
> 
> Does that approach make COMPILE_TEST break?
> 
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
> Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2018-01-04 11:15 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-12 12:31 [PATCH 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
2017-12-12 12:31 ` [PATCH 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver Ilia Lin
2017-12-12 14:03   ` Mark Rutland
2017-12-22  2:06     ` Stephen Boyd
2018-01-04 11:15       ` ilialin
2018-01-04 11:13     ` ilialin
2017-12-12 12:31 ` [PATCH 02/10] clk: qcom: Fix .set_rate to handle alpha PLLs w/wo dynamic update Ilia Lin
     [not found]   ` <1513081897-31612-3-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2017-12-12 15:05     ` Julien Thierry
2018-01-04 11:14       ` ilialin
2017-12-12 12:31 ` [PATCH 03/10] clk: qcom: Make clk_alpha_pll_configure available to modules Ilia Lin
2017-12-12 12:31 ` [PATCH 04/10] clk: qcom: Add CPU clock driver for msm8996 Ilia Lin
2017-12-15 22:35   ` Rob Herring
2018-01-04 11:15     ` ilialin
     [not found] ` <1513081897-31612-1-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2017-12-12 12:31   ` [PATCH 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL Ilia Lin
2017-12-12 12:31   ` [PATCH 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz Ilia Lin
2017-12-12 12:31   ` [PATCH 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996 Ilia Lin
2017-12-12 12:31 ` [PATCH 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe Ilia Lin
2017-12-12 12:31 ` [PATCH 09/10] DT: QCOM: Add cpufreq-dt to msm8996 Ilia Lin
2017-12-12 12:31 ` [PATCH 10/10] DT: QCOM: Add thermal mitigation " Ilia Lin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).