All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/10] clk: qcom: CPU clock driver for msm8996
@ 2018-02-14 13:59 ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ, ilialin-sgV2jX0FEOL9JmXXK+q4OQ,
	amit.kucheria-QSEj5FYQhm4dnm+yROfE0A,
	nicolas.dechesne-QSEj5FYQhm4dnm+yROfE0A,
	celster-sgV2jX0FEOL9JmXXK+q4OQ, tfinkel-sgV2jX0FEOL9JmXXK+q4OQ

[v3]
 * Rebased on top of the latest PLL driver changes
 * Addressed comment from Rob Herring for bindings

This series adds support for the CPU clocks on msm8996 devices.

The driver uses the existing PLL drivers and is required
to control the CPU frequency scaling on the MSM8996.

A previous post of RFC can be found here
https://patchwork.kernel.org/patch/10144485/

Ilia Lin (6):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: qcom: Add DT bindings for CPU clock driver for msm8996
  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

 .../devicetree/bindings/clock/qcom,kryocc.txt      |  17 +
 arch/arm64/Kconfig.platforms                       |   7 +
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts        |   4 +-
 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi       |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi              | 286 ++++++++++-
 drivers/clk/qcom/Kconfig                           |   8 +
 drivers/clk/qcom/Makefile                          |   1 +
 drivers/clk/qcom/clk-alpha-pll.c                   |   1 +
 drivers/clk/qcom/clk-cpu-8996.c                    | 554 +++++++++++++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c               |   3 +
 drivers/perf/qcom_l2_pmu.c                         |  50 +-
 drivers/soc/qcom/Makefile                          |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c               |  64 +++
 include/soc/qcom/kryo-l2-accessors.h               |  22 +
 14 files changed, 956 insertions(+), 64 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

-- 
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	[flat|nested] 101+ messages in thread

* [PATCH v3 00/10] clk: qcom: CPU clock driver for msm8996
@ 2018-02-14 13:59 ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, celster, tfinkel

[v3]
 * Rebased on top of the latest PLL driver changes
 * Addressed comment from Rob Herring for bindings

This series adds support for the CPU clocks on msm8996 devices.

The driver uses the existing PLL drivers and is required
to control the CPU frequency scaling on the MSM8996.

A previous post of RFC can be found here
https://patchwork.kernel.org/patch/10144485/

Ilia Lin (6):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: qcom: Add DT bindings for CPU clock driver for msm8996
  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

 .../devicetree/bindings/clock/qcom,kryocc.txt      |  17 +
 arch/arm64/Kconfig.platforms                       |   7 +
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts        |   4 +-
 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi       |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi              | 286 ++++++++++-
 drivers/clk/qcom/Kconfig                           |   8 +
 drivers/clk/qcom/Makefile                          |   1 +
 drivers/clk/qcom/clk-alpha-pll.c                   |   1 +
 drivers/clk/qcom/clk-cpu-8996.c                    | 554 +++++++++++++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c               |   3 +
 drivers/perf/qcom_l2_pmu.c                         |  50 +-
 drivers/soc/qcom/Makefile                          |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c               |  64 +++
 include/soc/qcom/kryo-l2-accessors.h               |  22 +
 14 files changed, 956 insertions(+), 64 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

-- 
1.9.1


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

* [PATCH v3 00/10] clk: qcom: CPU clock driver for msm8996
@ 2018-02-14 13:59 ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

[v3]
 * Rebased on top of the latest PLL driver changes
 * Addressed comment from Rob Herring for bindings

This series adds support for the CPU clocks on msm8996 devices.

The driver uses the existing PLL drivers and is required
to control the CPU frequency scaling on the MSM8996.

A previous post of RFC can be found here
https://patchwork.kernel.org/patch/10144485/

Ilia Lin (6):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: qcom: Add DT bindings for CPU clock driver for msm8996
  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

 .../devicetree/bindings/clock/qcom,kryocc.txt      |  17 +
 arch/arm64/Kconfig.platforms                       |   7 +
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts        |   4 +-
 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi       |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi              | 286 ++++++++++-
 drivers/clk/qcom/Kconfig                           |   8 +
 drivers/clk/qcom/Makefile                          |   1 +
 drivers/clk/qcom/clk-alpha-pll.c                   |   1 +
 drivers/clk/qcom/clk-cpu-8996.c                    | 554 +++++++++++++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c               |   3 +
 drivers/perf/qcom_l2_pmu.c                         |  50 +-
 drivers/soc/qcom/Makefile                          |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c               |  64 +++
 include/soc/qcom/kryo-l2-accessors.h               |  22 +
 14 files changed, 956 insertions(+), 64 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

-- 
1.9.1

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

* [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2018-02-14 13:59 ` Ilia Lin
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, 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           | 50 ++--------------------------
 drivers/soc/qcom/Makefile            |  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 64 ++++++++++++++++++++++++++++++++++++
 include/soc/qcom/kryo-l2-accessors.h | 22 +++++++++++++
 5 files changed, 96 insertions(+), 48 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 fbedbd8..78a103b 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -145,6 +145,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..8cece9e 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018 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
@@ -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 dcebf28..4e91e2a 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -12,3 +12,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..6743848
--- /dev/null
+++ b/drivers/soc/qcom/kryo-l2-accessors.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014-2015, 2018, 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;
+
+	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..e9a5eab
--- /dev/null
+++ b/include/soc/qcom/kryo-l2-accessors.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, 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);
+#endif
+
+#endif
-- 
1.9.1


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

* [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

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           | 50 ++--------------------------
 drivers/soc/qcom/Makefile            |  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 64 ++++++++++++++++++++++++++++++++++++
 include/soc/qcom/kryo-l2-accessors.h | 22 +++++++++++++
 5 files changed, 96 insertions(+), 48 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 fbedbd8..78a103b 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -145,6 +145,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..8cece9e 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018 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
@@ -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 dcebf28..4e91e2a 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -12,3 +12,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..6743848
--- /dev/null
+++ b/drivers/soc/qcom/kryo-l2-accessors.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014-2015, 2018, 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;
+
+	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..e9a5eab
--- /dev/null
+++ b/include/soc/qcom/kryo-l2-accessors.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, 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);
+#endif
+
+#endif
-- 
1.9.1

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

* [PATCH v3 02/10] clk: qcom: Make clk_alpha_pll_configure available to modules
  2018-02-14 13:59 ` Ilia Lin
  (?)
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

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 6d04cd9..5c962af 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -208,6 +208,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, PLL_MODE(pll), 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] 101+ messages in thread

* [PATCH v3 02/10] clk: qcom: Make clk_alpha_pll_configure available to modules
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, 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 6d04cd9..5c962af 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -208,6 +208,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, PLL_MODE(pll), 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] 101+ messages in thread

* [PATCH v3 02/10] clk: qcom: Make clk_alpha_pll_configure available to modules
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

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 6d04cd9..5c962af 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -208,6 +208,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, PLL_MODE(pll), 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] 101+ messages in thread

* [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
  2018-02-14 13:59 ` Ilia Lin
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, 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>
---
 drivers/clk/qcom/Kconfig        |   8 +
 drivers/clk/qcom/Makefile       |   1 +
 drivers/clk/qcom/clk-cpu-8996.c | 409 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 418 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index fbf4532..3274877 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
 	  Technologies, Inc. SPMI PMIC. It configures the frequency of
 	  clkdiv outputs of the PMIC. These clocks are typically wired
 	  through alternate functions on GPIO pins.
+
+config 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 230332c..57b38ba 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -33,6 +33,7 @@ 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_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
--- /dev/null
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2018, 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
+
+static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
+       [PLL_OFF_L_VAL] = 0x04,
+       [PLL_OFF_ALPHA_VAL] = 0x08,
+       [PLL_OFF_USER_CTL] = 0x10,
+       [PLL_OFF_CONFIG_CTL] = 0x18,
+       [PLL_OFF_CONFIG_CTL_U] = 0x1C,
+       [PLL_OFF_TEST_CTL] = 0x20,
+       [PLL_OFF_TEST_CTL_U] = 0x24,
+       [PLL_OFF_STATUS] = 0x28,
+};
+
+static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
+       [PLL_OFF_L_VAL] = 0x04,
+       [PLL_OFF_ALPHA_VAL] = 0x08,
+       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
+       [PLL_OFF_USER_CTL] = 0x10,
+       [PLL_OFF_USER_CTL_U] = 0x14,
+       [PLL_OFF_CONFIG_CTL] = 0x18,
+       [PLL_OFF_TEST_CTL] = 0x20,
+       [PLL_OFF_TEST_CTL_U] = 0x24,
+       [PLL_OFF_STATUS] = 0x28,
+};
+
+/* 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,
+	.regs = prim_pll_regs,
+	.flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
+	},
+};
+
+static struct clk_alpha_pll pwrcl_pll = {
+	.offset = 0x0,
+	.regs = prim_pll_regs,
+	.flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
+	.regs = alt_pll_regs,
+	.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,
+	.regs = alt_pll_regs,
+	.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 | CLK_IS_CRITICAL,
+	},
+};
+
+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",
+			"perfcl_pll_acd",
+			"perfcl_alt_pll",
+		},
+		.num_parents = 4,
+		.ops = &clk_cpu_8996_mux_ops,
+		.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+	},
+};
+
+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-msm8996-apcc" },
+	{}
+};
+
+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-msm8996-apcc",
+		.of_match_table = match_table,
+	},
+};
+
+module_platform_driver(qcom_cpu_clk_msm8996_driver);
+
+MODULE_ALIAS("platform:msm8996-apcc");
+MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


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

* [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 drivers/clk/qcom/Kconfig        |   8 +
 drivers/clk/qcom/Makefile       |   1 +
 drivers/clk/qcom/clk-cpu-8996.c | 409 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 418 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index fbf4532..3274877 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
 	  Technologies, Inc. SPMI PMIC. It configures the frequency of
 	  clkdiv outputs of the PMIC. These clocks are typically wired
 	  through alternate functions on GPIO pins.
+
+config 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 230332c..57b38ba 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -33,6 +33,7 @@ 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_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
--- /dev/null
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2018, 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
+
+static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
+       [PLL_OFF_L_VAL] = 0x04,
+       [PLL_OFF_ALPHA_VAL] = 0x08,
+       [PLL_OFF_USER_CTL] = 0x10,
+       [PLL_OFF_CONFIG_CTL] = 0x18,
+       [PLL_OFF_CONFIG_CTL_U] = 0x1C,
+       [PLL_OFF_TEST_CTL] = 0x20,
+       [PLL_OFF_TEST_CTL_U] = 0x24,
+       [PLL_OFF_STATUS] = 0x28,
+};
+
+static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
+       [PLL_OFF_L_VAL] = 0x04,
+       [PLL_OFF_ALPHA_VAL] = 0x08,
+       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
+       [PLL_OFF_USER_CTL] = 0x10,
+       [PLL_OFF_USER_CTL_U] = 0x14,
+       [PLL_OFF_CONFIG_CTL] = 0x18,
+       [PLL_OFF_TEST_CTL] = 0x20,
+       [PLL_OFF_TEST_CTL_U] = 0x24,
+       [PLL_OFF_STATUS] = 0x28,
+};
+
+/* 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,
+	.regs = prim_pll_regs,
+	.flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
+	},
+};
+
+static struct clk_alpha_pll pwrcl_pll = {
+	.offset = 0x0,
+	.regs = prim_pll_regs,
+	.flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
+	.regs = alt_pll_regs,
+	.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,
+	.regs = alt_pll_regs,
+	.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 | CLK_IS_CRITICAL,
+	},
+};
+
+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",
+			"perfcl_pll_acd",
+			"perfcl_alt_pll",
+		},
+		.num_parents = 4,
+		.ops = &clk_cpu_8996_mux_ops,
+		.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+	},
+};
+
+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-msm8996-apcc" },
+	{}
+};
+
+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-msm8996-apcc",
+		.of_match_table = match_table,
+	},
+};
+
+module_platform_driver(qcom_cpu_clk_msm8996_driver);
+
+MODULE_ALIAS("platform:msm8996-apcc");
+MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

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

* [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
  2018-02-14 13:59 ` Ilia Lin
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, celster, tfinkel

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index 0000000..e7cf15a
--- /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-msm8996-apcc"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+	kryocc: clock-controller@6400000 {
+		compatible = "qcom-msm8996-apcc";
+		reg = <0x6400000 0x90000>;
+		#clock-cells = <1>;
+	};
-- 
1.9.1


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

* [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index 0000000..e7cf15a
--- /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-msm8996-apcc"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+	kryocc: clock-controller at 6400000 {
+		compatible = "qcom-msm8996-apcc";
+		reg = <0x6400000 0x90000>;
+		#clock-cells = <1>;
+	};
-- 
1.9.1

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

* [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
  2018-02-14 13:59 ` Ilia Lin
  (?)
@ 2018-02-14 13:59     ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ, ilialin-sgV2jX0FEOL9JmXXK+q4OQ,
	amit.kucheria-QSEj5FYQhm4dnm+yROfE0A,
	nicolas.dechesne-QSEj5FYQhm4dnm+yROfE0A,
	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 42489f1..75bd014 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -140,10 +140,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)
 {
@@ -194,6 +198,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,
@@ -237,6 +262,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 *[]){
@@ -256,6 +282,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 *[]){
@@ -331,6 +358,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] 101+ messages in thread

* [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
@ 2018-02-14 13:59     ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, celster, tfinkel

From: Rajendra Nayak <rnayak@codeaurora.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@codeaurora.org>
Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -140,10 +140,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)
 {
@@ -194,6 +198,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,
@@ -237,6 +262,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 *[]){
@@ -256,6 +282,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 *[]){
@@ -331,6 +358,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


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

* [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
@ 2018-02-14 13:59     ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rajendra Nayak <rnayak@codeaurora.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@codeaurora.org>
Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -140,10 +140,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)
 {
@@ -194,6 +198,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,
@@ -237,6 +262,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 *[]){
@@ -256,6 +282,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 *[]){
@@ -331,6 +358,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

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

* [PATCH v3 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz
  2018-02-14 13:59 ` Ilia Lin
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, celster, tfinkel

From: Rajendra Nayak <rnayak@codeaurora.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@codeaurora.org>
Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 75bd014..854f327 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
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
        [PLL_OFF_L_VAL] = 0x04,
@@ -56,10 +57,11 @@
 
 static const struct alpha_pll_config hfpll_config = {
 	.l = 60,
-	.config_ctl_val = 0x200d4828,
+	.config_ctl_val = 0x200D4AA8,
 	.config_ctl_hi_val = 0x006,
 	.pre_div_mask = BIT(12),
 	.post_div_mask = 0x3 << 8,
+	.post_div_val = 0x1 << 8,
 	.main_output_mask = BIT(0),
 	.early_output_mask = BIT(3),
 };
@@ -101,7 +103,7 @@
 	.vco_mask = 0x3 << 20,
 	.config_ctl_val = 0x4001051b,
 	.post_div_mask = 0x3 << 8,
-	.post_div_val = 0x1,
+	.post_div_val = 0x1 << 8,
 	.main_output_mask = BIT(0),
 	.early_output_mask = BIT(3),
 };
@@ -142,6 +144,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;
 };
 
@@ -192,6 +195,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;
 
@@ -203,13 +213,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;
@@ -262,6 +278,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",
@@ -282,6 +299,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


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

* [PATCH v3 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rajendra Nayak <rnayak@codeaurora.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@codeaurora.org>
Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 75bd014..854f327 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
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
        [PLL_OFF_L_VAL] = 0x04,
@@ -56,10 +57,11 @@
 
 static const struct alpha_pll_config hfpll_config = {
 	.l = 60,
-	.config_ctl_val = 0x200d4828,
+	.config_ctl_val = 0x200D4AA8,
 	.config_ctl_hi_val = 0x006,
 	.pre_div_mask = BIT(12),
 	.post_div_mask = 0x3 << 8,
+	.post_div_val = 0x1 << 8,
 	.main_output_mask = BIT(0),
 	.early_output_mask = BIT(3),
 };
@@ -101,7 +103,7 @@
 	.vco_mask = 0x3 << 20,
 	.config_ctl_val = 0x4001051b,
 	.post_div_mask = 0x3 << 8,
-	.post_div_val = 0x1,
+	.post_div_val = 0x1 << 8,
 	.main_output_mask = BIT(0),
 	.early_output_mask = BIT(3),
 };
@@ -142,6 +144,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;
 };
 
@@ -192,6 +195,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;
 
@@ -203,13 +213,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;
@@ -262,6 +278,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",
@@ -282,6 +299,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

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

* [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
  2018-02-14 13:59 ` Ilia Lin
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, 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 | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 854f327..b0a3b73 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) { \
@@ -376,6 +376,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] 101+ messages in thread

* [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

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 | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 854f327..b0a3b73 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) { \
@@ -376,6 +376,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] 101+ messages in thread

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
  2018-02-14 13:59 ` Ilia Lin
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, celster, tfinkel

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@codeaurora.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 110 ++++++++++++++++++++++++++++++++++------
 1 file changed, 95 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index b0a3b73..1552791 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];
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
        [PLL_OFF_L_VAL] = 0x04,
@@ -67,7 +89,7 @@
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-	.offset = 0x80000,
+	.offset = PERFCL_REG_OFFSET,
 	.regs = prim_pll_regs,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
 	.clkr.hw.init = &(struct clk_init_data){
@@ -79,7 +101,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_pll = {
-	.offset = 0x0,
+	.offset = PWRCL_REG_OFFSET,
 	.regs = prim_pll_regs,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
 	.clkr.hw.init = &(struct clk_init_data){
@@ -109,7 +131,7 @@
 };
 
 static struct clk_alpha_pll perfcl_alt_pll = {
-	.offset = 0x80100,
+	.offset = PERFCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.regs = alt_pll_regs,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
@@ -123,7 +145,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_alt_pll = {
-	.offset = 0x100,
+	.offset = PWRCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.regs = alt_pll_regs,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
@@ -136,6 +158,8 @@
 	},
 };
 
+static void qcom_cpu_clk_msm8996_acd_init(void);
+
 /* Mux'es */
 
 struct clk_cpu_8996_mux {
@@ -218,6 +242,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)
@@ -225,7 +250,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;
@@ -242,7 +267,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) {
@@ -258,7 +283,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) {
@@ -274,7 +299,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,
@@ -295,7 +320,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,
@@ -399,10 +424,64 @@ 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;
@@ -415,17 +494,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);
@@ -433,6 +512,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

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

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

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@codeaurora.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 110 ++++++++++++++++++++++++++++++++++------
 1 file changed, 95 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index b0a3b73..1552791 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];
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
        [PLL_OFF_L_VAL] = 0x04,
