diff mbox series

[2/5] clocks: qcom: Add clock driver for SM6115 SoC

Message ID 20230324080418.3856409-3-bhupesh.sharma@linaro.org
State New
Headers show
Series New boards support: Qualcomm RB2 board | expand

Commit Message

Bhupesh Sharma March 24, 2023, 8:04 a.m. UTC
Currently the SM6115 clock driver initializes clocks for debug UART only.
Along with this import "qcom,gcc-sm6115.h" header from Linux mainline to
support DT bindings.

Signed-off-by: Bhupesh Sharma <bhupesh.sharma@linaro.org>
---
 arch/arm/mach-snapdragon/Makefile            |   1 +
 arch/arm/mach-snapdragon/clock-qrb4210-rb2.c | 110 +++++++++++++++++++
 arch/arm/mach-snapdragon/clock-snapdragon.c  |   1 +
 arch/arm/mach-snapdragon/clock-snapdragon.h  |   2 +
 4 files changed, 114 insertions(+)
 create mode 100644 arch/arm/mach-snapdragon/clock-qrb4210-rb2.c
diff mbox series

Patch

diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
index cbaaf23f6b..23aa1a974c 100644
--- a/arch/arm/mach-snapdragon/Makefile
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -19,3 +19,4 @@  obj-y += pinctrl-qcs404.o
 obj-y += pinctrl-sdm845.o
 obj-$(CONFIG_TARGET_QCS404EVB) += clock-qcs404.o
 obj-$(CONFIG_TARGET_QCS404EVB) += sysmap-qcs404.o
+obj-$(CONFIG_TARGET_QRB4210RB2) += clock-qrb4210-rb2.o
diff --git a/arch/arm/mach-snapdragon/clock-qrb4210-rb2.c b/arch/arm/mach-snapdragon/clock-qrb4210-rb2.c
new file mode 100644
index 0000000000..d67c69b320
--- /dev/null
+++ b/arch/arm/mach-snapdragon/clock-qrb4210-rb2.c
@@ -0,0 +1,110 @@ 
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Clock drivers for Qualcomm SM6115
+ *
+ * (C) Copyright 2023 Bhupesh Sharma <bhupesh.sharma@linaro.org>
+ *
+ * Based on Kernel driver, simplified
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include "clock-snapdragon.h"
+
+#include <dt-bindings/clock/qcom,gcc-sm6115.h>
+
+/* GPLL clock control registers */
+#define GPLL0_STATUS_ACTIVE	BIT(31)
+
+#define GCC_GLOBAL_EN_BASE		(0x84000)
+#define GCC_CLOBAL_PERIPHERALS_EN	BIT(5)
+
+#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE_1	(0x7900C)
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+struct freq_tbl {
+	uint freq;
+	uint src;
+	u8 pre_div;
+	u16 m;
+	u16 n;
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
+	F(7372800, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 384, 15625),
+	F(14745600, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 768, 15625),
+	F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
+	F(29491200, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 1536, 15625),
+	F(32000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 8, 75),
+	F(48000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 4, 25),
+	F(64000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 16, 75),
+	F(75000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 4, 0, 0),
+	F(80000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 4, 15),
+	F(96000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 8, 25),
+	F(100000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 3, 0, 0),
+	F(102400000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 128, 375),
+	F(112000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 28, 75),
+	F(117964800, CFG_CLK_SRC_GPLL0_OUT_AUX2, 1, 6144, 15625),
+	F(120000000, CFG_CLK_SRC_GPLL0_OUT_AUX2, 2.5, 0, 0),
+	F(128000000, CFG_CLK_SRC_GPLL6_OUT_MAIN, 3, 0, 0),
+	{ }
+};
+
+static const struct bcr_regs uart4_regs = {
+	.cfg_rcgr = UART4_APPS_CFG_RCGR,
+	.cmd_rcgr = UART4_APPS_CMD_RCGR,
+	.M = UART4_APPS_M,
+	.N = UART4_APPS_N,
+	.D = UART4_APPS_D,
+};
+
+const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate)
+{
+	if (!f)
+		return NULL;
+
+	if (!f->freq)
+		return f;
+
+	for (; f->freq; f++)
+		if (rate <= f->freq)
+			return f;
+
+	/* Default to our fastest rate */
+	return f - 1;
+}
+
+static int clk_init_uart(struct msm_clk_priv *priv, uint rate)
+{
+	const struct freq_tbl *freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate);
+
+	clk_rcg_set_rate_mnd(priv->base, &uart4_regs,
+						freq->pre_div, freq->m, freq->n, freq->src);
+
+	return 0;
+}
+
+ulong msm_set_rate(struct clk *clk, ulong rate)
+{
+	struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	case GCC_QUPV3_WRAP0_S4_CLK: /* UART4 */
+		return clk_init_uart(priv, rate);
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+int msm_enable(struct clk *clk)
+{
+	return 0;
+}
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.c b/arch/arm/mach-snapdragon/clock-snapdragon.c
index 0ac45dce9a..f306fd5b20 100644
--- a/arch/arm/mach-snapdragon/clock-snapdragon.c
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.c
@@ -167,6 +167,7 @@  static const struct udevice_id msm_clk_ids[] = {
 	{ .compatible = "qcom,gcc-msm8996" },
 	{ .compatible = "qcom,gcc-apq8096" },
 	{ .compatible = "qcom,gcc-sdm845" },
+	{ .compatible = "qcom,gcc-sm6115" },
 	{ .compatible = "qcom,gcc-qcs404" },
 	{ }
 };
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.h b/arch/arm/mach-snapdragon/clock-snapdragon.h
index c90bbefa58..9e520dbbce 100644
--- a/arch/arm/mach-snapdragon/clock-snapdragon.h
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.h
@@ -10,6 +10,8 @@ 
 #define CFG_CLK_SRC_CXO   (0 << 8)
 #define CFG_CLK_SRC_GPLL0 (1 << 8)
 #define CFG_CLK_SRC_GPLL0_EVEN (6 << 8)
+#define CFG_CLK_SRC_GPLL0_OUT_AUX2 (2 << 8)
+#define CFG_CLK_SRC_GPLL6_OUT_MAIN (4 << 8)
 #define CFG_CLK_SRC_MASK  (7 << 8)
 
 struct pll_vote_clk {