Re: [PATCH] cpufreq: qcom-kryo: add NULL entry to the end of_device_id array

2018-07-23 Thread Ilia Lin
On Mon, Jul 23, 2018 at 3:38 PM YueHaibing  wrote:
>
> Make sure of_device_id tables are NULL terminated
> Found by coccinelle spatch "misc/of_table.cocci"
>
> Signed-off-by: YueHaibing 
> ---
>  drivers/cpufreq/qcom-cpufreq-kryo.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
> b/drivers/cpufreq/qcom-cpufreq-kryo.c
> index 29389ac..efc9a7a 100644
> --- a/drivers/cpufreq/qcom-cpufreq-kryo.c
> +++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
> @@ -183,6 +183,7 @@ static struct platform_driver qcom_cpufreq_kryo_driver = {
>  static const struct of_device_id qcom_cpufreq_kryo_match_list[] __initconst 
> = {
> { .compatible = "qcom,apq8096", },
> { .compatible = "qcom,msm8996", },
> +   {}
>  };
>
>  /*
> --
> 2.7.0
>
>

Acked-by: Ilia Lin 


Re: [PATCH v11 2/2] dt: qcom: Add qcom-cpufreq-kryo driver configuration

2018-07-10 Thread Ilia Lin
Hi Niklas,

The frequency list in the DT is correct, but the initial frequency for
the CPUs 0,1 is configured by the XBL, while the CPUs 2,3 stay at XO
rate. Both rates are unlisted in the DT and that's OK.

BR,
Ilia Lin

On Tue, Jul 10, 2018 at 12:29 PM Niklas Cassel  wrote:
>
> On Wed, May 23, 2018 at 04:11:31PM +0300, Ilia Lin wrote:
> > 1. Add NVMEM node for the speedbin
> > 2. Add definitions for all possible MSM8996 CPU OPPs.
> > The qcom-cpufreq-kryo driver will select the appropriate subset.
> >
> > Signed-off-by: Ilia Lin 
> > Acked-by: Viresh Kumar 
> > ---
> >  arch/arm64/boot/dts/qcom/apq8096-db820c.dts |   2 +-
> >  arch/arm64/boot/dts/qcom/msm8996.dtsi   | 281 
> > ++--
> >  2 files changed, 270 insertions(+), 13 deletions(-)
> >
>
> Hello Ilia, Viresh
>
>
> I tried this patch series (together with you cpu clock driver).
>
> The first problem is that the driver fails to create debugfs entries.
>
> The second problem appears to be that it runs on unlisted frequency.
> Is this simply because of missing entries in the opp table?
>
> [4.538513] cpu cpu1: opp_list_debug_create_link: Failed to create link
> [4.538567] cpu cpu1: _add_opp_dev: Failed to register opp debugfs (-12)
> [4.544514] cpufreq: cpufreq_online: CPU0: Running at unlisted freq: 
> 614400 KHz
> [4.551441] cpufreq: cpufreq_online: CPU0: Unlisted initial frequency 
> changed to: 652800 KHz
> [4.563219] cpu cpu3: opp_list_debug_create_link: Failed to create link
> [4.566937] cpu cpu3: _add_opp_dev: Failed to register opp debugfs (-12)
> [4.573489] cpufreq: cpufreq_online: CPU2: Running at unlisted freq: 19200 
> KHz
> [4.580368] cpufreq: cpufreq_online: CPU2: Unlisted initial frequency 
> changed to: 307200 KHz
>
>
> Kind regards,
> Niklas


[PATCH v13 1/2] cpufreq: Add Kryo CPU scaling driver

2018-05-24 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/Kconfig.arm  |  10 ++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 206 +++
 4 files changed, 220 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..bc2e885
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   if (IS_ERR(msm_id))
+   return NUM_OF_MSM8996_VERSIONS;
+
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
+{
+   struct opp_table *opp_tables[NR_CPUS] = {0};
+   struct

[PATCH v13 0/2] Kryo CPU scaling driver

2018-05-24 Thread Ilia Lin
[v13]
 * Addressed comment from Sudeep about DT compatible check on init

[v12]
 * Addressed comments from Sudeep and Viresh about the single init

[v11]
 * Addressed comment from Russel about device_node reference
 * Addressed comment from Sudeep about the late_initcall
 * Transformed init into probe to take care of deferals

[v10]
 * Split the series into domains
 * Addressed comments from Viresh and Sudeep about logical CPU numbering.

The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

The series depends on the series from Viresh:
https://patchwork.kernel.org/patch/10418139/

The previous spin was here:
https://patchwork.kernel.org/patch/10423137/

Ilia Lin (2):
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 drivers/cpufreq/Kconfig.arm|  10 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 206 +++
 5 files changed, 900 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

-- 
1.9.1



[PATCH v13 2/2] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-24 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0

[PATCH v14 0/2] Kryo CPU scaling driver

2018-05-25 Thread Ilia Lin
[v14]
 * Addressed comment from Sudeep about DT compatible
 * Added MAINTAINERS entry

[v13]
 * Addressed comment from Sudeep about DT compatible check on init

[v12]
 * Addressed comments from Sudeep and Viresh about the single init

[v11]
 * Addressed comment from Russel about device_node reference
 * Addressed comment from Sudeep about the late_initcall
 * Transformed init into probe to take care of deferals

[v10]
 * Split the series into domains
 * Addressed comments from Viresh and Sudeep about logical CPU numbering.

The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

The series depends on the series from Viresh:
https://patchwork.kernel.org/patch/10418139/

The previous spin was here:
https://patchwork.kernel.org/patch/10424949/

Ilia Lin (2):
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 MAINTAINERS|   7 +
 drivers/cpufreq/Kconfig.arm|  10 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 206 +++
 6 files changed, 907 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

-- 
1.9.1



[PATCH v14 1/2] cpufreq: Add Kryo CPU scaling driver

2018-05-25 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 MAINTAINERS  |   7 ++
 drivers/cpufreq/Kconfig.arm  |  10 ++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 206 +++
 5 files changed, 227 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ba0adcb..648e0c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11687,6 +11687,13 @@ F: 
Documentation/devicetree/bindings/media/qcom,camss.txt
 F: Documentation/media/v4l-drivers/qcom_camss.rst
 F: drivers/media/platform/qcom/camss-8x16/
 
+QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
+M:  Ilia Lin 
+L:  linux...@vger.kernel.org
+S:  Maintained
+F:  Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
+F:  drivers/cpufreq/qcom-cpufreq-kryo.c
+
 QUALCOMM EMAC GIGABIT ETHERNET DRIVER
 M: Timur Tabi 
 L: net...@vger.kernel.org
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..bc2e885
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   if (IS_ERR(msm_id))
+   return NU

[PATCH v14 2/2] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-25 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0

[PATCH v14 0/2] Kryo CPU scaling driver

2018-05-25 Thread Ilia Lin
[v14]
 * Addressed comment from Sudeep about DT compatible
 * Added MAINTAINERS entry

[v13]
 * Addressed comment from Sudeep about DT compatible check on init

[v12]
 * Addressed comments from Sudeep and Viresh about the single init

[v11]
 * Addressed comment from Russel about device_node reference
 * Addressed comment from Sudeep about the late_initcall
 * Transformed init into probe to take care of deferals

[v10]
 * Split the series into domains
 * Addressed comments from Viresh and Sudeep about logical CPU numbering.

The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

The series depends on the series from Viresh:
https://patchwork.kernel.org/patch/10418139/

The previous spin was here:
https://patchwork.kernel.org/patch/10424949/


Ilia Lin (2):
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 MAINTAINERS|   7 +
 drivers/cpufreq/Kconfig.arm|  10 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 212 +++
 6 files changed, 913 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

-- 
1.9.1



[PATCH v14 2/2] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-25 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0

[PATCH v14 1/2] cpufreq: Add Kryo CPU scaling driver

2018-05-25 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 MAINTAINERS  |   7 ++
 drivers/cpufreq/Kconfig.arm  |  10 ++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 212 +++
 5 files changed, 233 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ba0adcb..648e0c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11687,6 +11687,13 @@ F: 
Documentation/devicetree/bindings/media/qcom,camss.txt
 F: Documentation/media/v4l-drivers/qcom_camss.rst
 F: drivers/media/platform/qcom/camss-8x16/
 
+QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
+M:  Ilia Lin 
+L:  linux...@vger.kernel.org
+S:  Maintained
+F:  Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
+F:  drivers/cpufreq/qcom-cpufreq-kryo.c
+
 QUALCOMM EMAC GIGABIT ETHERNET DRIVER
 M: Timur Tabi 
 L: net...@vger.kernel.org
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..d049fe4
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   if (IS_ERR(msm_id))
+   return NU

[PATCH v6 00/14] CPU scaling support for msm8996

2018-05-14 Thread Ilia Lin
[v6]
 * Addressed comments from Viresh about:
 ** Comments style
 ** Kconfig bool instead of tristate
 ** DT and documentation style
 ** Resourses deallocation on an error
 ** Typos

[v5]
 * Rebased
 * Addressed comments from Bjorn about SPDX style,
   functions and parameters naming
 * Addressed comments from Viresh DT properties and style, comments style,
   resourses deallocation, documentation placement
 * Addressed comments from Sricharan about unnessesary include
 * Addressed comments from Nicolas
 * Addressed comments from Rob about the commit messages and acks
 * Addressed comments from Mark

[v4]
 * Adressed all comments from Stephen
 * Added CPU regulator support
 * Added qcom-cpufreq-kryo driver

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

[v2]
 * Addressed comments from Rob Herring for bindings
 * Addressed comments from Mark Rutland for memory barrier
 * Addressed comments from Julien Thierry for clock reenabling condition
 * Tuned the HW configuration for clock frequencies below 600MHz

Clocks:
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.

Regulators:
Added SAW regulator support to the SPMI regulator driver. The SAW regulators
will be controlled through special CPU registers instead of direct
SPMI accesses.

Cpufreq:
The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

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

Ilia Lin (11):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: qcom: Add CPU clock driver for msm8996
  clk: qcom: Add DT bindings for CPU clock driver for msm8996
  clk: qcom: Add ACD path to CPU clock driver for msm8996
  dt: qcom: Add opp and thermal to the msm8996
  regulator: qcom_spmi: Add support for SAW
  dt-bindings: qcom_spmi: Add support for SAW documentation
  dt: qcom: Add SAW regulator for 8x96 CPUs
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu
  dt: qcom: Add qcom-cpufreq-kryo driver configuration

Rajendra Nayak (3):
  clk: qcom: Make clk_alpha_pll_configure available to modules
  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 +
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 .../bindings/regulator/qcom,spmi-regulator.txt |  45 ++
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts|   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi  | 650 +++-
 drivers/clk/clk-fixed-factor.c |   2 +-
 drivers/clk/qcom/Kconfig   |   9 +
 drivers/clk/qcom/Makefile  |   1 +
 drivers/clk/qcom/clk-alpha-pll.c   |   1 +
 drivers/clk/qcom/clk-alpha-pll.h   |   6 +
 drivers/clk/qcom/clk-cpu-8996.c| 519 
 drivers/cpufreq/Kconfig.arm|  11 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 148 +
 drivers/perf/Kconfig   |   1 +
 drivers/perf/qcom_l2_pmu.c |  90 +--
 drivers/regulator/qcom_spmi-regulator.c| 133 +++-
 drivers/soc/qcom/Kconfig   |   3 +
 drivers/soc/qcom/Makefile  |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c   |  65 ++
 include/soc/qcom/kryo-l2-accessors.h   |  21 +
 22 files changed, 2329 insertions(+), 80 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

-- 
1.9.1



[PATCH v6 01/14] soc: qcom: Separate kryo l2 accessors from PMU driver

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

Signed-off-by: Ilia Lin 
---
 drivers/perf/Kconfig |  1 +
 drivers/perf/qcom_l2_pmu.c   | 90 ++--
 drivers/soc/qcom/Kconfig |  3 ++
 drivers/soc/qcom/Makefile|  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 65 ++
 include/soc/qcom/kryo-l2-accessors.h | 21 +
 6 files changed, 115 insertions(+), 66 deletions(-)
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 28bb5a0..561252a 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -69,6 +69,7 @@ config HISI_PMU
 config QCOM_L2_PMU
bool "Qualcomm Technologies L2-cache PMU"
depends on ARCH_QCOM && ARM64 && ACPI
+   select QCOM_KRYO_L2_ACCESSORS
  help
  Provides support for the L2 cache performance monitor unit (PMU)
  in Qualcomm Technologies processors.
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 842135c..cc31f51 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define MAX_L2_CTRS 9
 
@@ -87,8 +88,6 @@
 #define L2_COUNTER_RELOAD   BIT_ULL(31)
 #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
 
-#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
-#define L2CPUSRDR_EL1   sys_reg(3, 3, 15, 0, 7)
 
 #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
 
@@ -107,48 +106,7 @@
 #define L2_EVENT_STREX 0x421
 #define L2_EVENT_CLREX 0x422
 
-static DEFINE_RAW_SPINLOCK(l2_access_lock);
 
-/**
- * set_l2_indirect_reg: write value to an L2 register
- * @reg: Address of L2 register.
- * @value: Value to be written to register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static void set_l2_indirect_reg(u64 reg, u64 val)
-{
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   write_sysreg_s(val, L2CPUSRDR_EL1);
-   isb();
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-}
-
-/**
- * get_l2_indirect_reg: read an L2 register value
- * @reg: Address of L2 register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static u64 get_l2_indirect_reg(u64 reg)
-{
-   u64 val;
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   val = read_sysreg_s(L2CPUSRDR_EL1);
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-
-   return val;
-}
 
 struct cluster_pmu;
 
@@ -219,28 +177,28 @@ static inline struct cluster_pmu *get_cluster_pmu(
 static void cluster_pmu_reset(void)
 {
/* Reset all counters */
-   set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
-   set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+   kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
 }
 
 static inline void cluster_pmu_enable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
 }
 
 static inline void cluster_pmu_disable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
 }
 
 static inline void cluster_pmu_counter_set_value(u32 idx, u64 value)
 {
if (idx == l2_cycle_ctr_idx)
-   set_l2_indirect_reg(L2PMCCNTR, value);
+   kryo_l2_set_indirect_reg(L2PMCCNTR, value);
else
-   set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
+   kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
 }
 
 static inline u64 cluster_pmu_counter_get_value(u32 idx)
@@ -248,46 +206,46 @@ static inline u64 cluster_pmu_counter_get_value(u32 idx)
u64 value;
 
if (idx == l2_cycle_ctr_idx)
-   value = get_l2_indirect_reg(L2PMCCNTR);
+   value = kryo_l2_get_indirect_reg(L2PMCCNTR);
else
-   value = get_l

[PATCH v6 06/14] clk: qcom: cpu-8996: Add support to switch below 600Mhz

2018-05-14 Thread Ilia Lin
From: Rajendra Nayak 

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

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 

Conflicts:
drivers/clk/qcom/clk-cpu-8996.c
---
 drivers/clk/qcom/clk-cpu-8996.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 390b369..3ea0446 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -77,6 +77,8 @@ enum _pmux_input {
NUM_OF_PMUX_INPUTS
 };
 
+#define DIV_2_THRESHOLD6
+
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
@@ -104,10 +106,11 @@ enum _pmux_input {
 
 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),
 };
@@ -149,7 +152,7 @@ enum _pmux_input {
.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),
 };
@@ -190,6 +193,7 @@ struct clk_cpu_8996_mux {
u8  width;
struct notifier_block nb;
struct clk_hw   *pll;
+   struct clk_hw   *pll_div_2;
struct clk_regmap clkr;
 };
 
@@ -235,6 +239,13 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, 
u8 index)
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
struct clk_hw *parent = cpuclk->pll;
 
+   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;
 
@@ -246,13 +257,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;
@@ -304,6 +321,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",
@@ -324,6 +342,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned 
long event,
.shift = 0,
.width = 2,
.pll = &perfcl_pll.clkr.hw,
+   .pll_div_2 = &perfcl_smux.clkr.hw,
.nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_pmux",
-- 
1.9.1



[PATCH v6 05/14] clk: qcom: cpu-8996: Add support to switch to alternate PLL

2018-05-14 Thread Ilia Lin
From: Rajendra Nayak 

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index beb97eb..390b369 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -61,6 +61,7 @@
  * detect voltage droops. We do not add support for ACD as yet.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -187,10 +188,14 @@ struct clk_cpu_8996_mux {
u32 reg;
u8  shift;
u8  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)
 {
@@ -236,6 +241,26 @@ 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,
@@ -279,6 +304,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 *[]){
@@ -298,6 +324,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 *[]){
@@ -356,6 +383,12 @@ struct clk_regmap *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);
+
return ret;
 }
 
-- 
1.9.1



[PATCH v6 03/14] clk: qcom: Add CPU clock driver for msm8996

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

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

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

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

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

ACD stands for Adaptive Clock Distribution and is used to
detect voltage droops. We do not add support for ACD as yet.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/clk-fixed-factor.c   |   2 +-
 drivers/clk/qcom/Kconfig |   9 +
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-alpha-pll.h |   6 +
 drivers/clk/qcom/clk-cpu-8996.c  | 412 +++
 5 files changed, 429 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index a5d402d..8e39bda 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -94,7 +94,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device 
*dev,
init.num_parents = 1;
 