@@ -67,7 +89,7 @@
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-	.offset = 0x80000,
+	.offset = PERFCL_REG_OFFSET,
 	.regs = prim_pll_regs,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
 	.clkr.hw.init = &(struct clk_init_data){
@@ -79,7 +101,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_pll = {
-	.offset = 0x0,
+	.offset = PWRCL_REG_OFFSET,
 	.regs = prim_pll_regs,
 	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
 	.clkr.hw.init = &(struct clk_init_data){
@@ -109,7 +131,7 @@
 };
 
 static struct clk_alpha_pll perfcl_alt_pll = {
-	.offset = 0x80100,
+	.offset = PERFCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.regs = alt_pll_regs,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
@@ -123,7 +145,7 @@
 };
 
 static struct clk_alpha_pll pwrcl_alt_pll = {
-	.offset = 0x100,
+	.offset = PWRCL_REG_OFFSET + ALT_PLL_OFFSET,
 	.regs = alt_pll_regs,
 	.vco_table = alt_pll_vco_modes,
 	.num_vco = ARRAY_SIZE(alt_pll_vco_modes),
@@ -136,6 +158,8 @@
 	},
 };
 
+static void qcom_cpu_clk_msm8996_acd_init(void);
+
 /* Mux'es */
 
 struct clk_cpu_8996_mux {
@@ -218,6 +242,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)
@@ -225,7 +250,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;
@@ -242,7 +267,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) {
@@ -258,7 +283,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) {
@@ -274,7 +299,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,
@@ -295,7 +320,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,
@@ -399,10 +424,64 @@ 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;
@@ -415,17 +494,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);
@@ -433,6 +512,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

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

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
  2018-02-14 13:59 ` Ilia Lin
  (?)
@ 2018-02-14 13:59     ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ, ilialin-sgV2jX0FEOL9JmXXK+q4OQ,
	amit.kucheria-QSEj5FYQhm4dnm+yROfE0A,
	nicolas.dechesne-QSEj5FYQhm4dnm+yROfE0A,
	celster-sgV2jX0FEOL9JmXXK+q4OQ, tfinkel-sgV2jX0FEOL9JmXXK+q4OQ

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-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts  |   4 +-
 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi        | 188 ++++++++++++++++++++++++++-
 drivers/cpufreq/cpufreq-dt-platdev.c         |   3 +
 4 files changed, 192 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..632cb42 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016,2018 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
@@ -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/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
index 492a011..930f68b 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016,2018 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
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 4b2afcc..0359197 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015,2018 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
@@ -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>;
@@ -403,7 +587,7 @@
 		};
 
 		kryocc: clock-controller@6400000 {
-			compatible = "qcom,apcc-msm8996";
+			compatible = "qcom-msm8996-apcc";
 			reg = <0x6400000 0x90000>;
 			#clock-cells = <1>;
 		};
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..b6cd0ae 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

--
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] 101+ messages in thread

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-02-14 13:59     ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, 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  |   4 +-
 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi        | 188 ++++++++++++++++++++++++++-
 drivers/cpufreq/cpufreq-dt-platdev.c         |   3 +
 4 files changed, 192 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..632cb42 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016,2018 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
@@ -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/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
index 492a011..930f68b 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016,2018 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
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 4b2afcc..0359197 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015,2018 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
@@ -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>;
@@ -403,7 +587,7 @@
 		};
 
 		kryocc: clock-controller@6400000 {
-			compatible = "qcom,apcc-msm8996";
+			compatible = "qcom-msm8996-apcc";
 			reg = <0x6400000 0x90000>;
 			#clock-cells = <1>;
 		};
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..b6cd0ae 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] 101+ messages in thread

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-02-14 13:59     ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

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  |   4 +-
 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi        | 188 ++++++++++++++++++++++++++-
 drivers/cpufreq/cpufreq-dt-platdev.c         |   3 +
 4 files changed, 192 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..632cb42 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016,2018 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
@@ -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/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
index 492a011..930f68b 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016,2018 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
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 4b2afcc..0359197 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015,2018 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
@@ -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 at 307200000 {
+			opp-hz = /bits/ 64 <  307200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 422400000 {
+			opp-hz = /bits/ 64 <  422400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 480000000 {
+			opp-hz = /bits/ 64 <  480000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 556800000 {
+			opp-hz = /bits/ 64 <  556800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 652800000 {
+			opp-hz = /bits/ 64 <  652800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 729600000 {
+			opp-hz = /bits/ 64 <  729600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 844800000 {
+			opp-hz = /bits/ 64 <  844800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 960000000 {
+			opp-hz = /bits/ 64 <  960000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1036800000 {
+			opp-hz = /bits/ 64 < 1036800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1113600000 {
+			opp-hz = /bits/ 64 < 1113600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1190400000 {
+			opp-hz = /bits/ 64 < 1190400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1228800000 {
+			opp-hz = /bits/ 64 < 1228800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1324800000 {
+			opp-hz = /bits/ 64 < 1324800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1401600000 {
+			opp-hz = /bits/ 64 < 1401600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1478400000 {
+			opp-hz = /bits/ 64 < 1478400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1593600000 {
+			opp-hz = /bits/ 64 < 1593600000 >;
+			clock-latency-ns = <200000>;
+		};
+	};
+
+	cluster1_opp: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp at 307200000 {
+			opp-hz = /bits/ 64 <  307200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 403200000 {
+			opp-hz = /bits/ 64 <  403200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 480000000 {
+			opp-hz = /bits/ 64 <  480000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 556800000 {
+			opp-hz = /bits/ 64 <  556800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 652800000 {
+			opp-hz = /bits/ 64 <  652800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 729600000 {
+			opp-hz = /bits/ 64 <  729600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 806400000 {
+			opp-hz = /bits/ 64 <  806400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 883200000 {
+			opp-hz = /bits/ 64 <  883200000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 940800000 {
+			opp-hz = /bits/ 64 <  940800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1036800000 {
+			opp-hz = /bits/ 64 < 1036800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1113600000 {
+			opp-hz = /bits/ 64 < 1113600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1190400000 {
+			opp-hz = /bits/ 64 < 1190400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1248000000 {
+			opp-hz = /bits/ 64 < 1248000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1324800000 {
+			opp-hz = /bits/ 64 < 1324800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1401600000 {
+			opp-hz = /bits/ 64 < 1401600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1478400000 {
+			opp-hz = /bits/ 64 < 1478400000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1552000000 {
+			opp-hz = /bits/ 64 < 1552000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1632000000 {
+			opp-hz = /bits/ 64 < 1632000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1708800000 {
+			opp-hz = /bits/ 64 < 1708800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1785600000 {
+			opp-hz = /bits/ 64 < 1785600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1824000000 {
+			opp-hz = /bits/ 64 < 1824000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1920000000 {
+			opp-hz = /bits/ 64 < 1920000000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 1996800000 {
+			opp-hz = /bits/ 64 < 1996800000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 2073600000 {
+			opp-hz = /bits/ 64 < 2073600000 >;
+			clock-latency-ns = <200000>;
+		};
+		opp at 2150400000 {
+			opp-hz = /bits/ 64 < 2150400000 >;
+			clock-latency-ns = <200000>;
+		};
+
+	};
 	thermal-zones {
 		cpu-thermal0 {
 			polling-delay-passive = <250>;
@@ -403,7 +587,7 @@
 		};
 
 		kryocc: clock-controller at 6400000 {
-			compatible = "qcom,apcc-msm8996";
+			compatible = "qcom-msm8996-apcc";
 			reg = <0x6400000 0x90000>;
 			#clock-cells = <1>;
 		};
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..b6cd0ae 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] 101+ messages in thread

* [PATCH v3 10/10] DT: QCOM: Add thermal mitigation to msm8996
  2018-02-14 13:59 ` Ilia Lin
@ 2018-02-14 13:59   ` Ilia Lin
  -1 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, 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 0359197..1df5b6f 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] 101+ messages in thread

* [PATCH v3 10/10] DT: QCOM: Add thermal mitigation to msm8996
@ 2018-02-14 13:59   ` Ilia Lin
  0 siblings, 0 replies; 101+ messages in thread
From: Ilia Lin @ 2018-02-14 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

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 0359197..1df5b6f 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] 101+ messages in thread

* Re: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
  2018-02-14 13:59   ` Ilia Lin
  (?)
@ 2018-02-19  3:12     ` Rob Herring
  -1 siblings, 0 replies; 101+ messages in thread
From: Rob Herring @ 2018-02-19  3:12 UTC (permalink / raw)
  To: Ilia Lin
  Cc: mark.rutland, devicetree, rnayak, linux-arm-msm, sboyd,
	will.deacon, amit.kucheria, nicolas.dechesne, celster, tfinkel,
	linux-clk, linux-arm-kernel

On Wed, Feb 14, 2018 at 03:59:46PM +0200, Ilia Lin wrote:
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

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

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

* Re: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
@ 2018-02-19  3:12     ` Rob Herring
  0 siblings, 0 replies; 101+ messages in thread
From: Rob Herring @ 2018-02-19  3:12 UTC (permalink / raw)
  To: Ilia Lin
  Cc: linux-clk, linux-arm-kernel, linux-arm-msm, sboyd, devicetree,
	mark.rutland, will.deacon, rnayak, amit.kucheria,
	nicolas.dechesne, celster, tfinkel

On Wed, Feb 14, 2018 at 03:59:46PM +0200, Ilia Lin wrote:
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

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

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

* [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
@ 2018-02-19  3:12     ` Rob Herring
  0 siblings, 0 replies; 101+ messages in thread
From: Rob Herring @ 2018-02-19  3:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 14, 2018 at 03:59:46PM +0200, Ilia Lin wrote:
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

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

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

* Re: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
  2018-02-14 13:59     ` Ilia Lin
  (?)
@ 2018-03-19 16:48       ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:51)
> diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> index 492a011..930f68b 100644
> --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2014-2016,2018 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

Why?

> diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> index 4b2afcc..0359197 100644
> --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> @@ -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 {

It looks like opp-480000000 now instead of opp@<freq>.

> +                       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 {
[...]
> +
> +       };
>         thermal-zones {
>                 cpu-thermal0 {
>                         polling-delay-passive = <250>;
> @@ -403,7 +587,7 @@
>                 };
>  
>                 kryocc: clock-controller@6400000 {
> -                       compatible = "qcom,apcc-msm8996";
> +                       compatible = "qcom-msm8996-apcc";

Bad change?

>                         reg = <0x6400000 0x90000>;
>                         #clock-cells = <1>;
>                 };
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index 3b585e4..b6cd0ae 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", },
> +

Why can't we base it on the kryocc node being present? Or even populate
the cpufreq-dt from the kryocc driver?

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

* Re: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-19 16:48       ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:48 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:51)
> diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> index 492a011..930f68b 100644
> --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2014-2016,2018 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

Why?

> diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> index 4b2afcc..0359197 100644
> --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> @@ -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 {

It looks like opp-480000000 now instead of opp@<freq>.

> +                       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 {
[...]
> +
> +       };
>         thermal-zones {
>                 cpu-thermal0 {
>                         polling-delay-passive = <250>;
> @@ -403,7 +587,7 @@
>                 };
>  
>                 kryocc: clock-controller@6400000 {
> -                       compatible = "qcom,apcc-msm8996";
> +                       compatible = "qcom-msm8996-apcc";

Bad change?

>                         reg = <0x6400000 0x90000>;
>                         #clock-cells = <1>;
>                 };
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index 3b585e4..b6cd0ae 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", },
> +

Why can't we base it on the kryocc node being present? Or even populate
the cpufreq-dt from the kryocc driver?

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

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-19 16:48       ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:48 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:51)
> diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> index 492a011..930f68b 100644
> --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2014-2016,2018 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

Why?

> diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> index 4b2afcc..0359197 100644
> --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> @@ -144,6 +152,182 @@
>                 };
>         };
>  
> +       cluster0_opp: opp_table0 {
> +               compatible = "operating-points-v2";
> +               opp-shared;
> +
> +               opp at 307200000 {
> +                       opp-hz = /bits/ 64 <  307200000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 422400000 {
> +                       opp-hz = /bits/ 64 <  422400000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 480000000 {

It looks like opp-480000000 now instead of opp@<freq>.

> +                       opp-hz = /bits/ 64 <  480000000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 556800000 {
> +                       opp-hz = /bits/ 64 <  556800000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 652800000 {
> +                       opp-hz = /bits/ 64 <  652800000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 729600000 {
> +                       opp-hz = /bits/ 64 <  729600000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 844800000 {
> +                       opp-hz = /bits/ 64 <  844800000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 960000000 {
> +                       opp-hz = /bits/ 64 <  960000000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1036800000 {
> +                       opp-hz = /bits/ 64 < 1036800000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1113600000 {
> +                       opp-hz = /bits/ 64 < 1113600000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1190400000 {
> +                       opp-hz = /bits/ 64 < 1190400000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1228800000 {
> +                       opp-hz = /bits/ 64 < 1228800000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1324800000 {
> +                       opp-hz = /bits/ 64 < 1324800000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1401600000 {
> +                       opp-hz = /bits/ 64 < 1401600000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1478400000 {
> +                       opp-hz = /bits/ 64 < 1478400000 >;
> +                       clock-latency-ns = <200000>;
> +               };
> +               opp at 1593600000 {
[...]
> +
> +       };
>         thermal-zones {
>                 cpu-thermal0 {
>                         polling-delay-passive = <250>;
> @@ -403,7 +587,7 @@
>                 };
>  
>                 kryocc: clock-controller at 6400000 {
> -                       compatible = "qcom,apcc-msm8996";
> +                       compatible = "qcom-msm8996-apcc";

Bad change?

>                         reg = <0x6400000 0x90000>;
>                         #clock-cells = <1>;
>                 };
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index 3b585e4..b6cd0ae 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", },
> +

Why can't we base it on the kryocc node being present? Or even populate
the cpufreq-dt from the kryocc driver?

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

* Re: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
  2018-02-14 13:59   ` Ilia Lin
  (?)
@ 2018-03-19 16:50     ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:50 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:49)
> The PLLs must be prepared enabled during the probe to be
> accessible by the OPPs. Otherwise an OPP may switch
> to non-enabled clock.

Sounds like an OPP problem.

> 
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
> index 854f327..b0a3b73 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>

Please leave a newline between linux/* and local includes.

>  #include "clk-alpha-pll.h"
>  
>  #define VCO(a, b, c) { \
> @@ -376,6 +376,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);

And this can't be done by the cpufreq-dt driver?

> +
> +       /* 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);

We have assigned rates in DT for this.

> +
>         ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
>         if (ret)
>                 return ret;

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

* Re: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
@ 2018-03-19 16:50     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:50 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:49)
> The PLLs must be prepared enabled during the probe to be
> accessible by the OPPs. Otherwise an OPP may switch
> to non-enabled clock.

Sounds like an OPP problem.

> 
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
> index 854f327..b0a3b73 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>

Please leave a newline between linux/* and local includes.

>  #include "clk-alpha-pll.h"
>  
>  #define VCO(a, b, c) { \
> @@ -376,6 +376,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);

And this can't be done by the cpufreq-dt driver?

> +
> +       /* 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);

We have assigned rates in DT for this.

> +
>         ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
>         if (ret)
>                 return ret;

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

* [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
@ 2018-03-19 16:50     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:50 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:49)
> The PLLs must be prepared enabled during the probe to be
> accessible by the OPPs. Otherwise an OPP may switch
> to non-enabled clock.

Sounds like an OPP problem.

> 
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
> index 854f327..b0a3b73 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>

Please leave a newline between linux/* and local includes.

>  #include "clk-alpha-pll.h"
>  
>  #define VCO(a, b, c) { \
> @@ -376,6 +376,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);

And this can't be done by the cpufreq-dt driver?

> +
> +       /* 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);

We have assigned rates in DT for this.

> +
>         ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
>         if (ret)
>                 return ret;

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

* Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
  2018-02-14 13:59   ` Ilia Lin
@ 2018-03-19 16:57     ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:57 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:50)
> diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
> index b0a3b73..1552791 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>

Put this above local includes please.

>  
>  #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
> +*/

Bad comment style and I have no idea what it means.

> +#define SSSCTL_VAL 0xF
> +
> +enum {
> +       APC_BASE,
> +       EFUSE_BASE,

Is this used? efuse should go through nvmem APIs.

> +       NUM_BASES
> +};
> +
> +static void __iomem *vbases[NUM_BASES];

Please just pass this to the function that uses it and drop EFUSE_BASE.

>  
>  static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
>         [PLL_OFF_L_VAL] = 0x04,
> @@ -399,10 +424,64 @@ 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

Please don't have #defines for random register settings. It just
obfuscates what's going on at the place where the define is used.

> +
> +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);

Please remove all useless comments, the code is obviously touching
registers.

> +
> +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
> +               /* Enable Soft Stop/Start */

Sigh.

> +               if (vbases[APC_BASE])

When is this false?

> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> +               /* Ensure SSSCTL config goes through before enabling ACD. */
> +               mb();

Use writel instead.

> +               /* Program ACD control bits */
> +               set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
> +       }
> +       if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) { //else {

What is that '// else {' stuff?

> +               /* 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();

Again, use writel.

> +       }
> +
> +       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;
> @@ -415,17 +494,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);

Cool, none of this diff is needed.

> @@ -433,6 +512,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();

Pass base here.

>  
>         data->hws[0] = &pwrcl_pmux.clkr.hw;
>         data->hws[1] = &perfcl_pmux.clkr.hw;

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

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-19 16:57     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:50)
> diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
> index b0a3b73..1552791 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>

Put this above local includes please.

>  
>  #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
> +*/

Bad comment style and I have no idea what it means.

> +#define SSSCTL_VAL 0xF
> +
> +enum {
> +       APC_BASE,
> +       EFUSE_BASE,

Is this used? efuse should go through nvmem APIs.

> +       NUM_BASES
> +};
> +
> +static void __iomem *vbases[NUM_BASES];

Please just pass this to the function that uses it and drop EFUSE_BASE.

>  
>  static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
>         [PLL_OFF_L_VAL] = 0x04,
> @@ -399,10 +424,64 @@ 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

Please don't have #defines for random register settings. It just
obfuscates what's going on at the place where the define is used.

> +
> +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);

Please remove all useless comments, the code is obviously touching
registers.

> +
> +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
> +               /* Enable Soft Stop/Start */

Sigh.

> +               if (vbases[APC_BASE])

When is this false?

> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> +               /* Ensure SSSCTL config goes through before enabling ACD. */
> +               mb();

Use writel instead.

> +               /* Program ACD control bits */
> +               set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
> +       }
> +       if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) { //else {

What is that '// else {' stuff?

> +               /* 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();

Again, use writel.

> +       }
> +
> +       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;
> @@ -415,17 +494,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);

Cool, none of this diff is needed.

> @@ -433,6 +512,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();

Pass base here.

>  
>         data->hws[0] = &pwrcl_pmux.clkr.hw;
>         data->hws[1] = &perfcl_pmux.clkr.hw;

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

* Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
  2018-02-14 13:59   ` Ilia Lin
  (?)
@ 2018-03-19 17:36     ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:36 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:45)
> 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

Thanks for the diagram. Please also put it at the top of the driver
file.

> 
> 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

Capitalize 'h' in units please.

>  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>
> ---
>  drivers/clk/qcom/Kconfig        |   8 +
>  drivers/clk/qcom/Makefile       |   1 +
>  drivers/clk/qcom/clk-cpu-8996.c | 409 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 418 insertions(+)
>  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> 
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index fbf4532..3274877 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
>           Technologies, Inc. SPMI PMIC. It configures the frequency of
>           clkdiv outputs of the PMIC. These clocks are typically wired
>           through alternate functions on GPIO pins.
> +
> +config 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.

Sort?

> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 230332c..57b38ba 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -33,6 +33,7 @@ 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

This doesn't look sorted.

>  obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
>  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
>  obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
> --- /dev/null
> +++ b/drivers/clk/qcom/clk-cpu-8996.c
> @@ -0,0 +1,409 @@
> +/*
> + * Copyright (c) 2018, 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.
> + */

Can we get the SPDX tags here please?

> +
> +#include <linux/clk.h>

clk-provider.h?

> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include "clk-alpha-pll.h"

#include "clk-regmap.h"

> +
> +#define VCO(a, b, c) { \
> +       .val = a,\
> +       .min_freq = b,\
> +       .max_freq = c,\
> +}

Can this define go into whatever PLL header file defines the struct?

> +
> +#define DIV_2_INDEX            0
> +#define PLL_INDEX              1
> +#define ACD_INDEX              2
> +#define ALT_INDEX              3
> +
> +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> +       [PLL_OFF_L_VAL] = 0x04,
> +       [PLL_OFF_ALPHA_VAL] = 0x08,
> +       [PLL_OFF_USER_CTL] = 0x10,
> +       [PLL_OFF_CONFIG_CTL] = 0x18,
> +       [PLL_OFF_CONFIG_CTL_U] = 0x1C,

Please use lowercase hex throughout. Consistency is key!

> +       [PLL_OFF_TEST_CTL] = 0x20,
> +       [PLL_OFF_TEST_CTL_U] = 0x24,
> +       [PLL_OFF_STATUS] = 0x28,
> +};
> +
> +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
> +       [PLL_OFF_L_VAL] = 0x04,
> +       [PLL_OFF_ALPHA_VAL] = 0x08,
> +       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
> +       [PLL_OFF_USER_CTL] = 0x10,
> +       [PLL_OFF_USER_CTL_U] = 0x14,
> +       [PLL_OFF_CONFIG_CTL] = 0x18,
> +       [PLL_OFF_TEST_CTL] = 0x20,
> +       [PLL_OFF_TEST_CTL_U] = 0x24,
> +       [PLL_OFF_STATUS] = 0x28,
> +};
> +
> +/* 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,
> +       .regs = prim_pll_regs,
> +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
> +       },
> +};
> +
> +static struct clk_alpha_pll pwrcl_pll = {
> +       .offset = 0x0,
> +       .regs = prim_pll_regs,
> +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
> +       .regs = alt_pll_regs,
> +       .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,
> +       .regs = alt_pll_regs,
> +       .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;

u8 shift?

> +       u32     width;

u8 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;

return val & mask;

> +}
> +
> +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       unsigned int val;

u32 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;

Does this happen?

> +
> +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> +       req->best_parent_hw = parent;

Is the parent index always the same? Perhaps just call
clk_hw_get_parent_by_index() then instead of adding a pointer to the
clk_cpu_8996_mux.

> +
> +       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_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 | CLK_IS_CRITICAL,
> +       },
> +};
> +
> +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",
> +                       "perfcl_pll_acd",
> +                       "perfcl_alt_pll",
> +               },
> +               .num_parents = 4,
> +               .ops = &clk_cpu_8996_mux_ops,
> +               .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,

Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
for now? We don't want to force XO to stay on forever here.

> +       },
> +};
> +
> +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[] = {

Move this next to driver structure and give it a more specific name.

> +       { .compatible = "qcom-msm8996-apcc" },

Bad compatible? Should be qcom,msm8996-apcc?

> +       {}
> +};
> +
> +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,

Please drop useless comments inside this array.

> +};
> +
> +struct clk_hw_clks {
> +       unsigned int num;
> +       struct clk_hw *hws[];
> +};

Please just NULL terminate the list of clk_hw pointers, or keep the
size around instead.

> +
> +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;

Maybe just open code the fixed factor clk registration? Then the
devm_clk_hw_register() function can be used on those static structs to
make removal simpler.

> +
> +       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;

Just call it regmap please.

> +       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);

Use devm_of_clk_add_hw_provider() instead.

> +
> +       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-msm8996-apcc",
> +               .of_match_table = match_table,
> +       },
> +};
> +
> +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> +
> +MODULE_ALIAS("platform:msm8996-apcc");
> +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");

Not sure why Driver is capitalized and clock is not.

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

* Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-03-19 17:36     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:36 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:45)
> 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

Thanks for the diagram. Please also put it at the top of the driver
file.

> 
> 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

Capitalize 'h' in units please.

>  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>
> ---
>  drivers/clk/qcom/Kconfig        |   8 +
>  drivers/clk/qcom/Makefile       |   1 +
>  drivers/clk/qcom/clk-cpu-8996.c | 409 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 418 insertions(+)
>  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> 
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index fbf4532..3274877 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
>           Technologies, Inc. SPMI PMIC. It configures the frequency of
>           clkdiv outputs of the PMIC. These clocks are typically wired
>           through alternate functions on GPIO pins.
> +
> +config 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.

Sort?

> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 230332c..57b38ba 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -33,6 +33,7 @@ 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

This doesn't look sorted.

>  obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
>  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
>  obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
> --- /dev/null
> +++ b/drivers/clk/qcom/clk-cpu-8996.c
> @@ -0,0 +1,409 @@
> +/*
> + * Copyright (c) 2018, 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.
> + */

Can we get the SPDX tags here please?

> +
> +#include <linux/clk.h>

clk-provider.h?

> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include "clk-alpha-pll.h"

#include "clk-regmap.h"

> +
> +#define VCO(a, b, c) { \
> +       .val = a,\
> +       .min_freq = b,\
> +       .max_freq = c,\
> +}

Can this define go into whatever PLL header file defines the struct?

> +
> +#define DIV_2_INDEX            0
> +#define PLL_INDEX              1
> +#define ACD_INDEX              2
> +#define ALT_INDEX              3
> +
> +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> +       [PLL_OFF_L_VAL] = 0x04,
> +       [PLL_OFF_ALPHA_VAL] = 0x08,
> +       [PLL_OFF_USER_CTL] = 0x10,
> +       [PLL_OFF_CONFIG_CTL] = 0x18,
> +       [PLL_OFF_CONFIG_CTL_U] = 0x1C,

