All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] clk: qcom: msm8996-cpu: Add CBF support
@ 2021-05-28 19:25 Konrad Dybcio
  2021-05-28 19:25 ` [PATCH 2/2] arm64: dts: qcom: msm8996: Add support for the CBF clock Konrad Dybcio
  0 siblings, 1 reply; 2+ messages in thread
From: Konrad Dybcio @ 2021-05-28 19:25 UTC (permalink / raw)
  To: ~postmarketos/upstreaming
  Cc: martin.botka, angelogioacchino.delregno, marijn.suijten,
	jamipkettunen, Konrad Dybcio, Andy Gross, Bjorn Andersson,
	Michael Turquette, Stephen Boyd, linux-arm-msm, linux-clk,
	linux-kernel

Add the required code to support the CBF clock, which is responsible for
core cluster interconnect frequency on msm8996.

Somewhat based on AngeloGioacchino del Regno's work at:
https://github.com/sonyxperiadev/kernel/blob/aosp/LE.UM.2.3.2.r1.4/drivers/clk/qcom/clk-cpu-8996.c

This fixes the issue with booting with all 4 cores enabled.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
---
 drivers/clk/qcom/clk-cpu-8996.c | 162 +++++++++++++++++++++++++++++++-
 1 file changed, 159 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 4a4fde8dd12d..8afc271f92d0 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -68,10 +68,19 @@ enum _pmux_input {
 	NUM_OF_PMUX_INPUTS
 };
 
+enum {
+	CBF_PLL_INDEX = 1,
+	CBF_DIV_2_INDEX,
+	CBF_SAFE_INDEX
+};
+
 #define DIV_2_THRESHOLD		600000000
 #define PWRCL_REG_OFFSET 0x0
 #define PERFCL_REG_OFFSET 0x80000
 #define MUX_OFFSET	0x40
+#define CBF_REG_OFFSET	0x0
+#define CBF_PLL_OFFSET	0xf000
+#define CBF_MUX_OFFSET 0x18
 #define ALT_PLL_OFFSET	0x100
 #define SSSCTL_OFFSET 0x160
 
@@ -98,6 +107,17 @@ static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = {
 	[PLL_OFF_STATUS] = 0x28,
 };
 
+static const u8 cbf_pll_regs[PLL_OFF_MAX_REGS] = {
+	[PLL_OFF_L_VAL] = 0x08,
+	[PLL_OFF_ALPHA_VAL] = 0x10,
+	[PLL_OFF_USER_CTL] = 0x18,
+	[PLL_OFF_CONFIG_CTL] = 0x20,
+	[PLL_OFF_CONFIG_CTL_U] = 0x24,
+	[PLL_OFF_TEST_CTL] = 0x30,
+	[PLL_OFF_TEST_CTL_U] = 0x34,
+	[PLL_OFF_STATUS] = 0x28,
+};
+
 /* PLLs */
 
 static const struct alpha_pll_config hfpll_config = {
@@ -111,6 +131,17 @@ static const struct alpha_pll_config hfpll_config = {
 	.early_output_mask = BIT(3),
 };
 
+static const struct alpha_pll_config cbfpll_config = {
+	.l = 72,
+	.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),
+};
+
 static struct clk_alpha_pll perfcl_pll = {
 	.offset = PERFCL_REG_OFFSET,
 	.regs = prim_pll_regs,
@@ -135,6 +166,18 @@ static struct clk_alpha_pll pwrcl_pll = {
 	},
 };
 
+static struct clk_alpha_pll cbf_pll = {
+	.offset = CBF_PLL_OFFSET,
+	.regs = cbf_pll_regs,
+	.flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "cbf_pll",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_huayra_ops,
+	},
+};
+
 static const struct pll_vco alt_pll_vco_modes[] = {
 	VCO(3,  250000000,  500000000),
 	VCO(2,  500000000,  750000000),
@@ -194,6 +237,9 @@ struct clk_cpu_8996_mux {
 static int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 			       void *data);
 
+static int cbf_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
+			       void *data);
+
 #define to_clk_cpu_8996_mux_nb(_nb) \
 	container_of(_nb, struct clk_cpu_8996_mux, nb)
 
@@ -329,6 +375,35 @@ static struct clk_cpu_8996_mux perfcl_pmux = {
 	},
 };
 
+static struct clk_cpu_8996_mux cbf_mux = {
+	.reg = CBF_REG_OFFSET + CBF_MUX_OFFSET,
+	.shift = 0,
+	.width = 2,
+	.pll = &cbf_pll.clkr.hw,
+	.nb.notifier_call = cbf_clk_notifier_cb,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "cbf_mux",
+		.parent_names = (const char *[]){
+			"xo",
+			"cbf_pll",
+			"cbf_pll_main",
+		},
+		.num_parents = 3,
+		.ops = &clk_cpu_8996_mux_ops,
+		/* CPU clock is critical and should never be gated */
+		.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+	},
+};
+
+static const struct regmap_config cbf_msm8996_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= 0x10000,
+	.fast_io		= true,
+	.val_format_endian	= REGMAP_ENDIAN_LITTLE,
+};
+
 static const struct regmap_config cpu_msm8996_regmap_config = {
 	.reg_bits		= 32,
 	.reg_stride		= 4,
@@ -397,6 +472,35 @@ static int qcom_cpu_clk_msm8996_register_clks(struct device *dev,
 	return ret;
 }
 
+static struct clk_regmap *cbf_msm8996_clks[] = {
+	&cbf_pll.clkr,
+	&cbf_mux.clkr,
+};
+
+static int qcom_cbf_clk_msm8996_register_clks(struct device *dev,
+					      struct regmap *regmap)
+{
+	int ret;
+
+	cbf_mux.pll_div_2 = clk_hw_register_fixed_factor(dev, "cbf_pll_main",
+						      "cbf_pll", CLK_SET_RATE_PARENT,
+						      1, 2);
+	if (IS_ERR(cbf_mux.pll_div_2)) {
+		dev_err(dev, "Failed to initialize cbf_pll_main\n");
+		return PTR_ERR(cbf_mux.pll_div_2);
+	}
+
+	ret = devm_clk_register_regmap(dev, cbf_msm8996_clks[0]);
+	ret = devm_clk_register_regmap(dev, cbf_msm8996_clks[1]);
+
+	clk_alpha_pll_configure(&cbf_pll, regmap, &cbfpll_config);
+	clk_set_rate(cbf_pll.clkr.hw.clk, 614400000);
+	clk_prepare_enable(cbf_pll.clkr.hw.clk);
+	clk_notifier_register(cbf_mux.clkr.hw.clk, &cbf_mux.nb);
+
+	return ret;
+}
+
 static int qcom_cpu_clk_msm8996_unregister_clks(void)
 {
 	int ret = 0;
@@ -409,8 +513,13 @@ static int qcom_cpu_clk_msm8996_unregister_clks(void)
 	if (ret)
 		return ret;
 
+	ret = clk_notifier_unregister(cbf_mux.clkr.hw.clk, &cbf_mux.nb);
+	if (ret)
+		return ret;
+
 	clk_hw_unregister(perfcl_smux.pll);
 	clk_hw_unregister(pwrcl_smux.pll);
+	clk_hw_unregister(cbf_mux.pll);
 
 	return 0;
 }
@@ -481,14 +590,48 @@ static int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
 	return notifier_from_errno(ret);
 };
 
+static int cbf_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
+			       void *data)
+{
+	struct clk_cpu_8996_mux *cbfclk = to_clk_cpu_8996_mux_nb(nb);
+	struct clk_notifier_data *cnd = data;
+	struct clk_hw *parent;
+	int ret;
+
+	switch (event) {
+	case PRE_RATE_CHANGE:
+		parent = clk_hw_get_parent_by_index(&cbfclk->clkr.hw, CBF_DIV_2_INDEX);
+		ret = clk_cpu_8996_mux_set_parent(&cbfclk->clkr.hw, CBF_DIV_2_INDEX);
+
+		if (cnd->old_rate > DIV_2_THRESHOLD && cnd->new_rate < DIV_2_THRESHOLD)
+			ret = clk_set_rate(parent->clk, cnd->old_rate / 2);
+		break;
+	case POST_RATE_CHANGE:
+		if (cnd->new_rate < DIV_2_THRESHOLD)
+			ret = clk_cpu_8996_mux_set_parent(&cbfclk->clkr.hw, CBF_DIV_2_INDEX);
+		else {
+			parent = clk_hw_get_parent_by_index(&cbfclk->clkr.hw, CBF_PLL_INDEX);
+			ret = clk_set_rate(parent->clk, cnd->new_rate);
+			ret = clk_cpu_8996_mux_set_parent(&cbfclk->clkr.hw, CBF_PLL_INDEX);
+		}
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	return notifier_from_errno(ret);
+};
+
 static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 {
-	struct regmap *regmap;
+	struct regmap *regmap, *regmap_cbf;
 	struct clk_hw_onecell_data *data;
 	struct device *dev = &pdev->dev;
+	static void __iomem *cbf_base;
 	int ret;
 
-	data = devm_kzalloc(dev, struct_size(data, hws, 2), GFP_KERNEL);
+	data = devm_kzalloc(dev, struct_size(data, hws, 3), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -506,9 +649,22 @@ static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev)
 
 	qcom_cpu_clk_msm8996_acd_init(base);
 
+	cbf_base = devm_platform_ioremap_resource(pdev, 1);
+	if (IS_ERR(cbf_base))
+		return PTR_ERR(cbf_base);
+
+	regmap_cbf = devm_regmap_init_mmio(dev, cbf_base, &cbf_msm8996_regmap_config);
+	if (IS_ERR(regmap_cbf))
+		return PTR_ERR(regmap_cbf);
+
+	ret = qcom_cbf_clk_msm8996_register_clks(dev, regmap_cbf);
+	if (ret)
+		return ret;
+
 	data->hws[0] = &pwrcl_pmux.clkr.hw;
 	data->hws[1] = &perfcl_pmux.clkr.hw;
-	data->num = 2;
+	data->hws[2] = &cbf_mux.clkr.hw;
+	data->num = 3;
 
 	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
 }
-- 
2.31.1


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

* [PATCH 2/2] arm64: dts: qcom: msm8996: Add support for the CBF clock
  2021-05-28 19:25 [PATCH 1/2] clk: qcom: msm8996-cpu: Add CBF support Konrad Dybcio
@ 2021-05-28 19:25 ` Konrad Dybcio
  0 siblings, 0 replies; 2+ messages in thread