hw = &fix->hw;
-   ret = clk_hw_register(dev, hw);
+   ret = devm_clk_hw_register(dev, hw);
if (ret) {
kfree(fix);
hw = ERR_PTR(ret);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index e42e1af..866ce1f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -33,6 +33,15 @@ config QCOM_CLK_APCS_MSM8916
  Say Y if you want to support CPU frequency scaling on devices
  such as msm8916.
 
+config QCOM_CLK_APCC_MSM8996
+   tristate "MSM8996 CPU Clock Controller"
+   depends on COMMON_CLK_QCOM
+   select QCOM_KRYO_L2_ACCESSORS
+   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.
+
 config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 7c09ab1..a822fc8 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
+obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f981b48..9ce2a32 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -50,6 +50,12 @@ struct pll_vco {
u32 val;
 };
 
+#define VCO(a, b, c) { \
+   .val = a,\
+   .min_freq = b,\
+   .max_freq = c,\
+}
+
 /**
  * struct clk_alpha_pll - phase locked loop (PLL)
  * @offset: base address of registers
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/q

[PATCH v6 09/14] regulator: qcom_spmi: Add support for SAW

2018-05-14 Thread Ilia Lin
Add support for SAW controlled regulators.
The regulators defined as SAW controlled in the device tree
will be controlled through special CPU registers instead of direct
SPMI accesses.
This is required especially for CPU supply regulators to synchronize
with clock scaling and for Automatic Voltage Switching.

Signed-off-by: Ilia Lin 
---
 drivers/regulator/qcom_spmi-regulator.c | 133 +++-
 1 file changed, 130 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/qcom_spmi-regulator.c 
b/drivers/regulator/qcom_spmi-regulator.c
index 63c7a0c..9817f1a 100644
--- a/drivers/regulator/qcom_spmi-regulator.c
+++ b/drivers/regulator/qcom_spmi-regulator.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 /* Pin control enable input pins. */
 #define SPMI_REGULATOR_PIN_CTRL_ENABLE_NONE0x00
@@ -181,6 +183,23 @@ enum spmi_boost_byp_registers {
SPMI_BOOST_BYP_REG_CURRENT_LIMIT= 0x4b,
 };
 
+enum spmi_saw3_registers {
+   SAW3_SECURE = 0x00,
+   SAW3_ID = 0x04,
+   SAW3_SPM_STS= 0x0C,
+   SAW3_AVS_STS= 0x10,
+   SAW3_PMIC_STS   = 0x14,
+   SAW3_RST= 0x18,
+   SAW3_VCTL   = 0x1C,
+   SAW3_AVS_CTL= 0x20,
+   SAW3_AVS_LIMIT  = 0x24,
+   SAW3_AVS_DLY= 0x28,
+   SAW3_AVS_HYSTERESIS = 0x2C,
+   SAW3_SPM_STS2   = 0x38,
+   SAW3_SPM_PMIC_DATA_3= 0x4C,
+   SAW3_VERSION= 0xFD0,
+};
+
 /* Used for indexing into ctrl_reg.  These are offets from 0x40 */
 enum spmi_common_control_register_index {
SPMI_COMMON_IDX_VOLTAGE_RANGE   = 0,
@@ -1035,6 +1054,89 @@ static irqreturn_t spmi_regulator_vs_ocp_isr(int irq, 
void *data)
return IRQ_HANDLED;
 }
 
+#define SAW3_VCTL_DATA_MASK0xFF
+#define SAW3_VCTL_CLEAR_MASK   0x700FF
+#define SAW3_AVS_CTL_EN_MASK   0x1
+#define SAW3_AVS_CTL_TGGL_MASK 0x800
+#define SAW3_AVS_CTL_CLEAR_MASK0x7efc00
+
+static struct regmap *saw_regmap = NULL;
+
+static void spmi_saw_set_vdd(void *data)
+{
+   u32 vctl, data3, avs_ctl, pmic_sts;
+   bool avs_enabled = false;
+   unsigned long timeout;
+   u8 voltage_sel = *(u8 *)data;
+
+   regmap_read(saw_regmap, SAW3_AVS_CTL, &avs_ctl);
+   regmap_read(saw_regmap, SAW3_VCTL, &vctl);
+   regmap_read(saw_regmap, SAW3_SPM_PMIC_DATA_3, &data3);
+
+   /* select the band */
+   vctl &= ~SAW3_VCTL_CLEAR_MASK;
+   vctl |= (u32)voltage_sel;
+
+   data3 &= ~SAW3_VCTL_CLEAR_MASK;
+   data3 |= (u32)voltage_sel;
+
+   /* If AVS is enabled, switch it off during the voltage change */
+   avs_enabled = SAW3_AVS_CTL_EN_MASK & avs_ctl;
+   if (avs_enabled) {
+   avs_ctl &= ~SAW3_AVS_CTL_TGGL_MASK;
+   regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl);
+   }
+
+   regmap_write(saw_regmap, SAW3_RST, 1);
+   regmap_write(saw_regmap, SAW3_VCTL, vctl);
+   regmap_write(saw_regmap, SAW3_SPM_PMIC_DATA_3, data3);
+
+   timeout = jiffies + usecs_to_jiffies(100);
+   do {
+   regmap_read(saw_regmap, SAW3_PMIC_STS, &pmic_sts);
+   pmic_sts &= SAW3_VCTL_DATA_MASK;
+   if (pmic_sts == (u32)voltage_sel)
+   break;
+
+   cpu_relax();
+
+   } while (time_before(jiffies, timeout));
+
+   /* After successful voltage change, switch the AVS back on */
+   if (avs_enabled) {
+   pmic_sts &= 0x3f;
+   avs_ctl &= ~SAW3_AVS_CTL_CLEAR_MASK;
+   avs_ctl |= ((pmic_sts - 4) << 10);
+   avs_ctl |= (pmic_sts << 17);
+   avs_ctl |= SAW3_AVS_CTL_TGGL_MASK;
+   regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl);
+   }
+}
+
+static int
+spmi_regulator_saw_set_voltage(struct regulator_dev *rdev, unsigned selector)
+{
+   struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
+   int ret;
+   u8 range_sel, voltage_sel;
+
+   ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel);
+   if (ret)
+   return ret;
+
+   if (0 != range_sel) {
+   dev_dbg(&rdev->dev, "range_sel = %02X voltage_sel = %02X", \
+   range_sel, voltage_sel);
+   return -EINVAL;
+   }
+
+   /* Always do the SAW register writes on the first CPU */
+   return smp_call_function_single(0, spmi_saw_set_vdd, \
+   &voltage_sel, true);
+}
+
+static struct regulator_ops spmi_saw_ops = {};
+
 static struct regulator_ops spmi_smp

[PATCH v6 07/14] clk: qcom: Add ACD path to CPU clock driver for msm8996

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

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

Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 75 +++--
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 3ea0446..396285c 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -62,9 +62,11 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "clk-alpha-pll.h"
 #include "clk-regmap.h"
@@ -78,6 +80,11 @@ enum _pmux_input {
 };
 
 #define DIV_2_THRESHOLD6
+#define PWRCL_REG_OFFSET 0x0
+#define PERFCL_REG_OFFSET 0x8
+#define MUX_OFFSET 0x40
+#define ALT_PLL_OFFSET 0x100
+#define SSSCTL_OFFSET 0x160
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
@@ -116,7 +123,7 @@ enum _pmux_input {
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-   .offset = 0x8,
+   .offset = PERFCL_REG_OFFSET,
.regs = prim_pll_regs,
.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data){
@@ -128,7 +135,7 @@ enum _pmux_input {
 };
 
 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){
@@ -158,7 +165,7 @@ enum _pmux_input {
 };
 
 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),
@@ -172,7 +179,7 @@ enum _pmux_input {
 };
 
 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),
@@ -185,6 +192,9 @@ enum _pmux_input {
},
 };
 