Please use lowercase hex throughout. Consistency is key!

> +       [PLL_OFF_TEST_CTL] = 0x20,
> +       [PLL_OFF_TEST_CTL_U] = 0x24,
> +       [PLL_OFF_STATUS] = 0x28,
> +};
> +
> +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
> +       [PLL_OFF_L_VAL] = 0x04,
> +       [PLL_OFF_ALPHA_VAL] = 0x08,
> +       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
> +       [PLL_OFF_USER_CTL] = 0x10,
> +       [PLL_OFF_USER_CTL_U] = 0x14,
> +       [PLL_OFF_CONFIG_CTL] = 0x18,
> +       [PLL_OFF_TEST_CTL] = 0x20,
> +       [PLL_OFF_TEST_CTL_U] = 0x24,
> +       [PLL_OFF_STATUS] = 0x28,
> +};
> +
> +/* 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,
> +       .regs = prim_pll_regs,
> +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
> +       },
> +};
> +
> +static struct clk_alpha_pll pwrcl_pll = {
> +       .offset = 0x0,
> +       .regs = prim_pll_regs,
> +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
> +       .regs = alt_pll_regs,
> +       .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,
> +       .regs = alt_pll_regs,
> +       .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;

u8 shift?

> +       u32     width;

u8 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;

return val & mask;

> +}
> +
> +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       unsigned int val;

u32 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;

Does this happen?

> +
> +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> +       req->best_parent_hw = parent;

Is the parent index always the same? Perhaps just call
clk_hw_get_parent_by_index() then instead of adding a pointer to the
clk_cpu_8996_mux.

> +
> +       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_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 | CLK_IS_CRITICAL,
> +       },
> +};
> +
> +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",
> +                       "perfcl_pll_acd",
> +                       "perfcl_alt_pll",
> +               },
> +               .num_parents = 4,
> +               .ops = &clk_cpu_8996_mux_ops,
> +               .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,

Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
for now? We don't want to force XO to stay on forever here.

> +       },
> +};
> +
> +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[] = {

Move this next to driver structure and give it a more specific name.

> +       { .compatible = "qcom-msm8996-apcc" },

Bad compatible? Should be qcom,msm8996-apcc?

> +       {}
> +};
> +
> +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,

Please drop useless comments inside this array.

> +};
> +
> +struct clk_hw_clks {
> +       unsigned int num;
> +       struct clk_hw *hws[];
> +};

Please just NULL terminate the list of clk_hw pointers, or keep the
size around instead.

> +
> +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;

Maybe just open code the fixed factor clk registration? Then the
devm_clk_hw_register() function can be used on those static structs to
make removal simpler.

> +
> +       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;

Just call it regmap please.

> +       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);

Use devm_of_clk_add_hw_provider() instead.

> +
> +       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-msm8996-apcc",
> +               .of_match_table = match_table,
> +       },
> +};
> +
> +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> +
> +MODULE_ALIAS("platform:msm8996-apcc");
> +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");

Not sure why Driver is capitalized and clock is not.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-03-19 17:36     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:36 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:45)
> 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

Thanks for the diagram. Please also put it at the top of the driver
file.

> 
> 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

Capitalize 'h' in units please.

>  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>
> ---
>  drivers/clk/qcom/Kconfig        |   8 +
>  drivers/clk/qcom/Makefile       |   1 +
>  drivers/clk/qcom/clk-cpu-8996.c | 409 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 418 insertions(+)
>  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> 
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index fbf4532..3274877 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
>           Technologies, Inc. SPMI PMIC. It configures the frequency of
>           clkdiv outputs of the PMIC. These clocks are typically wired
>           through alternate functions on GPIO pins.
> +
> +config 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.

Sort?

> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 230332c..57b38ba 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -33,6 +33,7 @@ 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

This doesn't look sorted.

>  obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
>  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
>  obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
> --- /dev/null
> +++ b/drivers/clk/qcom/clk-cpu-8996.c
> @@ -0,0 +1,409 @@
> +/*
> + * Copyright (c) 2018, 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.
> + */

Can we get the SPDX tags here please?

> +
> +#include <linux/clk.h>

clk-provider.h?

> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include "clk-alpha-pll.h"

#include "clk-regmap.h"

> +
> +#define VCO(a, b, c) { \
> +       .val = a,\
> +       .min_freq = b,\
> +       .max_freq = c,\
> +}

Can this define go into whatever PLL header file defines the struct?

> +
> +#define DIV_2_INDEX            0
> +#define PLL_INDEX              1
> +#define ACD_INDEX              2
> +#define ALT_INDEX              3
> +
> +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> +       [PLL_OFF_L_VAL] = 0x04,
> +       [PLL_OFF_ALPHA_VAL] = 0x08,
> +       [PLL_OFF_USER_CTL] = 0x10,
> +       [PLL_OFF_CONFIG_CTL] = 0x18,
> +       [PLL_OFF_CONFIG_CTL_U] = 0x1C,

Please use lowercase hex throughout. Consistency is key!

> +       [PLL_OFF_TEST_CTL] = 0x20,
> +       [PLL_OFF_TEST_CTL_U] = 0x24,
> +       [PLL_OFF_STATUS] = 0x28,
> +};
> +
> +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
> +       [PLL_OFF_L_VAL] = 0x04,
> +       [PLL_OFF_ALPHA_VAL] = 0x08,
> +       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
> +       [PLL_OFF_USER_CTL] = 0x10,
> +       [PLL_OFF_USER_CTL_U] = 0x14,
> +       [PLL_OFF_CONFIG_CTL] = 0x18,
> +       [PLL_OFF_TEST_CTL] = 0x20,
> +       [PLL_OFF_TEST_CTL_U] = 0x24,
> +       [PLL_OFF_STATUS] = 0x28,
> +};
> +
> +/* 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,
> +       .regs = prim_pll_regs,
> +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
> +       },
> +};
> +
> +static struct clk_alpha_pll pwrcl_pll = {
> +       .offset = 0x0,
> +       .regs = prim_pll_regs,
> +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
> +       .regs = alt_pll_regs,
> +       .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,
> +       .regs = alt_pll_regs,
> +       .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;

u8 shift?

> +       u32     width;

u8 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;

return val & mask;

> +}
> +
> +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       unsigned int val;

u32 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;

Does this happen?

> +
> +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> +       req->best_parent_hw = parent;

Is the parent index always the same? Perhaps just call
clk_hw_get_parent_by_index() then instead of adding a pointer to the
clk_cpu_8996_mux.

> +
> +       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_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 | CLK_IS_CRITICAL,
> +       },
> +};
> +
> +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",
> +                       "perfcl_pll_acd",
> +                       "perfcl_alt_pll",
> +               },
> +               .num_parents = 4,
> +               .ops = &clk_cpu_8996_mux_ops,
> +               .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,

Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
for now? We don't want to force XO to stay on forever here.

> +       },
> +};
> +
> +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[] = {

Move this next to driver structure and give it a more specific name.

> +       { .compatible = "qcom-msm8996-apcc" },

Bad compatible? Should be qcom,msm8996-apcc?

> +       {}
> +};
> +
> +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,

Please drop useless comments inside this array.

> +};
> +
> +struct clk_hw_clks {
> +       unsigned int num;
> +       struct clk_hw *hws[];
> +};

Please just NULL terminate the list of clk_hw pointers, or keep the
size around instead.

> +
> +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;

Maybe just open code the fixed factor clk registration? Then the
devm_clk_hw_register() function can be used on those static structs to
make removal simpler.

> +
> +       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;

Just call it regmap please.

> +       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);

Use devm_of_clk_add_hw_provider() instead.

> +
> +       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-msm8996-apcc",
> +               .of_match_table = match_table,
> +       },
> +};
> +
> +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> +
> +MODULE_ALIAS("platform:msm8996-apcc");
> +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");

Not sure why Driver is capitalized and clock is not.

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

* Re: [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2018-02-14 13:59   ` Ilia Lin
  (?)
@ 2018-03-19 17:45     ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:43)
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index fbedbd8..78a103b 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -145,6 +145,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

Is this really the proposed approach? Doesn't the PMU code use these
accessors? I would think the accessors are compiled if ARCH_QCOM=y so
that the PMU stuff keeps working. Drop this Kconfig addition?

> +       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..8cece9e 100644
> --- a/drivers/perf/qcom_l2_pmu.c
> +++ b/drivers/perf/qcom_l2_pmu.c
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
> +/* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.

Sorry, this makes little sense. First off, code is only being deleted
and more than half the file isn't being modified so why update copyright
dates?

>   *
>   * 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
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index dcebf28..4e91e2a 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -12,3 +12,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..6743848
> --- /dev/null
> +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (c) 2014-2015, 2018, 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.
> + */

SPDX tags?

> diff --git a/include/soc/qcom/kryo-l2-accessors.h b/include/soc/qcom/kryo-l2-accessors.h
> new file mode 100644
> index 0000000..e9a5eab
> --- /dev/null
> +++ b/include/soc/qcom/kryo-l2-accessors.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (c) 2018, 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

Maybe change this tO __SOC_ARCH_QCOM_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);
> +#endif

This ifdef isn't doing much. Drop it? Or provide the inline nop
alternatives.

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

* Re: [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
@ 2018-03-19 17:45     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:45 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:43)
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index fbedbd8..78a103b 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -145,6 +145,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

Is this really the proposed approach? Doesn't the PMU code use these
accessors? I would think the accessors are compiled if ARCH_QCOM=y so
that the PMU stuff keeps working. Drop this Kconfig addition?

> +       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..8cece9e 100644
> --- a/drivers/perf/qcom_l2_pmu.c
> +++ b/drivers/perf/qcom_l2_pmu.c
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
> +/* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.

Sorry, this makes little sense. First off, code is only being deleted
and more than half the file isn't being modified so why update copyright
dates?

>   *
>   * 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
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index dcebf28..4e91e2a 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -12,3 +12,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..6743848
> --- /dev/null
> +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (c) 2014-2015, 2018, 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.
> + */

SPDX tags?

> diff --git a/include/soc/qcom/kryo-l2-accessors.h b/include/soc/qcom/kryo-l2-accessors.h
> new file mode 100644
> index 0000000..e9a5eab
> --- /dev/null
> +++ b/include/soc/qcom/kryo-l2-accessors.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (c) 2018, 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

Maybe change this tO __SOC_ARCH_QCOM_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);
> +#endif

This ifdef isn't doing much. Drop it? Or provide the inline nop
alternatives.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
@ 2018-03-19 17:45     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:43)
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index fbedbd8..78a103b 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -145,6 +145,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

Is this really the proposed approach? Doesn't the PMU code use these
accessors? I would think the accessors are compiled if ARCH_QCOM=y so
that the PMU stuff keeps working. Drop this Kconfig addition?

> +       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..8cece9e 100644
> --- a/drivers/perf/qcom_l2_pmu.c
> +++ b/drivers/perf/qcom_l2_pmu.c
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
> +/* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.

Sorry, this makes little sense. First off, code is only being deleted
and more than half the file isn't being modified so why update copyright
dates?

>   *
>   * 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
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index dcebf28..4e91e2a 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -12,3 +12,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..6743848
> --- /dev/null
> +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (c) 2014-2015, 2018, 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.
> + */

SPDX tags?

> diff --git a/include/soc/qcom/kryo-l2-accessors.h b/include/soc/qcom/kryo-l2-accessors.h
> new file mode 100644
> index 0000000..e9a5eab
> --- /dev/null
> +++ b/include/soc/qcom/kryo-l2-accessors.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (c) 2018, 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

Maybe change this tO __SOC_ARCH_QCOM_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);
> +#endif

This ifdef isn't doing much. Drop it? Or provide the inline nop
alternatives.

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

* Re: [PATCH v3 02/10] clk: qcom: Make clk_alpha_pll_configure available to modules
  2018-02-14 13:59   ` Ilia Lin
  (?)
@ 2018-03-19 17:45     ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:44)
> 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>
> ---

Applied to clk-next

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

* Re: [PATCH v3 02/10] clk: qcom: Make clk_alpha_pll_configure available to modules
@ 2018-03-19 17:45     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:45 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: devicetree, robh, mark.rutland, will.deacon, rnayak, ilialin,
	amit.kucheria, nicolas.dechesne, celster, tfinkel

Quoting Ilia Lin (2018-02-14 05:59:44)
> 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>
> ---

Applied to clk-next


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

* [PATCH v3 02/10] clk: qcom: Make clk_alpha_pll_configure available to modules
@ 2018-03-19 17:45     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:44)
> 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>
> ---

Applied to clk-next

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

* Re: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
  2018-02-14 13:59   ` Ilia Lin
  (?)
@ 2018-03-19 17:46     ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:46 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:46)
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> new file mode 100644
> index 0000000..e7cf15a
> --- /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-msm8996-apcc"

Do you mean qcom,msm8996-apcc?

Rob?

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

* Re: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
@ 2018-03-19 17:46     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:46 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:46)
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> new file mode 100644
> index 0000000..e7cf15a
> --- /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-msm8996-apcc"

Do you mean qcom,msm8996-apcc?

Rob?

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

* [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
@ 2018-03-19 17:46     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:46)
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> new file mode 100644
> index 0000000..e7cf15a
> --- /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-msm8996-apcc"

Do you mean qcom,msm8996-apcc?

Rob?

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

* Re: [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
  2018-02-14 13:59     ` Ilia Lin
  (?)
@ 2018-03-19 17:47       ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:47 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:47)
> From: Rajendra Nayak <rnayak@codeaurora.org>
> 
> Each of the CPU clusters on msm8996 and powered via a primary

s/and/are/

> PLL and a secondary PLL. The primary PLL is what drivers the

s/drivers/drives/

I make the same typo all the time!

> 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@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
> --- a/drivers/clk/qcom/clk-cpu-8996.c
> +++ b/drivers/clk/qcom/clk-cpu-8996.c
> @@ -140,10 +140,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)
>  {
> @@ -194,6 +198,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,
> @@ -237,6 +262,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 *[]){
> @@ -256,6 +282,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 *[]){
> @@ -331,6 +358,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;
> +

Please resend this with the other patches that need rework.

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

* Re: [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
@ 2018-03-19 17:47       ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:47 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:47)
> From: Rajendra Nayak <rnayak@codeaurora.org>
> 
> Each of the CPU clusters on msm8996 and powered via a primary

s/and/are/

> PLL and a secondary PLL. The primary PLL is what drivers the

s/drivers/drives/

I make the same typo all the time!

> 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@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
> --- a/drivers/clk/qcom/clk-cpu-8996.c
> +++ b/drivers/clk/qcom/clk-cpu-8996.c
> @@ -140,10 +140,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)
>  {
> @@ -194,6 +198,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,
> @@ -237,6 +262,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 *[]){
> @@ -256,6 +282,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 *[]){
> @@ -331,6 +358,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;
> +

Please resend this with the other patches that need rework.

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

* [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
@ 2018-03-19 17:47       ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:47)
> From: Rajendra Nayak <rnayak@codeaurora.org>
> 
> Each of the CPU clusters on msm8996 and powered via a primary

s/and/are/

> PLL and a secondary PLL. The primary PLL is what drivers the

s/drivers/drives/

I make the same typo all the time!

> 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@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
> --- a/drivers/clk/qcom/clk-cpu-8996.c
> +++ b/drivers/clk/qcom/clk-cpu-8996.c
> @@ -140,10 +140,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)
>  {
> @@ -194,6 +198,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,
> @@ -237,6 +262,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 *[]){
> @@ -256,6 +282,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 *[]){
> @@ -331,6 +358,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;
> +

Please resend this with the other patches that need rework.

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

* Re: [PATCH v3 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz
  2018-02-14 13:59   ` Ilia Lin
  (?)
@ 2018-03-19 17:49     ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:48)
> From: Rajendra Nayak <rnayak@codeaurora.org>
> 
> The CPU clock controllers primary PLL operates on a single VCO range,

s/controllers/controller's/

> between 600Mhz and 3Ghz. However the CPUs do support OPPs with
> frequencies between 300Mhz and 600Mhz. In order to support running the

capitalize 'h' in units please.

> 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@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>

Rest looks ok, please resend.

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

