Re: [PATCH v13 8/8] clk: qcom: Add ACD path to CPU clock driver for msm8996
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
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
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
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 */ +