+void __iomem *base;
+static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base);
+
 /* Mux'es */
 
 struct clk_cpu_8996_mux {
@@ -262,6 +272,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(base);
break;
case POST_RATE_CHANGE:
if (cnd->new_rate < DIV_2_THRESHOLD)
@@ -269,7 +280,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;
@@ -285,7 +296,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) {
@@ -301,7 +312,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) {
@@ -317,7 +328,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,
@@ -338,7 +349,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,
@@ -402,6 +413,10 @@ struct clk_regmap *clks[] = {
clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
 
+   /* Enable alt PLLs

[PATCH v6 11/14] dt: qcom: Add SAW regulator for 8x96 CPUs

2018-05-14 Thread Ilia Lin
1. Add syscon node for the SAW CPU registers
2. Add SAW regulators gang definition for s8-s11
3. Add voltages to the OPP tables
4. Add the s11 SAW regulator as CPU regulator

Signed-off-by: Ilia Lin 
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 75 +++
 1 file changed, 75 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index e6cf290..d7adef9 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 / {
model = "Qualcomm Technologies, Inc. MSM8996";
@@ -99,6 +100,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster0_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_0>;
@@ -114,6 +116,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster0_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_0>;
@@ -125,6 +128,7 @@
reg = <0x0 0x100>;
enable-method = "psci";
clocks = <&kryocc 1>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster1_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_1>;
@@ -140,6 +144,7 @@
reg = <0x0 0x101>;
enable-method = "psci";
clocks = <&kryocc 1>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster1_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_1>;
@@ -174,66 +179,82 @@
 
opp-30720 {
opp-hz = /bits/ 64 <30720>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-42240 {
opp-hz = /bits/ 64 <42240>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-48000 {
opp-hz = /bits/ 64 <48000>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-55680 {
opp-hz = /bits/ 64 <55680>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-65280 {
opp-hz = /bits/ 64 <65280>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-72960 {
opp-hz = /bits/ 64 <72960>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-84480 {
opp-hz = /bits/ 64 <84480>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-96000 {
opp-hz = /bits/ 64 <96000>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-103680 {
opp-hz = /bits/ 64 <103680>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-111360 {
opp-hz = /bits/ 64 <111360>;
+   opp-microvolt = <905000 905000 114>;
clock-latency-ns = <20>;
};
opp-119040 {
opp-hz = /bits/ 64 <119040>;
+   opp-microvolt

[PATCH v6 13/14] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-14 Thread Ilia Lin
In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
that have KRYO processors, the CPU ferequencies subset and voltage value
of each OPP varies based on the silicon variant in use.
Qualcomm Technologies, Inc. Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation.

Signed-off-by: Ilia Lin 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   };
+
+   CPU2: cpu@100 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x100>;
+   enable-method = "psci";
+   clocks = <&kryocc 1>;
+   cpu-supply = &l

[PATCH v6 14/14] dt: qcom: Add qcom-cpufreq-kryo driver configuration

2018-05-14 Thread Ilia Lin
Signed-off-by: Ilia Lin 
---
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi   | 310 +++-
 2 files changed, 309 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts 
b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..da23bda 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -17,5 +17,5 @@
 
 / {
model = "Qualcomm Technologies, Inc. DB820c";
-   compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc";
+   compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096";
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index d7adef9..fbf92f6 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -174,218 +174,519 @@
};
 
cluster0_opp: opp_table0 {
-   compatible = "operating-points-v2";
+   compatible = "operating-points-v2-kryo-cpu";
+   nvmem-cells = <&speedbin_efuse>;
opp-shared;
 
opp-30720 {
opp-hz = /bits/ 64 <30720>;
opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x77>;
+   clock-latency-ns = <20>;
+   };
+   opp-38400 {
+   opp-hz = /bits/ 64 <38400>;
+   opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-42240 {
opp-hz = /bits/ 64 <42240>;
opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-46080 {
+   opp-hz = /bits/ 64 <46080>;
+   opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-48000 {
opp-hz = /bits/ 64 <48000>;
opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-53760 {
+   opp-hz = /bits/ 64 <53760>;
+   opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-55680 {
opp-hz = /bits/ 64 <55680>;
opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-61440 {
+   opp-hz = /bits/ 64 <61440>;
+   opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-65280 {
opp-hz = /bits/ 64 <65280>;
opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-69120 {
+   opp-hz = /bits/ 64 <69120>;
+   opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-72960 {
opp-hz = /bits/ 64 <72960>;
opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-76800 {
+   opp-hz = /bits/ 64 <76800>;
+   opp-microvolt = <905000 905000 114>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-84480 {
opp-hz = /bits/ 64 <84480>;
opp-microvolt = <905000 905000 

[PATCH v6 12/14] cpufreq: Add Kryo CPU scaling driver

2018-05-14 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU ferequencies subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/Kconfig.arm  |  11 +++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 148 +++
 4 files changed, 163 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..5c16f05 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,17 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Technologies, Inc. Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for
+ Qualcomm Technologies, Inc. Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..04bd0fa
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/* 
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+#define SILVER_LEAD0
+#define GOLD_LEAD  2
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int __init qcom_cpufreq_kryo_driver_init(void)
+{
+   size_t len;
+   int ret;
+   u32 versions;
+   enum _msm8996_version msm8996_version;
+   u8 *speedbin;
+   struct device *cpu_dev;
+   struct device_node *np;
+   struct nvmem_cell *speedbin_nvm

[PATCH v6 10/14] dt-bindings: qcom_spmi: Add support for SAW documentation

2018-05-14 Thread Ilia Lin
Add support for SAW controlled regulators.
The regulators defined as SAW controlled in the device tree
will be controlled through special CPU registers instead of direct
SPMI accesses.
This is required especially for CPU supply regulators to synchronize
with clock scaling and for Automatic Voltage Switching.
Document it.

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
---
 .../bindings/regulator/qcom,spmi-regulator.txt | 45 ++
 1 file changed, 45 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt 
b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
index 57d2c65..406f2e5 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
@@ -110,6 +110,11 @@ Qualcomm SPMI Regulators
Definition: Reference to regulator supplying the input pin, as
described in the data sheet.
 
+- qcom,saw-reg:
+   Usage: optional
+   Value type: 
+   Description: Reference to syscon node defining the SAW registers.
+
 
 The regulator node houses sub-nodes for each regulator within the device. Each
 sub-node is identified using the node's name, with valid values listed for each
@@ -201,6 +206,17 @@ see regulator.txt - with additional custom properties 
described below:
2 = 0.55 uA
3 = 0.75 uA
 
+- qcom,saw-slave:
+   Usage: optional
+   Value type: 
+   Description: SAW controlled gang slave. Will not be configured.
+
+- qcom,saw-leader:
+   Usage: optional
+   Value type: 
+   Description: SAW controlled gang leader. Will be configured as
+SAW regulator.
+
 Example:
 
regulators {
@@ -221,3 +237,32 @@ Example:
 

};
+
+Example 2:
+
+   saw3: syscon@9A1 {
+   compatible = "syscon";
+   reg = <0x9A1 0x1000>;
+   };
+
+   ...
+
+   spm-regulators {
+   compatible = "qcom,pm8994-regulators";
+   qcom,saw-reg = <&saw3>;
+   s8 {
+   qcom,saw-slave;
+   };
+   s9 {
+   qcom,saw-slave;
+   };
+   s10 {
+   qcom,saw-slave;
+   };
+   pm8994_s11_saw: s11 {
+   qcom,saw-leader;
+   regulator-always-on;
+   regulator-min-microvolt = <90>;
+   regulator-max-microvolt = <114>;
+   };
+   };
-- 
1.9.1



[PATCH v6 08/14] dt: qcom: Add opp and thermal to the msm8996

2018-05-14 Thread Ilia Lin
Signed-off-by: Ilia Lin 
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 269 --
 1 file changed, 260 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 37b7152c..e6cf290 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 / {
model = "Qualcomm Technologies, Inc. MSM8996";
@@ -97,6 +98,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x0>;
enable-method = "psci";
+   clocks = <&kryocc 0>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_0>;
L2_0: l2-cache {
  compatible = "cache";
@@ -109,6 +113,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x1>;
enable-method = "psci";
+   clocks = <&kryocc 0>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_0>;
};
 
@@ -117,6 +124,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x100>;
enable-method = "psci";
+   clocks = <&kryocc 1>;
+   operating-points-v2 = <&cluster1_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_1>;
L2_1: l2-cache {
  compatible = "cache";
@@ -129,6 +139,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x101>;
enable-method = "psci";
+   clocks = <&kryocc 1>;
+   operating-points-v2 = <&cluster1_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_1>;
};
 
@@ -155,6 +168,182 @@
};
};
 
+   cluster0_opp: opp_table0 {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   opp-30720 {
+   opp-hz = /bits/ 64 <30720>;
+   clock-latency-ns = <20>;
+   };
+   opp-42240 {
+   opp-hz = /bits/ 64 <42240>;
+   clock-latency-ns = <20>;
+   };
+   opp-48000 {
+   opp-hz = /bits/ 64 <48000>;
+   clock-latency-ns = <20>;
+   };
+   opp-55680 {
+   opp-hz = /bits/ 64 <55680>;
+   clock-latency-ns = <20>;
+   };
+   opp-65280 {
+   opp-hz = /bits/ 64 <65280>;
+   clock-latency-ns = <20>;
+   };
+   opp-72960 {
+   opp-hz = /bits/ 64 <72960>;
+   clock-latency-ns = <20>;
+   };
+   opp-84480 {
+   opp-hz = /bits/ 64 <84480>;
+   clock-latency-ns = <20>;
+   };
+   opp-96000 {
+   opp-hz = /bits/ 64 <96000>;
+   clock-latency-ns = <20>;
+   };
+   opp-103680 {
+   opp-hz = /bits/ 64 <103680>;
+   clock-latency-ns = <20>;
+   };
+   opp-111360 {
+   opp-hz = /bits/ 64 <111360>;
+   clock-latency-ns = <20>;
+   };
+   opp-119040 {
+   opp-hz = /bits/ 64 <119040>;
+   clock-latency-ns = <20>;
+   };
+   opp-122880 {
+   opp-hz = /bits/ 64 <122880>;
+   clock-latency-ns = <20>;
+   };
+   opp-132480 {
+   opp-hz = /bits/ 64 <132480>;
+   clock-latency-ns = <20>;
+   };
+   opp-140160 {
+   opp-hz = /bits/ 64 <1401600

[PATCH v6 04/14] clk: qcom: Add DT bindings for CPU clock driver for msm8996

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

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

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

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

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt 
b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index 000..8458783
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
@@ -0,0 +1,17 @@
+Qualcomm CPUSS clock controller for Kryo CPUs
+
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+   "qcom,msm8996-apcc"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+   kryocc: clock-controller@640 {
+   compatible = "qcom,msm8996-apcc";
+   reg = <0x640 0x9>;
+   #clock-cells = <1>;
+   };
-- 
1.9.1



[PATCH v6 02/14] clk: qcom: Make clk_alpha_pll_configure available to modules

2018-05-14 Thread Ilia Lin
From: Rajendra Nayak 

Allow clk_alpha_pll_configure to be called from loadable
kernel modules.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-alpha-pll.c | 1 +
 1 file changed, 1 insertion(+)

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



[PATCH v2] cpufreq: kryo: Fix possible error code dereference

2018-06-17 Thread ilia . lin
From: Ilia Lin 

In event of error returned by the nvmem_cell_read() non-pointer value
may be dereferenced. Fix this with error handling.
Additionally free the allocated speedbin buffer, as per the API.

Fixes: 9ce36edd1a52 (cpufreq: Add Kryo CPU scaling driver)
Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/qcom-cpufreq-kryo.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
index d049fe4b80c4..74b9b93d511b 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -115,6 +115,8 @@ static int qcom_cpufreq_kryo_probe(struct platform_device 
*pdev)
 
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
nvmem_cell_put(speedbin_nvmem);
+   if (IS_ERR(speedbin))
+   return PTR_ERR(speedbin);
 
switch (msm8996_version) {
case MSM8996_V3:
@@ -127,6 +129,7 @@ static int qcom_cpufreq_kryo_probe(struct platform_device 
*pdev)
BUG();
break;
}
+   kfree(speedbin);
 
for_each_possible_cpu(cpu) {
cpu_dev = get_cpu_device(cpu);
-- 
2.11.0



[PATCH v3] cpufreq: kryo: Add module remove and exit

2018-06-17 Thread ilia . lin
From: Ilia Lin 

Add device remove and module exit code to make the driver
functioning as a loadable module.

Fixes: ac28927659be (cpufreq: kryo: allow building as a loadable module)
Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/qcom-cpufreq-kryo.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
index 74b9b93d511b..01bddacf5c3b 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -42,6 +42,8 @@ enum _msm8996_version {
NUM_OF_MSM8996_VERSIONS,
 };
 
+struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
+
 static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
 {
size_t len;
@@ -74,7 +76,6 @@ static enum _msm8996_version __init 
qcom_cpufreq_kryo_get_msm_id(void)
 static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
 {
struct opp_table *opp_tables[NR_CPUS] = {0};
-   struct platform_device *cpufreq_dt_pdev;
enum _msm8996_version msm8996_version;
struct nvmem_cell *speedbin_nvmem;
struct device_node *np;
@@ -165,8 +166,15 @@ static int qcom_cpufreq_kryo_probe(struct platform_device 
*pdev)
return ret;
 }
 
+static int qcom_cpufreq_kryo_remove(struct platform_device *pdev)
+{
+   platform_device_unregister(cpufreq_dt_pdev);
+   return 0;
+}
+
 static struct platform_driver qcom_cpufreq_kryo_driver = {
.probe = qcom_cpufreq_kryo_probe,
+   .remove = qcom_cpufreq_kryo_remove,
.driver = {
.name = "qcom-cpufreq-kryo",
},
@@ -201,8 +209,9 @@ static int __init qcom_cpufreq_kryo_init(void)
if (unlikely(ret < 0))
return ret;
 
-   ret = PTR_ERR_OR_ZERO(platform_device_register_simple(
-   "qcom-cpufreq-kryo", -1, NULL, 0));
+   kryo_cpufreq_pdev = platform_device_register_simple(
+   "qcom-cpufreq-kryo", -1, NULL, 0);
+   ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev);
if (0 == ret)
return 0;
 
@@ -211,5 +220,12 @@ static int __init qcom_cpufreq_kryo_init(void)
 }
 module_init(qcom_cpufreq_kryo_init);
 
+static void __init qcom_cpufreq_kryo_exit(void)
+{
+   platform_device_unregister(kryo_cpufreq_pdev);
+   platform_driver_unregister(&qcom_cpufreq_kryo_driver);
+}
+module_exit(qcom_cpufreq_kryo_exit);
+
 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver");
 MODULE_LICENSE("GPL v2");
-- 
2.11.0



[PATCH] MAINTAINERS: Update e-mail address for Ilia Lin

2018-06-18 Thread ilia . lin
From: Ilia Lin 

Change to the @kernel.org address

Signed-off-by: Ilia Lin 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 035973b23b8b..15a836eebe9a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11799,7 +11799,7 @@ F:  Documentation/media/v4l-drivers/qcom_camss.rst
 F: drivers/media/platform/qcom/camss-8x16/
 
 QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
-M:  Ilia Lin 
+M:  Ilia Lin 
 L:  linux...@vger.kernel.org
 S:  Maintained
 F:  Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
-- 
2.11.0



Re: [PATCH v14 0/2] Kryo CPU scaling driver

2018-05-30 Thread Ilia Lin
Just like Viresh said, this is fixed in the v15.

On May 30, 2018 12:15:35 PM GMT+03:00, Viresh Kumar  
wrote:
>On 30-05-18, 10:08, Rafael J. Wysocki wrote:
>> On Fri, May 25, 2018 at 2:07 PM, Ilia Lin 
>wrote:
>> > [v14]
>> >  * Addressed comment from Sudeep about DT compatible
>> >  * Added MAINTAINERS entry
>> 
>> This causes a build issue to occur in my bleeding-edge branch.
>> 
>> Does it depend on anything new in arm-soc?
>
>He already sent a v15 and the changelog suggest he fixed that build
>issue.

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.


[PATCH] cpufreq: kryo: Fix possible error code dereference

2018-06-14 Thread ilia . lin
From: Ilia Lin 

In event of error returned by the nvmem_cell_read() non-pointer value
may be dereferenced. Fix this with error handling.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/qcom-cpufreq-kryo.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
index d049fe4b80c4..5e9511223ce9 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -115,6 +115,8 @@ static int qcom_cpufreq_kryo_probe(struct platform_device 
*pdev)
 
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
nvmem_cell_put(speedbin_nvmem);
+   if (IS_ERR(speedbin))
+   return PTR_ERR(speedbin);
 
switch (msm8996_version) {
case MSM8996_V3:
-- 
2.11.0



[PATCH v2] cpufreq: kryo: Add module remove and exit

2018-06-14 Thread ilia . lin
From: Ilia Lin 

Add device remove and module exit code to make the driver
functioning as a loadable module.

Fixes: ac28927659be (cpufreq: kryo: allow building as a loadable module)
Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/qcom-cpufreq-kryo.c | 23 ---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
index 5e9511223ce9..01bddacf5c3b 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -42,6 +42,8 @@ enum _msm8996_version {
NUM_OF_MSM8996_VERSIONS,
 };
 
+struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
+
 static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
 {
size_t len;
@@ -74,7 +76,6 @@ static enum _msm8996_version __init 
qcom_cpufreq_kryo_get_msm_id(void)
 static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
 {
struct opp_table *opp_tables[NR_CPUS] = {0};
-   struct platform_device *cpufreq_dt_pdev;
enum _msm8996_version msm8996_version;
struct nvmem_cell *speedbin_nvmem;
struct device_node *np;
@@ -129,6 +130,7 @@ static int qcom_cpufreq_kryo_probe(struct platform_device 
*pdev)
BUG();
break;
}
+   kfree(speedbin);
 
for_each_possible_cpu(cpu) {
cpu_dev = get_cpu_device(cpu);
@@ -164,8 +166,15 @@ static int qcom_cpufreq_kryo_probe(struct platform_device 
*pdev)
return ret;
 }
 
+static int qcom_cpufreq_kryo_remove(struct platform_device *pdev)
+{
+   platform_device_unregister(cpufreq_dt_pdev);
+   return 0;
+}
+
 static struct platform_driver qcom_cpufreq_kryo_driver = {
.probe = qcom_cpufreq_kryo_probe,
+   .remove = qcom_cpufreq_kryo_remove,
.driver = {
.name = "qcom-cpufreq-kryo",
},
@@ -200,8 +209,9 @@ static int __init qcom_cpufreq_kryo_init(void)
if (unlikely(ret < 0))
return ret;
 
-   ret = PTR_ERR_OR_ZERO(platform_device_register_simple(
-   "qcom-cpufreq-kryo", -1, NULL, 0));
+   kryo_cpufreq_pdev = platform_device_register_simple(
+   "qcom-cpufreq-kryo", -1, NULL, 0);
+   ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev);
if (0 == ret)
return 0;
 
@@ -210,5 +220,12 @@ static int __init qcom_cpufreq_kryo_init(void)
 }
 module_init(qcom_cpufreq_kryo_init);
 
+static void __init qcom_cpufreq_kryo_exit(void)
+{
+   platform_device_unregister(kryo_cpufreq_pdev);
+   platform_driver_unregister(&qcom_cpufreq_kryo_driver);
+}
+module_exit(qcom_cpufreq_kryo_exit);
+
 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver");
 MODULE_LICENSE("GPL v2");
-- 
2.11.0



[PATCH v13 3/8] clk: Use devm_ in the register fixed factor clock

2018-06-14 Thread ilia . lin
From: Ilia Lin 

Use devm_clk_hw_register instead of clk_hw_register
to simplify the usage of this API. This way drivers that call
the clk_hw_register_fixed_factor won't need to maintain
a data structure for further cleanup.

Signed-off-by: Ilia Lin 
Tested-by: Amit Kucheria 
---
 drivers/clk/clk-fixed-factor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index a5d402de5584..8e39bda8e596 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -94,7 +94,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device 
*dev,
init.num_parents = 1;
 
hw = &fix->hw;
-   ret = clk_hw_register(dev, hw);
+   ret = devm_clk_hw_register(dev, hw);
if (ret) {
kfree(fix);
hw = ERR_PTR(ret);
-- 
2.11.0



[PATCH v13 6/8] clk: qcom: cpu-8996: Add support to switch to alternate PLL

2018-06-14 Thread ilia . lin
From: Rajendra Nayak 

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
Tested-by: Amit Kucheria 
---
 drivers/clk/qcom/clk-cpu-8996.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index d92cad93af20..620fdc2266ba 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -52,6 +52,7 @@
  * detect voltage droops.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -178,10 +179,14 @@ struct clk_cpu_8996_mux {
u32 reg;
u8  shift;
u8  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)
 {
@@ -227,6 +232,26 @@ clk_cpu_8996_mux_determine_rate(struct clk_hw *hw, struct 
clk_rate_request *req)
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,
@@ -270,6 +295,7 @@ static struct clk_cpu_8996_mux pwrcl_pmux = {
.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 *[]){
@@ -289,6 +315,7 @@ static struct clk_cpu_8996_mux perfcl_pmux = {
.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 *[]){
@@ -347,6 +374,12 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
struct regmap *regmap)
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);
+
return ret;
 }
 
-- 
2.11.0



[PATCH v13 0/8] Clock for CPU scaling support for msm8996

2018-06-14 Thread ilia . lin
From: Ilia Lin 

[v13]
 * Rebased

[v12]
 * Addressed the kbuild fail on arm architecture

[v11]
 * Split the series into domains

[v9]
 * Addressed comments from Viresh and Russel about the error handling

[v8]
 * Reordered the patch series into 4 groups
 * Addressed comments from Amit about the comments and commit messages
 * Addressed comments from Amit and Viresh about the resourses deallocation

[v7]
 * Addressed comments from Viresh about resourses deallocation and DT compatible

[v6]
 * Addressed comments from Viresh about:
  ** Comments style
  ** Kconfig bool instead of tristate
  ** DT and documentation style
  ** Resourses deallocation on an error
  ** Typos

[v5]
 * Rebased
 * Addressed comments from Bjorn about SPDX style, functions and parameters 
naming
 * Addressed comments from Viresh DT properties and style, comments style, 
resourses deallocation, documentation placement
 * Addressed comments from Sricharan about unnessesary include
 * Addressed comments from Nicolas
 * Addressed comments from Rob about the commit messages and acks
 * Addressed comments from Mark

[v4]
 * Adressed all comments from Stephen
 * Added CPU regulator support
 * Added qcom-cpufreq-kryo driver

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

[v2]
 * Addressed comments from Rob Herring for bindings
 * Addressed comments from Mark Rutland for memory barrier
 * Addressed comments from Julien Thierry for clock reenabling condition
 * Tuned the HW configuration for clock frequencies below 600MHz

SOC (1/15):
Extracts the kryo l2 accessors driver from the QCOM PMU driver

Clocks (2/15-9/15):
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.

Ilia Lin (5):
soc: qcom: Separate kryo l2 accessors from PMU driver
clk: Use devm_ in the register fixed factor clock
clk: qcom: Add CPU clock driver for msm8996
dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996
clk: qcom: Add ACD path to CPU clock driver for msm8996

Rajendra Nayak (3):
clk: qcom: Make clk_alpha_pll_configure available to modules
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 +
drivers/clk/clk-fixed-factor.c |   2 +-
drivers/clk/qcom/Kconfig   |  10 +
drivers/clk/qcom/Makefile  |   1 +
drivers/clk/qcom/clk-alpha-pll.c   |   1 +
drivers/clk/qcom/clk-alpha-pll.h   |   6 +
drivers/clk/qcom/clk-cpu-8996.c| 510 +
drivers/perf/Kconfig   |   1 +
drivers/perf/qcom_l2_pmu.c |  90 +---
drivers/soc/qcom/Kconfig   |   3 +
drivers/soc/qcom/Makefile  |   1 +
drivers/soc/qcom/kryo-l2-accessors.c   |  56 +++
include/soc/qcom/kryo-l2-accessors.h   |  12 +
13 files changed, 643 insertions(+), 67 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

-- 
2.11.0



[PATCH v13 2/8] clk: qcom: Make clk_alpha_pll_configure available to modules

2018-06-14 Thread ilia . lin
From: Rajendra Nayak 

Allow clk_alpha_pll_configure to be called from loadable
kernel modules.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
Tested-by: Amit Kucheria 
---
 drivers/clk/qcom/clk-alpha-pll.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 3c49a60072f1..a43f80ac94a4 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -228,6 +228,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)
 {
-- 
2.11.0



[PATCH v13 8/8] clk: qcom: Add ACD path to CPU clock driver for msm8996

2018-06-14 Thread ilia . lin
From: Ilia Lin 

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

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

Signed-off-by: Ilia Lin 
Tested-by: Amit Kucheria 
---
 drivers/clk/qcom/clk-cpu-8996.c | 75 +++--
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index ff5c0a5740d2..0a908d849cda 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -53,9 +53,11 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "clk-alpha-pll.h"
 #include "clk-regmap.h"
@@ -69,6 +71,11 @@ enum _pmux_input {
 };
 
 #define DIV_2_THRESHOLD6
+#define PWRCL_REG_OFFSET 0x0
+#define PERFCL_REG_OFFSET 0x8
+#define MUX_OFFSET 0x40
+#define ALT_PLL_OFFSET 0x100
+#define SSSCTL_OFFSET 0x160
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
@@ -107,7 +114,7 @@ static const struct alpha_pll_config hfpll_config = {
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-   .offset = 0x8,
+   .offset = PERFCL_REG_OFFSET,
.regs = prim_pll_regs,
.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data){
@@ -119,7 +126,7 @@ static struct clk_alpha_pll perfcl_pll = {
 };
 
 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){
@@ -149,7 +156,7 @@ static const struct alpha_pll_config altpll_config = {
 };
 
 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),
@@ -163,7 +170,7 @@ static struct clk_alpha_pll perfcl_alt_pll = {
 };
 
 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),
@@ -176,6 +183,9 @@ static struct clk_alpha_pll pwrcl_alt_pll = {
},
 };
 
+void __iomem *base;
+static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base);
+
 /* Mux'es */
 
 struct clk_cpu_8996_mux {
@@ -253,6 +263,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(base);
break;
case POST_RATE_CHANGE:
if (cnd->new_rate < DIV_2_THRESHOLD)
@@ -260,7 +271,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;
@@ -276,7 +287,7 @@ const struct clk_ops clk_cpu_8996_mux_ops = {
 };
 
 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) {
@@ -292,7 +303,7 @@ static struct clk_cpu_8996_mux pwrcl_smux = {
 };
 
 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) {
@@ -308,7 +319,7 @@ static struct clk_cpu_8996_mux perfcl_smux = {
 };
 
 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,
@@ -329,7 +340,7 @@ static struct clk_cpu_8996_mux pwrcl_pmux = {
 };
 
 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,
@@ -393,6 +404,10 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
struct regmap *regmap)
clk_alpha_pll_configure(&perfcl_alt_pll, regmap

[PATCH v13 7/8] clk: qcom: cpu-8996: Add support to switch below 600Mhz

2018-06-14 Thread ilia . lin
From: Rajendra Nayak 

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

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
Tested-by: Amit Kucheria 
---
 drivers/clk/qcom/clk-cpu-8996.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 620fdc2266ba..ff5c0a5740d2 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -68,6 +68,8 @@ enum _pmux_input {
NUM_OF_PMUX_INPUTS
 };
 
+#define DIV_2_THRESHOLD6
+
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
@@ -95,10 +97,11 @@ static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
 
 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),
 };
@@ -140,7 +143,7 @@ static const struct alpha_pll_config altpll_config = {
.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),
 };
@@ -181,6 +184,7 @@ struct clk_cpu_8996_mux {
u8  width;
struct notifier_block nb;
struct clk_hw   *pll;
+   struct clk_hw   *pll_div_2;
struct clk_regmap clkr;
 };
 
@@ -226,6 +230,13 @@ 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_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;
 