* Re: [PATCH v3 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz
@ 2018-03-19 17:49     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:49 UTC (permalink / raw)
  To: Ilia Lin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, ilialin, nicolas.dechesne, celster

Quoting Ilia Lin (2018-02-14 05:59:48)
> From: Rajendra Nayak <rnayak@codeaurora.org>
> 
> The CPU clock controllers primary PLL operates on a single VCO range,

s/controllers/controller's/

> between 600Mhz and 3Ghz. However the CPUs do support OPPs with
> frequencies between 300Mhz and 600Mhz. In order to support running the

capitalize 'h' in units please.

> 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@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>

Rest looks ok, please resend.

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

* [PATCH v3 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz
@ 2018-03-19 17:49     ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ilia Lin (2018-02-14 05:59:48)
> From: Rajendra Nayak <rnayak@codeaurora.org>
> 
> The CPU clock controllers primary PLL operates on a single VCO range,

s/controllers/controller's/

> between 600Mhz and 3Ghz. However the CPUs do support OPPs with
> frequencies between 300Mhz and 600Mhz. In order to support running the

capitalize 'h' in units please.

> 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@codeaurora.org>
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>

Rest looks ok, please resend.

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

* Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
  2018-03-19 16:57     ` Stephen Boyd
  (?)
@ 2018-03-19 18:16       ` Robin Murphy
  -1 siblings, 0 replies; 101+ messages in thread
From: Robin Murphy @ 2018-03-19 18:16 UTC (permalink / raw)
  To: Stephen Boyd, Ilia Lin, linux-arm-kernel, linux-arm-msm,
	linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

On 19/03/18 16:57, Stephen Boyd wrote:
[...]
>> +
>> +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
>> +               /* Enable Soft Stop/Start */
> 
> Sigh.
> 
>> +               if (vbases[APC_BASE])
> 
> When is this false?
> 
>> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
>> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
>> +               /* Ensure SSSCTL config goes through before enabling ACD. */
>> +               mb();
> 
> Use writel instead.

Note that writel() only gives an implicit wmb() *before* the store to 
ensure ordering against any previous writes. If this code really needs 
to ensure that the given write has definitely completed before any other 
accesses happen, then it still needs an explicit barrier *after* the 
write*(), unless perhaps the next access is always guaranteed to be a 
non-relaxed write (thus implicitly providing a suitable DSB).

Robin.

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

* Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-19 18:16       ` Robin Murphy
  0 siblings, 0 replies; 101+ messages in thread
From: Robin Murphy @ 2018-03-19 18:16 UTC (permalink / raw)
  To: Stephen Boyd, Ilia Lin, linux-arm-kernel, linux-arm-msm,
	linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

On 19/03/18 16:57, Stephen Boyd wrote:
[...]
>> +
>> +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
>> +               /* Enable Soft Stop/Start */
> 
> Sigh.
> 
>> +               if (vbases[APC_BASE])
> 
> When is this false?
> 
>> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
>> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
>> +               /* Ensure SSSCTL config goes through before enabling ACD. */
>> +               mb();
> 
> Use writel instead.

Note that writel() only gives an implicit wmb() *before* the store to 
ensure ordering against any previous writes. If this code really needs 
to ensure that the given write has definitely completed before any other 
accesses happen, then it still needs an explicit barrier *after* the 
write*(), unless perhaps the next access is always guaranteed to be a 
non-relaxed write (thus implicitly providing a suitable DSB).

Robin.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-19 18:16       ` Robin Murphy
  0 siblings, 0 replies; 101+ messages in thread
From: Robin Murphy @ 2018-03-19 18:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/03/18 16:57, Stephen Boyd wrote:
[...]
>> +
>> +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
>> +               /* Enable Soft Stop/Start */
> 
> Sigh.
> 
>> +               if (vbases[APC_BASE])
> 
> When is this false?
> 
>> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
>> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
>> +               /* Ensure SSSCTL config goes through before enabling ACD. */
>> +               mb();
> 
> Use writel instead.

Note that writel() only gives an implicit wmb() *before* the store to 
ensure ordering against any previous writes. If this code really needs 
to ensure that the given write has definitely completed before any other 
accesses happen, then it still needs an explicit barrier *after* the 
write*(), unless perhaps the next access is always guaranteed to be a 
non-relaxed write (thus implicitly providing a suitable DSB).

Robin.

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

* Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
  2018-03-19 18:16       ` Robin Murphy
@ 2018-03-19 21:21         ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 21:21 UTC (permalink / raw)
  To: Ilia Lin, Robin Murphy, linux-arm-kernel, linux-arm-msm,
	linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Quoting Robin Murphy (2018-03-19 11:16:15)
> On 19/03/18 16:57, Stephen Boyd wrote:
> [...]
> >> +
> > 
> >> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
> >> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> >> +               /* Ensure SSSCTL config goes through before enabling ACD. */
> >> +               mb();
> > 
> > Use writel instead.
> 
> Note that writel() only gives an implicit wmb() *before* the store to 
> ensure ordering against any previous writes. If this code really needs 
> to ensure that the given write has definitely completed before any other 
> accesses happen, then it still needs an explicit barrier *after* the 
> write*(), unless perhaps the next access is always guaranteed to be a 
> non-relaxed write (thus implicitly providing a suitable DSB).
> 

Ah right. So this should be a wmb() too? I suspect it's to order with
the write to the l2 indirect registers, but reading that register before
the MMIO write is not a problem. The comment above the l2 accessors
could be slightly more specific here and it would help immensely.

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

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-19 21:21         ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-19 21:21 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Robin Murphy (2018-03-19 11:16:15)
> On 19/03/18 16:57, Stephen Boyd wrote:
> [...]
> >> +
> > 
> >> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
> >> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> >> +               /* Ensure SSSCTL config goes through before enabling ACD. */
> >> +               mb();
> > 
> > Use writel instead.
> 
> Note that writel() only gives an implicit wmb() *before* the store to 
> ensure ordering against any previous writes. If this code really needs 
> to ensure that the given write has definitely completed before any other 
> accesses happen, then it still needs an explicit barrier *after* the 
> write*(), unless perhaps the next access is always guaranteed to be a 
> non-relaxed write (thus implicitly providing a suitable DSB).
> 

Ah right. So this should be a wmb() too? I suspect it's to order with
the write to the l2 indirect registers, but reading that register before
the MMIO write is not a problem. The comment above the l2 accessors
could be slightly more specific here and it would help immensely.

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

* RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
  2018-03-19 16:48       ` Stephen Boyd
  (?)
@ 2018-03-20 13:46         ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 13:46 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:49
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:51)
> > diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > index 492a011..930f68b 100644
> > --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
> > + * Copyright (c) 2014-2016,2018 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
> 
> Why?
The file was changed again in 2018. I'm reflecting this in the file dates.
> 
> > diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > index 4b2afcc..0359197 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > @@ -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 {
> 
> It looks like opp-480000000 now instead of opp@<freq>.
Will be changed in the next spin.
> 
> > +                       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 {
> [...]
> > +
> > +       };
> >         thermal-zones {
> >                 cpu-thermal0 {
> >                         polling-delay-passive = <250>; @@ -403,7
> > +587,7 @@
> >                 };
> >
> >                 kryocc: clock-controller@6400000 {
> > -                       compatible = "qcom,apcc-msm8996";
> > +                       compatible = "qcom-msm8996-apcc";
> 
> Bad change?
This was required by Rob Herring.
> 
> >                         reg = <0x6400000 0x90000>;
> >                         #clock-cells = <1>;
> >                 };
> > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > index 3b585e4..b6cd0ae 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", },
> > +
> 
> Why can't we base it on the kryocc node being present?
This could be good idea, if I would writing a platform specific cpufreq driver, which may be a future option.
> Or even populate
> the cpufreq-dt from the kryocc driver?
There is a problem that during the clock probe the OPP table still doesn't exist. 

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

* RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-20 13:46         ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 13:46 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:49
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:51)
> > diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > index 492a011..930f68b 100644
> > --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
> > + * Copyright (c) 2014-2016,2018 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
> 
> Why?
The file was changed again in 2018. I'm reflecting this in the file dates.
> 
> > diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > index 4b2afcc..0359197 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > @@ -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 {
> 
> It looks like opp-480000000 now instead of opp@<freq>.
Will be changed in the next spin.
> 
> > +                       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 {
> [...]
> > +
> > +       };
> >         thermal-zones {
> >                 cpu-thermal0 {
> >                         polling-delay-passive = <250>; @@ -403,7
> > +587,7 @@
> >                 };
> >
> >                 kryocc: clock-controller@6400000 {
> > -                       compatible = "qcom,apcc-msm8996";
> > +                       compatible = "qcom-msm8996-apcc";
> 
> Bad change?
This was required by Rob Herring.
> 
> >                         reg = <0x6400000 0x90000>;
> >                         #clock-cells = <1>;
> >                 };
> > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > index 3b585e4..b6cd0ae 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", },
> > +
> 
> Why can't we base it on the kryocc node being present?
This could be good idea, if I would writing a platform specific cpufreq driver, which may be a future option.
> Or even populate
> the cpufreq-dt from the kryocc driver?
There is a problem that during the clock probe the OPP table still doesn't exist. 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-20 13:46         ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 13:46 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:49
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:51)
> > diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > index 492a011..930f68b 100644
> > --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
> > + * Copyright (c) 2014-2016,2018 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
> 
> Why?
The file was changed again in 2018. I'm reflecting this in the file dates.
> 
> > diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > index 4b2afcc..0359197 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > @@ -144,6 +152,182 @@
> >                 };
> >         };
> >
> > +       cluster0_opp: opp_table0 {
> > +               compatible = "operating-points-v2";
> > +               opp-shared;
> > +
> > +               opp at 307200000 {
> > +                       opp-hz = /bits/ 64 <  307200000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 422400000 {
> > +                       opp-hz = /bits/ 64 <  422400000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 480000000 {
> 
> It looks like opp-480000000 now instead of opp@<freq>.
Will be changed in the next spin.
> 
> > +                       opp-hz = /bits/ 64 <  480000000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 556800000 {
> > +                       opp-hz = /bits/ 64 <  556800000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 652800000 {
> > +                       opp-hz = /bits/ 64 <  652800000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 729600000 {
> > +                       opp-hz = /bits/ 64 <  729600000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 844800000 {
> > +                       opp-hz = /bits/ 64 <  844800000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 960000000 {
> > +                       opp-hz = /bits/ 64 <  960000000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1036800000 {
> > +                       opp-hz = /bits/ 64 < 1036800000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1113600000 {
> > +                       opp-hz = /bits/ 64 < 1113600000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1190400000 {
> > +                       opp-hz = /bits/ 64 < 1190400000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1228800000 {
> > +                       opp-hz = /bits/ 64 < 1228800000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1324800000 {
> > +                       opp-hz = /bits/ 64 < 1324800000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1401600000 {
> > +                       opp-hz = /bits/ 64 < 1401600000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1478400000 {
> > +                       opp-hz = /bits/ 64 < 1478400000 >;
> > +                       clock-latency-ns = <200000>;
> > +               };
> > +               opp at 1593600000 {
> [...]
> > +
> > +       };
> >         thermal-zones {
> >                 cpu-thermal0 {
> >                         polling-delay-passive = <250>; @@ -403,7
> > +587,7 @@
> >                 };
> >
> >                 kryocc: clock-controller at 6400000 {
> > -                       compatible = "qcom,apcc-msm8996";
> > +                       compatible = "qcom-msm8996-apcc";
> 
> Bad change?
This was required by Rob Herring.
> 
> >                         reg = <0x6400000 0x90000>;
> >                         #clock-cells = <1>;
> >                 };
> > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > index 3b585e4..b6cd0ae 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", },
> > +
> 
> Why can't we base it on the kryocc node being present?
This could be good idea, if I would writing a platform specific cpufreq driver, which may be a future option.
> Or even populate
> the cpufreq-dt from the kryocc driver?
There is a problem that during the clock probe the OPP table still doesn't exist. 

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

* RE: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
  2018-03-19 16:50     ` Stephen Boyd
  (?)
@ 2018-03-20 13:53       ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 13:53 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:50
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
> 
> Quoting Ilia Lin (2018-02-14 05:59:49)
> > The PLLs must be prepared enabled during the probe to be accessible by
> > the OPPs. Otherwise an OPP may switch to non-enabled clock.
> 
> Sounds like an OPP problem.

And again, it could be solved by a platform specific cpufreq driver. Worth it?

> 
> >
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >  drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++-
> >  1 file changed, 13 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/qcom/clk-cpu-8996.c
> > b/drivers/clk/qcom/clk-cpu-8996.c index 854f327..b0a3b73 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>
> 
> Please leave a newline between linux/* and local includes.

Will be changed in the next spin.

> 
> >  #include "clk-alpha-pll.h"
> >
> >  #define VCO(a, b, c) { \
> > @@ -376,6 +376,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);
> 
> And this can't be done by the cpufreq-dt driver?

Are you suggesting changing the cpufreq-dt as well?

> 
> > +
> > +       /* 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);
> 
> We have assigned rates in DT for this.

I assumed that the clock driver can live without the OPP table and any cpufreq driver. Or do you mean adding this as parameters for the kryocc DT node?

> 
> > +
> >         ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
> >         if (ret)
> >                 return ret;

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

* RE: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
@ 2018-03-20 13:53       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 13:53 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:50
> To: Ilia Lin <ilialin@codeaurora.org>; =
linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; =
ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on =
probe
>=20
> Quoting Ilia Lin (2018-02-14 05:59:49)
> > The PLLs must be prepared enabled during the probe to be accessible =
by
> > the OPPs. Otherwise an OPP may switch to non-enabled clock.
>=20
> Sounds like an OPP problem.

And again, it could be solved by a platform specific cpufreq driver. =
Worth it?

>=20
> >
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >  drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++-
> >  1 file changed, 13 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/qcom/clk-cpu-8996.c
> > b/drivers/clk/qcom/clk-cpu-8996.c index 854f327..b0a3b73 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>
>=20
> Please leave a newline between linux/* and local includes.

Will be changed in the next spin.

>=20
> >  #include "clk-alpha-pll.h"
> >
> >  #define VCO(a, b, c) { \
> > @@ -376,6 +376,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);
>=20
> And this can't be done by the cpufreq-dt driver?

Are you suggesting changing the cpufreq-dt as well?

>=20
> > +
> > +       /* 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);
>=20
> We have assigned rates in DT for this.

I assumed that the clock driver can live without the OPP table and any =
cpufreq driver. Or do you mean adding this as parameters for the kryocc =
DT node?

>=20
> > +
> >         ret =3D clk_notifier_register(pwrcl_pmux.clkr.hw.clk, =
&pwrcl_pmux.nb);
> >         if (ret)
> >                 return ret;


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

* [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
@ 2018-03-20 13:53       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 13:53 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:50
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
> 
> Quoting Ilia Lin (2018-02-14 05:59:49)
> > The PLLs must be prepared enabled during the probe to be accessible by
> > the OPPs. Otherwise an OPP may switch to non-enabled clock.
> 
> Sounds like an OPP problem.

And again, it could be solved by a platform specific cpufreq driver. Worth it?

> 
> >
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >  drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++-
> >  1 file changed, 13 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/qcom/clk-cpu-8996.c
> > b/drivers/clk/qcom/clk-cpu-8996.c index 854f327..b0a3b73 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>
> 
> Please leave a newline between linux/* and local includes.

Will be changed in the next spin.

> 
> >  #include "clk-alpha-pll.h"
> >
> >  #define VCO(a, b, c) { \
> > @@ -376,6 +376,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);
> 
> And this can't be done by the cpufreq-dt driver?

Are you suggesting changing the cpufreq-dt as well?

> 
> > +
> > +       /* 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);
> 
> We have assigned rates in DT for this.

I assumed that the clock driver can live without the OPP table and any cpufreq driver. Or do you mean adding this as parameters for the kryocc DT node?

> 
> > +
> >         ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
> >         if (ret)
> >                 return ret;

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

* RE: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
  2018-03-19 16:57     ` Stephen Boyd
  (?)
@ 2018-03-20 14:04       ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 14:04 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:57
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver
> for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:50)
> > diff --git a/drivers/clk/qcom/clk-cpu-8996.c
> > b/drivers/clk/qcom/clk-cpu-8996.c index b0a3b73..1552791 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>
> 
> Put this above local includes please.

Will be changed in the next spin.

> 
> >
> >  #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
> > +*/
> 
> Bad comment style and I have no idea what it means.

Will be changed in the next spin.

> 
> > +#define SSSCTL_VAL 0xF
> > +
> > +enum {
> > +       APC_BASE,
> > +       EFUSE_BASE,
> 
> Is this used? efuse should go through nvmem APIs.

Will be removed in the next spin.

> 
> > +       NUM_BASES
> > +};
> > +
> > +static void __iomem *vbases[NUM_BASES];
> 
> Please just pass this to the function that uses it and drop EFUSE_BASE.

Will be changed in the next spin.

> 
> >
> >  static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> >         [PLL_OFF_L_VAL] = 0x04,
> > @@ -399,10 +424,64 @@ 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
> 
> Please don't have #defines for random register settings. It just obfuscates
> what's going on at the place where the define is used.

So should I just use the values directly?

> 
> > +
> > +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);
> 
> Please remove all useless comments, the code is obviously touching
> registers.

Will be changed in the next spin.

> 
> > +
> > +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
> > +               /* Enable Soft Stop/Start */
> 
> Sigh.
> 
> > +               if (vbases[APC_BASE])
> 
> When is this false?

It is checked in the probe. You are right, I'll remove this check and pass the base as argument.

> 
> > +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
> > +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> > +               /* Ensure SSSCTL config goes through before enabling ACD. */
> > +               mb();
> 
> Use writel instead.

OK

> 
> > +               /* Program ACD control bits */
> > +               set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
> > +       }
> > +       if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) {
> > + //else {
> 
> What is that '// else {' stuff?

Missed leftover. Will be changed in the next spin.

> 
> > +               /* 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();
> 
> Again, use writel.

OK

> 
> > +       }
> > +
> > +       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;
> > @@ -415,17 +494,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);
> 
> Cool, none of this diff is needed.

Since the effuse code will not be implemented in the clock driver, you are right. Will be changed in the next spin.

> 
> > @@ -433,6 +512,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();
> 
> Pass base here.

Sure.

> 
> >
> >         data->hws[0] = &pwrcl_pmux.clkr.hw;
> >         data->hws[1] = &perfcl_pmux.clkr.hw;

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

* RE: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-20 14:04       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 14:04 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:57
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver
> for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:50)
> > diff --git a/drivers/clk/qcom/clk-cpu-8996.c
> > b/drivers/clk/qcom/clk-cpu-8996.c index b0a3b73..1552791 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>
> 
> Put this above local includes please.

Will be changed in the next spin.

> 
> >
> >  #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
> > +*/
> 
> Bad comment style and I have no idea what it means.

Will be changed in the next spin.

> 
> > +#define SSSCTL_VAL 0xF
> > +
> > +enum {
> > +       APC_BASE,
> > +       EFUSE_BASE,
> 
> Is this used? efuse should go through nvmem APIs.

Will be removed in the next spin.

> 
> > +       NUM_BASES
> > +};
> > +
> > +static void __iomem *vbases[NUM_BASES];
> 
> Please just pass this to the function that uses it and drop EFUSE_BASE.

Will be changed in the next spin.

> 
> >
> >  static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> >         [PLL_OFF_L_VAL] = 0x04,
> > @@ -399,10 +424,64 @@ 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
> 
> Please don't have #defines for random register settings. It just obfuscates
> what's going on at the place where the define is used.

So should I just use the values directly?

> 
> > +
> > +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);
> 
> Please remove all useless comments, the code is obviously touching
> registers.

Will be changed in the next spin.

> 
> > +
> > +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
> > +               /* Enable Soft Stop/Start */
> 
> Sigh.
> 
> > +               if (vbases[APC_BASE])
> 
> When is this false?

It is checked in the probe. You are right, I'll remove this check and pass the base as argument.

> 
> > +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
> > +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> > +               /* Ensure SSSCTL config goes through before enabling ACD. */
> > +               mb();
> 
> Use writel instead.

OK

> 
> > +               /* Program ACD control bits */
> > +               set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
> > +       }
> > +       if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) {
> > + //else {
> 
> What is that '// else {' stuff?

Missed leftover. Will be changed in the next spin.

> 
> > +               /* 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();
> 
> Again, use writel.

OK

> 
> > +       }
> > +
> > +       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;
> > @@ -415,17 +494,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);
> 
> Cool, none of this diff is needed.

Since the effuse code will not be implemented in the clock driver, you are right. Will be changed in the next spin.

> 
> > @@ -433,6 +512,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();
> 
> Pass base here.

Sure.

> 
> >
> >         data->hws[0] = &pwrcl_pmux.clkr.hw;
> >         data->hws[1] = &perfcl_pmux.clkr.hw;


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-20 14:04       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 14:04 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 18:57
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver
> for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:50)
> > diff --git a/drivers/clk/qcom/clk-cpu-8996.c
> > b/drivers/clk/qcom/clk-cpu-8996.c index b0a3b73..1552791 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>
> 
> Put this above local includes please.

Will be changed in the next spin.

> 
> >
> >  #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
> > +*/
> 
> Bad comment style and I have no idea what it means.

Will be changed in the next spin.

> 
> > +#define SSSCTL_VAL 0xF
> > +
> > +enum {
> > +       APC_BASE,
> > +       EFUSE_BASE,
> 
> Is this used? efuse should go through nvmem APIs.

Will be removed in the next spin.

> 
> > +       NUM_BASES
> > +};
> > +
> > +static void __iomem *vbases[NUM_BASES];
> 
> Please just pass this to the function that uses it and drop EFUSE_BASE.

Will be changed in the next spin.

> 
> >
> >  static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> >         [PLL_OFF_L_VAL] = 0x04,
> > @@ -399,10 +424,64 @@ 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
> 
> Please don't have #defines for random register settings. It just obfuscates
> what's going on at the place where the define is used.

So should I just use the values directly?

> 
> > +
> > +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);
> 
> Please remove all useless comments, the code is obviously touching
> registers.

Will be changed in the next spin.

> 
> > +
> > +       if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
> > +               /* Enable Soft Stop/Start */
> 
> Sigh.
> 
> > +               if (vbases[APC_BASE])
> 
> When is this false?

It is checked in the probe. You are right, I'll remove this check and pass the base as argument.

> 
> > +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
> > +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> > +               /* Ensure SSSCTL config goes through before enabling ACD. */
> > +               mb();
> 
> Use writel instead.

OK

> 
> > +               /* Program ACD control bits */
> > +               set_l2_indirect_reg(L2ACDCR_REG, ACDCR_VAL);
> > +       }
> > +       if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) {
> > + //else {
> 
> What is that '// else {' stuff?

Missed leftover. Will be changed in the next spin.

> 
> > +               /* 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();
> 
> Again, use writel.

OK

> 
> > +       }
> > +
> > +       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;
> > @@ -415,17 +494,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);
> 
> Cool, none of this diff is needed.

Since the effuse code will not be implemented in the clock driver, you are right. Will be changed in the next spin.

> 
> > @@ -433,6 +512,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();
> 
> Pass base here.

Sure.

> 
> >
> >         data->hws[0] = &pwrcl_pmux.clkr.hw;
> >         data->hws[1] = &perfcl_pmux.clkr.hw;

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

* RE: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
  2018-03-19 17:36     ` Stephen Boyd
  (?)
@ 2018-03-20 14:18       ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 14:18 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:37
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:45)
> > 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
> 
> Thanks for the diagram. Please also put it at the top of the driver file.

Will be added in the next spin.

> 
> >
> > 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
> 
> Capitalize 'h' in units please.

OK

> 
> >  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>
> > ---
> >  drivers/clk/qcom/Kconfig        |   8 +
> >  drivers/clk/qcom/Makefile       |   1 +
> >  drivers/clk/qcom/clk-cpu-8996.c | 409
> > ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 418 insertions(+)
> >  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> >
> > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index
> > fbf4532..3274877 100644
> > --- a/drivers/clk/qcom/Kconfig
> > +++ b/drivers/clk/qcom/Kconfig
> > @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
> >           Technologies, Inc. SPMI PMIC. It configures the frequency of
> >           clkdiv outputs of the PMIC. These clocks are typically wired
> >           through alternate functions on GPIO pins.
> > +
> > +config 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.
> 
> Sort?

Will be changed in the next spin.

> 
> > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> > index 230332c..57b38ba 100644
> > --- a/drivers/clk/qcom/Makefile
> > +++ b/drivers/clk/qcom/Makefile
> > @@ -33,6 +33,7 @@ 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
> 
> This doesn't look sorted.

Will be changed in the next spin.

> 
> >  obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
> >  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
> >  obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
> > --- /dev/null
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -0,0 +1,409 @@
> > +/*
> > + * Copyright (c) 2018, 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.
> > + */
> 
> Can we get the SPDX tags here please?

Will be changed in the next spin.

> 
> > +
> > +#include <linux/clk.h>
> 
> clk-provider.h?
> 
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "clk-alpha-pll.h"
> 
> #include "clk-regmap.h"
> 
> > +
> > +#define VCO(a, b, c) { \
> > +       .val = a,\
> > +       .min_freq = b,\
> > +       .max_freq = c,\
> > +}
> 
> Can this define go into whatever PLL header file defines the struct?

Will be changed in the next spin.

> 
> > +
> > +#define DIV_2_INDEX            0
> > +#define PLL_INDEX              1
> > +#define ACD_INDEX              2
> > +#define ALT_INDEX              3
> > +
> > +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_CONFIG_CTL_U] = 0x1C,
> 
> Please use lowercase hex throughout. Consistency is key!

Will be changed in the next spin.

> 
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_USER_CTL_U] = 0x14,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +/* 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,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_pll = {
> > +       .offset = 0x0,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
> > +       .regs = alt_pll_regs,
> > +       .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,
> > +       .regs = alt_pll_regs,
> > +       .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;
> 
> u8 shift?

Will be changed in the next spin.

> 
> > +       u32     width;
> 
> u8 width?

Will be changed in the next spin.

> 
> > +       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;
> 
> return val & mask;

struct clk_cpu_8996_mux *

> 
> > +}
> > +
> > +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index) {
> > +       unsigned int val;
> 
> u32 val?

Will be changed in the next spin.

> 
> > +       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;
> 
> Does this happen?

On successful probe it shouldn't. May I omit pointer checks in this case? Future maintenance ma y change the flow.

> 
> > +
> > +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> > +       req->best_parent_hw = parent;
> 
> Is the parent index always the same? Perhaps just call
> clk_hw_get_parent_by_index() then instead of adding a pointer to the
> clk_cpu_8996_mux.
> 
> > +
> > +       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_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 | CLK_IS_CRITICAL,
> > +       },
> > +};
> > +
> > +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",
> > +                       "perfcl_pll_acd",
> > +                       "perfcl_alt_pll",
> > +               },
> > +               .num_parents = 4,
> > +               .ops = &clk_cpu_8996_mux_ops,
> > +               .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> 
> Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
> for now? We don't want to force XO to stay on forever here.

Have to unit test this.

> 
> > +       },
> > +};
> > +
> > +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[] = {
> 
> Move this next to driver structure and give it a more specific name.

Will be changed in the next spin.

> 
> > +       { .compatible = "qcom-msm8996-apcc" },
> 
> Bad compatible? Should be qcom,msm8996-apcc?

The naming is per Rob Herring's requirement.

> 
> > +       {}
> > +};
> > +
> > +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,
> 
> Please drop useless comments inside this array.

Will be changed in the next spin.

> 
> > +};
> > +
> > +struct clk_hw_clks {
> > +       unsigned int num;
> > +       struct clk_hw *hws[];
> > +};
> 
> Please just NULL terminate the list of clk_hw pointers, or keep the size
> around instead.

Will be changed in the next spin.

> 
> > +
> > +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;
> 
> Maybe just open code the fixed factor clk registration? Then the
> devm_clk_hw_register() function can be used on those static structs to make
> removal simpler.

I will check this.

> 
> > +
> > +       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;
> 
> Just call it regmap please.

Will be changed in the next spin.

> 
> > +       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);
> 
> Use devm_of_clk_add_hw_provider() instead.

Will be changed in the next spin.

> 
> > +
> > +       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-msm8996-apcc",
> > +               .of_match_table = match_table,
> > +       },
> > +};
> > +
> > +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> > +
> > +MODULE_ALIAS("platform:msm8996-apcc");
> > +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
> 
> Not sure why Driver is capitalized and clock is not.

Will be changed in the next spin.

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

* RE: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-03-20 14:18       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 14:18 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:37
> To: Ilia Lin <ilialin@codeaurora.org>; =
linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; =
ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for =
msm8996
>=20
> Quoting Ilia Lin (2018-02-14 05:59:45)
> > 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
>=20
> Thanks for the diagram. Please also put it at the top of the driver =
file.

Will be added in the next spin.

>=20
> >
> > 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
>=20
> Capitalize 'h' in units please.

OK

>=20
> >  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>
> > ---
> >  drivers/clk/qcom/Kconfig        |   8 +
> >  drivers/clk/qcom/Makefile       |   1 +
> >  drivers/clk/qcom/clk-cpu-8996.c | 409
> > ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 418 insertions(+)
> >  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> >
> > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig =
index
> > fbf4532..3274877 100644
> > --- a/drivers/clk/qcom/Kconfig
> > +++ b/drivers/clk/qcom/Kconfig
> > @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
> >           Technologies, Inc. SPMI PMIC. It configures the frequency =
of
> >           clkdiv outputs of the PMIC. These clocks are typically =
wired
> >           through alternate functions on GPIO pins.
> > +
> > +config 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.
>=20
> Sort?

Will be changed in the next spin.

>=20
> > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> > index 230332c..57b38ba 100644
> > --- a/drivers/clk/qcom/Makefile
> > +++ b/drivers/clk/qcom/Makefile
> > @@ -33,6 +33,7 @@ obj-$(CONFIG_MSM_LCC_8960) +=3D lcc-msm8960.o
> >  obj-$(CONFIG_MSM_MMCC_8960) +=3D mmcc-msm8960.o
> >  obj-$(CONFIG_MSM_MMCC_8974) +=3D mmcc-msm8974.o
> >  obj-$(CONFIG_MSM_MMCC_8996) +=3D mmcc-msm8996.o
> > +obj-$(CONFIG_MSM_APCC_8996) +=3D clk-cpu-8996.o
>=20
> This doesn't look sorted.

Will be changed in the next spin.

>=20
> >  obj-$(CONFIG_QCOM_A53PLL) +=3D a53-pll.o
> >  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) +=3D apcs-msm8916.o
> >  obj-$(CONFIG_QCOM_CLK_RPM) +=3D clk-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..42489f1
> > --- /dev/null
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -0,0 +1,409 @@
> > +/*
> > + * Copyright (c) 2018, 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.
> > + */
>=20
> Can we get the SPDX tags here please?

Will be changed in the next spin.

>=20
> > +
> > +#include <linux/clk.h>
>=20
> clk-provider.h?
>=20
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "clk-alpha-pll.h"
>=20
> #include "clk-regmap.h"
>=20
> > +
> > +#define VCO(a, b, c) { \
> > +       .val =3D a,\
> > +       .min_freq =3D b,\
> > +       .max_freq =3D c,\
> > +}
>=20
> Can this define go into whatever PLL header file defines the struct?

Will be changed in the next spin.

>=20
> > +
> > +#define DIV_2_INDEX            0
> > +#define PLL_INDEX              1
> > +#define ACD_INDEX              2
> > +#define ALT_INDEX              3
> > +
> > +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] =3D {
> > +       [PLL_OFF_L_VAL] =3D 0x04,
> > +       [PLL_OFF_ALPHA_VAL] =3D 0x08,
> > +       [PLL_OFF_USER_CTL] =3D 0x10,
> > +       [PLL_OFF_CONFIG_CTL] =3D 0x18,
> > +       [PLL_OFF_CONFIG_CTL_U] =3D 0x1C,
>=20
> Please use lowercase hex throughout. Consistency is key!

Will be changed in the next spin.

>=20
> > +       [PLL_OFF_TEST_CTL] =3D 0x20,
> > +       [PLL_OFF_TEST_CTL_U] =3D 0x24,
> > +       [PLL_OFF_STATUS] =3D 0x28,
> > +};
> > +
> > +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] =3D {
> > +       [PLL_OFF_L_VAL] =3D 0x04,
> > +       [PLL_OFF_ALPHA_VAL] =3D 0x08,
> > +       [PLL_OFF_ALPHA_VAL_U] =3D 0x0c,
> > +       [PLL_OFF_USER_CTL] =3D 0x10,
> > +       [PLL_OFF_USER_CTL_U] =3D 0x14,
> > +       [PLL_OFF_CONFIG_CTL] =3D 0x18,
> > +       [PLL_OFF_TEST_CTL] =3D 0x20,
> > +       [PLL_OFF_TEST_CTL_U] =3D 0x24,
> > +       [PLL_OFF_STATUS] =3D 0x28,
> > +};
> > +
> > +/* PLLs */
> > +
> > +static const struct alpha_pll_config hfpll_config =3D {
> > +       .l =3D 60,
> > +       .config_ctl_val =3D 0x200d4828,
> > +       .config_ctl_hi_val =3D 0x006,
> > +       .pre_div_mask =3D BIT(12),
> > +       .post_div_mask =3D 0x3 << 8,
> > +       .main_output_mask =3D BIT(0),
> > +       .early_output_mask =3D BIT(3),
> > +};
> > +
> > +static struct clk_alpha_pll perfcl_pll =3D {
> > +       .offset =3D 0x80000,
> > +       .regs =3D prim_pll_regs,
> > +       .flags =3D SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data){
> > +               .name =3D "perfcl_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_huayra_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_pll =3D {
> > +       .offset =3D 0x0,
> > +       .regs =3D prim_pll_regs,
> > +       .flags =3D SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data){
> > +               .name =3D "pwrcl_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_huayra_ops,
> > +       },
> > +};
> > +
> > +static const struct pll_vco alt_pll_vco_modes[] =3D {
> > +       VCO(3,  250000000,  500000000),
> > +       VCO(2,  500000000,  750000000),
> > +       VCO(1,  750000000, 1000000000),
> > +       VCO(0, 1000000000, 2150400000), };
> > +
> > +static const struct alpha_pll_config altpll_config =3D {
> > +       .l =3D 16,
> > +       .vco_val =3D 0x3 << 20,
> > +       .vco_mask =3D 0x3 << 20,
> > +       .config_ctl_val =3D 0x4001051b,
> > +       .post_div_mask =3D 0x3 << 8,
> > +       .post_div_val =3D 0x1,
> > +       .main_output_mask =3D BIT(0),
> > +       .early_output_mask =3D BIT(3),
> > +};
> > +
> > +static struct clk_alpha_pll perfcl_alt_pll =3D {
> > +       .offset =3D 0x80100,
> > +       .regs =3D alt_pll_regs,
> > +       .vco_table =3D alt_pll_vco_modes,
> > +       .num_vco =3D ARRAY_SIZE(alt_pll_vco_modes),
> > +       .flags =3D SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "perfcl_alt_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_hwfsm_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_alt_pll =3D {
> > +       .offset =3D 0x100,
> > +       .regs =3D alt_pll_regs,
> > +       .vco_table =3D alt_pll_vco_modes,
> > +       .num_vco =3D ARRAY_SIZE(alt_pll_vco_modes),
> > +       .flags =3D SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "pwrcl_alt_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_hwfsm_ops,
> > +       },
> > +};
> > +
> > +/* Mux'es */
> > +
> > +struct clk_cpu_8996_mux {
> > +       u32     reg;
> > +       u32     shift;
>=20
> u8 shift?

Will be changed in the next spin.

>=20
> > +       u32     width;
>=20
> u8 width?

Will be changed in the next spin.

>=20
> > +       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 =3D to_clk_regmap(hw);
> > +       struct clk_cpu_8996_mux *cpuclk =3D =
to_clk_cpu_8996_mux_hw(hw);
> > +       unsigned int mask =3D GENMASK(cpuclk->width - 1, 0);
> > +
> > +       regmap_read(clkr->regmap, cpuclk->reg, &val);
> > +
> > +       val >>=3D cpuclk->shift;
> > +       val &=3D mask;
> > +
> > +       return val;
>=20
> return val & mask;

struct clk_cpu_8996_mux *

>=20
> > +}
> > +
> > +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index) =
{
> > +       unsigned int val;
>=20
> u32 val?

Will be changed in the next spin.

>=20
> > +       struct clk_regmap *clkr =3D to_clk_regmap(hw);
> > +       struct clk_cpu_8996_mux *cpuclk =3D =
to_clk_cpu_8996_mux_hw(hw);
> > +       unsigned int mask =3D GENMASK(cpuclk->width + cpuclk->shift =
- 1,
> > +                                   cpuclk->shift);
> > +
> > +       val =3D index;
> > +       val <<=3D 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 =3D =
to_clk_cpu_8996_mux_hw(hw);
> > +       struct clk_hw *parent =3D cpuclk->pll;
> > +
> > +       if (!cpuclk->pll)
> > +               return -EINVAL;
>=20
> Does this happen?

On successful probe it shouldn't. May I omit pointer checks in this =
case? Future maintenance ma y change the flow.

>=20
> > +
> > +       req->best_parent_rate =3D clk_hw_round_rate(parent, =
req->rate);
> > +       req->best_parent_hw =3D parent;
>=20
> Is the parent index always the same? Perhaps just call
> clk_hw_get_parent_by_index() then instead of adding a pointer to the
> clk_cpu_8996_mux.
>=20
> > +
> > +       return 0;
> > +}
> > +
> > +const struct clk_ops clk_cpu_8996_mux_ops =3D {
> > +       .set_parent =3D clk_cpu_8996_mux_set_parent,
> > +       .get_parent =3D clk_cpu_8996_mux_get_parent,
> > +       .determine_rate =3D clk_cpu_8996_mux_determine_rate, };
> [...]
> > +
> > +static struct clk_cpu_8996_mux pwrcl_pmux =3D {
> > +       .reg =3D 0x40,
> > +       .shift =3D 0,
> > +       .width =3D 2,
> > +       .pll =3D &pwrcl_pll.clkr.hw,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "pwrcl_pmux",
> > +               .parent_names =3D (const char *[]){
> > +                       "pwrcl_smux",
> > +                       "pwrcl_pll",
> > +                       "pwrcl_pll_acd",
> > +                       "pwrcl_alt_pll",
> > +               },
> > +               .num_parents =3D 4,
> > +               .ops =3D &clk_cpu_8996_mux_ops,
> > +               .flags =3D CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> > +       },
> > +};
> > +
> > +static struct clk_cpu_8996_mux perfcl_pmux =3D {
> > +       .reg =3D 0x80040,
> > +       .shift =3D 0,
> > +       .width =3D 2,
> > +       .pll =3D &perfcl_pll.clkr.hw,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "perfcl_pmux",
> > +               .parent_names =3D (const char *[]){
> > +                       "perfcl_smux",
> > +                       "perfcl_pll",
> > +                       "perfcl_pll_acd",
> > +                       "perfcl_alt_pll",
> > +               },
> > +               .num_parents =3D 4,
> > +               .ops =3D &clk_cpu_8996_mux_ops,
> > +               .flags =3D CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
>=20
> Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
> for now? We don't want to force XO to stay on forever here.

Have to unit test this.

>=20
> > +       },
> > +};
> > +
> > +static const struct regmap_config cpu_msm8996_regmap_config =3D {
> > +       .reg_bits               =3D 32,
> > +       .reg_stride             =3D 4,
> > +       .val_bits               =3D 32,
> > +       .max_register           =3D 0x80210,
> > +       .fast_io                =3D true,
> > +       .val_format_endian      =3D REGMAP_ENDIAN_LITTLE,
> > +};
> > +
> > +static const struct of_device_id match_table[] =3D {
>=20
> Move this next to driver structure and give it a more specific name.

Will be changed in the next spin.

>=20
> > +       { .compatible =3D "qcom-msm8996-apcc" },
>=20
> Bad compatible? Should be qcom,msm8996-apcc?

The naming is per Rob Herring's requirement.

>=20
> > +       {}
> > +};
> > +
> > +struct clk_regmap *clks[] =3D {
> > +       /* 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,
>=20
> Please drop useless comments inside this array.

Will be changed in the next spin.

>=20
> > +};
> > +
> > +struct clk_hw_clks {
> > +       unsigned int num;
> > +       struct clk_hw *hws[];
> > +};
>=20
> Please just NULL terminate the list of clk_hw pointers, or keep the =
size
> around instead.

Will be changed in the next spin.

>=20
> > +
> > +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] =3D clk_hw_register_fixed_factor(dev, =
"perfcl_pll_main",
> > +                                                  "perfcl_pll",
> > +                                                  =
CLK_SET_RATE_PARENT, 1, 2);
> > +       perfcl_smux.pll =3D hws->hws[0];
> > +
> > +       hws->hws[1] =3D clk_hw_register_fixed_factor(dev, =
"pwrcl_pll_main",
> > +                                                  "pwrcl_pll",
> > +                                                  =
CLK_SET_RATE_PARENT, 1, 2);
> > +       pwrcl_smux.pll =3D hws->hws[1];
> > +
> > +       hws->num =3D 2;
>=20
> Maybe just open code the fixed factor clk registration? Then the
> devm_clk_hw_register() function can be used on those static structs to =
make
> removal simpler.

I will check this.

>=20
> > +
> > +       for (i =3D 0; i < ARRAY_SIZE(clks); i++) {
> > +               ret =3D 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;
>=20
> Just call it regmap please.

Will be changed in the next spin.

>=20
> > +       struct clk_hw_clks *hws;
> > +       struct clk_hw_onecell_data *data;
> > +       struct device *dev =3D &pdev->dev;
> > +       struct device_node *node =3D dev->of_node;
> > +
> > +       data =3D devm_kzalloc(dev, sizeof(*data) + 2 * sizeof(struct =
clk_hw *),
> > +                           GFP_KERNEL);
> > +       if (!data)
> > +               return -ENOMEM;
> > +
> > +       hws =3D devm_kzalloc(dev, sizeof(*hws) + 2 * sizeof(struct =
clk_hw *),
> > +                          GFP_KERNEL);
> > +       if (!hws)
> > +               return -ENOMEM;
> > +
> > +       res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       base =3D devm_ioremap_resource(dev, res);
> > +       if (IS_ERR(base))
> > +               return PTR_ERR(base);
> > +
> > +       regmap_cpu =3D devm_regmap_init_mmio(dev, base,
> > +                                          =
&cpu_msm8996_regmap_config);
> > +       if (IS_ERR(regmap_cpu))
> > +               return PTR_ERR(regmap_cpu);
> > +
> > +       ret =3D qcom_cpu_clk_msm8996_register_clks(dev, hws, =
regmap_cpu);
> > +       if (ret)
> > +               return ret;
> > +
> > +       data->hws[0] =3D &pwrcl_pmux.clkr.hw;
> > +       data->hws[1] =3D &perfcl_pmux.clkr.hw;
> > +
> > +       data->num =3D 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 =3D &pdev->dev;
> > +       struct clk_hw_clks *hws =3D platform_get_drvdata(pdev);
> > +
> > +       for (i =3D 0; i < hws->num; i++)
> > +               clk_hw_unregister_fixed_rate(hws->hws[i]);
> > +
> > +       of_clk_del_provider(dev->of_node);
>=20
> Use devm_of_clk_add_hw_provider() instead.

Will be changed in the next spin.

>=20
> > +
> > +       return 0;
> > +}
> > +
> > +static struct platform_driver qcom_cpu_clk_msm8996_driver =3D {
> > +       .probe =3D qcom_cpu_clk_msm8996_driver_probe,
> > +       .remove =3D qcom_cpu_clk_msm8996_driver_remove,
> > +       .driver =3D {
> > +               .name =3D "qcom-msm8996-apcc",
> > +               .of_match_table =3D match_table,
> > +       },
> > +};
> > +
> > +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> > +
> > +MODULE_ALIAS("platform:msm8996-apcc");
> > +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
>=20
> Not sure why Driver is capitalized and clock is not.

Will be changed in the next spin.


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

* [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-03-20 14:18       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 14:18 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:37
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:45)
> > 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
> 
> Thanks for the diagram. Please also put it at the top of the driver file.

Will be added in the next spin.

> 
> >
> > 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
> 
> Capitalize 'h' in units please.

OK

> 
> >  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>
> > ---
> >  drivers/clk/qcom/Kconfig        |   8 +
> >  drivers/clk/qcom/Makefile       |   1 +
> >  drivers/clk/qcom/clk-cpu-8996.c | 409
> > ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 418 insertions(+)
> >  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> >
> > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index
> > fbf4532..3274877 100644
> > --- a/drivers/clk/qcom/Kconfig
> > +++ b/drivers/clk/qcom/Kconfig
> > @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
> >           Technologies, Inc. SPMI PMIC. It configures the frequency of
> >           clkdiv outputs of the PMIC. These clocks are typically wired
> >           through alternate functions on GPIO pins.
> > +
> > +config 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.
> 
> Sort?

Will be changed in the next spin.

> 
> > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> > index 230332c..57b38ba 100644
> > --- a/drivers/clk/qcom/Makefile
> > +++ b/drivers/clk/qcom/Makefile
> > @@ -33,6 +33,7 @@ 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
> 
> This doesn't look sorted.

Will be changed in the next spin.

> 
> >  obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
> >  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
> >  obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
> > --- /dev/null
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -0,0 +1,409 @@
> > +/*
> > + * Copyright (c) 2018, 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.
> > + */
> 
> Can we get the SPDX tags here please?

Will be changed in the next spin.

> 
> > +
> > +#include <linux/clk.h>
> 
> clk-provider.h?
> 
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "clk-alpha-pll.h"
> 
> #include "clk-regmap.h"
> 
> > +
> > +#define VCO(a, b, c) { \
> > +       .val = a,\
> > +       .min_freq = b,\
> > +       .max_freq = c,\
> > +}
> 
> Can this define go into whatever PLL header file defines the struct?

