clk: qcom: CPU clock driver for msm8996
Subsystems (8)
v3 cover clk: qcom: CPU clock driver for msm8996
[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
Signature · 1 line
1.9.1
PATCH v3 1/10 soc: qcom: Separate kryo l2 accessors from PMU driver
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.
--- 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
arch/arm64/Kconfig.platforms +7 -0
@@ -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
drivers/perf/qcom_l2_pmu.c +2 -48
71 lines not on this page · raw message
drivers/soc/qcom/Makefile +1 -0
@@ -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
drivers/soc/qcom/kryo-l2-accessors.c new file +64 -0
64 lines not on this page · raw message
include/soc/qcom/kryo-l2-accessors.h new file +22 -0
@@ -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
Signature · 1 line
1.9.1
Stephen Boyd
maintainerPATCH v3 1/10 soc: qcom: Separate kryo l2 accessors from PMU driver
Quoting Ilia Lin (2018-02-14 05:59:43)
arch/arm64/Kconfig.platforms config ARCH_REALTEK · line 150
Quoted 11 lines
arch/arm64/Kconfig.platforms +3
-0@@ -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?
Quoted 12 lines
arch/arm64/Kconfig.platforms +4
-0+ 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_CONTROLLERdrivers/perf/qcom_l2_pmu.c +0
-0
drivers/perf/qcom_l2_pmu.c line 1
Quoted 2 lines
drivers/perf/qcom_l2_pmu.c +1
-1@@ -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?
Quoted 20 lines
drivers/perf/qcom_l2_pmu.c +0
-0* * 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 drivers/soc/qcom/Makefile +1
-0@@ -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.odrivers/soc/qcom/kryo-l2-accessors.c new file +2
-0@@ -0,0 +1,64 @@ +/* +* Copyright (c) 2014-2015, 2018, The Linux Foundation. All rights reserved.
drivers/soc/qcom/kryo-l2-accessors.c line 12
Quoted 10 lines
drivers/soc/qcom/kryo-l2-accessors.c new file +10
-0+* +* 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?
Quoted 11 lines
include/soc/qcom/kryo-l2-accessors.h new file +5
-0@@ -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
include/soc/qcom/kryo-l2-accessors.h line 15
Quoted 10 lines
include/soc/qcom/kryo-l2-accessors.h new file +10
-0+* 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
include/soc/qcom/kryo-l2-accessors.h line 20
Quoted 5 lines
include/soc/qcom/kryo-l2-accessors.h new file +5
-0+ +#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.
PATCH v3 1/10 soc: qcom: Separate kryo l2 accessors from PMU driver
Quoted 24 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 19:45
To: Ilia Lin <[email protected]>; 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 driverQuoting Ilia Lin (2018-02-14 05:59:43)
Quoted 8 lines
(quoted diff) +0
-0b/arch/arm64/Kconfig.platforms index fbedbd8..78a103b 100644
arch/arm64/Kconfig.platforms +0
-0@@ -145,6 +145,13 @@ config ARCH_REALTEK This enables support for the ARMv8 based Realtek chipsets, like the RTD1295.
Quoted 7 lines
arch/arm64/Kconfig.platforms config ARCH_REALTEK · line 150
Quoted 3 lines
arch/arm64/Kconfig.platforms +3
-0+config ARCH_MSM8996 + bool "Enable Support for Qualcomm Technologies, Inc. MSM8996" + depends on ARCH_QCOMIs 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
Kconfigaddition?
I'll check whether the kryo-accessors code is SOC specific or not.
Quoted 10 lines
Quoted 10 lines
arch/arm64/Kconfig.platforms +4
-0+ 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.cb/drivers/perf/qcom_l2_pmu.cindex 4fdc848..8cece9e 100644
Quoted 8 lines
drivers/perf/qcom_l2_pmu.c line 1
Quoted 5 lines
drivers/perf/qcom_l2_pmu.c +1
-1@@ -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.
Quoted 28 lines
drivers/soc/qcom/Makefile obj-$(CONFIG_QCOM_SMEM_STATE) +=
Quoted 9 lines
drivers/perf/qcom_l2_pmu.c +0
-0* * 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 drivers/soc/qcom/Makefile +0
-0@@ -12,3 +12,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) +=smem_state.o
Quoted 18 lines
drivers/soc/qcom/Makefile +1
-0obj-$(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.odrivers/soc/qcom/kryo-l2-accessors.c new file +7
-0@@ -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.
Quoted 8 lines
drivers/soc/qcom/kryo-l2-accessors.c line 12
Quoted 6 lines
drivers/soc/qcom/kryo-l2-accessors.c new file +6
-0+* +* 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.
Quoted 18 lines
Quoted 18 lines
include/soc/qcom/kryo-l2-accessors.h new file +10
-0@@ -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
Quoted 8 lines
include/soc/qcom/kryo-l2-accessors.h line 15
Quoted 6 lines
include/soc/qcom/kryo-l2-accessors.h new file +6
-0+* 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_HMaybe change this tO
__SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H
No problem. Will change.
Quoted 7 lines
include/soc/qcom/kryo-l2-accessors.h
Quoted 5 lines
include/soc/qcom/kryo-l2-accessors.h new file +4
-0+ +#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.
PATCH v3 2/10 clk: qcom: Make clk_alpha_pll_configure available to modules
In reply to Ilia LinFrom: Rajendra Nayak <[email protected]>
Allow clk_alpha_pll_configure to be called from loadable kernel modules.
--- drivers/clk/qcom/clk-alpha-pll.c | 1 + 1 file changed, 1 insertion(+)
drivers/clk/qcom/clk-alpha-pll.c +1 -0
@@ -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) {
Signature · 1 line
1.9.1
PATCH v3 2/10 clk: qcom: Make clk_alpha_pll_configure available to modules
Quoting Ilia Lin (2018-02-14 05:59:44)
Quoted 8 lines
From: Rajendra Nayak <[email protected]>
Allow
clk_alpha_pll_configureto be called from loadable kernel modules.Signed-off-by Rajendra Nayak <[email protected]>Signed-off-by Ilia Lin <[email protected]>---
Applied to clk-next
PATCH v3 3/10 clk: qcom: Add CPU clock driver for msm8996
In reply to Ilia LinFrom: Rajendra Nayak <[email protected]>
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_EARLYThe 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.
--- 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
drivers/clk/qcom/Kconfig +8 -0
@@ -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.
drivers/clk/qcom/Makefile +1 -0
@@ -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
drivers/clk/qcom/clk-cpu-8996.c new file +409 -0
409 lines not on this page · raw message
Signature · 1 line
1.9.1
Stephen Boyd
maintainerPATCH v3 3/10 clk: qcom: Add CPU clock driver for msm8996
Quoting Ilia Lin (2018-02-14 05:59:45)
Quoted 19 lines
From: Rajendra Nayak <[email protected]>
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 | | +------>
Quoted 8 lines
| +------+-----------+ +------>2 PMUX |
+---------------+ | | | |
| +------+ | +-->3 |
+--^+ ACD +-----+ | +-------+
+---------------+ +------+ |
|Alt PLL | |
| +---------------------------+
+---------------+ PLL_EARLYThanks for the diagram. Please also put it at the top of the driver file.
Quoted 13 lines
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.
Quoted 3 lines
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.
Quoted 22 lines
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 <[email protected]>Signed-off-by Ilia Lin <[email protected]>--- 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.cdrivers/clk/qcom/Kconfig +0
-0@@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV Technologies, Inc. SPMI PMIC. It configures the frequency of
drivers/clk/qcom/Kconfig config SPMI_PMIC_CLKDIV · line 236
Quoted 10 lines
drivers/clk/qcom/Kconfig +8
-0clkdiv 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?
drivers/clk/qcom/Makefile obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o · line 36
Quoted 9 lines
drivers/clk/qcom/Makefile +1
-0@@ -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.
Quoted 11 lines
drivers/clk/qcom/Makefile +0
-0obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.odrivers/clk/qcom/clk-cpu-8996.c new file +2
-0@@ -0,0 +1,409 @@ +/* +* Copyright (c) 2018, The Linux Foundation. All rights reserved.
drivers/clk/qcom/clk-cpu-8996.c line 12
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+* +* 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?
drivers/clk/qcom/clk-cpu-8996.c line 14
Quoted 2 lines
drivers/clk/qcom/clk-cpu-8996.c new file +2
-0+ +#include <linux/clk.h>
clk-provider.h?
drivers/clk/qcom/clk-cpu-8996.c line 19
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +5
-0+#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include "clk-alpha-pll.h"
#include "clk-regmap.h"
drivers/clk/qcom/clk-cpu-8996.c line 25
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+ +#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?
drivers/clk/qcom/clk-cpu-8996.c line 37
Quoted 12 lines
drivers/clk/qcom/clk-cpu-8996.c new file +12
-0+ +#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!
Quoted 94 lines
drivers/clk/qcom/clk-cpu-8996.c new file +94
-0+ [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" },
drivers/clk/qcom/clk-cpu-8996.c line 141
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ .num_parents = 1, + .ops = &clk_alpha_pll_hwfsm_ops, + }, +}; + +/* Mux'es */ + +struct clk_cpu_8996_mux { +u32 reg; +u32 shift;
u8 shift?
drivers/clk/qcom/clk-cpu-8996.c line 142
Quoted 1 line
drivers/clk/qcom/clk-cpu-8996.c new file +1
-0+u32 width;
u8 width?
Quoted 13 lines
drivers/clk/qcom/clk-cpu-8996.c new file +13
-0+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;
drivers/clk/qcom/clk-cpu-8996.c line 165
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+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;
drivers/clk/qcom/clk-cpu-8996.c line 170
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +5
-0+} + +static int clk_cpu_8996_mux_set_parent (struct clk_hw *hw,u8 index) +{ +unsigned int val;
u32 val?
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c new file +9
-0+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);
drivers/clk/qcom/clk-cpu-8996.c line 189
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+} + +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?
drivers/clk/qcom/clk-cpu-8996.c line 192
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c new file +3
-0+ + 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.
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c new file +9
-0+ +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, +};
[...]
Quoted 26 lines
drivers/clk/qcom/clk-cpu-8996.c new file +26
-0+ +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 ) {
drivers/clk/qcom/clk-cpu-8996.c line 269
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ .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.
drivers/clk/qcom/clk-cpu-8996.c line 282
Quoted 13 lines
drivers/clk/qcom/clk-cpu-8996.c new file +13
-0+ }, +}; + +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.
Quoted 1 line
+ { .compatible = "qcom-msm8996-apcc" },
Bad compatible? Should be qcom,msm8996-apcc?
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +4
-0+ {} +}; + +struct clk_regmap *clks[] = {
drivers/clk/qcom/clk-cpu-8996.c line 297
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+/* 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.
drivers/clk/qcom/clk-cpu-8996.c line 303
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+}; + +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.
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c new file +8
-0+ +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",
drivers/clk/qcom/clk-cpu-8996.c line 321
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+"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.
Quoted 11 lines
drivers/clk/qcom/clk-cpu-8996.c new file +11
-0+ +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);
drivers/clk/qcom/clk-cpu-8996.c line 342
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ +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.
Quoted 39 lines
drivers/clk/qcom/clk-cpu-8996.c new file +39
-0+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); +} +
drivers/clk/qcom/clk-cpu-8996.c line 391
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+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.
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c new file +7
-0+ +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,
drivers/clk/qcom/clk-cpu-8996.c line 408
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ .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.
PATCH v3 3/10 clk: qcom: Add CPU clock driver for msm8996
Quoted 43 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 19:37
To: Ilia Lin <[email protected]>; 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 msm8996Quoting Ilia Lin (2018-02-14 05:59:45)
Quoted 19 lines
From: Rajendra Nayak <[email protected]>
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 | | +------>Quoted 8 lines
| +------+-----------+ +------>2 PMUX | +---------------+ | | | | | +------+ | +-->3 | +--^+ ACD +-----+ | +-------+ +---------------+ +------+ | |Alt PLL | | | +---------------------------+ +---------------+ PLL_EARLY
Quoted 1 line
Thanks for the diagram. Please also put it at the top of the driver file.
Will be added in the next spin.
Quoted 15 lines
Quoted 10 lines
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
Quoted 4 lines
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.
Quoted 5 lines
Quoted 3 lines
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 followCapitalize 'h' in units please.
OK
Quoted 28 lines
Quoted 28 lines
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 <[email protected]>Signed-off-by Ilia Lin <[email protected]>--- 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.cdrivers/clk/qcom/Kconfig index renamed from drivers/clk/qcom/Kconfig +0
-0fbf4532..3274877 100644
drivers/clk/qcom/Kconfig +2
-0@@ -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
Quoted 8 lines
drivers/clk/qcom/Kconfig config SPMI_PMIC_CLKDIV · line 236
Quoted 6 lines
drivers/clk/qcom/Kconfig +6
-0+ 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.
Quoted 12 lines
drivers/clk/qcom/Makefile obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o · line 36
Quoted 10 lines
drivers/clk/qcom/Makefile +1
-0@@ -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.oThis doesn't look sorted.
Will be changed in the next spin.
Quoted 16 lines
Quoted 16 lines
drivers/clk/qcom/Makefile +0
-0obj-$(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.cb/drivers/clk/qcom/clk-cpu-8996.cnew file mode 100644 index 0000000..42489f1drivers/clk/qcom/clk-cpu-8996.c new file +7
-0@@ -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.
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 12
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+* +* 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.
Quoted 14 lines
drivers/clk/qcom/clk-cpu-8996.c line 14
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c new file +2
-0+ +#include <linux/clk.h>
clk-provider.h?drivers/clk/qcom/clk-cpu-8996.c line 19
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +5
-0+#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include "clk-alpha-pll.h" #include "
clk-regmap.h"
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 25
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+ +#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.
Quoted 15 lines
drivers/clk/qcom/clk-cpu-8996.c line 37
Quoted 13 lines
drivers/clk/qcom/clk-cpu-8996.c new file +12
-0+ +#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.
Quoted 98 lines
Quoted 98 lines
drivers/clk/qcom/clk-cpu-8996.c new file +97
-0+ [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, + }, +};
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 141
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+ +/* Mux'es */ + +struct clk_cpu_8996_mux { +u32 reg; +u32 shift;u8 shift?
Will be changed in the next spin.
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c line 142
Quoted 2 lines
drivers/clk/qcom/clk-cpu-8996.c new file +1
-0+u32 width;u8 width?
Will be changed in the next spin.
Quoted 17 lines
drivers/clk/qcom/clk-cpu-8996.c
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+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) {
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c new file +9
-0+ 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 ); +
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 165
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+regmap_read (clkr->regmap, cpuclk->reg, &val); + + val >>= cpuclk->shift; + val &= mask; + +return val;return val & mask;
struct clk_cpu_8996_mux *
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c line 155
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +4
-0+} + +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.
Quoted 14 lines
Quoted 14 lines
drivers/clk/qcom/clk-cpu-8996.c new file +13
-0+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
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 189
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+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.
Quoted 49 lines
drivers/clk/qcom/clk-cpu-8996.c line 192
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +3
-0+ + 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 theclk_cpu_8996_mux.Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c new file +8
-0+ +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, };[...]
Quoted 31 lines
drivers/clk/qcom/clk-cpu-8996.c new file +31
-0+ +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" ,
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 269
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +5
-0+ "perfcl_alt_pll", + }, + .num_parents = 4, + .ops = &clk_cpu_8996_mux_ops, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,Not sure
CLK_IS_CRITICALis the right mode. PerhapsCLK_IGNORE_UNUSEDfor now? We don't want to force XO to stay on forever here.
Have to unit test this.
Quoted 16 lines
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +3
-0+ }, +}; +drivers/clk/qcom/clk-cpu-8996.c line 282
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+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.
Quoted 4 lines
Quoted 2 lines
+ { .compatible = "qcom-msm8996-apcc" },
Bad compatible? Should be qcom,msm8996-apcc?
The naming is per Rob Herring's requirement.
Quoted 17 lines
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +4
-0+ {} +}; + +struct clk_regmap *clks[] = {drivers/clk/qcom/clk-cpu-8996.c line 297
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+/* 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.
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c line 303
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+}; + +struct clk_hw_clks { +unsigned int num; +struct clk_hw *hws[]; +};Please just NULL terminate the list of
clk_hwpointers, or keep the size around instead.
Will be changed in the next spin.
Quoted 15 lines
drivers/clk/qcom/clk-cpu-8996.c
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +3
-0+ +static int +qcom_cpu_clk_msm8996_register_clks(struct device *dev, struct
clk_hw_clks*hws,Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ 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",
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 321
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +4
-0+ 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.
Quoted 17 lines
Quoted 17 lines
drivers/clk/qcom/clk-cpu-8996.c new file +16
-0+ +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; +} +
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 342
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+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.
Quoted 42 lines
Quoted 31 lines
drivers/clk/qcom/clk-cpu-8996.c new file +30
-0+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;drivers/clk/qcom/clk-cpu-8996.c
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ 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
Quoted 11 lines
drivers/clk/qcom/clk-cpu-8996.c line 391
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c new file +9
-0+*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.
Quoted 12 lines
Quoted 12 lines
drivers/clk/qcom/clk-cpu-8996.c new file +11
-0+ +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, + },
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 408
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+}; + +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.
Stephen Boyd
maintainerPATCH v3 3/10 clk: qcom: Add CPU clock driver for msm8996
Quoting ilialin at codeaurora.org (2018-03-20 07:18:57)
Quoted 24 lines
Quoted 15 lines
From: Stephen Boyd <[email protected]>
Quoted 13 lines
drivers/clk/qcom/clk-cpu-8996.c new file +13
-0+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, structQuoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 189
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+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?
Quoted 2 lines
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.
Quoted 27 lines
Quoted 11 lines
drivers/clk/qcom/clk-cpu-8996.c line 192
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +3
-0+ + 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 theclk_cpu_8996_mux.Quoted 15 lines
drivers/clk/qcom/clk-cpu-8996.c line 282
Quoted 13 lines
drivers/clk/qcom/clk-cpu-8996.c new file +13
-0+ }, +}; + +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.
Quoted 9 lines
Will be changed in the next spin.
Quoted 4 lines
Quoted 2 lines
+ { .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?
PATCH v3 3/10 clk: qcom: Add CPU clock driver for msm8996
In reply to Stephen BoydQuoted 456 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 19:37
To: Ilia Lin <[email protected]>; 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 msm8996Quoting Ilia Lin (2018-02-14 05:59:45)
Quoted 19 lines
From: Rajendra Nayak <[email protected]>
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 | | +------>Quoted 8 lines
| +------+-----------+ +------>2 PMUX | +---------------+ | | | | | +------+ | +-->3 | +--^+ ACD +-----+ | +-------+ +---------------+ +------+ | |Alt PLL | | | +---------------------------+ +---------------+ PLL_EARLYThanks for the diagram. Please also put it at the top of the driver file.
Quoted 9 lines
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
Quoted 7 lines
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 followCapitalize 'h' in units please.
Quoted 23 lines
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 <[email protected]>Signed-off-by Ilia Lin <[email protected]>--- 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.cdrivers/clk/qcom/Kconfig index renamed from drivers/clk/qcom/Kconfig +0
-0fbf4532..3274877 100644
drivers/clk/qcom/Kconfig +0
-0@@ -226,3 +226,11 @@ config SPMI_PMIC_CLKDIV Technologies, Inc. SPMI PMIC. It configures the frequency ofdrivers/clk/qcom/Kconfig config SPMI_PMIC_CLKDIV · line 236
Quoted 10 lines
drivers/clk/qcom/Kconfig +8
-0clkdiv 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?
drivers/clk/qcom/Makefile obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o · line 36
Quoted 9 lines
drivers/clk/qcom/Makefile +1
-0@@ -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.oThis doesn't look sorted.
Quoted 11 lines
drivers/clk/qcom/Makefile +0
-0obj-$(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.cb/drivers/clk/qcom/clk-cpu-8996.cnew file mode 100644 index 0000000..42489f1drivers/clk/qcom/clk-cpu-8996.c new file +3
-0@@ -0,0 +1,409 @@ +/* +* Copyright (c) 2018, The Linux Foundation. All rights reserved. +* drivers/clk/qcom/clk-cpu-8996.c line 13
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+* 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?
drivers/clk/qcom/clk-cpu-8996.c line 14
Quoted 2 lines
drivers/clk/qcom/clk-cpu-8996.c new file +2
-0+ +#include <linux/clk.h>
clk-provider.h?drivers/clk/qcom/clk-cpu-8996.c line 19
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +5
-0+#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include "clk-alpha-pll.h" #include "
clk-regmap.h"drivers/clk/qcom/clk-cpu-8996.c line 25
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+ +#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?
drivers/clk/qcom/clk-cpu-8996.c line 37
Quoted 12 lines
drivers/clk/qcom/clk-cpu-8996.c new file +12
-0+ +#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!
Quoted 93 lines
drivers/clk/qcom/clk-cpu-8996.c new file +93
-0+ [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" },drivers/clk/qcom/clk-cpu-8996.c line 141
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ .num_parents = 1, + .ops = &clk_alpha_pll_hwfsm_ops, + }, +}; + +/* Mux'es */ + +struct clk_cpu_8996_mux { +u32 reg; +u32 shift;u8 shift?
drivers/clk/qcom/clk-cpu-8996.c line 142
Quoted 1 line
drivers/clk/qcom/clk-cpu-8996.c new file +1
-0+u32 width;u8 width?
drivers/clk/qcom/clk-cpu-8996.c
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+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) {
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c new file +5
-0+ 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;drivers/clk/qcom/clk-cpu-8996.c line 165
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+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;
drivers/clk/qcom/clk-cpu-8996.c line 155
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +4
-0+} + +static int clk_cpu_8996_mux_set_parent (struct clk_hw *hw,u8 index) { +unsigned int val;u32 val?
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c new file +9
-0+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,drivers/clk/qcom/clk-cpu-8996.c line 189
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+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?
drivers/clk/qcom/clk-cpu-8996.c line 192
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c new file +3
-0+ + 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 theclk_cpu_8996_mux.Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c new file +8
-0+ +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, };[...]
Quoted 26 lines
drivers/clk/qcom/clk-cpu-8996.c new file +26
-0+ +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 ) {drivers/clk/qcom/clk-cpu-8996.c line 269
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ .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_CRITICALis the right mode. PerhapsCLK_IGNORE_UNUSEDfor now? We don't want to force XO to stay on forever here.drivers/clk/qcom/clk-cpu-8996.c line 282
Quoted 13 lines
drivers/clk/qcom/clk-cpu-8996.c new file +13
-0+ }, +}; + +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.
Quoted 1 line
+ { .compatible = "qcom-msm8996-apcc" },
Bad compatible? Should be qcom,msm8996-apcc?
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +4
-0+ {} +}; + +struct clk_regmap *clks[] = {drivers/clk/qcom/clk-cpu-8996.c line 297
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+/* 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.
drivers/clk/qcom/clk-cpu-8996.c line 303
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c new file +6
-0+}; + +struct clk_hw_clks { +unsigned int num; +struct clk_hw *hws[]; +};Please just NULL terminate the list of
clk_hwpointers, or keep the size around instead.drivers/clk/qcom/clk-cpu-8996.c
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c new file +3
-0+ +static int +qcom_cpu_clk_msm8996_register_clks(struct device *dev, struct
clk_hw_clks*hws,Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ 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",
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 321
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c new file +4
-0+ 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.
Quoted 98 lines
Quoted 13 lines
drivers/clk/qcom/clk-cpu-8996.c new file +12
-0+ +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);drivers/clk/qcom/clk-cpu-8996.c line 342
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ +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.
Quoted 30 lines
drivers/clk/qcom/clk-cpu-8996.c new file +30
-0+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;drivers/clk/qcom/clk-cpu-8996.c
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ 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_devicedrivers/clk/qcom/clk-cpu-8996.c line 391
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c new file +9
-0+*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.Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c new file +7
-0+ +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,drivers/clk/qcom/clk-cpu-8996.c line 408
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c new file +10
-0+ .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.
Stephen Boyd
maintainerPATCH v3 3/10 clk: qcom: Add CPU clock driver for msm8996
Quoting ilialin at codeaurora.org (2018-03-22 03:47:30)
Quoted 2 lines
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.
PATCH v3 4/10 clk: qcom: Add DT bindings for CPU clock driver for msm8996
In reply to Ilia Lin--- Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
Documentation/devicetree/bindings/clock/qcom,kryocc.txt new file +17 -0
@@ -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>; + };
Signature · 1 line
1.9.1
Rob Herring
maintainerPATCH v3 4/10 clk: qcom: Add DT bindings for CPU clock driver for msm8996
Quoted 5 lines · Ilia Lin
Signed-off-by Ilia Lin <[email protected]>--- Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
Stephen Boyd
maintainerPATCH v3 4/10 clk: qcom: Add DT bindings for CPU clock driver for msm8996
In reply to Ilia LinQuoting Ilia Lin (2018-02-14 05:59:46)
Quoted 12 lines
Signed-off-by Ilia Lin <[email protected]>--- Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txtDocumentation/devicetree/bindings/clock/qcom,kryocc.txt new file +0
-0
Documentation/devicetree/bindings/clock/qcom,kryocc.txt line 7
Quoted 7 lines
Documentation/devicetree/bindings/clock/qcom,kryocc.txt new file +7
-0@@ -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?
PATCH v3 4/10 clk: qcom: Add DT bindings for CPU clock driver for msm8996
Quoted 26 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 19:47
To: Ilia Lin <[email protected]>; 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 msm8996Quoting Ilia Lin (2018-02-14 05:59:46)
Quoted 3 lines
Signed-off-by Ilia Lin <[email protected]>--- Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17+++++++++++++++++
Quoted 2 lines
1 file changed, 17 insertions(+) create mode 100644
Documentation/devicetree/bindings/clock/qcom,kryocc.txtReview
Quoted 2 lines
(quoted diff) +0
-0
b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
Quoted 14 lines
Documentation/devicetree/bindings/clock/qcom,kryocc.txt line 7
Quoted 12 lines
new file mode 100644
index 0000000..e7cf15aDocumentation/devicetree/bindings/clock/qcom,kryocc.txt new file +7
-0@@ -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.
Quoted 2 lines
Rob?
PATCH v3 5/10 clk: qcom: cpu-8996: Add support to switch to alternate PLL
In reply to Ilia LinFrom: Rajendra Nayak <[email protected]>
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.
--- drivers/clk/qcom/clk-cpu-8996.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
drivers/clk/qcom/clk-cpu-8996.c +35 -0
@@ -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; }
Signature · 1 line
1.9.1
Stephen Boyd
maintainerPATCH v3 5/10 clk: qcom: cpu-8996: Add support to switch to alternate PLL
Quoting Ilia Lin (2018-02-14 05:59:47)
Quoted 3 lines
From: Rajendra Nayak <[email protected]>
Each of the CPU clusters on msm8996 and powered via a primary
s/and/are/
Quoted 1 line
PLL and a secondary PLL. The primary PLL is what drivers the
s/drivers/drives/
I make the same typo all the time!
Quoted 75 lines
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 <[email protected]>Signed-off-by Ilia Lin <[email protected]>--- drivers/clk/qcom/clk-cpu-8996.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)drivers/clk/qcom/clk-cpu-8996.c +27
-0@@ -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);
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 368
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c +8
-0clk_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.
PATCH v3 5/10 clk: qcom: cpu-8996: Add support to switch to alternate PLL
Will be fixed and respinned.
Quoted 118 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 19:48
To: Ilia Lin <[email protected]>; 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 PLLQuoting Ilia Lin (2018-02-14 05:59:47)
Quoted 3 lines
From: Rajendra Nayak <[email protected]>
Each of the CPU clusters on msm8996 and powered via a primary
s/and/are/
Quoted 1 line
PLL and a secondary PLL. The primary PLL is what drivers the
s/drivers/drives/
I make the same typo all the time!
Quoted 19 lines
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 <[email protected]>Signed-off-by Ilia Lin <[email protected]>--- drivers/clk/qcom/clk-cpu-8996.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)(quoted diff) +0
-0
b/drivers/clk/qcom/clk-cpu-8996.cindex 42489f1..75bd014 100644drivers/clk/qcom/clk-cpu-8996.c +0
-0@@ -140,10 +140,14 @@ struct clk_cpu_8996_mux {u32 reg;u32 shift;u32 width;drivers/clk/qcom/clk-cpu-8996.c struct clk_cpu_8996_mux { · line 152
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-0+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){
drivers/clk/qcom/clk-cpu-8996.c static int clk_cpu_8996_mux_set_parent(struct
Quoted 1 line
drivers/clk/qcom/clk-cpu-8996.c +0
-0@@ -194,6 +198,27 @@ static int clk_cpu_8996_mux_set_parent(struct
clk_hw*hw, u8 index)drivers/clk/qcom/clk-cpu-8996.c static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
Quoted 12 lines
drivers/clk/qcom/clk-cpu-8996.c +9
-0return 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);drivers/clk/qcom/clk-cpu-8996.c static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c +3
-0+break ; +case POST_RATE_CHANGE : + ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw,
PLL_INDEX);Quoted 32 lines
drivers/clk/qcom/clk-cpu-8996.c +8
-0+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);drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks {
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+ 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);
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 364
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c +3
-0+if (ret) +return ret; +Please resend this with the other patches that need rework.
PATCH v3 6/10 clk: qcom: cpu-8996: Add support to switch below 600Mhz
In reply to Ilia LinFrom: Rajendra Nayak <[email protected]>
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
--- drivers/clk/qcom/clk-cpu-8996.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-)
drivers/clk/qcom/clk-cpu-8996.c +21 -3
@@ -28,6 +28,7 @@#define PLL_INDEX 1#define ACD_INDEX 2#define ALT_INDEX 3 +#define DIV_2_THRESHOLD 600000000static 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" ,
Signature · 1 line
1.9.1
Stephen Boyd
maintainerPATCH v3 6/10 clk: qcom: cpu-8996: Add support to switch below 600Mhz
Quoting Ilia Lin (2018-02-14 05:59:48)
Quoted 3 lines
From: Rajendra Nayak <[email protected]>
The CPU clock controllers primary PLL operates on a single VCO range,
s/controllers/controller's/
Quoted 2 lines
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.
Quoted 10 lines
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 clkSigned-off-by Rajendra Nayak <[email protected]>Signed-off-by Ilia Lin <[email protected]>
Rest looks ok, please resend.
PATCH v3 7/10 clk: qcom: clk-cpu-8996: Prepare PLLs on probe
In reply to Ilia LinThe PLLs must be prepared enabled during the probe to be accessible by the OPPs. Otherwise an OPP may switch to non-enabled clock.
--- drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/clk/qcom/clk-cpu-8996.c +13 -1
@@ -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;
Signature · 1 line
1.9.1
Stephen Boyd
maintainerPATCH v3 7/10 clk: qcom: clk-cpu-8996: Prepare PLLs on probe
Quoting Ilia Lin (2018-02-14 05:59:49)
Quoted 3 lines
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.
Quoted 11 lines
Signed-off-by Ilia Lin <[email protected]>--- drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)drivers/clk/qcom/clk-cpu-8996.c +0
-0
drivers/clk/qcom/clk-cpu-8996.c line 18
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +1
-1@@ -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.
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 383
Quoted 12 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0#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?
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 389
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c +6
-0+ +/* 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.
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +1
-0+ ret =clk_notifier_register (pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);if (ret)return ret;
PATCH v3 7/10 clk: qcom: clk-cpu-8996: Prepare PLLs on probe
Quoted 14 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 18:50
To: Ilia Lin <[email protected]>; 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
Quoted 5 lines
Quoting Ilia Lin (2018-02-14 05:59:49)
Quoted 2 lines
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?
Quoted 7 lines
Quoted 7 lines
Signed-off-by Ilia Lin <[email protected]>--- drivers/clk/qcom/clk-cpu-8996.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
Quoted 12 lines
drivers/clk/qcom/clk-cpu-8996.c line 18
Quoted 10 lines
(quoted diff) +0
-0
b/drivers/clk/qcom/clk-cpu-8996.cindex 854f327..b0a3b73 100644drivers/clk/qcom/clk-cpu-8996.c +1
-1@@ -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.
Quoted 9 lines
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c +0
-0#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);
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 383
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+/* 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?
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 389
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c +6
-0+ +/* 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?
Quoted 5 lines
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +1
-0+ ret =clk_notifier_register (pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);if (ret)return ret;
Stephen Boyd
maintainerPATCH v3 7/10 clk: qcom: clk-cpu-8996: Prepare PLLs on probe
Quoting ilialin at codeaurora.org (2018-03-20 06:53:08)
Quoted 39 lines
Quoted 14 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 18:50
To: Ilia Lin <[email protected]>; 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 probeQuoted 5 lines
Quoting Ilia Lin (2018-02-14 05:59:49)
Quoted 2 lines
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?
Quoted 9 lines
Quoted 9 lines
#include "
clk-alpha-pll.h"#define
VCO(a, b, c){ \drivers/clk/qcom/clk-cpu-8996.c +0
-0@@ -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);Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 383
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+/* 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?
Quoted 1 line
Are you suggesting changing the cpufreq-dt as well?
Yes?
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c +6
-0+ +/* 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 );
Quoted 4 lines
Quoted 1 line
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.
PATCH v3 8/10 clk: qcom: Add ACD path to CPU clock driver for msm8996
In reply to Ilia LinThe 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.
--- drivers/clk/qcom/clk-cpu-8996.c | 110 ++++++++++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 15 deletions(-)
drivers/clk/qcom/clk-cpu-8996.c +95 -15
@@ -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;
Signature · 1 line
1.9.1
Stephen Boyd
maintainerPATCH v3 8/10 clk: qcom: Add ACD path to CPU clock driver for msm8996
Quoting Ilia Lin (2018-02-14 05:59:50)
drivers/clk/qcom/clk-cpu-8996.c line 20
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c +1
-0@@ -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.
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c +2
-0#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
drivers/clk/qcom/clk-cpu-8996.c line 44
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c +10
-0+#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.
drivers/clk/qcom/clk-cpu-8996.c line 49
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+#define SSSCTL_VAL 0xF + +enum { +APC_BASE , +EFUSE_BASE ,
Is this used? efuse should go through nvmem APIs.
drivers/clk/qcom/clk-cpu-8996.c line 53
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-0+ NUM_BASES +}; + +static void __iomem *vbases[NUM_BASES ];
Please just pass this to the function that uses it and drop EFUSE_BASE.
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c +3
-0static 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
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 439
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c +10
-0+ +/* 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.
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c +8
-0+ +static DEFINE_SPINLOCK (acd_lock); + +static void qcom_cpu_clk_msm8996_acd_init (void ) +{ +u64 hwid; +unsigned long flags; +
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 457
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c +10
-0+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.
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 460
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c +3
-0+ +if (PWRCL_CPU_REG_MASK == (hwid |PWRCL_CPU_REG_MASK )) { +/* Enable Soft Stop/Start */
Sigh.
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 461
Quoted 1 line
drivers/clk/qcom/clk-cpu-8996.c +1
-0+if (vbases[APC_BASE ])
When is this false?
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 465
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-0+writel_relaxed (SSSCTL_VAL , vbases[APC_BASE ] + +PWRCL_REG_OFFSET +SSSCTL_OFFSET ); +/* Ensure SSSCTL config goes through before enabling ACD. */ +mb ();
Use writel instead.
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 469
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-0+/* 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?
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 477
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c +8
-0+/* 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.
Quoted 24 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-4+ } + +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))
drivers/clk/qcom/clk-cpu-8996.c static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev) · line 510
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-2-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.
drivers/clk/qcom/clk-cpu-8996.c static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev) · line 515
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +1
-0@@ -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.
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c +0
-0data->hws[0 ] = &pwrcl_pmux.clkr.hw; data->hws[1 ] = &perfcl_pmux.clkr.hw;
PATCH v3 8/10 clk: qcom: Add ACD path to CPU clock driver for msm8996
On 19/03/18 16:57, Stephen Boyd wrote:
[...]
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 460
Quoted 3 lines
drivers/clk/qcom/clk-cpu-8996.c +3
-0+ +if (PWRCL_CPU_REG_MASK == (hwid |PWRCL_CPU_REG_MASK )) { +/* Enable Soft Stop/Start */ Sigh.
Quoted 1 line
+ if (vbases[APC_BASE])
Quoted 8 lines
When is this false?
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 465
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-0+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.
Stephen Boyd
maintainerPATCH v3 8/10 clk: qcom: Add ACD path to CPU clock driver for msm8996
Quoting Robin Murphy (2018-03-19 11:16:15)
Quoted 9 lines · Stephen Boyd
[...]
Quoted 7 lines
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+ +writel_relaxed (SSSCTL_VAL , vbases[APC_BASE ] + +PWRCL_REG_OFFSET +SSSCTL_OFFSET ); +/* Ensure SSSCTL config goes through before enabling ACD. */ +mb ();
Quoted 9 lines
Quoted 1 line
Use writel instead.
Note that
writel()only gives an implicitwmb()*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.
PATCH v3 8/10 clk: qcom: Add ACD path to CPU clock driver for msm8996
Quoted 20 lines · Stephen Boyd
Quoting Robin Murphy (2018-03-19 11:16:15)
Quoted 9 lines · Stephen Boyd
[...]
Quoted 7 lines
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+ +writel_relaxed (SSSCTL_VAL , vbases[APC_BASE ] + +PWRCL_REG_OFFSET +SSSCTL_OFFSET ); +/* Ensure SSSCTL config goes through before enabling ACD. */ +mb ();Quoted 9 lines
Quoted 1 line
Use writel instead.
Note that
writel()only gives an implicitwmb()*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).
Quoted 4 lines
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.
PATCH v3 8/10 clk: qcom: Add ACD path to CPU clock driver for msm8996
In reply to Stephen BoydQuoted 16 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 18:57
To: Ilia Lin <[email protected]>; 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 msm8996Quoting Ilia Lin (2018-02-14 05:59:50)
Quoted 11 lines
drivers/clk/qcom/clk-cpu-8996.c line 20
Quoted 9 lines
(quoted diff) +0
-0
b/drivers/clk/qcom/clk-cpu-8996.cindex b0a3b73..1552791 100644drivers/clk/qcom/clk-cpu-8996.c +1
-0@@ -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.
Quoted 14 lines
Quoted 14 lines
drivers/clk/qcom/clk-cpu-8996.c +6
-0#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 +/*
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 44
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c +6
-0+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.
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c line 49
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+#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.
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c line 53
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-0+ 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.
Quoted 15 lines
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +0
-0static const u8 prim_pll_regs[PLL_OFF_MAX_REGS ] = { [PLL_OFF_L_VAL ] =0x04 ,drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 432
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c +6
-0@@ -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
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 433
Quoted 1 line
drivers/clk/qcom/clk-cpu-8996.c +1
-0+#define L2ACDSSCR_REG 0x589ULL #define ACDTD_VAL 0x00006A11#define
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 435
Quoted 2 lines
drivers/clk/qcom/clk-cpu-8996.c +2
-0+ACDCR_VAL 0x002C5FFD #define ACDSSCR_VAL 0x00000601 #define +ACDDVMRC_VAL 0x000E0F0FPlease 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?
Quoted 14 lines
Quoted 14 lines
drivers/clk/qcom/clk-cpu-8996.c +13
-0+ +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) */
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 457
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+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.
Quoted 10 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 460
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +3
-0+ +if (PWRCL_CPU_REG_MASK == (hwid |PWRCL_CPU_REG_MASK )) { +/* Enable Soft Stop/Start */ Sigh.
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 457
Quoted 1 line
drivers/clk/qcom/clk-cpu-8996.c +1
-0+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.
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 465
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +4
-0+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
Quoted 8 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks {
Quoted 6 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-0+/* 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.
Quoted 11 lines
drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 477
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c +8
-0+/* 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
Quoted 31 lines
drivers/clk/qcom/clk-cpu-8996.c static int
Quoted 12 lines
drivers/clk/qcom/clk-cpu-8996.c +3
-1+ } + +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)Quoted 18 lines
drivers/clk/qcom/clk-cpu-8996.c +5
-4if (!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 ]);
Quoted 7 lines
drivers/clk/qcom/clk-cpu-8996.c static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev) · line 510
Quoted 5 lines
drivers/clk/qcom/clk-cpu-8996.c +1
-1- 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.
Quoted 9 lines
drivers/clk/qcom/clk-cpu-8996.c static int
Quoted 2 lines
drivers/clk/qcom/clk-cpu-8996.c +0
-0@@ -433,6 +512,7 @@ static int
qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)drivers/clk/qcom/clk-cpu-8996.c static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev) · line 515
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +1
-0ret =qcom_cpu_clk_msm8996_register_clks (dev, hws, regmap_cpu);if (ret)return ret; +qcom_cpu_clk_msm8996_acd_init ();Pass base here.
Sure.
Quoted 4 lines
Quoted 4 lines
drivers/clk/qcom/clk-cpu-8996.c +0
-0data->hws[0 ] = &pwrcl_pmux.clkr.hw; data->hws[1 ] = &perfcl_pmux.clkr.hw;
Stephen Boyd
maintainerPATCH v3 8/10 clk: qcom: Add ACD path to CPU clock driver for msm8996
Quoting ilialin at codeaurora.org (2018-03-20 07:04:05)
Quoted 18 lines
Quoted 18 lines
From: Stephen Boyd <[email protected]>
Quoting Ilia Lin (2018-02-14 05:59:50)drivers/clk/qcom/clk-cpu-8996.c struct clk_hw_clks { · line 432
Quoted 13 lines
static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = { [PLL_OFF_L_VAL] = 0x04,drivers/clk/qcom/clk-cpu-8996.c +6
-0@@ -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
0x584ULLQuoted 1 line
(quoted diff) +1
-0+#define L2ACDSSCR_REG 0x589ULL #define ACDTD_VAL 0x00006A11
Quoted 8 lines
Quoted 6 lines
#define
Review struct clk_hw_clks { · line 435
Quoted 2 lines
(quoted diff) +2
-0+ACDCR_VAL 0x002C5FFD #define ACDSSCR_VAL 0x00000601 #define +ACDDVMRC_VAL 0x000E0F0FPlease 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.
PATCH v3 9/10 DT: QCOM: Add cpufreq-dt to msm8996
In reply to Ilia LinAdd device tree frequency table for the MSM8996 to be used by the upstream cpufreq-dt driver with the clk-cpu-8996 driver as infrastructure.
--- 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(-)
arch/arm64/boot/dts/qcom/apq8096-db820c.dts +2 -2
@@ -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"; };
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +1 -1
@@ -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
arch/arm64/boot/dts/qcom/msm8996.dtsi +186 -2
227 lines not on this page · raw message
drivers/cpufreq/cpufreq-dt-platdev.c +3 -0
@@ -95,6 +95,9 @@ { .compatible = "xlnx,zynq-7000", }, { .compatible = "xlnx,zynqmp", }, + { .compatible = "qcom,msm8996", }, + { .compatible = "qcom,apq8096", }, + { } };
Signature · 1 line
1.9.1
Stephen Boyd
maintainerPATCH v3 9/10 DT: QCOM: Add cpufreq-dt to msm8996
Quoting Ilia Lin (2018-02-14 05:59:51)
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi line 5
Quoted 11 lines
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +1
-1@@ -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?
Quoted 11 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +3
-0@@ -144,6 +152,182 @@ }; }; + cluster0_opp: opp_table0 { + compatible = "operating-points-v2"; + opp-shared;
arch/arm64/boot/dts/qcom/msm8996.dtsi line 167
Quoted 10 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +10
-0+ + 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>.
Quoted 52 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +52
-0+ 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 {
[...]
arch/arm64/boot/dts/qcom/msm8996.dtsi line 590
Quoted 11 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +3
-1+ + }; 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?
Quoted 8 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +0
-0reg = <0x6400000 0x90000>; #clock-cells = <1>; };drivers/cpufreq/cpufreq-dt-platdev.c +0
-0
drivers/cpufreq/cpufreq-dt-platdev.c line 100
Quoted 6 lines
drivers/cpufreq/cpufreq-dt-platdev.c +3
-0@@ -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?
PATCH v3 9/10 DT: QCOM: Add cpufreq-dt to msm8996
Quoted 15 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
Sent: Monday, March 19, 2018 18:49
To: Ilia Lin <[email protected]>; 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 msm8996Quoting Ilia Lin (2018-02-14 05:59:51)
Quoted 14 lines
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi line 5
Quoted 12 lines
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +1
-1@@ -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 andWhy?
The file was changed again in 2018. I'm reflecting this in the file dates.
Quoted 10 lines
Quoted 10 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +0
-0@@ -144,6 +152,182 @@ }; };
Quoted 15 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi line 167
Quoted 13 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +13
-0+ 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.
Quoted 62 lines
Quoted 53 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +52
-0+ 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 {[...]
Quoted 8 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +3
-0+ + }; thermal-zones { cpu-thermal0 { polling-delay-passive = <250>; @@ -403,7 +587,7 @@ };
Quoted 5 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi line 590
Quoted 3 lines
kryocc: clock-controller at 6400000 {arch/arm64/boot/dts/qcom/msm8996.dtsi +1
-1- compatible = "qcom,apcc-msm8996"; + compatible = "qcom-msm8996-apcc";Bad change?
This was required by Rob Herring.
Quoted 13 lines
Quoted 13 lines
reg = <0x6400000 0x90000>; #clock-cells = <1>; };drivers/cpufreq/cpufreq-dt-platdev.c +0
-0@@ -95,6 +95,9 @@ { .compatible = "xlnx,zynq-7000", }, { .compatible = "xlnx,zynqmp", },
Quoted 5 lines
drivers/cpufreq/cpufreq-dt-platdev.c line 100
Quoted 3 lines
drivers/cpufreq/cpufreq-dt-platdev.c +3
-0+ { .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.
Quoted 2 lines
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.
Stephen Boyd
maintainerPATCH v3 9/10 DT: QCOM: Add cpufreq-dt to msm8996
Quoting ilialin at codeaurora.org (2018-03-20 06:46:19)
Quoted 11 lines
Quoted 11 lines
From: Stephen Boyd <[email protected]>
Quoting Ilia Lin (2018-02-14 05:59:51)Quoted 9 lines
drivers/cpufreq/cpufreq-dt-platdev.c +0
-0@@ -95,6 +95,9 @@ { .compatible = "xlnx,zynq-7000", }, { .compatible = "xlnx,zynqmp", },
Quoted 6 lines
Quoted 5 lines
drivers/cpufreq/cpufreq-dt-platdev.c line 100
Quoted 3 lines
drivers/cpufreq/cpufreq-dt-platdev.c +3
-0+ { .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.
Quoted 3 lines
Quoted 2 lines
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?
PATCH v3 9/10 DT: QCOM: Add cpufreq-dt to msm8996
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.
Quoted 41 lines
-----Original Message-----
From: Stephen Boyd <[email protected]>
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 msm8996Quoting ilialin at codeaurora.org (2018-03-20 06:46:19)
Quoted 11 lines
Quoted 11 lines
From: Stephen Boyd <[email protected]> Quoting Ilia Lin (2018-02-14 05:59:51)
Quoted 9 lines
drivers/cpufreq/cpufreq-dt-platdev.c +0
-0@@ -95,6 +95,9 @@ { .compatible = "xlnx,zynq-7000", }, { .compatible = "xlnx,zynqmp", },Quoted 6 lines
Quoted 5 lines
drivers/cpufreq/cpufreq-dt-platdev.c line 100
Quoted 3 lines
drivers/cpufreq/cpufreq-dt-platdev.c +3
-0+ { .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.
Quoted 3 lines
Quoted 2 lines
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?
Stephen Boyd
maintainerPATCH v3 9/10 DT: QCOM: Add cpufreq-dt to msm8996
Quoting ilialin at codeaurora.org (2018-03-20 13:34:04)
Quoted 4 lines
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.
PATCH v3 10/10 DT: QCOM: Add thermal mitigation to msm8996
In reply to Ilia LinAdd thermal mitigation configuration to msm8996. With the cpufreq-dt OPP table the CPU frequency may be scaled and therefore throttled by the thermal config.
--- arch/arm64/boot/dts/qcom/msm8996.dtsi | 98 +++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 11 deletions(-)
arch/arm64/boot/dts/qcom/msm8996.dtsi +87 -11
@@ -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>; + }; + }; }; };
Signature · 1 line
1.9.1