@@ -237,13 +248,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;
@@ -295,6 +312,7 @@ static struct clk_cpu_8996_mux pwrcl_pmux = {
.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",
@@ -315,6 +333,7 @@ static struct clk_cpu_8996_mux perfcl_pmux = {
.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",
-- 
2.11.0



[PATCH v13 4/8] clk: qcom: Add CPU clock driver for msm8996

2018-06-14 Thread ilia . lin
From: Ilia Lin 

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

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

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

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

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

ACD stands for Adaptive Clock Distribution and is used to
detect voltage droops.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
Tested-by: Amit Kucheria 
---
 drivers/clk/qcom/Kconfig |  10 +
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-alpha-pll.h |   6 +
 drivers/clk/qcom/clk-cpu-8996.c  | 403 +++
 4 files changed, 420 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 9c3480dcc38a..fe01df59f923 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -33,6 +33,16 @@ config QCOM_CLK_APCS_MSM8916
  Say Y if you want to support CPU frequency scaling on devices
  such as msm8916.
 
+config QCOM_CLK_APCC_MSM8996
+   tristate "MSM8996 CPU Clock Controller"
+   depends on ARM64
+   depends on COMMON_CLK_QCOM
+   select QCOM_KRYO_L2_ACCESSORS
+   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.
+
 config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 762c01137c2f..d142778f6e92 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
+obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f981b486c468..9ce2a32f30ab 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -50,6 +50,12 @@ struct pll_vco {
u32 val;
 };
 
+#define VCO(a, b, c) { \
+   .val = a,\
+   .min_freq = b,\
+   .max_freq = c,\
+}
+
 /**
  * struct clk_alpha_pll - phase locked loop (PLL)
  * @offset: base address of registers
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
new file mode 100644
index ..d92cad93af20
--- /dev/null
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * 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

[PATCH v13 5/8] dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996

2018-06-14 Thread ilia . lin
From: Ilia Lin 

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

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

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

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

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Tested-by: Amit Kucheria 
---
 Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt 
b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index ..8458783c5a1a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
@@ -0,0 +1,17 @@
+Qualcomm CPUSS clock controller for Kryo CPUs
+
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+   "qcom,msm8996-apcc"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+   kryocc: clock-controller@640 {
+   compatible = "qcom,msm8996-apcc";
+   reg = <0x640 0x9>;
+   #clock-cells = <1>;
+   };
-- 
2.11.0



[PATCH v13 1/8] soc: qcom: Separate kryo l2 accessors from PMU driver

2018-06-14 Thread ilia . lin
From: Ilia Lin 

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

Signed-off-by: Ilia Lin 
Reviewed-by: Amit Kucheria 
Tested-by: Amit Kucheria 
---
 drivers/perf/Kconfig |  1 +
 drivers/perf/qcom_l2_pmu.c   | 90 ++--
 drivers/soc/qcom/Kconfig |  3 ++
 drivers/soc/qcom/Makefile|  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 56 ++
 include/soc/qcom/kryo-l2-accessors.h | 12 +
 6 files changed, 97 insertions(+), 66 deletions(-)
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 08ebaf7cca8b..5c3f07cd79f4 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -71,6 +71,7 @@ config HISI_PMU
 config QCOM_L2_PMU
bool "Qualcomm Technologies L2-cache PMU"
depends on ARCH_QCOM && ARM64 && ACPI
+   select QCOM_KRYO_L2_ACCESSORS
  help
  Provides support for the L2 cache performance monitor unit (PMU)
  in Qualcomm Technologies processors.
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 842135cf35a3..cc31f5162942 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define MAX_L2_CTRS 9
 
@@ -87,8 +88,6 @@
 #define L2_COUNTER_RELOAD   BIT_ULL(31)
 #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
 
-#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
-#define L2CPUSRDR_EL1   sys_reg(3, 3, 15, 0, 7)
 
 #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
 
@@ -107,48 +106,7 @@
 #define L2_EVENT_STREX 0x421
 #define L2_EVENT_CLREX 0x422
 
-static DEFINE_RAW_SPINLOCK(l2_access_lock);
 
-/**
- * set_l2_indirect_reg: write value to an L2 register
- * @reg: Address of L2 register.
- * @value: Value to be written to register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static void set_l2_indirect_reg(u64 reg, u64 val)
-{
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   write_sysreg_s(val, L2CPUSRDR_EL1);
-   isb();
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-}
-
-/**
- * get_l2_indirect_reg: read an L2 register value
- * @reg: Address of L2 register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static u64 get_l2_indirect_reg(u64 reg)
-{
-   u64 val;
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   val = read_sysreg_s(L2CPUSRDR_EL1);
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-
-   return val;
-}
 
 struct cluster_pmu;
 
@@ -219,28 +177,28 @@ static inline struct cluster_pmu *get_cluster_pmu(
 static void cluster_pmu_reset(void)
 {
/* Reset all counters */
-   set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
-   set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+   kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
 }
 
 static inline void cluster_pmu_enable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
 }
 
 static inline void cluster_pmu_disable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
 }
 
 static inline void cluster_pmu_counter_set_value(u32 idx, u64 value)
 {
if (idx == l2_cycle_ctr_idx)
-   set_l2_indirect_reg(L2PMCCNTR, value);
+   kryo_l2_set_indirect_reg(L2PMCCNTR, value);
else
-   set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
+   kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
 }
 
 static inline u64 cluster_pmu_counter_get_value(u32 idx)
@@ -248,46 +206,46 @@ static inline u64 cluster_pmu_counter_get_value(u32 idx)
u64 value;
 
if (idx == l2_cycle_ctr_idx)
-   value = get_l2_indirect_reg(L2PMCCNTR);
+   value = kryo_l2

[PATCH v8 00/15] CPU scaling support for msm8996

2018-05-17 Thread Ilia Lin
[v8]
 * Reordered the patch series into 4 groups
 * Addressed comments from Amit about the comments and commit messages
 * Addressed comments from Amit and Viresh about the resourses deallocation

[v7]
 * Addressed comments from Viresh about resourses deallocation
   and DT compatible

[v6]
 * Addressed comments from Viresh about:
 ** Comments style
 ** Kconfig bool instead of tristate
 ** DT and documentation style
 ** Resourses deallocation on an error
 ** Typos

[v5]
 * Rebased
 * Addressed comments from Bjorn about SPDX style,
   functions and parameters naming
 * Addressed comments from Viresh DT properties and style, comments style,
   resourses deallocation, documentation placement
 * Addressed comments from Sricharan about unnessesary include
 * Addressed comments from Nicolas
 * Addressed comments from Rob about the commit messages and acks
 * Addressed comments from Mark

[v4]
 * Adressed all comments from Stephen
 * Added CPU regulator support
 * Added qcom-cpufreq-kryo driver

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

[v2]
 * Addressed comments from Rob Herring for bindings
 * Addressed comments from Mark Rutland for memory barrier
 * Addressed comments from Julien Thierry for clock reenabling condition
 * Tuned the HW configuration for clock frequencies below 600MHz

The series contains 4 groups of patches, which can be merged in the chain order,
while each group depends on all the previous groups.
(However, Only SOC, or SOC and Clocks, or SOC and Clocks and Cpufreq will work) 
 

SOC (1/15):
Extracts the kryo l2 accessors driver from the QCOM PMU driver

Clocks (2/15-9/15):
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.

Cpufreq (10/15-12/15):
The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

Regulators (13/15-15/15):
Added SAW regulator support to the SPMI regulator driver. The SAW regulators
will be controlled through special CPU registers instead of direct
SPMI accesses.

Ilia Lin (13):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: Use devm_ in the register fixed factor clock
  clk: qcom: Add CPU clock driver for msm8996
  dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996
  clk: qcom: cpu-8996: Add support to switch below 600Mhz
  clk: qcom: Add ACD path to CPU clock driver for msm8996
  dt: qcom: Add opp and thermal to the msm8996
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu
  dt: qcom: Add qcom-cpufreq-kryo driver configuration
  regulator: qcom_spmi: Add support for SAW
  dt-bindings: qcom_spmi: Document SAW support
  dt: qcom: Add SAW regulator for 8x96 CPUs

Rajendra Nayak (2):
  clk: qcom: Make clk_alpha_pll_configure available to modules
  clk: qcom: cpu-8996: Add support to switch to alternate PLL

 .../devicetree/bindings/clock/qcom,kryocc.txt  |  17 +
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 .../bindings/regulator/qcom,spmi-regulator.txt |  45 ++
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts|   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi  | 665 +++-
 drivers/clk/clk-fixed-factor.c |   2 +-
 drivers/clk/qcom/Kconfig   |   9 +
 drivers/clk/qcom/Makefile  |   1 +
 drivers/clk/qcom/clk-alpha-pll.c   |   1 +
 drivers/clk/qcom/clk-alpha-pll.h   |   6 +
 drivers/clk/qcom/clk-cpu-8996.c| 510 
 drivers/cpufreq/Kconfig.arm|  10 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 166 +
 drivers/perf/Kconfig   |   1 +
 drivers/perf/qcom_l2_pmu.c |  90 +--
 drivers/regulator/qcom_spmi-regulator.c| 133 +++-
 drivers/soc/qcom/Kconfig   |   3 +
 drivers/soc/qcom/Makefile  |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c   |  56 ++
 include/soc/qcom/kryo-l2-accessors.h   |  12 +
 22 files changed, 2324 insertions(+), 90 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

-- 
1.9.1



[PATCH v8 01/15] soc: qcom: Separate kryo l2 accessors from PMU driver

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

Signed-off-by: Ilia Lin 
---
 drivers/perf/Kconfig |  1 +
 drivers/perf/qcom_l2_pmu.c   | 90 ++--
 drivers/soc/qcom/Kconfig |  3 ++
 drivers/soc/qcom/Makefile|  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 56 ++
 include/soc/qcom/kryo-l2-accessors.h | 12 +
 6 files changed, 97 insertions(+), 66 deletions(-)
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 28bb5a0..561252a 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -69,6 +69,7 @@ config HISI_PMU
 config QCOM_L2_PMU
bool "Qualcomm Technologies L2-cache PMU"
depends on ARCH_QCOM && ARM64 && ACPI
+   select QCOM_KRYO_L2_ACCESSORS
  help
  Provides support for the L2 cache performance monitor unit (PMU)
  in Qualcomm Technologies processors.
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 842135c..cc31f51 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define MAX_L2_CTRS 9
 
@@ -87,8 +88,6 @@
 #define L2_COUNTER_RELOAD   BIT_ULL(31)
 #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
 
-#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
-#define L2CPUSRDR_EL1   sys_reg(3, 3, 15, 0, 7)
 
 #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
 
@@ -107,48 +106,7 @@
 #define L2_EVENT_STREX 0x421
 #define L2_EVENT_CLREX 0x422
 
-static DEFINE_RAW_SPINLOCK(l2_access_lock);
 
-/**
- * set_l2_indirect_reg: write value to an L2 register
- * @reg: Address of L2 register.
- * @value: Value to be written to register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static void set_l2_indirect_reg(u64 reg, u64 val)
-{
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   write_sysreg_s(val, L2CPUSRDR_EL1);
-   isb();
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-}
-
-/**
- * get_l2_indirect_reg: read an L2 register value
- * @reg: Address of L2 register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static u64 get_l2_indirect_reg(u64 reg)
-{
-   u64 val;
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   val = read_sysreg_s(L2CPUSRDR_EL1);
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-
-   return val;
-}
 
 struct cluster_pmu;
 
@@ -219,28 +177,28 @@ static inline struct cluster_pmu *get_cluster_pmu(
 static void cluster_pmu_reset(void)
 {
/* Reset all counters */
-   set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
-   set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+   kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
 }
 
 static inline void cluster_pmu_enable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
 }
 
 static inline void cluster_pmu_disable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
 }
 
 static inline void cluster_pmu_counter_set_value(u32 idx, u64 value)
 {
if (idx == l2_cycle_ctr_idx)
-   set_l2_indirect_reg(L2PMCCNTR, value);
+   kryo_l2_set_indirect_reg(L2PMCCNTR, value);
else
-   set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
+   kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
 }
 
 static inline u64 cluster_pmu_counter_get_value(u32 idx)
@@ -248,46 +206,46 @@ static inline u64 cluster_pmu_counter_get_value(u32 idx)
u64 value;
 
if (idx == l2_cycle_ctr_idx)
-   value = get_l2_indirect_reg(L2PMCCNTR);
+   value = kryo_l2_get_indirect_reg(L2PMCCNTR);
else
-   value = get_l2_indirect_reg(reg_idx(IA

[PATCH v8 02/15] clk: qcom: Make clk_alpha_pll_configure available to modules

2018-05-17 Thread Ilia Lin
From: Rajendra Nayak 

Allow clk_alpha_pll_configure to be called from loadable
kernel modules.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-alpha-pll.c | 1 +
 1 file changed, 1 insertion(+)

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



[PATCH v8 03/15] clk: Use devm_ in the register fixed factor clock

2018-05-17 Thread Ilia Lin
Use devm_clk_hw_register instead of clk_hw_register
to simplify the usage of this API. This way drivers that call
the clk_hw_register_fixed_factor won't need to maintain
a data structure for further cleanup.

Signed-off-by: Ilia Lin 
---
 drivers/clk/clk-fixed-factor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index a5d402d..8e39bda 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -94,7 +94,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device 
*dev,
init.num_parents = 1;
 
hw = &fix->hw;
-   ret = clk_hw_register(dev, hw);
+   ret = devm_clk_hw_register(dev, hw);
if (ret) {
kfree(fix);
hw = ERR_PTR(ret);
-- 
1.9.1



[PATCH v8 05/15] dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996

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

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

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

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

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt 
b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index 000..8458783
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
@@ -0,0 +1,17 @@
+Qualcomm CPUSS clock controller for Kryo CPUs
+
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+   "qcom,msm8996-apcc"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+   kryocc: clock-controller@640 {
+   compatible = "qcom,msm8996-apcc";
+   reg = <0x640 0x9>;
+   #clock-cells = <1>;
+   };
-- 
1.9.1



[PATCH v8 06/15] clk: qcom: cpu-8996: Add support to switch to alternate PLL

2018-05-17 Thread Ilia Lin
From: Rajendra Nayak 

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index d92cad93..620fdc2 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -52,6 +52,7 @@
  * detect voltage droops.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -178,10 +179,14 @@ struct clk_cpu_8996_mux {
u32 reg;
u8  shift;
u8  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)
 {
@@ -227,6 +232,26 @@ 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,
@@ -270,6 +295,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 *[]){
@@ -289,6 +315,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 *[]){
@@ -347,6 +374,12 @@ struct clk_regmap *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);
+
return ret;
 }
 
-- 
1.9.1



[PATCH v8 07/15] clk: qcom: cpu-8996: Add support to switch below 600Mhz

2018-05-17 Thread Ilia Lin
The CPU clock controller's primary PLL operates on a single VCO range,
between 600MHz and 3GHz. However the CPUs do support OPPs with
frequencies between 300MHz and 600MHz. In order to support running the
CPUs at those frequencies we end up having to lock the PLL at twice the
rate and drive the CPU clk via the PLL/2 output and SMUX.

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 620fdc2..ff5c0a5 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -68,6 +68,8 @@ enum _pmux_input {
NUM_OF_PMUX_INPUTS
 };
 
+#define DIV_2_THRESHOLD6
+
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
@@ -95,10 +97,11 @@ enum _pmux_input {
 
 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),
 };
@@ -140,7 +143,7 @@ enum _pmux_input {
.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),
 };
@@ -181,6 +184,7 @@ struct clk_cpu_8996_mux {
u8  width;
struct notifier_block nb;
struct clk_hw   *pll;
+   struct clk_hw   *pll_div_2;
struct clk_regmap clkr;
 };
 
@@ -226,6 +230,13 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, 
u8 index)
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
struct clk_hw *parent = cpuclk->pll;
 
+   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;
 
@@ -237,13 +248,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;
@@ -295,6 +312,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",
@@ -315,6 +333,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned 
long event,
.shift = 0,
.width = 2,
.pll = &perfcl_pll.clkr.hw,
+   .pll_div_2 = &perfcl_smux.clkr.hw,
.nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_pmux",
-- 
1.9.1



[PATCH v8 08/15] clk: qcom: Add ACD path to CPU clock driver for msm8996

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

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

Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 75 +++--
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index ff5c0a5..0a908d8 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -53,9 +53,11 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "clk-alpha-pll.h"
 #include "clk-regmap.h"
@@ -69,6 +71,11 @@ enum _pmux_input {
 };
 
 #define DIV_2_THRESHOLD6
+#define PWRCL_REG_OFFSET 0x0
+#define PERFCL_REG_OFFSET 0x8
+#define MUX_OFFSET 0x40
+#define ALT_PLL_OFFSET 0x100
+#define SSSCTL_OFFSET 0x160
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
@@ -107,7 +114,7 @@ enum _pmux_input {
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-   .offset = 0x8,
+   .offset = PERFCL_REG_OFFSET,
.regs = prim_pll_regs,
.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data){
@@ -119,7 +126,7 @@ enum _pmux_input {
 };
 
 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){
@@ -149,7 +156,7 @@ enum _pmux_input {
 };
 
 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),
@@ -163,7 +170,7 @@ enum _pmux_input {
 };
 
 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),
@@ -176,6 +183,9 @@ enum _pmux_input {
},
 };
 