Will be changed in the next spin.

> 
> > +
> > +#define DIV_2_INDEX            0
> > +#define PLL_INDEX              1
> > +#define ACD_INDEX              2
> > +#define ALT_INDEX              3
> > +
> > +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_CONFIG_CTL_U] = 0x1C,
> 
> Please use lowercase hex throughout. Consistency is key!

Will be changed in the next spin.

> 
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_USER_CTL_U] = 0x14,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +/* 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,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_pll = {
> > +       .offset = 0x0,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
> > +       .regs = alt_pll_regs,
> > +       .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,
> > +       .regs = alt_pll_regs,
> > +       .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;
> 
> u8 shift?

Will be changed in the next spin.

> 
> > +       u32     width;
> 
> u8 width?

Will be changed in the next spin.

> 
> > +       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;
> 
> return val & mask;

struct clk_cpu_8996_mux *

> 
> > +}
> > +
> > +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index) {
> > +       unsigned int val;
> 
> u32 val?

Will be changed in the next spin.

> 
> > +       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;
> 
> Does this happen?

On successful probe it shouldn't. May I omit pointer checks in this case? Future maintenance ma y change the flow.

> 
> > +
> > +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> > +       req->best_parent_hw = parent;
> 
> Is the parent index always the same? Perhaps just call
> clk_hw_get_parent_by_index() then instead of adding a pointer to the
> clk_cpu_8996_mux.
> 
> > +
> > +       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_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 | CLK_IS_CRITICAL,
> > +       },
> > +};
> > +
> > +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",
> > +                       "perfcl_pll_acd",
> > +                       "perfcl_alt_pll",
> > +               },
> > +               .num_parents = 4,
> > +               .ops = &clk_cpu_8996_mux_ops,
> > +               .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> 
> Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
> for now? We don't want to force XO to stay on forever here.

Have to unit test this.

> 
> > +       },
> > +};
> > +
> > +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[] = {
> 
> Move this next to driver structure and give it a more specific name.

Will be changed in the next spin.

> 
> > +       { .compatible = "qcom-msm8996-apcc" },
> 
> Bad compatible? Should be qcom,msm8996-apcc?

The naming is per Rob Herring's requirement.

> 
> > +       {}
> > +};
> > +
> > +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,
> 
> Please drop useless comments inside this array.

Will be changed in the next spin.

> 
> > +};
> > +
> > +struct clk_hw_clks {
> > +       unsigned int num;
> > +       struct clk_hw *hws[];
> > +};
> 
> Please just NULL terminate the list of clk_hw pointers, or keep the size
> around instead.

Will be changed in the next spin.

> 
> > +
> > +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;
> 
> Maybe just open code the fixed factor clk registration? Then the
> devm_clk_hw_register() function can be used on those static structs to make
> removal simpler.

I will check this.

> 
> > +
> > +       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;
> 
> Just call it regmap please.

Will be changed in the next spin.

> 
> > +       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);
> 
> Use devm_of_clk_add_hw_provider() instead.

Will be changed in the next spin.

> 
> > +
> > +       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-msm8996-apcc",
> > +               .of_match_table = match_table,
> > +       },
> > +};
> > +
> > +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> > +
> > +MODULE_ALIAS("platform:msm8996-apcc");
> > +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
> 
> Not sure why Driver is capitalized and clock is not.

Will be changed in the next spin.

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

* RE: [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
  2018-03-19 17:45     ` Stephen Boyd
  (?)
@ 2018-03-20 18:42       ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 18:42 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:45
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from
> PMU driver
> 
> Quoting Ilia Lin (2018-02-14 05:59:43)
> > diff --git a/arch/arm64/Kconfig.platforms
> > b/arch/arm64/Kconfig.platforms index fbedbd8..78a103b 100644
> > --- a/arch/arm64/Kconfig.platforms
> > +++ b/arch/arm64/Kconfig.platforms
> > @@ -145,6 +145,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
> 
> Is this really the proposed approach? Doesn't the PMU code use these
> accessors? I would think the accessors are compiled if ARCH_QCOM=y so
> that the PMU stuff keeps working. Drop this Kconfig addition?

I'll check whether the kryo-accessors code is SOC specific or not.

> 
> > +       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..8cece9e 100644
> > --- a/drivers/perf/qcom_l2_pmu.c
> > +++ b/drivers/perf/qcom_l2_pmu.c
> > @@ -1,4 +1,4 @@
> > -/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
> > +/* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
> 
> Sorry, this makes little sense. First off, code is only being deleted and more
> than half the file isn't being modified so why update copyright dates?

Agree. Will roll back.

> 
> >   *
> >   * 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
> > diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> > index dcebf28..4e91e2a 100644
> > --- a/drivers/soc/qcom/Makefile
> > +++ b/drivers/soc/qcom/Makefile
> > @@ -12,3 +12,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..6743848
> > --- /dev/null
> > +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> > @@ -0,0 +1,64 @@
> > +/*
> > + * Copyright (c) 2014-2015, 2018, 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.
> > + */
> 
> SPDX tags?