From: Konrad Dybcio @ 2021-05-28 19:25 UTC (permalink / raw)
  To: ~postmarketos/upstreaming
  Cc: martin.botka, angelogioacchino.delregno, marijn.suijten,
	jamipkettunen, Konrad Dybcio, Andy Gross, Bjorn Andersson,
	Michael Turquette, Stephen Boyd, linux-arm-msm, linux-clk,
	linux-kernel, Rob Herring, devicetree

Add the CBF PLL register to the kryocc node and assign a frequency
to the clock.

This makes sure the core cluster interconnect is running at a decent
speed, so that it's no longer a pain to use the device with all cores
enabled.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 10e6fecc9e13..99dc4068980d 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -2533,7 +2533,10 @@ apss_merge_funnel_out: endpoint {
 
 		kryocc: clock-controller@6400000 {
 			compatible = "qcom,msm8996-apcc";
-			reg = <0x06400000 0x90000>;
+			reg = <0x06400000 0x90000>, <0x09a11000 0x10000>;
+
+			assigned-clocks = <&kryocc 2>;
+			assigned-clock-rates = <1382400000>;
 
 			clock-names = "xo";
 			clocks = <&xo_board>;
-- 
2.31.1


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

end of thread, other threads:[~2021-05-28 19:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-28 19:25 [PATCH 1/2] clk: qcom: msm8996-cpu: Add CBF support Konrad Dybcio
2021-05-28 19:25 ` [PATCH 2/2] arm64: dts: qcom: msm8996: Add support for the CBF clock Konrad Dybcio

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