+void __iomem *base;
+static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base);
+
 /* Mux'es */
 
 struct clk_cpu_8996_mux {
@@ -253,6 +263,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(base);
break;
case POST_RATE_CHANGE:
if (cnd->new_rate < DIV_2_THRESHOLD)
@@ -260,7 +271,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;
@@ -276,7 +287,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) {
@@ -292,7 +303,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) {
@@ -308,7 +319,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,
@@ -329,7 +340,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,
@@ -393,6 +404,10 @@ struct clk_regmap *clks[] = {
clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
 
+   /* Enable alt PLLs

[PATCH v8 13/15] regulator: qcom_spmi: Add support for SAW

2018-05-17 Thread Ilia Lin
Add support for SAW controlled regulators.
The regulators defined as SAW controlled in the device tree
will be controlled through special CPU registers instead of direct
SPMI accesses.
This is required especially for CPU supply regulators to synchronize
with clock scaling and for Automatic Voltage Switching.

Signed-off-by: Ilia Lin 
---
 drivers/regulator/qcom_spmi-regulator.c | 133 +++-
 1 file changed, 130 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/qcom_spmi-regulator.c 
b/drivers/regulator/qcom_spmi-regulator.c
index 63c7a0c..9817f1a 100644
--- a/drivers/regulator/qcom_spmi-regulator.c
+++ b/drivers/regulator/qcom_spmi-regulator.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 /* Pin control enable input pins. */
 #define SPMI_REGULATOR_PIN_CTRL_ENABLE_NONE0x00
@@ -181,6 +183,23 @@ enum spmi_boost_byp_registers {
SPMI_BOOST_BYP_REG_CURRENT_LIMIT= 0x4b,
 };
 
+enum spmi_saw3_registers {
+   SAW3_SECURE = 0x00,
+   SAW3_ID = 0x04,
+   SAW3_SPM_STS= 0x0C,
+   SAW3_AVS_STS= 0x10,
+   SAW3_PMIC_STS   = 0x14,
+   SAW3_RST= 0x18,
+   SAW3_VCTL   = 0x1C,
+   SAW3_AVS_CTL= 0x20,
+   SAW3_AVS_LIMIT  = 0x24,
+   SAW3_AVS_DLY= 0x28,
+   SAW3_AVS_HYSTERESIS = 0x2C,
+   SAW3_SPM_STS2   = 0x38,
+   SAW3_SPM_PMIC_DATA_3= 0x4C,
+   SAW3_VERSION= 0xFD0,
+};
+
 /* Used for indexing into ctrl_reg.  These are offets from 0x40 */
 enum spmi_common_control_register_index {
SPMI_COMMON_IDX_VOLTAGE_RANGE   = 0,
@@ -1035,6 +1054,89 @@ static irqreturn_t spmi_regulator_vs_ocp_isr(int irq, 
void *data)
return IRQ_HANDLED;
 }
 
+#define SAW3_VCTL_DATA_MASK0xFF
+#define SAW3_VCTL_CLEAR_MASK   0x700FF
+#define SAW3_AVS_CTL_EN_MASK   0x1
+#define SAW3_AVS_CTL_TGGL_MASK 0x800
+#define SAW3_AVS_CTL_CLEAR_MASK0x7efc00
+
+static struct regmap *saw_regmap = NULL;
+
+static void spmi_saw_set_vdd(void *data)
+{
+   u32 vctl, data3, avs_ctl, pmic_sts;
+   bool avs_enabled = false;
+   unsigned long timeout;
+   u8 voltage_sel = *(u8 *)data;
+
+   regmap_read(saw_regmap, SAW3_AVS_CTL, &avs_ctl);
+   regmap_read(saw_regmap, SAW3_VCTL, &vctl);
+   regmap_read(saw_regmap, SAW3_SPM_PMIC_DATA_3, &data3);
+
+   /* select the band */
+   vctl &= ~SAW3_VCTL_CLEAR_MASK;
+   vctl |= (u32)voltage_sel;
+
+   data3 &= ~SAW3_VCTL_CLEAR_MASK;
+   data3 |= (u32)voltage_sel;
+
+   /* If AVS is enabled, switch it off during the voltage change */
+   avs_enabled = SAW3_AVS_CTL_EN_MASK & avs_ctl;
+   if (avs_enabled) {
+   avs_ctl &= ~SAW3_AVS_CTL_TGGL_MASK;
+   regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl);
+   }
+
+   regmap_write(saw_regmap, SAW3_RST, 1);
+   regmap_write(saw_regmap, SAW3_VCTL, vctl);
+   regmap_write(saw_regmap, SAW3_SPM_PMIC_DATA_3, data3);
+
+   timeout = jiffies + usecs_to_jiffies(100);
+   do {
+   regmap_read(saw_regmap, SAW3_PMIC_STS, &pmic_sts);
+   pmic_sts &= SAW3_VCTL_DATA_MASK;
+   if (pmic_sts == (u32)voltage_sel)
+   break;
+
+   cpu_relax();
+
+   } while (time_before(jiffies, timeout));
+
+   /* After successful voltage change, switch the AVS back on */
+   if (avs_enabled) {
+   pmic_sts &= 0x3f;
+   avs_ctl &= ~SAW3_AVS_CTL_CLEAR_MASK;
+   avs_ctl |= ((pmic_sts - 4) << 10);
+   avs_ctl |= (pmic_sts << 17);
+   avs_ctl |= SAW3_AVS_CTL_TGGL_MASK;
+   regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl);
+   }
+}
+
+static int
+spmi_regulator_saw_set_voltage(struct regulator_dev *rdev, unsigned selector)
+{
+   struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
+   int ret;
+   u8 range_sel, voltage_sel;
+
+   ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel);
+   if (ret)
+   return ret;
+
+   if (0 != range_sel) {
+   dev_dbg(&rdev->dev, "range_sel = %02X voltage_sel = %02X", \
+   range_sel, voltage_sel);
+   return -EINVAL;
+   }
+
+   /* Always do the SAW register writes on the first CPU */
+   return smp_call_function_single(0, spmi_saw_set_vdd, \
+   &voltage_sel, true);
+}
+
+static struct regulator_ops spmi_saw_ops = {};
+
 static struct regulator_ops spmi_smp

[PATCH v8 14/15] dt-bindings: qcom_spmi: Document SAW support

2018-05-17 Thread Ilia Lin
Document the DT bindings for the SAW regulators.

The saw-leader is the only property that is configurable in DT.

The saw-slave property allows ganging (grouping) of
several regulators so that their outputs can be combined.

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
---
 .../bindings/regulator/qcom,spmi-regulator.txt | 45 ++
 1 file changed, 45 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt 
b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
index 57d2c65..406f2e5 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
@@ -110,6 +110,11 @@ Qualcomm SPMI Regulators
Definition: Reference to regulator supplying the input pin, as
described in the data sheet.
 
+- qcom,saw-reg:
+   Usage: optional
+   Value type: 
+   Description: Reference to syscon node defining the SAW registers.
+
 
 The regulator node houses sub-nodes for each regulator within the device. Each
 sub-node is identified using the node's name, with valid values listed for each
@@ -201,6 +206,17 @@ see regulator.txt - with additional custom properties 
described below:
2 = 0.55 uA
3 = 0.75 uA
 
+- qcom,saw-slave:
+   Usage: optional
+   Value type: 
+   Description: SAW controlled gang slave. Will not be configured.
+
+- qcom,saw-leader:
+   Usage: optional
+   Value type: 
+   Description: SAW controlled gang leader. Will be configured as
+SAW regulator.
+
 Example:
 
regulators {
@@ -221,3 +237,32 @@ Example:
 

};
+
+Example 2:
+
+   saw3: syscon@9A1 {
+   compatible = "syscon";
+   reg = <0x9A1 0x1000>;
+   };
+
+   ...
+
+   spm-regulators {
+   compatible = "qcom,pm8994-regulators";
+   qcom,saw-reg = <&saw3>;
+   s8 {
+   qcom,saw-slave;
+   };
+   s9 {
+   qcom,saw-slave;
+   };
+   s10 {
+   qcom,saw-slave;
+   };
+   pm8994_s11_saw: s11 {
+   qcom,saw-leader;
+   regulator-always-on;
+   regulator-min-microvolt = <90>;
+   regulator-max-microvolt = <114>;
+   };
+   };
-- 
1.9.1



[PATCH v8 15/15] dt: qcom: Add SAW regulator for 8x96 CPUs