Will do.

> 
> > diff --git a/include/soc/qcom/kryo-l2-accessors.h
> > b/include/soc/qcom/kryo-l2-accessors.h
> > new file mode 100644
> > index 0000000..e9a5eab
> > --- /dev/null
> > +++ b/include/soc/qcom/kryo-l2-accessors.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * Copyright (c) 2018, 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
> 
> Maybe change this tO __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H

No problem. Will change.

> 
> > +
> > +#ifdef CONFIG_ARCH_QCOM
> > +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> > +u64 get_l2_indirect_reg(u64 reg_addr); #endif
> 
> This ifdef isn't doing much. Drop it? Or provide the inline nop alternatives.

Right. I'll drop it.

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

* RE: [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
@ 2018-03-20 18:42       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 18:42 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:45
> To: Ilia Lin <ilialin@codeaurora.org>; =
linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; =
ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors =
from
> PMU driver
>=20
> Quoting Ilia Lin (2018-02-14 05:59:43)
> > diff --git a/arch/arm64/Kconfig.platforms
> > b/arch/arm64/Kconfig.platforms index fbedbd8..78a103b 100644
> > --- a/arch/arm64/Kconfig.platforms
> > +++ b/arch/arm64/Kconfig.platforms
> > @@ -145,6 +145,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
>=20
> Is this really the proposed approach? Doesn't the PMU code use these
> accessors? I would think the accessors are compiled if ARCH_QCOM=3Dy =
so
> that the PMU stuff keeps working. Drop this Kconfig addition?

I'll check whether the kryo-accessors code is SOC specific or not.

>=20
> > +       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..8cece9e 100644
> > --- a/drivers/perf/qcom_l2_pmu.c
> > +++ b/drivers/perf/qcom_l2_pmu.c
> > @@ -1,4 +1,4 @@
> > -/* Copyright (c) 2015-2017 The Linux Foundation. All rights =
reserved.
> > +/* Copyright (c) 2015-2018 The Linux Foundation. All rights =
reserved.
>=20
> Sorry, this makes little sense. First off, code is only being deleted =
and more
> than half the file isn't being modified so why update copyright dates?

Agree. Will roll back.

>=20
> >   *
> >   * 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
> > diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> > index dcebf28..4e91e2a 100644
> > --- a/drivers/soc/qcom/Makefile
> > +++ b/drivers/soc/qcom/Makefile
> > @@ -12,3 +12,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) +=3D
> smem_state.o
> >  obj-$(CONFIG_QCOM_SMP2P)       +=3D smp2p.o
> >  obj-$(CONFIG_QCOM_SMSM)        +=3D smsm.o
> >  obj-$(CONFIG_QCOM_WCNSS_CTRL) +=3D wcnss_ctrl.o
> > +obj-$(CONFIG_ARCH_MSM8996) +=3D  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..6743848
> > --- /dev/null
> > +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> > @@ -0,0 +1,64 @@
> > +/*
> > + * Copyright (c) 2014-2015, 2018, 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.
> > + */
>=20
> SPDX tags?

Will do.

>=20
> > diff --git a/include/soc/qcom/kryo-l2-accessors.h
> > b/include/soc/qcom/kryo-l2-accessors.h
> > new file mode 100644
> > index 0000000..e9a5eab
> > --- /dev/null
> > +++ b/include/soc/qcom/kryo-l2-accessors.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * Copyright (c) 2018, 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
>=20
> Maybe change this tO __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H

No problem. Will change.

>=20
> > +
> > +#ifdef CONFIG_ARCH_QCOM
> > +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> > +u64 get_l2_indirect_reg(u64 reg_addr); #endif
>=20
> This ifdef isn't doing much. Drop it? Or provide the inline nop =
alternatives.

Right. I'll drop it.


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

* [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver
@ 2018-03-20 18:42       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 18:42 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:45
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from
> PMU driver
> 
> Quoting Ilia Lin (2018-02-14 05:59:43)
> > diff --git a/arch/arm64/Kconfig.platforms
> > b/arch/arm64/Kconfig.platforms index fbedbd8..78a103b 100644
> > --- a/arch/arm64/Kconfig.platforms
> > +++ b/arch/arm64/Kconfig.platforms
> > @@ -145,6 +145,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
> 
> Is this really the proposed approach? Doesn't the PMU code use these
> accessors? I would think the accessors are compiled if ARCH_QCOM=y so
> that the PMU stuff keeps working. Drop this Kconfig addition?

I'll check whether the kryo-accessors code is SOC specific or not.

> 
> > +       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..8cece9e 100644
> > --- a/drivers/perf/qcom_l2_pmu.c
> > +++ b/drivers/perf/qcom_l2_pmu.c
> > @@ -1,4 +1,4 @@
> > -/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
> > +/* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
> 
> Sorry, this makes little sense. First off, code is only being deleted and more
> than half the file isn't being modified so why update copyright dates?

Agree. Will roll back.

> 
> >   *
> >   * 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
> > diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> > index dcebf28..4e91e2a 100644
> > --- a/drivers/soc/qcom/Makefile
> > +++ b/drivers/soc/qcom/Makefile
> > @@ -12,3 +12,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..6743848
> > --- /dev/null
> > +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> > @@ -0,0 +1,64 @@
> > +/*
> > + * Copyright (c) 2014-2015, 2018, 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.
> > + */
> 
> SPDX tags?

Will do.

> 
> > diff --git a/include/soc/qcom/kryo-l2-accessors.h
> > b/include/soc/qcom/kryo-l2-accessors.h
> > new file mode 100644
> > index 0000000..e9a5eab
> > --- /dev/null
> > +++ b/include/soc/qcom/kryo-l2-accessors.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * Copyright (c) 2018, 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
> 
> Maybe change this tO __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H

No problem. Will change.

> 
> > +
> > +#ifdef CONFIG_ARCH_QCOM
> > +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> > +u64 get_l2_indirect_reg(u64 reg_addr); #endif
> 
> This ifdef isn't doing much. Drop it? Or provide the inline nop alternatives.

Right. I'll drop it.

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

* RE: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
  2018-03-19 17:46     ` Stephen Boyd
  (?)
@ 2018-03-20 18:43       ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 18:43 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:47
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver
> for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:46)
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17
> +++++++++++++++++
> >  1 file changed, 17 insertions(+)
> >  create mode 100644
> Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> >
> > diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> > new file mode 100644
> > index 0000000..e7cf15a
> > --- /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-msm8996-apcc"
> 
> Do you mean qcom,msm8996-apcc?

The naming is per Rob's requirement.

> 
> Rob?

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

* RE: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
@ 2018-03-20 18:43       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 18:43 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:47
> To: Ilia Lin <ilialin@codeaurora.org>; =
linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; =
ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock =
driver
> for msm8996
>=20
> Quoting Ilia Lin (2018-02-14 05:59:46)
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17
> +++++++++++++++++
> >  1 file changed, 17 insertions(+)
> >  create mode 100644
> Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> >
> > diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> > new file mode 100644
> > index 0000000..e7cf15a
> > --- /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-msm8996-apcc"
>=20
> Do you mean qcom,msm8996-apcc?

The naming is per Rob's requirement.

>=20
> Rob?


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

* [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver for msm8996
@ 2018-03-20 18:43       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 18:43 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:47
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 04/10] clk: qcom: Add DT bindings for CPU clock driver
> for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:46)
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
> > ---
> >  Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17
> +++++++++++++++++
> >  1 file changed, 17 insertions(+)
> >  create mode 100644
> Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> >
> > diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
> > new file mode 100644
> > index 0000000..e7cf15a
> > --- /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-msm8996-apcc"
> 
> Do you mean qcom,msm8996-apcc?

The naming is per Rob's requirement.

> 
> Rob?

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

* RE: [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
  2018-03-19 17:47       ` Stephen Boyd
  (?)
@ 2018-03-20 18:45         ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 18:45 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Will be fixed and respinned.

> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:48
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to
> alternate PLL
> 
> Quoting Ilia Lin (2018-02-14 05:59:47)
> > From: Rajendra Nayak <rnayak@codeaurora.org>
> >
> > Each of the CPU clusters on msm8996 and powered via a primary
> 
> s/and/are/
> 
> > PLL and a secondary PLL. The primary PLL is what drivers the
> 
> s/drivers/drives/
> 
> I make the same typo all the time!
> 
> > 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@codeaurora.org>
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
> > --- a/drivers/clk/qcom/clk-cpu-8996.c
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -140,10 +140,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)
> {
> > @@ -194,6 +198,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, @@ -237,6 +262,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 *[]){ @@ -256,6 +282,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 *[]){ @@ -331,6 +358,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;
> > +
> 
> Please resend this with the other patches that need rework.

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

* RE: [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
@ 2018-03-20 18:45         ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 18:45 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Will be fixed and respinned.

> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:48
> To: Ilia Lin <ilialin@codeaurora.org>; =
linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; =
ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to =
switch to
> alternate PLL
>=20
> Quoting Ilia Lin (2018-02-14 05:59:47)
> > From: Rajendra Nayak <rnayak@codeaurora.org>
> >
> > Each of the CPU clusters on msm8996 and powered via a primary
>=20
> s/and/are/
>=20
> > PLL and a secondary PLL. The primary PLL is what drivers the
>=20
> s/drivers/drives/
>=20
> I make the same typo all the time!
>=20
> > 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@codeaurora.org>
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
> > --- a/drivers/clk/qcom/clk-cpu-8996.c
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -140,10 +140,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)
> {
> > @@ -194,6 +198,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 =3D =
to_clk_cpu_8996_mux_nb(nb);
> > +
> > +       switch (event) {
> > +       case PRE_RATE_CHANGE:
> > +               ret =3D =
clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
> ALT_INDEX);
> > +               break;
> > +       case POST_RATE_CHANGE:
> > +               ret =3D =
clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
> PLL_INDEX);
> > +               break;
> > +       default:
> > +               ret =3D 0;
> > +               break;
> > +       }
> > +
> > +       return notifier_from_errno(ret); };
> > +
> >  const struct clk_ops clk_cpu_8996_mux_ops =3D {
> >         .set_parent =3D clk_cpu_8996_mux_set_parent,
> >         .get_parent =3D clk_cpu_8996_mux_get_parent, @@ -237,6 =
+262,7 @@
> > static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
> >         .shift =3D 0,
> >         .width =3D 2,
> >         .pll =3D &pwrcl_pll.clkr.hw,
> > +       .nb.notifier_call =3D cpu_clk_notifier_cb,
> >         .clkr.hw.init =3D &(struct clk_init_data) {
> >                 .name =3D "pwrcl_pmux",
> >                 .parent_names =3D (const char *[]){ @@ -256,6 +282,7 =
@@
> > static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
> >         .shift =3D 0,
> >         .width =3D 2,
> >         .pll =3D &perfcl_pll.clkr.hw,
> > +       .nb.notifier_call =3D cpu_clk_notifier_cb,
> >         .clkr.hw.init =3D &(struct clk_init_data) {
> >                 .name =3D "perfcl_pmux",
> >                 .parent_names =3D (const char *[]){ @@ -331,6 =
+358,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 =3D clk_notifier_register(pwrcl_pmux.clkr.hw.clk, =
&pwrcl_pmux.nb);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret =3D clk_notifier_register(perfcl_pmux.clkr.hw.clk,
> &perfcl_pmux.nb);
> > +       if (ret)
> > +               return ret;
> > +
>=20
> Please resend this with the other patches that need rework.


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

* [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL
@ 2018-03-20 18:45         ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

Will be fixed and respinned.

> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:48
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to
> alternate PLL
> 
> Quoting Ilia Lin (2018-02-14 05:59:47)
> > From: Rajendra Nayak <rnayak@codeaurora.org>
> >
> > Each of the CPU clusters on msm8996 and powered via a primary
> 
> s/and/are/
> 
> > PLL and a secondary PLL. The primary PLL is what drivers the
> 
> s/drivers/drives/
> 
> I make the same typo all the time!
> 
> > 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@codeaurora.org>
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.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 42489f1..75bd014 100644
> > --- a/drivers/clk/qcom/clk-cpu-8996.c
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -140,10 +140,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)
> {
> > @@ -194,6 +198,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, @@ -237,6 +262,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 *[]){ @@ -256,6 +282,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 *[]){ @@ -331,6 +358,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;
> > +
> 
> Please resend this with the other patches that need rework.

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

* RE: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
  2018-03-20 14:18       ` ilialin
@ 2018-03-20 20:01         ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:01 UTC (permalink / raw)
  To: ilialin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Quoting ilialin@codeaurora.org (2018-03-20 07:18:57)
> > From: Stephen Boyd <sboyd@kernel.org>
> > 
> > > +       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;
> > 
> > Does this happen?
> 
> On successful probe it shouldn't. May I omit pointer checks in this case? Future maintenance ma y change the flow.
> 

Yes please omit useless checks.

> > 
> > > +
> > > +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> > > +       req->best_parent_hw = parent;
> > 
> > Is the parent index always the same? Perhaps just call
> > clk_hw_get_parent_by_index() then instead of adding a pointer to the
> > clk_cpu_8996_mux.
> > 
> 
> > 
> > > +       },
> > > +};
> > > +
> > > +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[] = {
> > 
> > Move this next to driver structure and give it a more specific name.
> 
> Will be changed in the next spin.
> 
> > 
> > > +       { .compatible = "qcom-msm8996-apcc" },
> > 
> > Bad compatible? Should be qcom,msm8996-apcc?
> 
> The naming is per Rob Herring's requirement.
> 

Hmm, maybe Rob made a typo?

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

* [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-03-20 20:01         ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:01 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting ilialin at codeaurora.org (2018-03-20 07:18:57)
> > From: Stephen Boyd <sboyd@kernel.org>
> > 
> > > +       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;
> > 
> > Does this happen?
> 
> On successful probe it shouldn't. May I omit pointer checks in this case? Future maintenance ma y change the flow.
> 

Yes please omit useless checks.

> > 
> > > +
> > > +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> > > +       req->best_parent_hw = parent;
> > 
> > Is the parent index always the same? Perhaps just call
> > clk_hw_get_parent_by_index() then instead of adding a pointer to the
> > clk_cpu_8996_mux.
> > 
> 
> > 
> > > +       },
> > > +};
> > > +
> > > +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[] = {
> > 
> > Move this next to driver structure and give it a more specific name.
> 
> Will be changed in the next spin.
> 
> > 
> > > +       { .compatible = "qcom-msm8996-apcc" },
> > 
> > Bad compatible? Should be qcom,msm8996-apcc?
> 
> The naming is per Rob Herring's requirement.
> 

Hmm, maybe Rob made a typo?

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

* RE: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
  2018-03-20 13:53       ` ilialin
@ 2018-03-20 20:03         ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:03 UTC (permalink / raw)
  To: ilialin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Quoting ilialin@codeaurora.org (2018-03-20 06:53:08)
> 
> 
> > -----Original Message-----
> > From: Stephen Boyd <sboyd@kernel.org>
> > Sent: Monday, March 19, 2018 18:50
> > To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> > linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> > sboyd@codeaurora.org
> > Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> > rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> > amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> > nicolas.dechesne@linaro.org; celster@codeaurora.org
> > Subject: Re: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
> > 
> > Quoting Ilia Lin (2018-02-14 05:59:49)
> > > The PLLs must be prepared enabled during the probe to be accessible by
> > > the OPPs. Otherwise an OPP may switch to non-enabled clock.
> > 
> > Sounds like an OPP problem.
> 
> And again, it could be solved by a platform specific cpufreq driver. Worth it?
> 
> > 
> > >  #include "clk-alpha-pll.h"
> > >
> > >  #define VCO(a, b, c) { \
> > > @@ -376,6 +376,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);
> > 
> > And this can't be done by the cpufreq-dt driver?
> 
> Are you suggesting changing the cpufreq-dt as well?

Yes?

> 
> > 
> > > +
> > > +       /* 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);
> > 
> > We have assigned rates in DT for this.
> 
> I assumed that the clock driver can live without the OPP table and any cpufreq driver. Or do you mean adding this as parameters for the kryocc DT node?
> 

Yes I mean adding assigned rates to the kroycc DT node to setup PLLs to
rates you want.

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

* [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
@ 2018-03-20 20:03         ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:03 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting ilialin at codeaurora.org (2018-03-20 06:53:08)
> 
> 
> > -----Original Message-----
> > From: Stephen Boyd <sboyd@kernel.org>
> > Sent: Monday, March 19, 2018 18:50
> > To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> > linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> > sboyd at codeaurora.org
> > Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> > rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> > amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> > nicolas.dechesne at linaro.org; celster at codeaurora.org
> > Subject: Re: [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe
> > 
> > Quoting Ilia Lin (2018-02-14 05:59:49)
> > > The PLLs must be prepared enabled during the probe to be accessible by
> > > the OPPs. Otherwise an OPP may switch to non-enabled clock.
> > 
> > Sounds like an OPP problem.
> 
> And again, it could be solved by a platform specific cpufreq driver. Worth it?
> 
> > 
> > >  #include "clk-alpha-pll.h"
> > >
> > >  #define VCO(a, b, c) { \
> > > @@ -376,6 +376,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);
> > 
> > And this can't be done by the cpufreq-dt driver?
> 
> Are you suggesting changing the cpufreq-dt as well?

Yes?

> 
> > 
> > > +
> > > +       /* 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);
> > 
> > We have assigned rates in DT for this.
> 
> I assumed that the clock driver can live without the OPP table and any cpufreq driver. Or do you mean adding this as parameters for the kryocc DT node?
> 

Yes I mean adding assigned rates to the kroycc DT node to setup PLLs to
rates you want.

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

* RE: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
  2018-03-20 14:04       ` ilialin
@ 2018-03-20 20:04         ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:04 UTC (permalink / raw)
  To: ilialin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Quoting ilialin@codeaurora.org (2018-03-20 07:04:05)
> > From: Stephen Boyd <sboyd@kernel.org>
> > Quoting Ilia Lin (2018-02-14 05:59:50)
> > 
> > >
> > >  static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> > >         [PLL_OFF_L_VAL] = 0x04,
> > > @@ -399,10 +424,64 @@ 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
> > 
> > Please don't have #defines for random register settings. It just obfuscates
> > what's going on at the place where the define is used.
> 
> So should I just use the values directly?

Yes.

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

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-20 20:04         ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:04 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting ilialin at codeaurora.org (2018-03-20 07:04:05)
> > From: Stephen Boyd <sboyd@kernel.org>
> > Quoting Ilia Lin (2018-02-14 05:59:50)
> > 
> > >
> > >  static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> > >         [PLL_OFF_L_VAL] = 0x04,
> > > @@ -399,10 +424,64 @@ 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
> > 
> > Please don't have #defines for random register settings. It just obfuscates
> > what's going on at the place where the define is used.
> 
> So should I just use the values directly?

Yes.

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

* RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
  2018-03-20 13:46         ` ilialin
@ 2018-03-20 20:06           ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:06 UTC (permalink / raw)
  To: ilialin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Quoting ilialin@codeaurora.org (2018-03-20 06:46:19)
> > From: Stephen Boyd <sboyd@kernel.org>
> > Quoting Ilia Lin (2018-02-14 05:59:51)
> > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > index 3b585e4..b6cd0ae 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", },
> > > +
> > 
> > Why can't we base it on the kryocc node being present?
> This could be good idea, if I would writing a platform specific cpufreq driver, which may be a future option.

Well maybe cpufreq-dt can also look at the cpus nodes for a cpu with a
certain type (in this case kryo). Then we can add cpufreq dt based on
that CPU node being there.

> > Or even populate
> > the cpufreq-dt from the kryocc driver?
> There is a problem that during the clock probe the OPP table still doesn't exist. 

The OPP table is in DT? Why doesn't it exist?

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

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-20 20:06           ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting ilialin at codeaurora.org (2018-03-20 06:46:19)
> > From: Stephen Boyd <sboyd@kernel.org>
> > Quoting Ilia Lin (2018-02-14 05:59:51)
> > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > index 3b585e4..b6cd0ae 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", },
> > > +
> > 
> > Why can't we base it on the kryocc node being present?
> This could be good idea, if I would writing a platform specific cpufreq driver, which may be a future option.

Well maybe cpufreq-dt can also look at the cpus nodes for a cpu with a
certain type (in this case kryo). Then we can add cpufreq dt based on
that CPU node being there.

> > Or even populate
> > the cpufreq-dt from the kryocc driver?
> There is a problem that during the clock probe the OPP table still doesn't exist. 

The OPP table is in DT? Why doesn't it exist?

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

* RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
  2018-03-20 20:06           ` Stephen Boyd
  (?)
@ 2018-03-20 20:34             ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 20:34 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Understood, what you mean. I assumed that the cpufreq-dt is generic driver, and adding architecture specific code to it is no not correct from architectural point of view. Anyway, I'm considering adding a platform specific cpufreq driver, which will handle the efuse data as well.

Meanwhile this is the way to use the generic driver.

> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Tuesday, March 20, 2018 22:06
> To: ilialin@codeaurora.org; linux-arm-kernel@lists.infradead.org; linux-arm-
> msm@vger.kernel.org; linux-clk@vger.kernel.org; sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
> 
> Quoting ilialin@codeaurora.org (2018-03-20 06:46:19)
> > > From: Stephen Boyd <sboyd@kernel.org> Quoting Ilia Lin (2018-02-14
> > > 05:59:51)
> > > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > index 3b585e4..b6cd0ae 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", },
> > > > +
> > >
> > > Why can't we base it on the kryocc node being present?
> > This could be good idea, if I would writing a platform specific cpufreq driver,
> which may be a future option.
> 
> Well maybe cpufreq-dt can also look at the cpus nodes for a cpu with a
> certain type (in this case kryo). Then we can add cpufreq dt based on that
> CPU node being there.
> 
> > > Or even populate
> > > the cpufreq-dt from the kryocc driver?
> > There is a problem that during the clock probe the OPP table still doesn't
> exist.
> 
> The OPP table is in DT? Why doesn't it exist?

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

* RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-20 20:34             ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-20 20:34 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Understood, what you mean. I assumed that the cpufreq-dt is generic =
driver, and adding architecture specific code to it is no not correct =
from architectural point of view. Anyway, I'm considering adding a =
platform specific cpufreq driver, which will handle the efuse data as =
well.

Meanwhile this is the way to use the generic driver.

> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Tuesday, March 20, 2018 22:06
> To: ilialin@codeaurora.org; linux-arm-kernel@lists.infradead.org; =
linux-arm-
> msm@vger.kernel.org; linux-clk@vger.kernel.org; sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
>=20
> Quoting ilialin@codeaurora.org (2018-03-20 06:46:19)
> > > From: Stephen Boyd <sboyd@kernel.org> Quoting Ilia Lin (2018-02-14
> > > 05:59:51)
> > > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > index 3b585e4..b6cd0ae 100644
> > > > --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > @@ -95,6 +95,9 @@
> > > >         { .compatible =3D "xlnx,zynq-7000", },
> > > >         { .compatible =3D "xlnx,zynqmp", },
> > > >
> > > > +       { .compatible =3D "qcom,msm8996", },
> > > > +       { .compatible =3D "qcom,apq8096", },
> > > > +
> > >
> > > Why can't we base it on the kryocc node being present?
> > This could be good idea, if I would writing a platform specific =
cpufreq driver,
> which may be a future option.
>=20
> Well maybe cpufreq-dt can also look at the cpus nodes for a cpu with a
> certain type (in this case kryo). Then we can add cpufreq dt based on =
that
> CPU node being there.
>=20
> > > Or even populate
> > > the cpufreq-dt from the kryocc driver?
> > There is a problem that during the clock probe the OPP table still =
doesn't
> exist.
>=20
> The OPP table is in DT? Why doesn't it exist?


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

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-20 20:34             ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-20 20:34 UTC (permalink / raw)
  To: linux-arm-kernel

Understood, what you mean. I assumed that the cpufreq-dt is generic driver, and adding architecture specific code to it is no not correct from architectural point of view. Anyway, I'm considering adding a platform specific cpufreq driver, which will handle the efuse data as well.

Meanwhile this is the way to use the generic driver.

> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Tuesday, March 20, 2018 22:06
> To: ilialin at codeaurora.org; linux-arm-kernel at lists.infradead.org; linux-arm-
> msm at vger.kernel.org; linux-clk at vger.kernel.org; sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
> 
> Quoting ilialin at codeaurora.org (2018-03-20 06:46:19)
> > > From: Stephen Boyd <sboyd@kernel.org> Quoting Ilia Lin (2018-02-14
> > > 05:59:51)
> > > > diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > b/drivers/cpufreq/cpufreq-dt-platdev.c
> > > > index 3b585e4..b6cd0ae 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", },
> > > > +
> > >
> > > Why can't we base it on the kryocc node being present?
> > This could be good idea, if I would writing a platform specific cpufreq driver,
> which may be a future option.
> 
> Well maybe cpufreq-dt can also look at the cpus nodes for a cpu with a
> certain type (in this case kryo). Then we can add cpufreq dt based on that
> CPU node being there.
> 
> > > Or even populate
> > > the cpufreq-dt from the kryocc driver?
> > There is a problem that during the clock probe the OPP table still doesn't
> exist.
> 
> The OPP table is in DT? Why doesn't it exist?

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

* RE: [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
  2018-03-20 20:34             ` ilialin
@ 2018-03-20 21:46               ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 21:46 UTC (permalink / raw)
  To: ilialin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Quoting ilialin@codeaurora.org (2018-03-20 13:34:04)
> Understood, what you mean. I assumed that the cpufreq-dt is generic driver, and adding architecture specific code to it is no not correct from architectural point of view. Anyway, I'm considering adding a platform specific cpufreq driver, which will handle the efuse data as well.
> 
> Meanwhile this is the way to use the generic driver.
> 

You'll need to Cc Viresh Kumar, who can comment further on cpufreq-dt.
I wasn't recommending adding architecture specific code to cpufreq-dt,
but at least updating how it handles CPU clk on/off state around hotplug
would be good to do.

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

* [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996
@ 2018-03-20 21:46               ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-03-20 21:46 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting ilialin at codeaurora.org (2018-03-20 13:34:04)
> Understood, what you mean. I assumed that the cpufreq-dt is generic driver, and adding architecture specific code to it is no not correct from architectural point of view. Anyway, I'm considering adding a platform specific cpufreq driver, which will handle the efuse data as well.
> 
> Meanwhile this is the way to use the generic driver.
> 

You'll need to Cc Viresh Kumar, who can comment further on cpufreq-dt.
I wasn't recommending adding architecture specific code to cpufreq-dt,
but at least updating how it handles CPU clk on/off state around hotplug
would be good to do.

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

* RE: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
  2018-03-19 17:36     ` Stephen Boyd
  (?)
@ 2018-03-22 10:47       ` ilialin
  -1 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-22 10:47 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:37
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:45)
> > 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
> 
> Thanks for the diagram. Please also put it at the top of the driver file.
> 
> >
> > 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
> 
> Capitalize 'h' in units please.
> 
> >  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>
> > ---
> >  drivers/clk/qcom/Kconfig        |   8 +
> >  drivers/clk/qcom/Makefile       |   1 +
> >  drivers/clk/qcom/clk-cpu-8996.c | 409
> > ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 418 insertions(+)
> >  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> >
> > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index
> > fbf4532..3274877 100644
> > --- a/drivers/clk/qcom/Kconfig
> > +++ b/drivers/clk/qcom/Kconfig
> > @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
> >           Technologies, Inc. SPMI PMIC. It configures the frequency of
> >           clkdiv outputs of the PMIC. These clocks are typically wired
> >           through alternate functions on GPIO pins.
> > +
> > +config 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.
> 
> Sort?
> 
> > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> > index 230332c..57b38ba 100644
> > --- a/drivers/clk/qcom/Makefile
> > +++ b/drivers/clk/qcom/Makefile
> > @@ -33,6 +33,7 @@ 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
> 
> This doesn't look sorted.
> 
> >  obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
> >  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
> >  obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
> > --- /dev/null
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -0,0 +1,409 @@
> > +/*
> > + * Copyright (c) 2018, 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.
> > + */
> 
> Can we get the SPDX tags here please?
> 
> > +
> > +#include <linux/clk.h>
> 
> clk-provider.h?
> 
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "clk-alpha-pll.h"
> 
> #include "clk-regmap.h"
> 
> > +
> > +#define VCO(a, b, c) { \
> > +       .val = a,\
> > +       .min_freq = b,\
> > +       .max_freq = c,\
> > +}
> 
> Can this define go into whatever PLL header file defines the struct?
> 
> > +
> > +#define DIV_2_INDEX            0
> > +#define PLL_INDEX              1
> > +#define ACD_INDEX              2
> > +#define ALT_INDEX              3
> > +
> > +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_CONFIG_CTL_U] = 0x1C,
> 
> Please use lowercase hex throughout. Consistency is key!
> 
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_USER_CTL_U] = 0x14,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +/* 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,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_pll = {
> > +       .offset = 0x0,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
> > +       .regs = alt_pll_regs,
> > +       .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,
> > +       .regs = alt_pll_regs,
> > +       .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;
> 
> u8 shift?
> 
> > +       u32     width;
> 
> u8 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;
> 
> return val & mask;
> 
> > +}
> > +
> > +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index) {
> > +       unsigned int val;
> 
> u32 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;
> 
> Does this happen?
> 
> > +
> > +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> > +       req->best_parent_hw = parent;
> 
> Is the parent index always the same? Perhaps just call
> clk_hw_get_parent_by_index() then instead of adding a pointer to the
> clk_cpu_8996_mux.
> 
> > +
> > +       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_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 | CLK_IS_CRITICAL,
> > +       },
> > +};
> > +
> > +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",
> > +                       "perfcl_pll_acd",
> > +                       "perfcl_alt_pll",
> > +               },
> > +               .num_parents = 4,
> > +               .ops = &clk_cpu_8996_mux_ops,
> > +               .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> 
> Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
> for now? We don't want to force XO to stay on forever here.
> 
> > +       },
> > +};
> > +
> > +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[] = {
> 
> Move this next to driver structure and give it a more specific name.
> 
> > +       { .compatible = "qcom-msm8996-apcc" },
> 
> Bad compatible? Should be qcom,msm8996-apcc?
> 
> > +       {}
> > +};
> > +
> > +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,
> 
> Please drop useless comments inside this array.
> 
> > +};
> > +
> > +struct clk_hw_clks {
> > +       unsigned int num;
> > +       struct clk_hw *hws[];
> > +};
> 
> Please just NULL terminate the list of clk_hw pointers, or keep the size
> around instead.
> 
> > +
> > +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;
> 
> Maybe just open code the fixed factor clk registration? Then the
> devm_clk_hw_register() function can be used on those static structs to make
> removal simpler.

I will have to change the clk_hw_unregister_fixed_rate() as well then, right? This will be an API change.

> 
> > +
> > +       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;
> 
> Just call it regmap please.
> 
> > +       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);
> 
> Use devm_of_clk_add_hw_provider() instead.
> 
> > +
> > +       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-msm8996-apcc",
> > +               .of_match_table = match_table,
> > +       },
> > +};
> > +
> > +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> > +
> > +MODULE_ALIAS("platform:msm8996-apcc");
> > +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
> 
> Not sure why Driver is capitalized and clock is not.

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

* RE: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-03-22 10:47       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin @ 2018-03-22 10:47 UTC (permalink / raw)
  To: 'Stephen Boyd',
	linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:37
> To: Ilia Lin <ilialin@codeaurora.org>; =
linux-arm-kernel@lists.infradead.org;
> linux-arm-msm@vger.kernel.org; linux-clk@vger.kernel.org;
> sboyd@codeaurora.org
> Cc: mark.rutland@arm.com; devicetree@vger.kernel.org;
> rnayak@codeaurora.org; robh@kernel.org; will.deacon@arm.com;
> amit.kucheria@linaro.org; tfinkel@codeaurora.org; =
ilialin@codeaurora.org;
> nicolas.dechesne@linaro.org; celster@codeaurora.org
> Subject: Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for =
msm8996
>=20
> Quoting Ilia Lin (2018-02-14 05:59:45)
> > 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
>=20
> Thanks for the diagram. Please also put it at the top of the driver =
file.
>=20
> >
> > 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
>=20
> Capitalize 'h' in units please.
>=20
> >  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>
> > ---
> >  drivers/clk/qcom/Kconfig        |   8 +
> >  drivers/clk/qcom/Makefile       |   1 +
> >  drivers/clk/qcom/clk-cpu-8996.c | 409
> > ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 418 insertions(+)
> >  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> >
> > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig =
index
> > fbf4532..3274877 100644
> > --- a/drivers/clk/qcom/Kconfig
> > +++ b/drivers/clk/qcom/Kconfig
> > @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
> >           Technologies, Inc. SPMI PMIC. It configures the frequency =
of
> >           clkdiv outputs of the PMIC. These clocks are typically =
wired
> >           through alternate functions on GPIO pins.
> > +
> > +config 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.
>=20
> Sort?
>=20
> > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> > index 230332c..57b38ba 100644
> > --- a/drivers/clk/qcom/Makefile
> > +++ b/drivers/clk/qcom/Makefile
> > @@ -33,6 +33,7 @@ obj-$(CONFIG_MSM_LCC_8960) +=3D lcc-msm8960.o
> >  obj-$(CONFIG_MSM_MMCC_8960) +=3D mmcc-msm8960.o
> >  obj-$(CONFIG_MSM_MMCC_8974) +=3D mmcc-msm8974.o
> >  obj-$(CONFIG_MSM_MMCC_8996) +=3D mmcc-msm8996.o
> > +obj-$(CONFIG_MSM_APCC_8996) +=3D clk-cpu-8996.o
>=20
> This doesn't look sorted.
>=20
> >  obj-$(CONFIG_QCOM_A53PLL) +=3D a53-pll.o
> >  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) +=3D apcs-msm8916.o
> >  obj-$(CONFIG_QCOM_CLK_RPM) +=3D clk-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..42489f1
> > --- /dev/null
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -0,0 +1,409 @@
> > +/*
> > + * Copyright (c) 2018, 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.
> > + */
>=20
> Can we get the SPDX tags here please?
>=20
> > +
> > +#include <linux/clk.h>
>=20
> clk-provider.h?
>=20
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "clk-alpha-pll.h"
>=20
> #include "clk-regmap.h"
>=20
> > +
> > +#define VCO(a, b, c) { \
> > +       .val =3D a,\
> > +       .min_freq =3D b,\
> > +       .max_freq =3D c,\
> > +}
>=20
> Can this define go into whatever PLL header file defines the struct?
>=20
> > +
> > +#define DIV_2_INDEX            0
> > +#define PLL_INDEX              1
> > +#define ACD_INDEX              2
> > +#define ALT_INDEX              3
> > +
> > +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] =3D {
> > +       [PLL_OFF_L_VAL] =3D 0x04,
> > +       [PLL_OFF_ALPHA_VAL] =3D 0x08,
> > +       [PLL_OFF_USER_CTL] =3D 0x10,
> > +       [PLL_OFF_CONFIG_CTL] =3D 0x18,
> > +       [PLL_OFF_CONFIG_CTL_U] =3D 0x1C,
>=20
> Please use lowercase hex throughout. Consistency is key!
>=20
> > +       [PLL_OFF_TEST_CTL] =3D 0x20,
> > +       [PLL_OFF_TEST_CTL_U] =3D 0x24,
> > +       [PLL_OFF_STATUS] =3D 0x28,
> > +};
> > +
> > +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] =3D {
> > +       [PLL_OFF_L_VAL] =3D 0x04,
> > +       [PLL_OFF_ALPHA_VAL] =3D 0x08,
> > +       [PLL_OFF_ALPHA_VAL_U] =3D 0x0c,
> > +       [PLL_OFF_USER_CTL] =3D 0x10,
> > +       [PLL_OFF_USER_CTL_U] =3D 0x14,
> > +       [PLL_OFF_CONFIG_CTL] =3D 0x18,
> > +       [PLL_OFF_TEST_CTL] =3D 0x20,
> > +       [PLL_OFF_TEST_CTL_U] =3D 0x24,
> > +       [PLL_OFF_STATUS] =3D 0x28,
> > +};
> > +
> > +/* PLLs */
> > +
> > +static const struct alpha_pll_config hfpll_config =3D {
> > +       .l =3D 60,
> > +       .config_ctl_val =3D 0x200d4828,
> > +       .config_ctl_hi_val =3D 0x006,
> > +       .pre_div_mask =3D BIT(12),
> > +       .post_div_mask =3D 0x3 << 8,
> > +       .main_output_mask =3D BIT(0),
> > +       .early_output_mask =3D BIT(3),
> > +};
> > +
> > +static struct clk_alpha_pll perfcl_pll =3D {
> > +       .offset =3D 0x80000,
> > +       .regs =3D prim_pll_regs,
> > +       .flags =3D SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data){
> > +               .name =3D "perfcl_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_huayra_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_pll =3D {
> > +       .offset =3D 0x0,
> > +       .regs =3D prim_pll_regs,
> > +       .flags =3D SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data){
> > +               .name =3D "pwrcl_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_huayra_ops,
> > +       },
> > +};
> > +
> > +static const struct pll_vco alt_pll_vco_modes[] =3D {
> > +       VCO(3,  250000000,  500000000),
> > +       VCO(2,  500000000,  750000000),
> > +       VCO(1,  750000000, 1000000000),
> > +       VCO(0, 1000000000, 2150400000), };
> > +
> > +static const struct alpha_pll_config altpll_config =3D {
> > +       .l =3D 16,
> > +       .vco_val =3D 0x3 << 20,
> > +       .vco_mask =3D 0x3 << 20,
> > +       .config_ctl_val =3D 0x4001051b,
> > +       .post_div_mask =3D 0x3 << 8,
> > +       .post_div_val =3D 0x1,
> > +       .main_output_mask =3D BIT(0),
> > +       .early_output_mask =3D BIT(3),
> > +};
> > +
> > +static struct clk_alpha_pll perfcl_alt_pll =3D {
> > +       .offset =3D 0x80100,
> > +       .regs =3D alt_pll_regs,
> > +       .vco_table =3D alt_pll_vco_modes,
> > +       .num_vco =3D ARRAY_SIZE(alt_pll_vco_modes),
> > +       .flags =3D SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "perfcl_alt_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_hwfsm_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_alt_pll =3D {
> > +       .offset =3D 0x100,
> > +       .regs =3D alt_pll_regs,
> > +       .vco_table =3D alt_pll_vco_modes,
> > +       .num_vco =3D ARRAY_SIZE(alt_pll_vco_modes),
> > +       .flags =3D SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "pwrcl_alt_pll",
> > +               .parent_names =3D (const char *[]){ "xo" },
> > +               .num_parents =3D 1,
> > +               .ops =3D &clk_alpha_pll_hwfsm_ops,
> > +       },
> > +};
> > +
> > +/* Mux'es */
> > +
> > +struct clk_cpu_8996_mux {
> > +       u32     reg;
> > +       u32     shift;
>=20
> u8 shift?
>=20
> > +       u32     width;
>=20
> u8 width?
>=20
> > +       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 =3D to_clk_regmap(hw);
> > +       struct clk_cpu_8996_mux *cpuclk =3D =
to_clk_cpu_8996_mux_hw(hw);
> > +       unsigned int mask =3D GENMASK(cpuclk->width - 1, 0);
> > +
> > +       regmap_read(clkr->regmap, cpuclk->reg, &val);
> > +
> > +       val >>=3D cpuclk->shift;
> > +       val &=3D mask;
> > +
> > +       return val;
>=20
> return val & mask;
>=20
> > +}
> > +
> > +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index) =
{
> > +       unsigned int val;
>=20
> u32 val?
>=20
> > +       struct clk_regmap *clkr =3D to_clk_regmap(hw);
> > +       struct clk_cpu_8996_mux *cpuclk =3D =
to_clk_cpu_8996_mux_hw(hw);
> > +       unsigned int mask =3D GENMASK(cpuclk->width + cpuclk->shift =
- 1,
> > +                                   cpuclk->shift);
> > +
> > +       val =3D index;
> > +       val <<=3D 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 =3D =
to_clk_cpu_8996_mux_hw(hw);
> > +       struct clk_hw *parent =3D cpuclk->pll;
> > +
> > +       if (!cpuclk->pll)
> > +               return -EINVAL;
>=20
> Does this happen?
>=20
> > +
> > +       req->best_parent_rate =3D clk_hw_round_rate(parent, =
req->rate);
> > +       req->best_parent_hw =3D parent;
>=20
> Is the parent index always the same? Perhaps just call
> clk_hw_get_parent_by_index() then instead of adding a pointer to the
> clk_cpu_8996_mux.
>=20
> > +
> > +       return 0;
> > +}
> > +
> > +const struct clk_ops clk_cpu_8996_mux_ops =3D {
> > +       .set_parent =3D clk_cpu_8996_mux_set_parent,
> > +       .get_parent =3D clk_cpu_8996_mux_get_parent,
> > +       .determine_rate =3D clk_cpu_8996_mux_determine_rate, };
> [...]
> > +
> > +static struct clk_cpu_8996_mux pwrcl_pmux =3D {
> > +       .reg =3D 0x40,
> > +       .shift =3D 0,
> > +       .width =3D 2,
> > +       .pll =3D &pwrcl_pll.clkr.hw,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "pwrcl_pmux",
> > +               .parent_names =3D (const char *[]){
> > +                       "pwrcl_smux",
> > +                       "pwrcl_pll",
> > +                       "pwrcl_pll_acd",
> > +                       "pwrcl_alt_pll",
> > +               },
> > +               .num_parents =3D 4,
> > +               .ops =3D &clk_cpu_8996_mux_ops,
> > +               .flags =3D CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> > +       },
> > +};
> > +
> > +static struct clk_cpu_8996_mux perfcl_pmux =3D {
> > +       .reg =3D 0x80040,
> > +       .shift =3D 0,
> > +       .width =3D 2,
> > +       .pll =3D &perfcl_pll.clkr.hw,
> > +       .clkr.hw.init =3D &(struct clk_init_data) {
> > +               .name =3D "perfcl_pmux",
> > +               .parent_names =3D (const char *[]){
> > +                       "perfcl_smux",
> > +                       "perfcl_pll",
> > +                       "perfcl_pll_acd",
> > +                       "perfcl_alt_pll",
> > +               },
> > +               .num_parents =3D 4,
> > +               .ops =3D &clk_cpu_8996_mux_ops,
> > +               .flags =3D CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
>=20
> Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
> for now? We don't want to force XO to stay on forever here.
>=20
> > +       },
> > +};
> > +
> > +static const struct regmap_config cpu_msm8996_regmap_config =3D {
> > +       .reg_bits               =3D 32,
> > +       .reg_stride             =3D 4,
> > +       .val_bits               =3D 32,
> > +       .max_register           =3D 0x80210,
> > +       .fast_io                =3D true,
> > +       .val_format_endian      =3D REGMAP_ENDIAN_LITTLE,
> > +};
> > +
> > +static const struct of_device_id match_table[] =3D {
>=20
> Move this next to driver structure and give it a more specific name.
>=20
> > +       { .compatible =3D "qcom-msm8996-apcc" },
>=20
> Bad compatible? Should be qcom,msm8996-apcc?
>=20
> > +       {}
> > +};
> > +
> > +struct clk_regmap *clks[] =3D {
> > +       /* 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,
>=20
> Please drop useless comments inside this array.
>=20
> > +};
> > +
> > +struct clk_hw_clks {
> > +       unsigned int num;
> > +       struct clk_hw *hws[];
> > +};
>=20
> Please just NULL terminate the list of clk_hw pointers, or keep the =
size
> around instead.
>=20
> > +
> > +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] =3D clk_hw_register_fixed_factor(dev, =
"perfcl_pll_main",
> > +                                                  "perfcl_pll",
> > +                                                  =
CLK_SET_RATE_PARENT, 1, 2);
> > +       perfcl_smux.pll =3D hws->hws[0];
> > +
> > +       hws->hws[1] =3D clk_hw_register_fixed_factor(dev, =
"pwrcl_pll_main",
> > +                                                  "pwrcl_pll",
> > +                                                  =
CLK_SET_RATE_PARENT, 1, 2);
> > +       pwrcl_smux.pll =3D hws->hws[1];
> > +
> > +       hws->num =3D 2;
>=20
> Maybe just open code the fixed factor clk registration? Then the
> devm_clk_hw_register() function can be used on those static structs to =
make
> removal simpler.

I will have to change the clk_hw_unregister_fixed_rate() as well then, =
right? This will be an API change.

>=20
> > +
> > +       for (i =3D 0; i < ARRAY_SIZE(clks); i++) {
> > +               ret =3D 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;
>=20
> Just call it regmap please.
>=20
> > +       struct clk_hw_clks *hws;
> > +       struct clk_hw_onecell_data *data;
> > +       struct device *dev =3D &pdev->dev;
> > +       struct device_node *node =3D dev->of_node;
> > +
> > +       data =3D devm_kzalloc(dev, sizeof(*data) + 2 * sizeof(struct =
clk_hw *),
> > +                           GFP_KERNEL);
> > +       if (!data)
> > +               return -ENOMEM;
> > +
> > +       hws =3D devm_kzalloc(dev, sizeof(*hws) + 2 * sizeof(struct =
clk_hw *),
> > +                          GFP_KERNEL);
> > +       if (!hws)
> > +               return -ENOMEM;
> > +
> > +       res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       base =3D devm_ioremap_resource(dev, res);
> > +       if (IS_ERR(base))
> > +               return PTR_ERR(base);
> > +
> > +       regmap_cpu =3D devm_regmap_init_mmio(dev, base,
> > +                                          =
&cpu_msm8996_regmap_config);
> > +       if (IS_ERR(regmap_cpu))
> > +               return PTR_ERR(regmap_cpu);
> > +
> > +       ret =3D qcom_cpu_clk_msm8996_register_clks(dev, hws, =
regmap_cpu);
> > +       if (ret)
> > +               return ret;
> > +
> > +       data->hws[0] =3D &pwrcl_pmux.clkr.hw;
> > +       data->hws[1] =3D &perfcl_pmux.clkr.hw;
> > +
> > +       data->num =3D 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 =3D &pdev->dev;
> > +       struct clk_hw_clks *hws =3D platform_get_drvdata(pdev);
> > +
> > +       for (i =3D 0; i < hws->num; i++)
> > +               clk_hw_unregister_fixed_rate(hws->hws[i]);
> > +
> > +       of_clk_del_provider(dev->of_node);
>=20
> Use devm_of_clk_add_hw_provider() instead.
>=20
> > +
> > +       return 0;
> > +}
> > +
> > +static struct platform_driver qcom_cpu_clk_msm8996_driver =3D {
> > +       .probe =3D qcom_cpu_clk_msm8996_driver_probe,
> > +       .remove =3D qcom_cpu_clk_msm8996_driver_remove,
> > +       .driver =3D {
> > +               .name =3D "qcom-msm8996-apcc",
> > +               .of_match_table =3D match_table,
> > +       },
> > +};
> > +
> > +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> > +
> > +MODULE_ALIAS("platform:msm8996-apcc");
> > +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
>=20
> Not sure why Driver is capitalized and clock is not.


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

* [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-03-22 10:47       ` ilialin
  0 siblings, 0 replies; 101+ messages in thread
From: ilialin at codeaurora.org @ 2018-03-22 10:47 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Monday, March 19, 2018 19:37
> To: Ilia Lin <ilialin@codeaurora.org>; linux-arm-kernel at lists.infradead.org;
> linux-arm-msm at vger.kernel.org; linux-clk at vger.kernel.org;
> sboyd at codeaurora.org
> Cc: mark.rutland at arm.com; devicetree at vger.kernel.org;
> rnayak at codeaurora.org; robh at kernel.org; will.deacon at arm.com;
> amit.kucheria at linaro.org; tfinkel at codeaurora.org; ilialin at codeaurora.org;
> nicolas.dechesne at linaro.org; celster at codeaurora.org
> Subject: Re: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
> 
> Quoting Ilia Lin (2018-02-14 05:59:45)
> > 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
> 
> Thanks for the diagram. Please also put it at the top of the driver file.
> 
> >
> > 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
> 
> Capitalize 'h' in units please.
> 
> >  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>
> > ---
> >  drivers/clk/qcom/Kconfig        |   8 +
> >  drivers/clk/qcom/Makefile       |   1 +
> >  drivers/clk/qcom/clk-cpu-8996.c | 409
> > ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 418 insertions(+)
> >  create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
> >
> > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index
> > fbf4532..3274877 100644
> > --- a/drivers/clk/qcom/Kconfig
> > +++ b/drivers/clk/qcom/Kconfig
> > @@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV
> >           Technologies, Inc. SPMI PMIC. It configures the frequency of
> >           clkdiv outputs of the PMIC. These clocks are typically wired
> >           through alternate functions on GPIO pins.
> > +
> > +config 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.
> 
> Sort?
> 
> > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> > index 230332c..57b38ba 100644
> > --- a/drivers/clk/qcom/Makefile
> > +++ b/drivers/clk/qcom/Makefile
> > @@ -33,6 +33,7 @@ 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
> 
> This doesn't look sorted.
> 
> >  obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
> >  obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
> >  obj-$(CONFIG_QCOM_CLK_RPM) += clk-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..42489f1
> > --- /dev/null
> > +++ b/drivers/clk/qcom/clk-cpu-8996.c
> > @@ -0,0 +1,409 @@
> > +/*
> > + * Copyright (c) 2018, 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.
> > + */
> 
> Can we get the SPDX tags here please?
> 
> > +
> > +#include <linux/clk.h>
> 
> clk-provider.h?
> 
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "clk-alpha-pll.h"
> 
> #include "clk-regmap.h"
> 
> > +
> > +#define VCO(a, b, c) { \
> > +       .val = a,\
> > +       .min_freq = b,\
> > +       .max_freq = c,\
> > +}
> 
> Can this define go into whatever PLL header file defines the struct?
> 
> > +
> > +#define DIV_2_INDEX            0
> > +#define PLL_INDEX              1
> > +#define ACD_INDEX              2
> > +#define ALT_INDEX              3
> > +
> > +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_CONFIG_CTL_U] = 0x1C,
> 
> Please use lowercase hex throughout. Consistency is key!
> 
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
> > +       [PLL_OFF_L_VAL] = 0x04,
> > +       [PLL_OFF_ALPHA_VAL] = 0x08,
> > +       [PLL_OFF_ALPHA_VAL_U] = 0x0c,
> > +       [PLL_OFF_USER_CTL] = 0x10,
> > +       [PLL_OFF_USER_CTL_U] = 0x14,
> > +       [PLL_OFF_CONFIG_CTL] = 0x18,
> > +       [PLL_OFF_TEST_CTL] = 0x20,
> > +       [PLL_OFF_TEST_CTL_U] = 0x24,
> > +       [PLL_OFF_STATUS] = 0x28,
> > +};
> > +
> > +/* 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,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_ops,
> > +       },
> > +};
> > +
> > +static struct clk_alpha_pll pwrcl_pll = {
> > +       .offset = 0x0,
> > +       .regs = prim_pll_regs,
> > +       .flags = SUPPORTS_DYNAMIC_UPDATE | 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_huayra_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,
> > +       .regs = alt_pll_regs,
> > +       .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,
> > +       .regs = alt_pll_regs,
> > +       .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;
> 
> u8 shift?
> 
> > +       u32     width;
> 
> u8 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;
> 
> return val & mask;
> 
> > +}
> > +
> > +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index) {
> > +       unsigned int val;
> 
> u32 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;
> 
> Does this happen?
> 
> > +
> > +       req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
> > +       req->best_parent_hw = parent;
> 
> Is the parent index always the same? Perhaps just call
> clk_hw_get_parent_by_index() then instead of adding a pointer to the
> clk_cpu_8996_mux.
> 
> > +
> > +       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_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 | CLK_IS_CRITICAL,
> > +       },
> > +};
> > +
> > +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",
> > +                       "perfcl_pll_acd",
> > +                       "perfcl_alt_pll",
> > +               },
> > +               .num_parents = 4,
> > +               .ops = &clk_cpu_8996_mux_ops,
> > +               .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> 
> Not sure CLK_IS_CRITICAL is the right mode. Perhaps CLK_IGNORE_UNUSED
> for now? We don't want to force XO to stay on forever here.
> 
> > +       },
> > +};
> > +
> > +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[] = {
> 
> Move this next to driver structure and give it a more specific name.
> 
> > +       { .compatible = "qcom-msm8996-apcc" },
> 
> Bad compatible? Should be qcom,msm8996-apcc?
> 
> > +       {}
> > +};
> > +
> > +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,
> 
> Please drop useless comments inside this array.
> 
> > +};
> > +
> > +struct clk_hw_clks {
> > +       unsigned int num;
> > +       struct clk_hw *hws[];
> > +};
> 
> Please just NULL terminate the list of clk_hw pointers, or keep the size
> around instead.
> 
> > +
> > +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;
> 
> Maybe just open code the fixed factor clk registration? Then the
> devm_clk_hw_register() function can be used on those static structs to make
> removal simpler.

I will have to change the clk_hw_unregister_fixed_rate() as well then, right? This will be an API change.

> 
> > +
> > +       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;
> 
> Just call it regmap please.
> 
> > +       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);
> 
> Use devm_of_clk_add_hw_provider() instead.
> 
> > +
> > +       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-msm8996-apcc",
> > +               .of_match_table = match_table,
> > +       },
> > +};
> > +
> > +module_platform_driver(qcom_cpu_clk_msm8996_driver);
> > +
> > +MODULE_ALIAS("platform:msm8996-apcc");
> > +MODULE_DESCRIPTION("QCOM MSM8996 CPU clock Driver");
> 
> Not sure why Driver is capitalized and clock is not.

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

* Re: [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
  2018-03-19 21:21         ` Stephen Boyd
@ 2018-03-22 18:56           ` Robin Murphy
  -1 siblings, 0 replies; 101+ messages in thread
From: Robin Murphy @ 2018-03-22 18:56 UTC (permalink / raw)
  To: Stephen Boyd, Ilia Lin, linux-arm-kernel, linux-arm-msm,
	linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

On 19/03/18 21:21, Stephen Boyd wrote:
> Quoting Robin Murphy (2018-03-19 11:16:15)
>> On 19/03/18 16:57, Stephen Boyd wrote:
>> [...]
>>>> +
>>>
>>>> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
>>>> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
>>>> +               /* Ensure SSSCTL config goes through before enabling ACD. */
>>>> +               mb();
>>>
>>> Use writel instead.
>>
>> Note that writel() only gives an implicit wmb() *before* the store to
>> ensure ordering against any previous writes. If this code really needs
>> to ensure that the given write has definitely completed before any other
>> accesses happen, then it still needs an explicit barrier *after* the
>> write*(), unless perhaps the next access is always guaranteed to be a
>> non-relaxed write (thus implicitly providing a suitable DSB).
>>
> 
> Ah right. So this should be a wmb() too? I suspect it's to order with
> the write to the l2 indirect registers, but reading that register before
> the MMIO write is not a problem. The comment above the l2 accessors
> could be slightly more specific here and it would help immensely.

