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

2018-10-16 Thread Stephen Boyd
Quoting ilia@gmail.com (2018-06-14 14:53:55)
> @@ -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);
> +

Why are we doing this?

> @@ -393,6 +404,10 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
> struct regmap *regmap)
> clk_alpha_pll_configure(_alt_pll, regmap, _config);
> clk_alpha_pll_configure(_alt_pll, regmap, _config);
>  
> +   /* Enable alt PLLs */
> +   clk_prepare_enable(pwrcl_alt_pll.clkr.hw.clk);
> +   clk_prepare_enable(perfcl_alt_pll.clkr.hw.clk);

Are the alt PLLs CLK_IS_CRITICAL?

> +
> ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, _pmux.nb);
> if (ret)
> return ret;
> @@ -402,10 +417,48 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
> struct regmap *regmap)
> return ret;
>  }
>  
> +#define CPU_AFINITY_MASK 0xFFF
> +#define PWRCL_CPU_REG_MASK 0x3
> +#define PERFCL_CPU_REG_MASK 0x103
> +
> +#define L2ACDCR_REG 0x580ULL
> +#define L2ACDTD_REG 0x581ULL
> +#define L2ACDDVMRC_REG 0x584ULL
> +#define L2ACDSSCR_REG 0x589ULL
> +
> +static DEFINE_SPINLOCK(acd_lock);
> +
> +static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base)
> +{
> +   u64 hwid;
> +   unsigned long flags;
> +
> +   spin_lock_irqsave(_lock, flags);
> +
> +   hwid = read_cpuid_mpidr() & CPU_AFINITY_MASK;
> +
> +   kryo_l2_set_indirect_reg(L2ACDTD_REG, 0x6A11);
> +   kryo_l2_set_indirect_reg(L2ACDDVMRC_REG, 0x000E0F0F);
> +   kryo_l2_set_indirect_reg(L2ACDSSCR_REG, 0x0601);
> +
> +   if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
> +   writel(0xF, base + PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> +   wmb();
> +   kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002C5FFD);
> +   }
> +
> +   if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) {
> +   kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002C5FFD);
> +   writel(0xF, base + PERFCL_REG_OFFSET + SSSCTL_OFFSET);
> +   wmb();

Please add comments to the barriers here so we know what they're doing.
I guess the first one is ordering writel with the indirect register
access, but the other one I don't know what it's doing.

> +   }
> +
> +   spin_unlock_irqrestore(_lock, flags);
> +}
> +
>  static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
>  {
> int ret;
> -   void __iomem *base;

Ok but still, why?

> struct resource *res;
> struct regmap *regmap;
> struct clk_hw_onecell_data *data;
> @@ -429,6 +482,8 @@ static int qcom_cpu_clk_msm8996_driver_probe(struct 
> platform_device *pdev)
> if (ret)
> return ret;
>  
> +   qcom_cpu_clk_msm8996_acd_init(base);
> +
> data->hws[0] = _pmux.clkr.hw;
> data->hws[1] = _pmux.clkr.hw;
> data->num = 2;
> -- 
> 2.11.0
> 


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

2018-10-16 Thread Stephen Boyd
Quoting ilia@gmail.com (2018-06-14 14:53:55)
> @@ -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);
> +

Why are we doing this?

> @@ -393,6 +404,10 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
> struct regmap *regmap)
> clk_alpha_pll_configure(_alt_pll, regmap, _config);
> clk_alpha_pll_configure(_alt_pll, regmap, _config);
>  
> +   /* Enable alt PLLs */
> +   clk_prepare_enable(pwrcl_alt_pll.clkr.hw.clk);
> +   clk_prepare_enable(perfcl_alt_pll.clkr.hw.clk);

Are the alt PLLs CLK_IS_CRITICAL?

> +
> ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, _pmux.nb);
> if (ret)
> return ret;
> @@ -402,10 +417,48 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
> struct regmap *regmap)
> return ret;
>  }
>  
> +#define CPU_AFINITY_MASK 0xFFF
> +#define PWRCL_CPU_REG_MASK 0x3
> +#define PERFCL_CPU_REG_MASK 0x103
> +
> +#define L2ACDCR_REG 0x580ULL
> +#define L2ACDTD_REG 0x581ULL
> +#define L2ACDDVMRC_REG 0x584ULL
> +#define L2ACDSSCR_REG 0x589ULL
> +
> +static DEFINE_SPINLOCK(acd_lock);
> +
> +static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base)
> +{
> +   u64 hwid;
> +   unsigned long flags;
> +
> +   spin_lock_irqsave(_lock, flags);
> +
> +   hwid = read_cpuid_mpidr() & CPU_AFINITY_MASK;
> +
> +   kryo_l2_set_indirect_reg(L2ACDTD_REG, 0x6A11);
> +   kryo_l2_set_indirect_reg(L2ACDDVMRC_REG, 0x000E0F0F);
> +   kryo_l2_set_indirect_reg(L2ACDSSCR_REG, 0x0601);
> +
> +   if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) {
> +   writel(0xF, base + PWRCL_REG_OFFSET + SSSCTL_OFFSET);
> +   wmb();
> +   kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002C5FFD);
> +   }
> +
> +   if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) {
> +   kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002C5FFD);
> +   writel(0xF, base + PERFCL_REG_OFFSET + SSSCTL_OFFSET);
> +   wmb();

Please add comments to the barriers here so we know what they're doing.
I guess the first one is ordering writel with the indirect register
access, but the other one I don't know what it's doing.

> +   }
> +
> +   spin_unlock_irqrestore(_lock, flags);
> +}
> +
>  static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
>  {
> int ret;
> -   void __iomem *base;

Ok but still, why?

> struct resource *res;
> struct regmap *regmap;
> struct clk_hw_onecell_data *data;
> @@ -429,6 +482,8 @@ static int qcom_cpu_clk_msm8996_driver_probe(struct 
> platform_device *pdev)
> if (ret)
> return ret;
>  
> +   qcom_cpu_clk_msm8996_acd_init(base);
> +
> data->hws[0] = _pmux.clkr.hw;
> data->hws[1] = _pmux.clkr.hw;
> data->num = 2;
> -- 
> 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(>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(>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 = _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 = _pll.clkr.hw,
@@ -393,6 +404,10 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
struct regmap *regmap)
clk_alpha_pll_configure(_alt_pll, regmap, _config);
clk_alpha_pll_configure(_alt_pll, regmap, _config);
 
+   /* Enable alt PLLs */
+   

[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(>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(>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 = _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 = _pll.clkr.hw,
@@ -393,6 +404,10 @@ qcom_cpu_clk_msm8996_register_clks(struct device *dev, 
struct regmap *regmap)
clk_alpha_pll_configure(_alt_pll, regmap, _config);
clk_alpha_pll_configure(_alt_pll, regmap, _config);
 
+   /* Enable alt PLLs */
+