2018-05-17 Thread Ilia Lin
1. Add syscon node for the SAW CPU registers
2. Add SAW regulators gang definition for s8-s11
3. Add voltages to the OPP tables
4. Add the s11 SAW regulator as CPU regulator

Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 119 ++
 1 file changed, 119 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index d96a112..871bfac 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 / {
model = "Qualcomm Technologies, Inc. MSM8996";
@@ -92,6 +93,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster0_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_0>;
@@ -107,6 +109,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster0_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_0>;
@@ -118,6 +121,7 @@
reg = <0x0 0x100>;
enable-method = "psci";
clocks = <&kryocc 1>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster1_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_1>;
@@ -133,6 +137,7 @@
reg = <0x0 0x101>;
enable-method = "psci";
clocks = <&kryocc 1>;
+   cpu-supply = <&pm8994_s11_saw>;
operating-points-v2 = <&cluster1_opp>;
#cooling-cells = <2>;
next-level-cache = <&L2_1>;
@@ -169,171 +174,205 @@
 
opp-30720 {
opp-hz = /bits/ 64 <30720>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x77>;
clock-latency-ns = <20>;
};
opp-38400 {
opp-hz = /bits/ 64 <38400>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-42240 {
opp-hz = /bits/ 64 <42240>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x7>;
clock-latency-ns = <20>;
};
opp-46080 {
opp-hz = /bits/ 64 <46080>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-48000 {
opp-hz = /bits/ 64 <48000>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x7>;
clock-latency-ns = <20>;
};
opp-53760 {
opp-hz = /bits/ 64 <53760>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-55680 {
opp-hz = /bits/ 64 <55680>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x7>;
clock-latency-ns = <20>;
};
opp-61440 {
opp-hz = /bits/ 64 <61440>;
+   opp-microvolt = <905000 905000 114>;
opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-65280 {
opp-hz = /bits/ 64 <65280>;
+   opp-microvol

[PATCH v8 12/15] dt: qcom: Add qcom-cpufreq-kryo driver configuration

2018-05-17 Thread Ilia Lin
1. Add NVMEM node for the speedbin
2. Add definitions for all possible MSM8996 CPU OPPs.
The qcom-cpufreq-kryo driver will select the appropriate subset.

Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi   | 281 ++--
 2 files changed, 270 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts 
b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..da23bda 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -17,5 +17,5 @@
 
 / {
model = "Qualcomm Technologies, Inc. DB820c";
-   compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc";
+   compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096";
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index e6cf290..d96a112 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -1,13 +1,6 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved.
  */
 
 #include 
@@ -169,177 +162,436 @@
};
 
cluster0_opp: opp_table0 {
-   compatible = "operating-points-v2";
+   compatible = "operating-points-v2-kryo-cpu",
+   "operating-points-v2";
+   nvmem-cells = <&speedbin_efuse>;
opp-shared;
 
opp-30720 {
opp-hz = /bits/ 64 <30720>;
+   opp-supported-hw = <0x77>;
+   clock-latency-ns = <20>;
+   };
+   opp-38400 {
+   opp-hz = /bits/ 64 <38400>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-42240 {
opp-hz = /bits/ 64 <42240>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-46080 {
+   opp-hz = /bits/ 64 <46080>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-48000 {
opp-hz = /bits/ 64 <48000>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-53760 {
+   opp-hz = /bits/ 64 <53760>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-55680 {
opp-hz = /bits/ 64 <55680>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-61440 {
+   opp-hz = /bits/ 64 <61440>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-65280 {
opp-hz = /bits/ 64 <65280>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-69120 {
+   opp-hz = /bits/ 64 <69120>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-72960 {
opp-hz = /bits/ 64 <72960>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-76800 {
+   opp-hz = /bits/ 64 <76800>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-84480 {
opp-hz 

[PATCH v8 11/15] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-17 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   };
+
+   C

[PATCH v8 10/15] cpufreq: Add Kryo CPU scaling driver

2018-05-17 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 drivers/cpufreq/Kconfig.arm  |  10 +++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 166 +++
 4 files changed, 180 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..a2b9fb2
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+#define SILVER_LEAD0
+#define GOLD_LEAD  2
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int __init qcom_cpufreq_kryo_driver_init(void)
+{
+   size_t len;
+   int ret = 0;
+   u32 versions;
+   enum _msm8996_vers

[PATCH v8 09/15] dt: qcom: Add opp and thermal to the msm8996

2018-05-17 Thread Ilia Lin
Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 269 --
 1 file changed, 260 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 37b7152c..e6cf290 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 / {
model = "Qualcomm Technologies, Inc. MSM8996";
@@ -97,6 +98,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x0>;
enable-method = "psci";
+   clocks = <&kryocc 0>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_0>;
L2_0: l2-cache {
  compatible = "cache";
@@ -109,6 +113,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x1>;
enable-method = "psci";
+   clocks = <&kryocc 0>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_0>;
};
 
@@ -117,6 +124,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x100>;
enable-method = "psci";
+   clocks = <&kryocc 1>;
+   operating-points-v2 = <&cluster1_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_1>;
L2_1: l2-cache {
  compatible = "cache";
@@ -129,6 +139,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x101>;
enable-method = "psci";
+   clocks = <&kryocc 1>;
+   operating-points-v2 = <&cluster1_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_1>;
};
 
@@ -155,6 +168,182 @@
};
};
 
+   cluster0_opp: opp_table0 {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   opp-30720 {
+   opp-hz = /bits/ 64 <30720>;
+   clock-latency-ns = <20>;
+   };
+   opp-42240 {
+   opp-hz = /bits/ 64 <42240>;
+   clock-latency-ns = <20>;
+   };
+   opp-48000 {
+   opp-hz = /bits/ 64 <48000>;
+   clock-latency-ns = <20>;
+   };
+   opp-55680 {
+   opp-hz = /bits/ 64 <55680>;
+   clock-latency-ns = <20>;
+   };
+   opp-65280 {
+   opp-hz = /bits/ 64 <65280>;
+   clock-latency-ns = <20>;
+   };
+   opp-72960 {
+   opp-hz = /bits/ 64 <72960>;
+   clock-latency-ns = <20>;
+   };
+   opp-84480 {
+   opp-hz = /bits/ 64 <84480>;
+   clock-latency-ns = <20>;
+   };
+   opp-96000 {
+   opp-hz = /bits/ 64 <96000>;
+   clock-latency-ns = <20>;
+   };
+   opp-103680 {
+   opp-hz = /bits/ 64 <103680>;
+   clock-latency-ns = <20>;
+   };
+   opp-111360 {
+   opp-hz = /bits/ 64 <111360>;
+   clock-latency-ns = <20>;
+   };
+   opp-119040 {
+   opp-hz = /bits/ 64 <119040>;
+   clock-latency-ns = <20>;
+   };
+   opp-122880 {
+   opp-hz = /bits/ 64 <122880>;
+   clock-latency-ns = <20>;
+   };
+   opp-132480 {
+   opp-hz = /bits/ 64 <132480>;
+   clock-latency-ns = <20>;
+   };
+   opp-140160 {
+   opp-hz = /bits/ 64

[PATCH v8 04/15] clk: qcom: Add CPU clock driver for msm8996

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

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

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

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

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

ACD stands for Adaptive Clock Distribution and is used to
detect voltage droops.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/Kconfig |   9 +
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-alpha-pll.h |   6 +
 drivers/clk/qcom/clk-cpu-8996.c  | 403 +++
 4 files changed, 419 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index e42e1af..866ce1f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -33,6 +33,15 @@ config QCOM_CLK_APCS_MSM8916
  Say Y if you want to support CPU frequency scaling on devices
  such as msm8916.
 
+config QCOM_CLK_APCC_MSM8996
+   tristate "MSM8996 CPU Clock Controller"
+   depends on COMMON_CLK_QCOM
+   select QCOM_KRYO_L2_ACCESSORS
+   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.
+
 config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 7c09ab1..a822fc8 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
+obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f981b48..9ce2a32 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -50,6 +50,12 @@ struct pll_vco {
u32 val;
 };
 
+#define VCO(a, b, c) { \
+   .val = a,\
+   .min_freq = b,\
+   .max_freq = c,\
+}
+
 /**
  * struct clk_alpha_pll - phase locked loop (PLL)
  * @offset: base address of registers
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
new file mode 100644
index 000..d92cad93
--- /dev/null
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * 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 |   |
+ *   +--&

[PATCH] cpufreq: Add Kryo CPU scaling driver

2018-05-22 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 drivers/cpufreq/Kconfig.arm  |  10 +++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 163 +++
 4 files changed, 177 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..c5bb070
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int __init qcom_cpufreq_kryo_driver_init(void)
+{
+   struct opp_table *opp_tables[NR_CPUS] = {0};
+   enum _msm8996_version msm8996_version;
+   struct nvmem_cell *speedbin_nvmem;

[PATCH] cpufreq: Add Kryo CPU scaling driver

2018-05-23 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/Kconfig.arm  |  10 +++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 163 +++
 4 files changed, 177 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..885051e
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int __init qcom_cpufreq_kryo_driver_init(void)
+{
+   struct opp_table *opp_tables[NR_CPUS] = {0};
+   enum _msm8996_version msm8996_version;
+   struct nvmem_cell *speedbin_nvmem;
+   struct platf

[PATCH v10 2/2] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-23 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0

[PATCH v10 0/2] Kryo CPU scaling driver

2018-05-23 Thread Ilia Lin
[v10]
 * Split the series into domains
 * Addressed comments from Viresh and Sudeep about logical CPU numbering.

The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

The series depends on the series from Viresh:
https://patchwork.kernel.org/patch/10418139/

The previous spin was here:
https://patchwork.kernel.org/patch/10420751/
https://patchwork.kernel.org/patch/10414761/

Ilia Lin (2):
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 drivers/cpufreq/Kconfig.arm|  10 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 163 +
 5 files changed, 857 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

-- 
1.9.1



[PATCH v10 1/2] cpufreq: Add Kryo CPU scaling driver

2018-05-23 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/Kconfig.arm  |  10 +++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 163 +++
 4 files changed, 177 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..885051e
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int __init qcom_cpufreq_kryo_driver_init(void)
+{
+   struct opp_table *opp_tables[NR_CPUS] = {0};
+   enum _msm8996_version msm8996_version;
+   struct nvmem_cell *speedbin_nvmem;
+   struct platf

[PATCH v11 1/2] cpufreq: Add Kryo CPU scaling driver

2018-05-23 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/Kconfig.arm  |  10 ++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 181 +++
 4 files changed, 195 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..2339ea99d
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
+{
+   struct opp_table *opp_tables[NR_CPUS] = {0};
+   struct platform_device *cpufreq_dt_pdev;
+   enum _msm8996_version msm8996_version;
+

[PATCH v11 2/2] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-23 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0

[PATCH v11 0/2] Kryo CPU scaling driver

2018-05-23 Thread Ilia Lin
[v11]
 * Addressed comment from Russel about device_node reference
 * Addressed comment from Sudeep about the late_initcall
 * Transformed init into probe to take care of deferals

[v10]
 * Split the series into domains
 * Addressed comments from Viresh and Sudeep about logical CPU numbering.

The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

The series depends on the series from Viresh:
https://patchwork.kernel.org/patch/10418139/

The previous spin was here:
https://patchwork.kernel.org/patch/10420809/

Ilia Lin (2):
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 drivers/cpufreq/Kconfig.arm|  10 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 181 ++
 5 files changed, 875 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

-- 
1.9.1



[PATCH v11 0/8] CPU scaling support for msm8996

2018-05-23 Thread Ilia Lin
[v11]
 * Split the series into domains

[v9]
 * Addressed comments from Viresh and Russel about the error handling

[v8]
 * Reordered the patch series into 4 groups
 * Addressed comments from Amit about the comments and commit messages
 * Addressed comments from Amit and Viresh about the resourses deallocation

[v7]
 * Addressed comments from Viresh about resourses deallocation
   and DT compatible

[v6]
 * Addressed comments from Viresh about:
 ** Comments style
 ** Kconfig bool instead of tristate
 ** DT and documentation style
 ** Resourses deallocation on an error
 ** Typos

[v5]
 * Rebased
 * Addressed comments from Bjorn about SPDX style,
   functions and parameters naming
 * Addressed comments from Viresh DT properties and style, comments style,
   resourses deallocation, documentation placement
 * Addressed comments from Sricharan about unnessesary include
 * Addressed comments from Nicolas
 * Addressed comments from Rob about the commit messages and acks
 * Addressed comments from Mark

[v4]
 * Adressed all comments from Stephen
 * Added CPU regulator support
 * Added qcom-cpufreq-kryo driver

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

[v2]
 * Addressed comments from Rob Herring for bindings
 * Addressed comments from Mark Rutland for memory barrier
 * Addressed comments from Julien Thierry for clock reenabling condition
 * Tuned the HW configuration for clock frequencies below 600MHz

SOC (1/15):
Extracts the kryo l2 accessors driver from the QCOM PMU driver

Clocks (2/15-9/15):
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.

Ilia Lin (6):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: Use devm_ in the register fixed factor clock
  clk: qcom: Add CPU clock driver for msm8996
  dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996
  clk: qcom: cpu-8996: Add support to switch below 600Mhz
  clk: qcom: Add ACD path to CPU clock driver for msm8996

Rajendra Nayak (2):
  clk: qcom: Make clk_alpha_pll_configure available to modules
  clk: qcom: cpu-8996: Add support to switch to alternate PLL

 .../devicetree/bindings/clock/qcom,kryocc.txt  |  17 +
 drivers/clk/clk-fixed-factor.c |   2 +-
 drivers/clk/qcom/Kconfig   |   9 +
 drivers/clk/qcom/Makefile  |   1 +
 drivers/clk/qcom/clk-alpha-pll.c   |   1 +
 drivers/clk/qcom/clk-alpha-pll.h   |   6 +
 drivers/clk/qcom/clk-cpu-8996.c| 510 +
 drivers/perf/Kconfig   |   1 +
 drivers/perf/qcom_l2_pmu.c |  90 +---
 drivers/soc/qcom/Kconfig   |   3 +
 drivers/soc/qcom/Makefile  |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c   |  56 +++
 include/soc/qcom/kryo-l2-accessors.h   |  12 +
 13 files changed, 642 insertions(+), 67 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

-- 
1.9.1



[PATCH v11 1/8] soc: qcom: Separate kryo l2 accessors from PMU driver

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

Signed-off-by: Ilia Lin 
---
 drivers/perf/Kconfig |  1 +
 drivers/perf/qcom_l2_pmu.c   | 90 ++--
 drivers/soc/qcom/Kconfig |  3 ++
 drivers/soc/qcom/Makefile|  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 56 ++
 include/soc/qcom/kryo-l2-accessors.h | 12 +
 6 files changed, 97 insertions(+), 66 deletions(-)
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 28bb5a0..561252a 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -69,6 +69,7 @@ config HISI_PMU
 config QCOM_L2_PMU
bool "Qualcomm Technologies L2-cache PMU"
depends on ARCH_QCOM && ARM64 && ACPI
+   select QCOM_KRYO_L2_ACCESSORS
  help
  Provides support for the L2 cache performance monitor unit (PMU)
  in Qualcomm Technologies processors.
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 842135c..cc31f51 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define MAX_L2_CTRS 9
 
@@ -87,8 +88,6 @@
 #define L2_COUNTER_RELOAD   BIT_ULL(31)
 #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
 
-#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
-#define L2CPUSRDR_EL1   sys_reg(3, 3, 15, 0, 7)
 
 #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
 
@@ -107,48 +106,7 @@
 #define L2_EVENT_STREX 0x421
 #define L2_EVENT_CLREX 0x422
 
-static DEFINE_RAW_SPINLOCK(l2_access_lock);
 
-/**
- * set_l2_indirect_reg: write value to an L2 register
- * @reg: Address of L2 register.
- * @value: Value to be written to register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static void set_l2_indirect_reg(u64 reg, u64 val)
-{
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   write_sysreg_s(val, L2CPUSRDR_EL1);
-   isb();
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-}
-
-/**
- * get_l2_indirect_reg: read an L2 register value
- * @reg: Address of L2 register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static u64 get_l2_indirect_reg(u64 reg)
-{
-   u64 val;
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   val = read_sysreg_s(L2CPUSRDR_EL1);
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-
-   return val;
-}
 
 struct cluster_pmu;
 
@@ -219,28 +177,28 @@ static inline struct cluster_pmu *get_cluster_pmu(
 static void cluster_pmu_reset(void)
 {
/* Reset all counters */
-   set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
-   set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+   kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
 }
 
 static inline void cluster_pmu_enable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
 }
 
 static inline void cluster_pmu_disable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
 }
 
 static inline void cluster_pmu_counter_set_value(u32 idx, u64 value)
 {
if (idx == l2_cycle_ctr_idx)
-   set_l2_indirect_reg(L2PMCCNTR, value);
+   kryo_l2_set_indirect_reg(L2PMCCNTR, value);
else
-   set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
+   kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
 }
 
 static inline u64 cluster_pmu_counter_get_value(u32 idx)
@@ -248,46 +206,46 @@ static inline u64 cluster_pmu_counter_get_value(u32 idx)
u64 value;
 
if (idx == l2_cycle_ctr_idx)
-   value = get_l2_indirect_reg(L2PMCCNTR);
+   value = kryo_l2_get_indirect_reg(L2PMCCNTR);
else
-   value = get_l2_indirect_reg(reg_idx(IA

[PATCH v11 2/8] clk: qcom: Make clk_alpha_pll_configure available to modules

2018-05-23 Thread Ilia Lin
From: Rajendra Nayak 

Allow clk_alpha_pll_configure to be called from loadable
kernel modules.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-alpha-pll.c | 1 +
 1 file changed, 1 insertion(+)

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



[PATCH v11 5/8] dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996

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

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

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

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

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt 
b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index 000..8458783
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
@@ -0,0 +1,17 @@
+Qualcomm CPUSS clock controller for Kryo CPUs
+
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+   "qcom,msm8996-apcc"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+   kryocc: clock-controller@640 {
+   compatible = "qcom,msm8996-apcc";
+   reg = <0x640 0x9>;
+   #clock-cells = <1>;
+   };
-- 
1.9.1



[PATCH v11 4/8] clk: qcom: Add CPU clock driver for msm8996

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

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

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

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

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

ACD stands for Adaptive Clock Distribution and is used to
detect voltage droops.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/Kconfig |   9 +
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-alpha-pll.h |   6 +
 drivers/clk/qcom/clk-cpu-8996.c  | 403 +++
 4 files changed, 419 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index e42e1af..866ce1f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -33,6 +33,15 @@ config QCOM_CLK_APCS_MSM8916
  Say Y if you want to support CPU frequency scaling on devices
  such as msm8916.
 
+config QCOM_CLK_APCC_MSM8996
+   tristate "MSM8996 CPU Clock Controller"
+   depends on COMMON_CLK_QCOM
+   select QCOM_KRYO_L2_ACCESSORS
+   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.
+
 config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 7c09ab1..a822fc8 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
+obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f981b48..9ce2a32 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -50,6 +50,12 @@ struct pll_vco {
u32 val;
 };
 
+#define VCO(a, b, c) { \
+   .val = a,\
+   .min_freq = b,\
+   .max_freq = c,\
+}
+
 /**
  * struct clk_alpha_pll - phase locked loop (PLL)
  * @offset: base address of registers
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
new file mode 100644
index 000..d92cad93
--- /dev/null
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * 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 |   |
+ *   +--&

[PATCH v11 7/8] clk: qcom: cpu-8996: Add support to switch below 600Mhz

2018-05-23 Thread Ilia Lin
The CPU clock controller's primary PLL operates on a single VCO range,
between 600MHz and 3GHz. However the CPUs do support OPPs with
frequencies between 300MHz and 600MHz. In order to support running the
CPUs at those frequencies we end up having to lock the PLL at twice the
rate and drive the CPU clk via the PLL/2 output and SMUX.

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 620fdc2..ff5c0a5 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -68,6 +68,8 @@ enum _pmux_input {
NUM_OF_PMUX_INPUTS
 };
 
+#define DIV_2_THRESHOLD6
+
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
@@ -95,10 +97,11 @@ enum _pmux_input {
 
 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),
 };
@@ -140,7 +143,7 @@ enum _pmux_input {
.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),
 };
@@ -181,6 +184,7 @@ struct clk_cpu_8996_mux {
u8  width;
struct notifier_block nb;
struct clk_hw   *pll;
+   struct clk_hw   *pll_div_2;
struct clk_regmap clkr;
 };
 
@@ -226,6 +230,13 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, 
u8 index)
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
struct clk_hw *parent = cpuclk->pll;
 
+   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;
 
@@ -237,13 +248,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;
@@ -295,6 +312,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",
@@ -315,6 +333,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned 
long event,
.shift = 0,
.width = 2,
.pll = &perfcl_pll.clkr.hw,
+   .pll_div_2 = &perfcl_smux.clkr.hw,
.nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_pmux",
-- 
1.9.1



[PATCH v11 8/8] clk: qcom: Add ACD path to CPU clock driver for msm8996

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

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

Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 75 +++--
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index ff5c0a5..0a908d8 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -53,9 +53,11 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "clk-alpha-pll.h"
 #include "clk-regmap.h"
@@ -69,6 +71,11 @@ enum _pmux_input {
 };
 
 #define DIV_2_THRESHOLD6
+#define PWRCL_REG_OFFSET 0x0
+#define PERFCL_REG_OFFSET 0x8
+#define MUX_OFFSET 0x40
+#define ALT_PLL_OFFSET 0x100
+#define SSSCTL_OFFSET 0x160
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
@@ -107,7 +114,7 @@ enum _pmux_input {
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-   .offset = 0x8,
+   .offset = PERFCL_REG_OFFSET,
.regs = prim_pll_regs,
.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data){
@@ -119,7 +126,7 @@ enum _pmux_input {
 };
 
 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){
@@ -149,7 +156,7 @@ enum _pmux_input {
 };
 
 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),
@@ -163,7 +170,7 @@ enum _pmux_input {
 };
 
 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),
@@ -176,6 +183,9 @@ enum _pmux_input {
},
 };
 
+void __iomem *base;
+static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base);
+
 /* Mux'es */
 
 struct clk_cpu_8996_mux {
@@ -253,6 +263,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(base);
break;
case POST_RATE_CHANGE:
if (cnd->new_rate < DIV_2_THRESHOLD)
@@ -260,7 +271,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;
@@ -276,7 +287,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) {
@@ -292,7 +303,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) {
@@ -308,7 +319,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,
@@ -329,7 +340,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,
@@ -393,6 +404,10 @@ struct clk_regmap *clks[] = {
clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
 
+   /* Enable alt PLLs

[PATCH v11 6/8] clk: qcom: cpu-8996: Add support to switch to alternate PLL

2018-05-23 Thread Ilia Lin
From: Rajendra Nayak 

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index d92cad93..620fdc2 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -52,6 +52,7 @@
  * detect voltage droops.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -178,10 +179,14 @@ struct clk_cpu_8996_mux {
u32 reg;
u8  shift;
u8  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)
 {
@@ -227,6 +232,26 @@ 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,
@@ -270,6 +295,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 *[]){
@@ -289,6 +315,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 *[]){
@@ -347,6 +374,12 @@ struct clk_regmap *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);
+
return ret;
 }
 
-- 
1.9.1



[PATCH v11 3/8] clk: Use devm_ in the register fixed factor clock

2018-05-23 Thread Ilia Lin
Use devm_clk_hw_register instead of clk_hw_register
to simplify the usage of this API. This way drivers that call
the clk_hw_register_fixed_factor won't need to maintain
a data structure for further cleanup.

Signed-off-by: Ilia Lin 
---
 drivers/clk/clk-fixed-factor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index a5d402d..8e39bda 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -94,7 +94,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device 
*dev,
init.num_parents = 1;
 
hw = &fix->hw;
-   ret = clk_hw_register(dev, hw);
+   ret = devm_clk_hw_register(dev, hw);
if (ret) {
kfree(fix);
hw = ERR_PTR(ret);
-- 
1.9.1



[PATCH v11 1/2] dt: qcom: Add opp and thermal to the msm8996

2018-05-23 Thread Ilia Lin
Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 269 --
 1 file changed, 260 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 37b7152c..e6cf290 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 / {
model = "Qualcomm Technologies, Inc. MSM8996";
@@ -97,6 +98,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x0>;
enable-method = "psci";
+   clocks = <&kryocc 0>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_0>;
L2_0: l2-cache {
  compatible = "cache";
@@ -109,6 +113,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x1>;
enable-method = "psci";
+   clocks = <&kryocc 0>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_0>;
};
 
@@ -117,6 +124,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x100>;
enable-method = "psci";
+   clocks = <&kryocc 1>;
+   operating-points-v2 = <&cluster1_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_1>;
L2_1: l2-cache {
  compatible = "cache";
@@ -129,6 +139,9 @@
compatible = "qcom,kryo";
reg = <0x0 0x101>;
enable-method = "psci";
+   clocks = <&kryocc 1>;
+   operating-points-v2 = <&cluster1_opp>;
+   #cooling-cells = <2>;
next-level-cache = <&L2_1>;
};
 
@@ -155,6 +168,182 @@
};
};
 
+   cluster0_opp: opp_table0 {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   opp-30720 {
+   opp-hz = /bits/ 64 <30720>;
+   clock-latency-ns = <20>;
+   };
+   opp-42240 {
+   opp-hz = /bits/ 64 <42240>;
+   clock-latency-ns = <20>;
+   };
+   opp-48000 {
+   opp-hz = /bits/ 64 <48000>;
+   clock-latency-ns = <20>;
+   };
+   opp-55680 {
+   opp-hz = /bits/ 64 <55680>;
+   clock-latency-ns = <20>;
+   };
+   opp-65280 {
+   opp-hz = /bits/ 64 <65280>;
+   clock-latency-ns = <20>;
+   };
+   opp-72960 {
+   opp-hz = /bits/ 64 <72960>;
+   clock-latency-ns = <20>;
+   };
+   opp-84480 {
+   opp-hz = /bits/ 64 <84480>;
+   clock-latency-ns = <20>;
+   };
+   opp-96000 {
+   opp-hz = /bits/ 64 <96000>;
+   clock-latency-ns = <20>;
+   };
+   opp-103680 {
+   opp-hz = /bits/ 64 <103680>;
+   clock-latency-ns = <20>;
+   };
+   opp-111360 {
+   opp-hz = /bits/ 64 <111360>;
+   clock-latency-ns = <20>;
+   };
+   opp-119040 {
+   opp-hz = /bits/ 64 <119040>;
+   clock-latency-ns = <20>;
+   };
+   opp-122880 {
+   opp-hz = /bits/ 64 <122880>;
+   clock-latency-ns = <20>;
+   };
+   opp-132480 {
+   opp-hz = /bits/ 64 <132480>;
+   clock-latency-ns = <20>;
+   };
+   opp-140160 {
+   opp-hz = /bits/ 64

[PATCH v11 0/2] CPU scaling support for msm8996 DT

2018-05-23 Thread Ilia Lin
[v11]
 * Split the series into domains

The series adds OPP tables, thermal and CPU definitions in order to support
the CPU frequency scaling on msm8996 CPUs.

Ilia Lin (2):
  dt: qcom: Add opp and thermal to the msm8996
  dt: qcom: Add qcom-cpufreq-kryo driver configuration

 arch/arm64/boot/dts/qcom/apq8096-db820c.dts |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi   | 546 +++-
 2 files changed, 528 insertions(+), 20 deletions(-)

-- 
1.9.1



[PATCH v11 2/2] dt: qcom: Add qcom-cpufreq-kryo driver configuration

2018-05-23 Thread Ilia Lin
1. Add NVMEM node for the speedbin
2. Add definitions for all possible MSM8996 CPU OPPs.
The qcom-cpufreq-kryo driver will select the appropriate subset.

Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
---
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts |   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi   | 281 ++--
 2 files changed, 270 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts 
b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 230e9c8..da23bda 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -17,5 +17,5 @@
 
 / {
model = "Qualcomm Technologies, Inc. DB820c";
-   compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc";
+   compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096";
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi 
b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index e6cf290..d96a112 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -1,13 +1,6 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved.
  */
 
 #include 
@@ -169,177 +162,436 @@
};
 
cluster0_opp: opp_table0 {
-   compatible = "operating-points-v2";
+   compatible = "operating-points-v2-kryo-cpu",
+   "operating-points-v2";
+   nvmem-cells = <&speedbin_efuse>;
opp-shared;
 
opp-30720 {
opp-hz = /bits/ 64 <30720>;
+   opp-supported-hw = <0x77>;
+   clock-latency-ns = <20>;
+   };
+   opp-38400 {
+   opp-hz = /bits/ 64 <38400>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-42240 {
opp-hz = /bits/ 64 <42240>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-46080 {
+   opp-hz = /bits/ 64 <46080>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-48000 {
opp-hz = /bits/ 64 <48000>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-53760 {
+   opp-hz = /bits/ 64 <53760>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-55680 {
opp-hz = /bits/ 64 <55680>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-61440 {
+   opp-hz = /bits/ 64 <61440>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-65280 {
opp-hz = /bits/ 64 <65280>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-69120 {
+   opp-hz = /bits/ 64 <69120>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-72960 {
opp-hz = /bits/ 64 <72960>;
+   opp-supported-hw = <0x7>;
+   clock-latency-ns = <20>;
+   };
+   opp-76800 {
+   opp-hz = /bits/ 64 <76800>;
+   opp-supported-hw = <0x70>;
clock-latency-ns = <20>;
};
opp-84480 {
opp-hz 

[PATCH v12 1/8] soc: qcom: Separate kryo l2 accessors from PMU driver

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

Signed-off-by: Ilia Lin 
---
 drivers/perf/Kconfig |  1 +
 drivers/perf/qcom_l2_pmu.c   | 90 ++--
 drivers/soc/qcom/Kconfig |  3 ++
 drivers/soc/qcom/Makefile|  1 +
 drivers/soc/qcom/kryo-l2-accessors.c | 56 ++
 include/soc/qcom/kryo-l2-accessors.h | 12 +
 6 files changed, 97 insertions(+), 66 deletions(-)
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 28bb5a0..561252a 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -69,6 +69,7 @@ config HISI_PMU
 config QCOM_L2_PMU
bool "Qualcomm Technologies L2-cache PMU"
depends on ARCH_QCOM && ARM64 && ACPI
+   select QCOM_KRYO_L2_ACCESSORS
  help
  Provides support for the L2 cache performance monitor unit (PMU)
  in Qualcomm Technologies processors.
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 842135c..cc31f51 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define MAX_L2_CTRS 9
 
@@ -87,8 +88,6 @@
 #define L2_COUNTER_RELOAD   BIT_ULL(31)
 #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
 
-#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
-#define L2CPUSRDR_EL1   sys_reg(3, 3, 15, 0, 7)
 
 #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
 
@@ -107,48 +106,7 @@
 #define L2_EVENT_STREX 0x421
 #define L2_EVENT_CLREX 0x422
 
-static DEFINE_RAW_SPINLOCK(l2_access_lock);
 
-/**
- * set_l2_indirect_reg: write value to an L2 register
- * @reg: Address of L2 register.
- * @value: Value to be written to register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static void set_l2_indirect_reg(u64 reg, u64 val)
-{
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   write_sysreg_s(val, L2CPUSRDR_EL1);
-   isb();
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-}
-
-/**
- * get_l2_indirect_reg: read an L2 register value
- * @reg: Address of L2 register.
- *
- * Use architecturally required barriers for ordering between system register
- * accesses
- */
-static u64 get_l2_indirect_reg(u64 reg)
-{
-   u64 val;
-   unsigned long flags;
-
-   raw_spin_lock_irqsave(&l2_access_lock, flags);
-   write_sysreg_s(reg, L2CPUSRSELR_EL1);
-   isb();
-   val = read_sysreg_s(L2CPUSRDR_EL1);
-   raw_spin_unlock_irqrestore(&l2_access_lock, flags);
-
-   return val;
-}
 
 struct cluster_pmu;
 
@@ -219,28 +177,28 @@ static inline struct cluster_pmu *get_cluster_pmu(
 static void cluster_pmu_reset(void)
 {
/* Reset all counters */
-   set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
-   set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
-   set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+   kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
+   kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
 }
 
 static inline void cluster_pmu_enable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
 }
 
 static inline void cluster_pmu_disable(void)
 {
-   set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
+   kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
 }
 
 static inline void cluster_pmu_counter_set_value(u32 idx, u64 value)
 {
if (idx == l2_cycle_ctr_idx)
-   set_l2_indirect_reg(L2PMCCNTR, value);
+   kryo_l2_set_indirect_reg(L2PMCCNTR, value);
else
-   set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
+   kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
 }
 
 static inline u64 cluster_pmu_counter_get_value(u32 idx)
@@ -248,46 +206,46 @@ static inline u64 cluster_pmu_counter_get_value(u32 idx)
u64 value;
 
if (idx == l2_cycle_ctr_idx)
-   value = get_l2_indirect_reg(L2PMCCNTR);
+   value = kryo_l2_get_indirect_reg(L2PMCCNTR);
else
-   value = get_l2_indirect_reg(reg_idx(IA

[PATCH v12 2/8] clk: qcom: Make clk_alpha_pll_configure available to modules

2018-05-24 Thread Ilia Lin
From: Rajendra Nayak 

Allow clk_alpha_pll_configure to be called from loadable
kernel modules.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-alpha-pll.c | 1 +
 1 file changed, 1 insertion(+)

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



[PATCH v12 8/8] clk: qcom: Add ACD path to CPU clock driver for msm8996

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

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

Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 75 +++--
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index ff5c0a5..0a908d8 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -53,9 +53,11 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "clk-alpha-pll.h"
 #include "clk-regmap.h"
@@ -69,6 +71,11 @@ enum _pmux_input {
 };
 
 #define DIV_2_THRESHOLD6
+#define PWRCL_REG_OFFSET 0x0
+#define PERFCL_REG_OFFSET 0x8
+#define MUX_OFFSET 0x40
+#define ALT_PLL_OFFSET 0x100
+#define SSSCTL_OFFSET 0x160
 
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
@@ -107,7 +114,7 @@ enum _pmux_input {
 };
 
 static struct clk_alpha_pll perfcl_pll = {
-   .offset = 0x8,
+   .offset = PERFCL_REG_OFFSET,
.regs = prim_pll_regs,
.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
.clkr.hw.init = &(struct clk_init_data){
@@ -119,7 +126,7 @@ enum _pmux_input {
 };
 
 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){
@@ -149,7 +156,7 @@ enum _pmux_input {
 };
 
 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),
@@ -163,7 +170,7 @@ enum _pmux_input {
 };
 
 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),
@@ -176,6 +183,9 @@ enum _pmux_input {
},
 };
 
+void __iomem *base;
+static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base);
+
 /* Mux'es */
 
 struct clk_cpu_8996_mux {
@@ -253,6 +263,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(base);
break;
case POST_RATE_CHANGE:
if (cnd->new_rate < DIV_2_THRESHOLD)
@@ -260,7 +271,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;
@@ -276,7 +287,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) {
@@ -292,7 +303,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) {
@@ -308,7 +319,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,
@@ -329,7 +340,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,
@@ -393,6 +404,10 @@ struct clk_regmap *clks[] = {
clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
 
+   /* Enable alt PLLs

[PATCH v12 6/8] clk: qcom: cpu-8996: Add support to switch to alternate PLL

2018-05-24 Thread Ilia Lin
From: Rajendra Nayak 

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index d92cad93..620fdc2 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -52,6 +52,7 @@
  * detect voltage droops.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -178,10 +179,14 @@ struct clk_cpu_8996_mux {
u32 reg;
u8  shift;
u8  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)
 {
@@ -227,6 +232,26 @@ 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,
@@ -270,6 +295,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 *[]){
@@ -289,6 +315,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 *[]){
@@ -347,6 +374,12 @@ struct clk_regmap *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);
+
return ret;
 }
 
-- 
1.9.1



[PATCH v12 7/8] clk: qcom: cpu-8996: Add support to switch below 600Mhz

2018-05-24 Thread Ilia Lin
The CPU clock controller's primary PLL operates on a single VCO range,
between 600MHz and 3GHz. However the CPUs do support OPPs with
frequencies between 300MHz and 600MHz. In order to support running the
CPUs at those frequencies we end up having to lock the PLL at twice the
rate and drive the CPU clk via the PLL/2 output and SMUX.

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 620fdc2..ff5c0a5 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -68,6 +68,8 @@ enum _pmux_input {
NUM_OF_PMUX_INPUTS
 };
 
+#define DIV_2_THRESHOLD6
+
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
@@ -95,10 +97,11 @@ enum _pmux_input {
 
 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),
 };
@@ -140,7 +143,7 @@ enum _pmux_input {
.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),
 };
@@ -181,6 +184,7 @@ struct clk_cpu_8996_mux {
u8  width;
struct notifier_block nb;
struct clk_hw   *pll;
+   struct clk_hw   *pll_div_2;
struct clk_regmap clkr;
 };
 
@@ -226,6 +230,13 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, 
u8 index)
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
struct clk_hw *parent = cpuclk->pll;
 
+   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;
 
@@ -237,13 +248,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;
@@ -295,6 +312,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",
@@ -315,6 +333,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned 
long event,
.shift = 0,
.width = 2,
.pll = &perfcl_pll.clkr.hw,
+   .pll_div_2 = &perfcl_smux.clkr.hw,
.nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_pmux",
-- 
1.9.1



[PATCH v12 3/8] clk: Use devm_ in the register fixed factor clock

2018-05-24 Thread Ilia Lin
Use devm_clk_hw_register instead of clk_hw_register
to simplify the usage of this API. This way drivers that call
the clk_hw_register_fixed_factor won't need to maintain
a data structure for further cleanup.

Signed-off-by: Ilia Lin 
---
 drivers/clk/clk-fixed-factor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index a5d402d..8e39bda 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -94,7 +94,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device 
*dev,
init.num_parents = 1;
 
hw = &fix->hw;
-   ret = clk_hw_register(dev, hw);
+   ret = devm_clk_hw_register(dev, hw);
if (ret) {
kfree(fix);
hw = ERR_PTR(ret);
-- 
1.9.1



[PATCH v12 0/8] Clock for CPU scaling support for msm8996

2018-05-24 Thread Ilia Lin
[v12]
 * Addressed the kbuild fail on arm architecture

[v11]
 * Split the series into domains

[v9]
 * Addressed comments from Viresh and Russel about the error handling

[v8]
 * Reordered the patch series into 4 groups
 * Addressed comments from Amit about the comments and commit messages
 * Addressed comments from Amit and Viresh about the resourses deallocation

[v7]
 * Addressed comments from Viresh about resourses deallocation
   and DT compatible

[v6]
 * Addressed comments from Viresh about:
 ** Comments style
 ** Kconfig bool instead of tristate
 ** DT and documentation style
 ** Resourses deallocation on an error
 ** Typos

[v5]
 * Rebased
 * Addressed comments from Bjorn about SPDX style,
   functions and parameters naming
 * Addressed comments from Viresh DT properties and style, comments style,
   resourses deallocation, documentation placement
 * Addressed comments from Sricharan about unnessesary include
 * Addressed comments from Nicolas
 * Addressed comments from Rob about the commit messages and acks
 * Addressed comments from Mark

[v4]
 * Adressed all comments from Stephen
 * Added CPU regulator support
 * Added qcom-cpufreq-kryo driver

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

[v2]
 * Addressed comments from Rob Herring for bindings
 * Addressed comments from Mark Rutland for memory barrier
 * Addressed comments from Julien Thierry for clock reenabling condition
 * Tuned the HW configuration for clock frequencies below 600MHz

SOC (1/15):
Extracts the kryo l2 accessors driver from the QCOM PMU driver

Clocks (2/15-9/15):
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.

Ilia Lin (6):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: Use devm_ in the register fixed factor clock
  clk: qcom: Add CPU clock driver for msm8996
  dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996
  clk: qcom: cpu-8996: Add support to switch below 600Mhz
  clk: qcom: Add ACD path to CPU clock driver for msm8996

Rajendra Nayak (2):
  clk: qcom: Make clk_alpha_pll_configure available to modules
  clk: qcom: cpu-8996: Add support to switch to alternate PLL

 .../devicetree/bindings/clock/qcom,kryocc.txt  |  17 +
 drivers/clk/clk-fixed-factor.c |   2 +-
 drivers/clk/qcom/Kconfig   |  10 +
 drivers/clk/qcom/Makefile  |   1 +
 drivers/clk/qcom/clk-alpha-pll.c   |   1 +
 drivers/clk/qcom/clk-alpha-pll.h   |   6 +
 drivers/clk/qcom/clk-cpu-8996.c| 510 +
 drivers/perf/Kconfig   |   1 +
 drivers/perf/qcom_l2_pmu.c |  90 +---
 drivers/soc/qcom/Kconfig   |   3 +
 drivers/soc/qcom/Makefile  |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c   |  56 +++
 include/soc/qcom/kryo-l2-accessors.h   |  12 +
 13 files changed, 643 insertions(+), 67 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

-- 
1.9.1



[PATCH v12 5/8] dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996

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

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

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

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

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/clock/qcom,kryocc.txt | 17 +
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,kryocc.txt 
b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
new file mode 100644
index 000..8458783
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,kryocc.txt
@@ -0,0 +1,17 @@
+Qualcomm CPUSS clock controller for Kryo CPUs
+
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+   "qcom,msm8996-apcc"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+   kryocc: clock-controller@640 {
+   compatible = "qcom,msm8996-apcc";
+   reg = <0x640 0x9>;
+   #clock-cells = <1>;
+   };
-- 
1.9.1



[PATCH v12 4/8] clk: qcom: Add CPU clock driver for msm8996

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

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

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

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

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

ACD stands for Adaptive Clock Distribution and is used to
detect voltage droops.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/Kconfig |  10 +
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-alpha-pll.h |   6 +
 drivers/clk/qcom/clk-cpu-8996.c  | 403 +++
 4 files changed, 420 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index e42e1af..42e84b5 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -33,6 +33,16 @@ config QCOM_CLK_APCS_MSM8916
  Say Y if you want to support CPU frequency scaling on devices
  such as msm8916.
 
+config QCOM_CLK_APCC_MSM8996
+   tristate "MSM8996 CPU Clock Controller"
+   depends on ARM64
+   depends on COMMON_CLK_QCOM
+   select QCOM_KRYO_L2_ACCESSORS
+   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.
+
 config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 7c09ab1..a822fc8 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
+obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f981b48..9ce2a32 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -50,6 +50,12 @@ struct pll_vco {
u32 val;
 };
 
+#define VCO(a, b, c) { \
+   .val = a,\
+   .min_freq = b,\
+   .max_freq = c,\
+}
+
 /**
  * struct clk_alpha_pll - phase locked loop (PLL)
  * @offset: base address of registers
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
new file mode 100644
index 000..d92cad93
--- /dev/null
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * 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
+ *
+ *  +---

[PATCH v12 0/2] Kryo CPU scaling driver

2018-05-24 Thread Ilia Lin
[v12]
 * Addressed comments from Sudeep and Viresh about the single init

[v11]
 * Addressed comment from Russel about device_node reference
 * Addressed comment from Sudeep about the late_initcall
 * Transformed init into probe to take care of deferals

[v10]
 * Split the series into domains
 * Addressed comments from Viresh and Sudeep about logical CPU numbering.

The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

The series depends on the series from Viresh:
https://patchwork.kernel.org/patch/10418139/

The previous spin was here:
https://patchwork.kernel.org/patch/10421143/

Ilia Lin (2):
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 drivers/cpufreq/Kconfig.arm|  10 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 194 ++
 5 files changed, 888 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

-- 
1.9.1



[PATCH v12 2/2] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-24 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0

[PATCH v12 1/2] cpufreq: Add Kryo CPU scaling driver

2018-05-24 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/Kconfig.arm  |  10 ++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 194 +++
 4 files changed, 208 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..9fe379c
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
+{
+   struct opp_table *opp_tables[NR_CPUS] = {0};
+   struct platform_device *cpufreq_dt_pdev;
+   enum _msm8996_version msm8996_version;
+   s

[PATCH v15 2/2] dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

2018-05-29 Thread Ilia Lin
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

This change adds documentation for the DT bindings.
The "operating-points-v2-kryo-cpu" DT extends the "operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-supported-hw: A single 32 bit bitmap value,
  representing compatible HW:
0:  MSM8996 V3, speedbin 0
1:  MSM8996 V3, speedbin 1
2:  MSM8996 V3, speedbin 2
3:  unused
4:  MSM8996 SG, speedbin 0
5:  MSM8996 SG, speedbin 1
6:  MSM8996 SG, speedbin 2
7-31:   unused

Signed-off-by: Ilia Lin 
Reviewed-by: Rob Herring 
Reviewed-by: Amit Kucheria 
Tested-by: Amit Kucheria 
Acked-by: Viresh Kumar 
---
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 1 file changed, 680 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
new file mode 100644
index 000..c2127b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
@@ -0,0 +1,680 @@
+Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings
+===
+
+In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996
+that have KRYO processors, the CPU ferequencies subset and voltage value
+of each OPP varies based on the silicon variant in use.
+Qualcomm Technologies, Inc. Process Voltage Scaling Tables
+defines the voltage and frequency value based on the msm-id in SMEM
+and speedbin blown in the efuse combination.
+The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+to provide the OPP framework with required information (existing HW bitmap).
+This is used to determine the voltage and frequency value for each OPP of
+operating-points-v2 table when it is parsed by the OPP framework.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the
+   speedbin that is used to select the right frequency/voltage
+   value pair.
+   Please refer the for nvmem-cells
+   bindings Documentation/devicetree/bindings/nvmem/nvmem.txt
+   and also examples below.
+
+In every OPP node:
+- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW.
+   Bitmap:
+   0:  MSM8996 V3, speedbin 0
+   1:  MSM8996 V3, speedbin 1
+   2:  MSM8996 V3, speedbin 2
+   3:  unused
+   4:  MSM8996 SG, speedbin 0
+   5:  MSM8996 SG, speedbin 1
+   6:  MSM8996 SG, speedbin 2
+   7-31:   unused
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   CPU0: cpu@0 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x0>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   next-level-cache = <&L2_0>;
+   L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+   };
+   };
+
+   CPU1: cpu@1 {
+   device_type = "cpu";
+   compatible = "qcom,kryo";
+   reg = <0x0 0x1>;
+   enable-method = "psci";
+   clocks = <&kryocc 0>;
+   cpu-supply = <&pm8994_s11_saw>;
+   operating-points-v2 = <&cluster0_opp>;
+   #cooling-cells = <2>;
+   

[PATCH v15 0/2] Kryo CPU scaling driver

2018-05-29 Thread Ilia Lin
[v15]
 * Addressed the kbuild error

[v14]
 * Addressed comment from Sudeep about DT compatible
 * Added MAINTAINERS entry

[v13]
 * Addressed comment from Sudeep about DT compatible check on init

[v12]
 * Addressed comments from Sudeep and Viresh about the single init

[v11]
 * Addressed comment from Russel about device_node reference
 * Addressed comment from Sudeep about the late_initcall
 * Transformed init into probe to take care of deferals

[v10]
 * Split the series into domains
 * Addressed comments from Viresh and Sudeep about logical CPU numbering.

The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

The series depends on the series from Viresh:
https://patchwork.kernel.org/patch/10418139/

The previous spin was here:
https://patchwork.kernel.org/patch/10427315/

Ilia Lin (2):
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu

 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 MAINTAINERS|   7 +
 drivers/cpufreq/Kconfig.arm|  11 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 212 +++
 6 files changed, 914 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

-- 
1.9.1



[PATCH v15 1/2] cpufreq: Add Kryo CPU scaling driver

2018-05-29 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
Acked-by: Viresh Kumar 
Reviewed-by: Amit Kucheria 
Tested-by: Amit Kucheria 
---
 MAINTAINERS  |   7 ++
 drivers/cpufreq/Kconfig.arm  |  11 ++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 212 +++
 5 files changed, 234 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ba0adcb..648e0c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11687,6 +11687,13 @@ F: 
Documentation/devicetree/bindings/media/qcom,camss.txt
 F: Documentation/media/v4l-drivers/qcom_camss.rst
 F: drivers/media/platform/qcom/camss-8x16/
 
+QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
+M:  Ilia Lin 
+L:  linux...@vger.kernel.org
+S:  Maintained
+F:  Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
+F:  drivers/cpufreq/qcom-cpufreq-kryo.c
+
 QUALCOMM EMAC GIGABIT ETHERNET DRIVER
 M: Timur Tabi 
 L: net...@vger.kernel.org
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..86e87bb 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,17 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Kryo based CPUFreq"
+   depends on ARM64
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..d049fe4
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom

Re: [PATCH] cpufreq: kryo: allow building as a loadable module

2018-06-05 Thread Ilia Lin
Viresh got ahead of my answer a bit. :)
Sure I'll post the module exit later.

On June 6, 2018 7:09:29 AM GMT+03:00, Viresh Kumar  
wrote:
>On 05-06-18, 13:44, Arnd Bergmann wrote:
>> Building the kryo cpufreq driver while QCOM_SMEM is a loadable module
>> results in a link error:
>> 
>> drivers/cpufreq/qcom-cpufreq-kryo.o: In function
>`qcom_cpufreq_kryo_probe':
>> qcom-cpufreq-kryo.c:(.text+0xbc): undefined reference to
>`qcom_smem_get'
>> 
>> The problem is that Kconfig ignores interprets the dependency as met
>> when the dependent symbol is a 'bool' one. By making it 'tristate',
>> it will be forced to be a module here, which builds successfully.
>> 
>> Fixes: 46e2856b8e18 ("cpufreq: Add Kryo CPU scaling driver")
>> Signed-off-by: Arnd Bergmann 
>> ---
>>  drivers/cpufreq/Kconfig.arm | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/drivers/cpufreq/Kconfig.arm
>b/drivers/cpufreq/Kconfig.arm
>> index c7ce928fbf1f..52f5f1a2040c 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -125,7 +125,7 @@ config ARM_OMAP2PLUS_CPUFREQ
>>  default ARCH_OMAP2PLUS
>>  
>>  config ARM_QCOM_CPUFREQ_KRYO
>> -bool "Qualcomm Kryo based CPUFreq"
>> +tristate "Qualcomm Kryo based CPUFreq"
>>  depends on ARM64
>>  depends on QCOM_QFPROM
>>  depends on QCOM_SMEM
>
>Okay, so we really need this to be a module. But the driver can't
>really work as
>a module right now if we do this: insmod, rmmod, insmod. Because it
>doesn't free
>resources at rmmmod and will fail on second insmod.
>
>Because what you are fixing is a critical build error, we better get it
>merged
>right now.
>
>Acked-by: Viresh Kumar 
>
>But Ilia needs to cook another patch to add the module removal code for
>the
>driver and mark your patch's commit id in the fixes tag.

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.


[PATCH v7 02/14] clk: qcom: Make clk_alpha_pll_configure available to modules

2018-05-15 Thread Ilia Lin
From: Rajendra Nayak 

Allow clk_alpha_pll_configure to be called from loadable
kernel modules.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-alpha-pll.c | 1 +
 1 file changed, 1 insertion(+)

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



[PATCH v7 00/14] CPU scaling support for msm8996

2018-05-15 Thread Ilia Lin
[v7]
 * Addressed comments from Viresh about resourses deallocation
   and DT compatible

[v6]
 * Addressed comments from Viresh about:
 ** Comments style
 ** Kconfig bool instead of tristate
 ** DT and documentation style
 ** Resourses deallocation on an error
 ** Typos

[v5]
 * Rebased
 * Addressed comments from Bjorn about SPDX style,
   functions and parameters naming
 * Addressed comments from Viresh DT properties and style, comments style,
   resourses deallocation, documentation placement
 * Addressed comments from Sricharan about unnessesary include
 * Addressed comments from Nicolas
 * Addressed comments from Rob about the commit messages and acks
 * Addressed comments from Mark

[v4]
 * Adressed all comments from Stephen
 * Added CPU regulator support
 * Added qcom-cpufreq-kryo driver

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

[v2]
 * Addressed comments from Rob Herring for bindings
 * Addressed comments from Mark Rutland for memory barrier
 * Addressed comments from Julien Thierry for clock reenabling condition
 * Tuned the HW configuration for clock frequencies below 600MHz

Clocks:
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.

Regulators:
Added SAW regulator support to the SPMI regulator driver. The SAW regulators
will be controlled through special CPU registers instead of direct
SPMI accesses.

Cpufreq:
The qcom-cpufreq-kryo driver is aimed to support different SOC versions.
The driver reads eFuse information and chooses the required OPP subset
by passing the OPP supported-hw parameter.

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

Ilia Lin (11):
  soc: qcom: Separate kryo l2 accessors from PMU driver
  clk: qcom: Add CPU clock driver for msm8996
  clk: qcom: Add DT bindings for CPU clock driver for msm8996
  clk: qcom: Add ACD path to CPU clock driver for msm8996
  dt: qcom: Add opp and thermal to the msm8996
  regulator: qcom_spmi: Add support for SAW
  dt-bindings: qcom_spmi: Add support for SAW documentation
  dt: qcom: Add SAW regulator for 8x96 CPUs
  cpufreq: Add Kryo CPU scaling driver
  dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu
  dt: qcom: Add qcom-cpufreq-kryo driver configuration

Rajendra Nayak (3):
  clk: qcom: Make clk_alpha_pll_configure available to modules
  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 +
 .../devicetree/bindings/opp/kryo-cpufreq.txt   | 680 +
 .../bindings/regulator/qcom,spmi-regulator.txt |  45 ++
 arch/arm64/boot/dts/qcom/apq8096-db820c.dts|   2 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi  | 651 +++-
 drivers/clk/clk-fixed-factor.c |   2 +-
 drivers/clk/qcom/Kconfig   |   9 +
 drivers/clk/qcom/Makefile  |   1 +
 drivers/clk/qcom/clk-alpha-pll.c   |   1 +
 drivers/clk/qcom/clk-alpha-pll.h   |   6 +
 drivers/clk/qcom/clk-cpu-8996.c| 519 
 drivers/cpufreq/Kconfig.arm|  11 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 150 +
 drivers/perf/Kconfig   |   1 +
 drivers/perf/qcom_l2_pmu.c |  90 +--
 drivers/regulator/qcom_spmi-regulator.c| 133 +++-
 drivers/soc/qcom/Kconfig   |   3 +
 drivers/soc/qcom/Makefile  |   1 +
 drivers/soc/qcom/kryo-l2-accessors.c   |  65 ++
 include/soc/qcom/kryo-l2-accessors.h   |  21 +
 22 files changed, 2332 insertions(+), 80 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,kryocc.txt
 create mode 100644 Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c
 create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
 create mode 100644 include/soc/qcom/kryo-l2-accessors.h

-- 
1.9.1



[PATCH v7 06/14] clk: qcom: cpu-8996: Add support to switch below 600Mhz

2018-05-15 Thread Ilia Lin
From: Rajendra Nayak 

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

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 

Conflicts:
drivers/clk/qcom/clk-cpu-8996.c
---
 drivers/clk/qcom/clk-cpu-8996.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 390b369..3ea0446 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -77,6 +77,8 @@ enum _pmux_input {
NUM_OF_PMUX_INPUTS
 };
 
+#define DIV_2_THRESHOLD6
+
 static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_ALPHA_VAL] = 0x08,
@@ -104,10 +106,11 @@ enum _pmux_input {
 
 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),
 };
@@ -149,7 +152,7 @@ enum _pmux_input {
.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),
 };
@@ -190,6 +193,7 @@ struct clk_cpu_8996_mux {
u8  width;
struct notifier_block nb;
struct clk_hw   *pll;
+   struct clk_hw   *pll_div_2;
struct clk_regmap clkr;
 };
 
@@ -235,6 +239,13 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, 
u8 index)
struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw);
struct clk_hw *parent = cpuclk->pll;
 
+   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;
 
@@ -246,13 +257,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;
@@ -304,6 +321,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",
@@ -324,6 +342,7 @@ int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned 
long event,
.shift = 0,
.width = 2,
.pll = &perfcl_pll.clkr.hw,
+   .pll_div_2 = &perfcl_smux.clkr.hw,
.nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_pmux",
-- 
1.9.1



[PATCH v7 05/14] clk: qcom: cpu-8996: Add support to switch to alternate PLL

2018-05-15 Thread Ilia Lin
From: Rajendra Nayak 

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

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/qcom/clk-cpu-8996.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index beb97eb..390b369 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -61,6 +61,7 @@
  * detect voltage droops. We do not add support for ACD as yet.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -187,10 +188,14 @@ struct clk_cpu_8996_mux {
u32 reg;
u8  shift;
u8  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)
 {
@@ -236,6 +241,26 @@ 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,
@@ -279,6 +304,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 *[]){
@@ -298,6 +324,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 *[]){
@@ -356,6 +383,12 @@ struct clk_regmap *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);
+
return ret;
 }
 
-- 
1.9.1



[PATCH v7 03/14] clk: qcom: Add CPU clock driver for msm8996

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

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

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

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

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

ACD stands for Adaptive Clock Distribution and is used to
detect voltage droops. We do not add support for ACD as yet.

Signed-off-by: Rajendra Nayak 
Signed-off-by: Ilia Lin 
---
 drivers/clk/clk-fixed-factor.c   |   2 +-
 drivers/clk/qcom/Kconfig |   9 +
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-alpha-pll.h |   6 +
 drivers/clk/qcom/clk-cpu-8996.c  | 412 +++
 5 files changed, 429 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/qcom/clk-cpu-8996.c

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index a5d402d..8e39bda 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -94,7 +94,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device 
*dev,
init.num_parents = 1;
 
hw = &fix->hw;
-   ret = clk_hw_register(dev, hw);
+   ret = devm_clk_hw_register(dev, hw);
if (ret) {
kfree(fix);
hw = ERR_PTR(ret);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index e42e1af..866ce1f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -33,6 +33,15 @@ config QCOM_CLK_APCS_MSM8916
  Say Y if you want to support CPU frequency scaling on devices
  such as msm8916.
 
+config QCOM_CLK_APCC_MSM8996
+   tristate "MSM8996 CPU Clock Controller"
+   depends on COMMON_CLK_QCOM
+   select QCOM_KRYO_L2_ACCESSORS
+   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.
+
 config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 7c09ab1..a822fc8 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
 obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
+obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f981b48..9ce2a32 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -50,6 +50,12 @@ struct pll_vco {
u32 val;
 };
 
+#define VCO(a, b, c) { \
+   .val = a,\
+   .min_freq = b,\
+   .max_freq = c,\
+}
+
 /**
  * struct clk_alpha_pll - phase locked loop (PLL)
  * @offset: base address of registers
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/q

[PATCH v7 09/14] regulator: qcom_spmi: Add support for SAW

2018-05-15 Thread Ilia Lin
Add support for SAW controlled regulators.
The regulators defined as SAW controlled in the device tree
will be controlled through special CPU registers instead of direct
SPMI accesses.
This is required especially for CPU supply regulators to synchronize
with clock scaling and for Automatic Voltage Switching.

Signed-off-by: Ilia Lin 
---
 drivers/regulator/qcom_spmi-regulator.c | 133 +++-
 1 file changed, 130 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/qcom_spmi-regulator.c 
b/drivers/regulator/qcom_spmi-regulator.c
index 63c7a0c..9817f1a 100644
--- a/drivers/regulator/qcom_spmi-regulator.c
+++ b/drivers/regulator/qcom_spmi-regulator.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 /* Pin control enable input pins. */
 #define SPMI_REGULATOR_PIN_CTRL_ENABLE_NONE0x00
@@ -181,6 +183,23 @@ enum spmi_boost_byp_registers {
SPMI_BOOST_BYP_REG_CURRENT_LIMIT= 0x4b,
 };
 
+enum spmi_saw3_registers {
+   SAW3_SECURE = 0x00,
+   SAW3_ID = 0x04,
+   SAW3_SPM_STS= 0x0C,
+   SAW3_AVS_STS= 0x10,
+   SAW3_PMIC_STS   = 0x14,
+   SAW3_RST= 0x18,
+   SAW3_VCTL   = 0x1C,
+   SAW3_AVS_CTL= 0x20,
+   SAW3_AVS_LIMIT  = 0x24,
+   SAW3_AVS_DLY= 0x28,
+   SAW3_AVS_HYSTERESIS = 0x2C,
+   SAW3_SPM_STS2   = 0x38,
+   SAW3_SPM_PMIC_DATA_3= 0x4C,
+   SAW3_VERSION= 0xFD0,
+};
+
 /* Used for indexing into ctrl_reg.  These are offets from 0x40 */
 enum spmi_common_control_register_index {
SPMI_COMMON_IDX_VOLTAGE_RANGE   = 0,
@@ -1035,6 +1054,89 @@ static irqreturn_t spmi_regulator_vs_ocp_isr(int irq, 
void *data)
return IRQ_HANDLED;
 }
 
+#define SAW3_VCTL_DATA_MASK0xFF
+#define SAW3_VCTL_CLEAR_MASK   0x700FF
+#define SAW3_AVS_CTL_EN_MASK   0x1
+#define SAW3_AVS_CTL_TGGL_MASK 0x800
+#define SAW3_AVS_CTL_CLEAR_MASK0x7efc00
+
+static struct regmap *saw_regmap = NULL;
+
+static void spmi_saw_set_vdd(void *data)
+{
+   u32 vctl, data3, avs_ctl, pmic_sts;
+   bool avs_enabled = false;
+   unsigned long timeout;
+   u8 voltage_sel = *(u8 *)data;
+
+   regmap_read(saw_regmap, SAW3_AVS_CTL, &avs_ctl);
+   regmap_read(saw_regmap, SAW3_VCTL, &vctl);
+   regmap_read(saw_regmap, SAW3_SPM_PMIC_DATA_3, &data3);
+
+   /* select the band */
+   vctl &= ~SAW3_VCTL_CLEAR_MASK;
+   vctl |= (u32)voltage_sel;
+
+   data3 &= ~SAW3_VCTL_CLEAR_MASK;
+   data3 |= (u32)voltage_sel;
+
+   /* If AVS is enabled, switch it off during the voltage change */
+   avs_enabled = SAW3_AVS_CTL_EN_MASK & avs_ctl;
+   if (avs_enabled) {
+   avs_ctl &= ~SAW3_AVS_CTL_TGGL_MASK;
+   regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl);
+   }
+
+   regmap_write(saw_regmap, SAW3_RST, 1);
+   regmap_write(saw_regmap, SAW3_VCTL, vctl);
+   regmap_write(saw_regmap, SAW3_SPM_PMIC_DATA_3, data3);
+
+   timeout = jiffies + usecs_to_jiffies(100);
+   do {
+   regmap_read(saw_regmap, SAW3_PMIC_STS, &pmic_sts);
+   pmic_sts &= SAW3_VCTL_DATA_MASK;
+   if (pmic_sts == (u32)voltage_sel)
+   break;
+
+   cpu_relax();
+
+   } while (time_before(jiffies, timeout));
+
+   /* After successful voltage change, switch the AVS back on */
+   if (avs_enabled) {
+   pmic_sts &= 0x3f;
+   avs_ctl &= ~SAW3_AVS_CTL_CLEAR_MASK;
+   avs_ctl |= ((pmic_sts - 4) << 10);
+   avs_ctl |= (pmic_sts << 17);
+   avs_ctl |= SAW3_AVS_CTL_TGGL_MASK;
+   regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl);
+   }
+}
+
+static int
+spmi_regulator_saw_set_voltage(struct regulator_dev *rdev, unsigned selector)
+{
+   struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
+   int ret;
+   u8 range_sel, voltage_sel;
+
+   ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel);
+   if (ret)
+   return ret;
+
+   if (0 != range_sel) {
+   dev_dbg(&rdev->dev, "range_sel = %02X voltage_sel = %02X", \
+   range_sel, voltage_sel);
+   return -EINVAL;
+   }
+
+   /* Always do the SAW register writes on the first CPU */
+   return smp_call_function_single(0, spmi_saw_set_vdd, \
+   &voltage_sel, true);
+}
+
+static struct regulator_ops spmi_saw_ops = {};
+
 static struct regulator_ops spmi_smp

[PATCH v7 12/14] cpufreq: Add Kryo CPU scaling driver

2018-05-15 Thread Ilia Lin
In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU ferequencies subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin 
---
 drivers/cpufreq/Kconfig.arm  |  11 +++
 drivers/cpufreq/Makefile |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 150 +++
 4 files changed, 165 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..5c16f05 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,17 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+   bool "Qualcomm Technologies, Inc. Kryo based CPUFreq"
+   depends on QCOM_QFPROM
+   depends on QCOM_SMEM
+   select PM_OPP
+   help
+ This adds the CPUFreq driver for
+ Qualcomm Technologies, Inc. Kryo SoC based boards.
+
+ If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
bool
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
{ .compatible = "nvidia,tegra124", },
 
+   { .compatible = "qcom,apq8096", },
+   { .compatible = "qcom,msm8996", },
+
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 000..10d7236
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/* 
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MSM_ID_SMEM137
+#define SILVER_LEAD0
+#define GOLD_LEAD  2
+
+enum _msm_id {
+   MSM8996V3 = 0xF6ul,
+   APQ8096V3 = 0x123ul,
+   MSM8996SG = 0x131ul,
+   APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+   MSM8996_V3,
+   MSM8996_SG,
+   NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+   size_t len;
+   u32 *msm_id;
+   enum _msm8996_version version;
+
+   msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+   /* The first 4 bytes are format, next to them is the actual msm-id */
+   msm_id++;
+
+   switch ((enum _msm_id)*msm_id) {
+   case MSM8996V3:
+   case APQ8096V3:
+   version = MSM8996_V3;
+   break;
+   case MSM8996SG:
+   case APQ8096SG:
+   version = MSM8996_SG;
+   break;
+   default:
+   version = NUM_OF_MSM8996_VERSIONS;
+   }
+
+   return version;
+}
+
+static int __init qcom_cpufreq_kryo_driver_init(void)
+{
+   size_t len;
+   int ret;
+   u32 versions;
+   enum _msm8996_version msm8996_version;
+   u8 *speedbin;
+   struct device *cpu_dev;
+   struct device_node *np;
+   struct nvmem_cell *speedbin_nvm

  1   2   >