diff mbox series

[RFC,v1,04/14] clk: thead: Add clock driver for TH1520 Video Output subsystem

Message ID 20241203134137.2114847-5-m.wilczynski@samsung.com
State New
Headers show
Series Enable drm/imagination BXM-4-64 Support for LicheePi 4A | expand

Commit Message

Michal Wilczynski Dec. 3, 2024, 1:41 p.m. UTC
The Video Output (VO) module on the T-Head TH1520 SoC has its own set of
clocks that need proper management. This commit introduces the
clk-th1520-vo driver to support the VO subsystem clocks.

Currently, only the clock gates are implemented, as they are the primary
relevant clocks for the VO subsystem at this stage.

Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
 drivers/clk/thead/Kconfig                    |  11 ++
 drivers/clk/thead/Makefile                   |   1 +
 drivers/clk/thead/clk-th1520-vo.c            | 168 +++++++++++++++++++
 include/dt-bindings/clock/thead,th1520-clk.h |  34 ++++
 4 files changed, 214 insertions(+)
 create mode 100644 drivers/clk/thead/clk-th1520-vo.c
diff mbox series

Patch

diff --git a/drivers/clk/thead/Kconfig b/drivers/clk/thead/Kconfig
index 95e0d9eb965e..937927a1a4b8 100644
--- a/drivers/clk/thead/Kconfig
+++ b/drivers/clk/thead/Kconfig
@@ -11,3 +11,14 @@  config CLK_THEAD_TH1520_AP
 	  on the T-HEAD TH1520 SoC. This includes configuration of
 	  both CPU PLLs, both DPU PLLs as well as the GMAC, VIDEO,
 	  and TEE PLLs.