It depends a bit on what exactly the hardware requires. If it's merely 
that write(s) to register A (and perhaps others) arrive before any write 
to register B, then the sensible thing to do would be to just make the 
write to B non-relaxed, i.e.:

	writel_relaxed(x, base + A);
	...
	writel(y, base + B);

That still only guarantees that the previous write(s) have been pushed 
all the way to the endpoint before the write to B is issued, though - 
for many devices that's sufficient, but in some cases the only way to be 
totally sure that the write has both been received *and* taken effect is 
by reading back some suitable indicator before proceeding.

If we only care about making sure writes are pushed out, rather than 
synchronising more complicated memory accesses between multiple agents, 
then a full mb() is probably overkill (as ordering against outstanding 
loads too only adds more overhead in the interconnect), and wmb() 
(ideally implicit in a subsequent writel() as above) should be enough.

Robin.

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

* [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996
@ 2018-03-22 18:56           ` Robin Murphy
  0 siblings, 0 replies; 101+ messages in thread
From: Robin Murphy @ 2018-03-22 18:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 19/03/18 21:21, Stephen Boyd wrote:
> Quoting Robin Murphy (2018-03-19 11:16:15)
>> On 19/03/18 16:57, Stephen Boyd wrote:
>> [...]
>>>> +
>>>
>>>> +                       writel_relaxed(SSSCTL_VAL, vbases[APC_BASE] +
>>>> +                                       PWRCL_REG_OFFSET + SSSCTL_OFFSET);
>>>> +               /* Ensure SSSCTL config goes through before enabling ACD. */
>>>> +               mb();
>>>
>>> Use writel instead.
>>
>> Note that writel() only gives an implicit wmb() *before* the store to
>> ensure ordering against any previous writes. If this code really needs
>> to ensure that the given write has definitely completed before any other
>> accesses happen, then it still needs an explicit barrier *after* the
>> write*(), unless perhaps the next access is always guaranteed to be a
>> non-relaxed write (thus implicitly providing a suitable DSB).
>>
> 
> Ah right. So this should be a wmb() too? I suspect it's to order with
> the write to the l2 indirect registers, but reading that register before
> the MMIO write is not a problem. The comment above the l2 accessors
> could be slightly more specific here and it would help immensely.

It depends a bit on what exactly the hardware requires. If it's merely 
that write(s) to register A (and perhaps others) arrive before any write 
to register B, then the sensible thing to do would be to just make the 
write to B non-relaxed, i.e.:

	writel_relaxed(x, base + A);
	...
	writel(y, base + B);

That still only guarantees that the previous write(s) have been pushed 
all the way to the endpoint before the write to B is issued, though - 
for many devices that's sufficient, but in some cases the only way to be 
totally sure that the write has both been received *and* taken effect is 
by reading back some suitable indicator before proceeding.

If we only care about making sure writes are pushed out, rather than 
synchronising more complicated memory accesses between multiple agents, 
then a full mb() is probably overkill (as ordering against outstanding 
loads too only adds more overhead in the interconnect), and wmb() 
(ideally implicit in a subsequent writel() as above) should be enough.

Robin.

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

* RE: [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
  2018-03-22 10:47       ` ilialin
@ 2018-04-06 18:18         ` Stephen Boyd
  -1 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-04-06 18:18 UTC (permalink / raw)
  To: ilialin, linux-arm-kernel, linux-arm-msm, linux-clk, sboyd
  Cc: mark.rutland, devicetree, rnayak, robh, will.deacon,
	amit.kucheria, tfinkel, nicolas.dechesne, celster

Quoting ilialin@codeaurora.org (2018-03-22 03:47:30)
> 
> I will have to change the clk_hw_unregister_fixed_rate() as well then, right? This will be an API change.

You won't need to unregister anything? devm will take care of it.

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

* [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996
@ 2018-04-06 18:18         ` Stephen Boyd
  0 siblings, 0 replies; 101+ messages in thread
From: Stephen Boyd @ 2018-04-06 18:18 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting ilialin at codeaurora.org (2018-03-22 03:47:30)
> 
> I will have to change the clk_hw_unregister_fixed_rate() as well then, right? This will be an API change.

You won't need to unregister anything? devm will take care of it.

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

end of thread, other threads:[~2018-04-06 18:18 UTC | newest]

Thread overview: 101+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-14 13:59 [PATCH v3 00/10] clk: qcom: CPU clock driver for msm8996 Ilia Lin
2018-02-14 13:59 ` Ilia Lin
2018-02-14 13:59 ` Ilia Lin
2018-02-14 13:59 ` [PATCH v3 01/10] soc: qcom: Separate kryo l2 accessors from PMU driver Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-03-19 17:45   ` Stephen Boyd
2018-03-19 17:45     ` Stephen Boyd
2018-03-19 17:45     ` Stephen Boyd
2018-03-20 18:42     ` ilialin
2018-03-20 18:42       ` ilialin at codeaurora.org
2018-03-20 18:42       ` ilialin
2018-02-14 13:59 ` [PATCH v3 02/10] clk: qcom: Make clk_alpha_pll_configure available to modules Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-03-19 17:45   ` Stephen Boyd
2018-03-19 17:45     ` Stephen Boyd
2018-03-19 17:45     ` Stephen Boyd
2018-02-14 13:59 ` [PATCH v3 03/10] clk: qcom: Add CPU clock driver for msm8996 Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-03-19 17:36   ` Stephen Boyd
2018-03-19 17:36     ` Stephen Boyd
2018-03-19 17:36     ` Stephen Boyd
2018-03-20 14:18     ` ilialin
2018-03-20 14:18       ` ilialin at codeaurora.org
2018-03-20 14:18       ` ilialin
2018-03-20 20:01       ` Stephen Boyd
2018-03-20 20:01         ` Stephen Boyd
2018-03-22 10:47     ` ilialin
2018-03-22 10:47       ` ilialin at codeaurora.org
2018-03-22 10:47       ` ilialin
2018-04-06 18:18       ` Stephen Boyd
2018-04-06 18:18         ` Stephen Boyd
2018-02-14 13:59 ` [PATCH v3 04/10] clk: qcom: Add DT bindings for " Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-02-19  3:12   ` Rob Herring
2018-02-19  3:12     ` Rob Herring
2018-02-19  3:12     ` Rob Herring
2018-03-19 17:46   ` Stephen Boyd
2018-03-19 17:46     ` Stephen Boyd
2018-03-19 17:46     ` Stephen Boyd
2018-03-20 18:43     ` ilialin
2018-03-20 18:43       ` ilialin at codeaurora.org
2018-03-20 18:43       ` ilialin
2018-02-14 13:59 ` [PATCH v3 06/10] clk: qcom: cpu-8996: Add support to switch below 600Mhz Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-03-19 17:49   ` Stephen Boyd
2018-03-19 17:49     ` Stephen Boyd
2018-03-19 17:49     ` Stephen Boyd
2018-02-14 13:59 ` [PATCH v3 07/10] clk: qcom: clk-cpu-8996: Prepare PLLs on probe Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-03-19 16:50   ` Stephen Boyd
2018-03-19 16:50     ` Stephen Boyd
2018-03-19 16:50     ` Stephen Boyd
2018-03-20 13:53     ` ilialin
2018-03-20 13:53       ` ilialin at codeaurora.org
2018-03-20 13:53       ` ilialin
2018-03-20 20:03       ` Stephen Boyd
2018-03-20 20:03         ` Stephen Boyd
2018-02-14 13:59 ` [PATCH v3 08/10] clk: qcom: Add ACD path to CPU clock driver for msm8996 Ilia Lin
2018-02-14 13:59   ` Ilia Lin
2018-03-19 16:57   ` Stephen Boyd
2018-03-19 16:57     ` Stephen Boyd
2018-03-19 18:16     ` Robin Murphy
2018-03-19 18:16       ` Robin Murphy
2018-03-19 18:16       ` Robin Murphy
2018-03-19 21:21       ` Stephen Boyd
2018-03-19 21:21         ` Stephen Boyd
2018-03-22 18:56         ` Robin Murphy
2018-03-22 18:56           ` Robin Murphy
2018-03-20 14:04     ` ilialin
2018-03-20 14:04       ` ilialin at codeaurora.org
2018-03-20 14:04       ` ilialin
2018-03-20 20:04       ` Stephen Boyd
2018-03-20 20:04         ` Stephen Boyd
     [not found] ` <1518616792-29028-1-git-send-email-ilialin-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-02-14 13:59   ` [PATCH v3 05/10] clk: qcom: cpu-8996: Add support to switch to alternate PLL Ilia Lin
2018-02-14 13:59     ` Ilia Lin
2018-02-14 13:59     ` Ilia Lin
2018-03-19 17:47     ` Stephen Boyd
2018-03-19 17:47       ` Stephen Boyd
2018-03-19 17:47       ` Stephen Boyd
2018-03-20 18:45       ` ilialin
2018-03-20 18:45         ` ilialin at codeaurora.org
2018-03-20 18:45         ` ilialin
2018-02-14 13:59   ` [PATCH v3 09/10] DT: QCOM: Add cpufreq-dt to msm8996 Ilia Lin
2018-02-14 13:59     ` Ilia Lin
2018-02-14 13:59     ` Ilia Lin
2018-03-19 16:48     ` Stephen Boyd
2018-03-19 16:48       ` Stephen Boyd
2018-03-19 16:48       ` Stephen Boyd
2018-03-20 13:46       ` ilialin
2018-03-20 13:46         ` ilialin at codeaurora.org
2018-03-20 13:46         ` ilialin
2018-03-20 20:06         ` Stephen Boyd
2018-03-20 20:06           ` Stephen Boyd
2018-03-20 20:34           ` ilialin
2018-03-20 20:34             ` ilialin at codeaurora.org
2018-03-20 20:34             ` ilialin
2018-03-20 21:46             ` Stephen Boyd
2018-03-20 21:46               ` Stephen Boyd
2018-02-14 13:59 ` [PATCH v3 10/10] DT: QCOM: Add thermal mitigation " Ilia Lin
2018-02-14 13:59   ` Ilia Lin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.