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@xxxxxxxxxxx> --- 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 --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@xxxxxxxxxxx> + */ + +#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@xxxxxxxxxxx>"); +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 -- 2.34.1