+
+config CLK_THEAD_TH1520_VO
+	bool "T-HEAD TH1520 VO clock support"
+	depends on ARCH_THEAD || COMPILE_TEST
+	depends on 64BIT
+	default ARCH_THEAD
+	select REGMAP_MMIO
+	help
+	  Say yes here to support the VO sub system clock controller
+	  on the T-HEAD TH1520 SoC. This includes clock gates for the
+	  Video Output components like HDMI, MIPI, DPU and GPU.
diff --git a/drivers/clk/thead/Makefile b/drivers/clk/thead/Makefile
index d7cf88390b69..9afaee27b0b9 100644
--- a/drivers/clk/thead/Makefile
+++ b/drivers/clk/thead/Makefile
@@ -1,2 +1,3 @@ 
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_CLK_THEAD_TH1520_AP) += clk-th1520.o clk-th1520-ap.o
+obj-$(CONFIG_CLK_THEAD_TH1520_VO) += clk-th1520.o clk-th1520-vo.o
diff --git a/drivers/clk/thead/clk-th1520-vo.c b/drivers/clk/thead/clk-th1520-vo.c
new file mode 100644
index 000000000000..3c6d246ab53a
--- /dev/null
+++ b/drivers/clk/thead/clk-th1520-vo.c
@@ -0,0 +1,168 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ */
+
+#include <linux/mfd/syscon.h>
+#include "clk-th1520.h"
+
+#define NR_CLKS (CLK_HDMI_PIXCLK + 1)
+
+static const struct clk_parent_data video_pll_pd[] = {
+	/* TODO: provide a proper parent here */
+	NULL,
+};
+
+static CCU_GATE_REGMAP(CLK_AXI4_VO_ACLK, axi4_vo_aclk, "axi4-vo-aclk",
+		       video_pll_pd, 0x50, BIT(0), 0);
+static CCU_GATE_REGMAP(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_pd,
+		       0x50, BIT(3), 0);
+static CCU_GATE_REGMAP(CLK_GPU_CFG_ACLK, gpu_cfg_aclk, "gpu-cfg-aclk",
+		       video_pll_pd, 0x50, BIT(4), 0);
+static CCU_GATE_REGMAP(CLK_DPU_PIXELCLK0, dpu0_pixelclk, "dpu0-pixelclk",
+		       video_pll_pd, 0x50, BIT(5), 0);
+static CCU_GATE_REGMAP(CLK_DPU_PIXELCLK1, dpu1_pixelclk, "dpu1-pixelclk",
+		       video_pll_pd, 0x50, BIT(6), 0);
+static CCU_GATE_REGMAP(CLK_DPU_HCLK, dpu_hclk, "dpu-hclk", video_pll_pd, 0x50,
+		       BIT(7), 0);
+static CCU_GATE_REGMAP(CLK_DPU_ACLK, dpu_aclk, "dpu-aclk", video_pll_pd, 0x50,
+		       BIT(8), 0);
+static CCU_GATE_REGMAP(CLK_DPU_CCLK, dpu_cclk, "dpu-cclk", video_pll_pd, 0x50,
+		       BIT(9), 0);
+static CCU_GATE_REGMAP(CLK_HDMI_SFR, hdmi_sfr_clk, "hdmi-sfr-clk", video_pll_pd,
+		       0x50, BIT(10), 0);
+static CCU_GATE_REGMAP(CLK_HDMI_PCLK, hdmi_pclk, "hdmi-pclk", video_pll_pd,
+		       0x50, BIT(11), 0);
+static CCU_GATE_REGMAP(CLK_HDMI_CEC, hdmi_cec_clk, "hdmi-cec-clk", video_pll_pd,
+		       0x50, BIT(12), 0);
+static CCU_GATE_REGMAP(CLK_MIPI_DSI0_PCLK, mipi_dsi0_pclk, "mipi-dsi0-pclk",
+		       video_pll_pd, 0x50, BIT(13), 0);
+static CCU_GATE_REGMAP(CLK_MIPI_DSI1_PCLK, mipi_dsi1_pclk, "mipi-dsi1-pclk",
+		       video_pll_pd, 0x50, BIT(14), 0);
+static CCU_GATE_REGMAP(CLK_MIPI_DSI0_CFG, mipi_dsi0_cfg_clk,
+		       "mipi-dsi0-cfg-clk", video_pll_pd, 0x50, BIT(15), 0);
+static CCU_GATE_REGMAP(CLK_MIPI_DSI1_CFG, mipi_dsi1_cfg_clk,
+		       "mipi-dsi1-cfg-clk", video_pll_pd, 0x50, BIT(16), 0);
+static CCU_GATE_REGMAP(CLK_MIPI_DSI0_REFCLK, mipi_dsi0_refclk,
+		       "mipi-dsi0-refclk", video_pll_pd, 0x50, BIT(17), 0);
+static CCU_GATE_REGMAP(CLK_MIPI_DSI1_REFCLK, mipi_dsi1_refclk,
+		       "mipi-dsi1-refclk", video_pll_pd, 0x50, BIT(18), 0);
+static CCU_GATE_REGMAP(CLK_HDMI_I2S, hdmi_i2c_clk, "hdmi-i2c-clk", video_pll_pd,
+		       0x50, BIT(19), 0);
+static CCU_GATE_REGMAP(CLK_X2H_DPU1_ACLK, x2h_dpu1_aclk, "x2h-dpu1-aclk",
+		       video_pll_pd, 0x50, BIT(20), 0);
+static CCU_GATE_REGMAP(CLK_X2H_DPU_ACLK, x2h_dpu_aclk, "x2h-dpu-aclk",
+		       video_pll_pd, 0x50, BIT(21), 0);
+static CCU_GATE_REGMAP(CLK_AXI4_VO_PCLK, axi4_vo_pclk, "axi4-vo-pclk",
+		       video_pll_pd, 0x50, BIT(22), 0);
+static CCU_GATE_REGMAP(CLK_IOPMP_VOSYS_DPU_PCLK, iopmp_vosys_dpu_pclk,
+		       "iopmp-vosys-dpu-pclk", video_pll_pd, 0x50, BIT(23), 0);
+static CCU_GATE_REGMAP(CLK_IOPMP_VOSYS_DPU1_PCLK, iopmp_vosys_dpu1_pclk,
+		       "iopmp-vosys-dpu1-pclk", video_pll_pd, 0x50, BIT(24), 0);
+static CCU_GATE_REGMAP(CLK_IOPMP_VOSYS_GPU_PCLK, iopmp_vosys_gpu_pclk,
+		       "iopmp-vosys-gpu-pclk", video_pll_pd, 0x50, BIT(25), 0);
+static CCU_GATE_REGMAP(CLK_IOPMP_DPU1_ACLK, iopmp_dpu1_aclk, "iopmp-dpu1-aclk",
+		       video_pll_pd, 0x50, BIT(27), 0);
+static CCU_GATE_REGMAP(CLK_IOPMP_DPU_ACLK, iopmp_dpu_aclk, "iopmp-dpu-aclk",
+		       video_pll_pd, 0x50, BIT(28), 0);
+static CCU_GATE_REGMAP(CLK_IOPMP_GPU_ACLK, iopmp_gpu_aclk, "iopmp-gpu-aclk",
+		       video_pll_pd, 0x50, BIT(29), 0);
+static CCU_GATE_REGMAP(CLK_MIPIDSI0_PIXCLK, mipi_dsi0_pixclk,
+		       "mipi-dsi0-pixclk", video_pll_pd, 0x50, BIT(30), 0);
+static CCU_GATE_REGMAP(CLK_MIPIDSI1_PIXCLK, mipi_dsi1_pixclk,
+		       "mipi-dsi1-pixclk", video_pll_pd, 0x50, BIT(31), 0);
+static CCU_GATE_REGMAP(CLK_HDMI_PIXCLK, hdmi_pixclk, "hdmi-pixclk",
+		       video_pll_pd, 0x54, BIT(0), 0);
+
+static struct ccu_common *th1520_vo_gate_clks[] = {
+	&axi4_vo_aclk.common,
+	&gpu_core_clk.common,
+	&gpu_cfg_aclk.common,
+	&dpu0_pixelclk.common,
+	&dpu1_pixelclk.common,
+	&dpu_hclk.common,
+	&dpu_aclk.common,
+	&dpu_cclk.common,
+	&hdmi_sfr_clk.common,
+	&hdmi_pclk.common,
+	&hdmi_cec_clk.common,
+	&mipi_dsi0_pclk.common,
+	&mipi_dsi1_pclk.common,
+	&mipi_dsi0_cfg_clk.common,
+	&mipi_dsi1_cfg_clk.common,
+	&mipi_dsi0_refclk.common,
+	&mipi_dsi1_refclk.common,
+	&hdmi_i2c_clk.common,
+	&x2h_dpu1_aclk.common,
+	&x2h_dpu_aclk.common,
+	&axi4_vo_pclk.common,
+	&iopmp_vosys_dpu_pclk.common,
+	&iopmp_vosys_dpu1_pclk.common,
+	&iopmp_vosys_gpu_pclk.common,
+	&iopmp_dpu1_aclk.common,
+	&iopmp_dpu_aclk.common,
+	&iopmp_gpu_aclk.common,
+	&mipi_dsi0_pixclk.common,
+	&mipi_dsi1_pixclk.common,
+	&hdmi_pixclk.common
+};
+
+static int th1520_clk_vo_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct clk_hw_onecell_data *priv;
+	struct regmap *map;
+	struct clk_hw *hw;
+	int ret, i;
+
+	priv = devm_kzalloc(dev, struct_size(priv, hws, NR_CLKS), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->num = NR_CLKS;
+
+	map = syscon_regmap_lookup_by_phandle(np, "thead,vosys-regmap");
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	for (i = 0; i < ARRAY_SIZE(th1520_vo_gate_clks); i++) {
+		struct ccu_gate *cg = hw_to_ccu_gate(&th1520_vo_gate_clks[i]->hw);
+
+		th1520_vo_gate_clks[i]->map = map;
+
+		ret = devm_clk_hw_register(dev, &th1520_vo_gate_clks[i]->hw);
+		if (ret)
+			return ret;
+
+		priv->hws[cg->common.clkid] = hw;
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id th1520_clk_vo_match[] = {
+	{
+		.compatible = "thead,th1520-clk-vo",
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, th1520_clk_vo_match);
+
+static struct platform_driver th1520_clk_vo_driver = {
+	.probe		= th1520_clk_vo_probe,
+	.driver		= {
+		.name	= "th1520-clk-vo",
+		.of_match_table = th1520_clk_vo_match,
+	},
+};
+module_platform_driver(th1520_clk_vo_driver);
+
+MODULE_DESCRIPTION("T-HEAD TH1520 VO Clock driver");
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/dt-bindings/clock/thead,th1520-clk.h b/include/dt-bindings/clock/thead,th1520-clk.h
index a199784b3512..86a7cf2c9acf 100644
--- a/include/dt-bindings/clock/thead,th1520-clk.h
+++ b/include/dt-bindings/clock/thead,th1520-clk.h
@@ -7,6 +7,7 @@ 
 #ifndef _DT_BINDINGS_CLK_TH1520_H_
 #define _DT_BINDINGS_CLK_TH1520_H_
 
+/* AP clocks */
 #define CLK_CPU_PLL0		0
 #define CLK_CPU_PLL1		1
 #define CLK_GMAC_PLL		2
@@ -93,4 +94,37 @@ 
 #define CLK_SRAM3		83
 #define CLK_PLL_GMAC_100M	84
 #define CLK_UART_SCLK		85
+
+/* VO clocks */
+#define CLK_AXI4_VO_ACLK		0
+#define CLK_GPU_CORE			1
+#define CLK_GPU_CFG_ACLK		2
+#define CLK_DPU_PIXELCLK0		3
+#define CLK_DPU_PIXELCLK1		4
+#define CLK_DPU_HCLK			5
+#define CLK_DPU_ACLK			6
+#define CLK_DPU_CCLK			7
+#define CLK_HDMI_SFR			8
+#define CLK_HDMI_PCLK			9
+#define CLK_HDMI_CEC			10
+#define CLK_MIPI_DSI0_PCLK		11
+#define CLK_MIPI_DSI1_PCLK		12
+#define CLK_MIPI_DSI0_CFG		13
+#define CLK_MIPI_DSI1_CFG		14
+#define CLK_MIPI_DSI0_REFCLK		15
+#define CLK_MIPI_DSI1_REFCLK		16
+#define CLK_HDMI_I2S			17
+#define CLK_X2H_DPU1_ACLK		18
+#define CLK_X2H_DPU_ACLK		19
+#define CLK_AXI4_VO_PCLK		20
+#define CLK_IOPMP_VOSYS_DPU_PCLK	21
+#define CLK_IOPMP_VOSYS_DPU1_PCLK	22
+#define CLK_IOPMP_VOSYS_GPU_PCLK	23
+#define CLK_IOPMP_DPU1_ACLK		24
+#define CLK_IOPMP_DPU_ACLK		25
+#define CLK_IOPMP_GPU_ACLK		26
+#define CLK_MIPIDSI0_PIXCLK		27
+#define CLK_MIPIDSI1_PIXCLK		28
+#define CLK_HDMI_PIXCLK			29
+
 #endif