Merge tag 'thead-clk-for-v6.16' of https://github.com/pdp7/linux into clk-thead

Pull T-HEAD clk driver updates from Drew Fustini:

 - Clk driver for Video Output (VO) subsystem in the T-HEAD TH1520 SoC

* tag 'thead-clk-for-v6.16' of https://github.com/pdp7/linux:
  clk: thead: Add clock support for VO subsystem in T-HEAD TH1520 SoC
  dt-bindings: clock: thead: Add TH1520 VO clock controller
This commit is contained in:
Stephen Boyd
2025-05-22 15:21:43 -07:00
3 changed files with 216 additions and 31 deletions
@@ -8,7 +8,8 @@ title: T-HEAD TH1520 AP sub-system clock controller
description: |
The T-HEAD TH1520 AP sub-system clock controller configures the
CPU, DPU, GMAC and TEE PLLs.
CPU, DPU, GMAC and TEE PLLs. Additionally the VO subsystem configures
the clock gates for the HDMI, MIPI and the GPU.
SoC reference manual
https://openbeagle.org/beaglev-ahead/beaglev-ahead/-/blob/main/docs/TH1520%20System%20User%20Manual.pdf
@@ -20,14 +21,24 @@ maintainers:
properties:
compatible:
const: thead,th1520-clk-ap
enum:
- thead,th1520-clk-ap
- thead,th1520-clk-vo
reg:
maxItems: 1
clocks:
items:
- description: main oscillator (24MHz)
- description: |
One input clock:
- For "thead,th1520-clk-ap": the clock input must be the 24 MHz
main oscillator.
- For "thead,th1520-clk-vo": the clock input must be the VIDEO_PLL,
which is configured by the AP clock controller. According to the
TH1520 manual, VIDEO_PLL is a Silicon Creations Sigma-Delta PLL
(integer PLL) typically running at 792 MHz (FOUTPOSTDIV), with
a maximum FOUTVCO of 2376 MHz.
"#clock-cells":
const: 1
+168 -28
View File
@@ -847,6 +847,67 @@ static CCU_GATE(CLK_SRAM1, sram1_clk, "sram1", axi_aclk_pd, 0x20c, BIT(3), 0);
static CCU_GATE(CLK_SRAM2, sram2_clk, "sram2", axi_aclk_pd, 0x20c, BIT(2), 0);
static CCU_GATE(CLK_SRAM3, sram3_clk, "sram3", axi_aclk_pd, 0x20c, BIT(1), 0);
static CCU_GATE(CLK_AXI4_VO_ACLK, axi4_vo_aclk, "axi4-vo-aclk",
video_pll_clk_pd, 0x0, BIT(0), 0);
static CCU_GATE(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_clk_pd,
0x0, BIT(3), 0);
static CCU_GATE(CLK_GPU_CFG_ACLK, gpu_cfg_aclk, "gpu-cfg-aclk",
video_pll_clk_pd, 0x0, BIT(4), 0);
static CCU_GATE(CLK_DPU_PIXELCLK0, dpu0_pixelclk, "dpu0-pixelclk",
video_pll_clk_pd, 0x0, BIT(5), 0);
static CCU_GATE(CLK_DPU_PIXELCLK1, dpu1_pixelclk, "dpu1-pixelclk",
video_pll_clk_pd, 0x0, BIT(6), 0);
static CCU_GATE(CLK_DPU_HCLK, dpu_hclk, "dpu-hclk", video_pll_clk_pd, 0x0,
BIT(7), 0);
static CCU_GATE(CLK_DPU_ACLK, dpu_aclk, "dpu-aclk", video_pll_clk_pd, 0x0,
BIT(8), 0);
static CCU_GATE(CLK_DPU_CCLK, dpu_cclk, "dpu-cclk", video_pll_clk_pd, 0x0,
BIT(9), 0);
static CCU_GATE(CLK_HDMI_SFR, hdmi_sfr_clk, "hdmi-sfr-clk", video_pll_clk_pd,
0x0, BIT(10), 0);
static CCU_GATE(CLK_HDMI_PCLK, hdmi_pclk, "hdmi-pclk", video_pll_clk_pd, 0x0,
BIT(11), 0);
static CCU_GATE(CLK_HDMI_CEC, hdmi_cec_clk, "hdmi-cec-clk", video_pll_clk_pd,
0x0, BIT(12), 0);
static CCU_GATE(CLK_MIPI_DSI0_PCLK, mipi_dsi0_pclk, "mipi-dsi0-pclk",
video_pll_clk_pd, 0x0, BIT(13), 0);
static CCU_GATE(CLK_MIPI_DSI1_PCLK, mipi_dsi1_pclk, "mipi-dsi1-pclk",
video_pll_clk_pd, 0x0, BIT(14), 0);
static CCU_GATE(CLK_MIPI_DSI0_CFG, mipi_dsi0_cfg_clk, "mipi-dsi0-cfg-clk",
video_pll_clk_pd, 0x0, BIT(15), 0);
static CCU_GATE(CLK_MIPI_DSI1_CFG, mipi_dsi1_cfg_clk, "mipi-dsi1-cfg-clk",
video_pll_clk_pd, 0x0, BIT(16), 0);
static CCU_GATE(CLK_MIPI_DSI0_REFCLK, mipi_dsi0_refclk, "mipi-dsi0-refclk",
video_pll_clk_pd, 0x0, BIT(17), 0);
static CCU_GATE(CLK_MIPI_DSI1_REFCLK, mipi_dsi1_refclk, "mipi-dsi1-refclk",
video_pll_clk_pd, 0x0, BIT(18), 0);
static CCU_GATE(CLK_HDMI_I2S, hdmi_i2s_clk, "hdmi-i2s-clk", video_pll_clk_pd,
0x0, BIT(19), 0);
static CCU_GATE(CLK_X2H_DPU1_ACLK, x2h_dpu1_aclk, "x2h-dpu1-aclk",
video_pll_clk_pd, 0x0, BIT(20), 0);
static CCU_GATE(CLK_X2H_DPU_ACLK, x2h_dpu_aclk, "x2h-dpu-aclk",
video_pll_clk_pd, 0x0, BIT(21), 0);
static CCU_GATE(CLK_AXI4_VO_PCLK, axi4_vo_pclk, "axi4-vo-pclk",
video_pll_clk_pd, 0x0, BIT(22), 0);
static CCU_GATE(CLK_IOPMP_VOSYS_DPU_PCLK, iopmp_vosys_dpu_pclk,
"iopmp-vosys-dpu-pclk", video_pll_clk_pd, 0x0, BIT(23), 0);
static CCU_GATE(CLK_IOPMP_VOSYS_DPU1_PCLK, iopmp_vosys_dpu1_pclk,
"iopmp-vosys-dpu1-pclk", video_pll_clk_pd, 0x0, BIT(24), 0);
static CCU_GATE(CLK_IOPMP_VOSYS_GPU_PCLK, iopmp_vosys_gpu_pclk,
"iopmp-vosys-gpu-pclk", video_pll_clk_pd, 0x0, BIT(25), 0);
static CCU_GATE(CLK_IOPMP_DPU1_ACLK, iopmp_dpu1_aclk, "iopmp-dpu1-aclk",
video_pll_clk_pd, 0x0, BIT(27), 0);
static CCU_GATE(CLK_IOPMP_DPU_ACLK, iopmp_dpu_aclk, "iopmp-dpu-aclk",
video_pll_clk_pd, 0x0, BIT(28), 0);
static CCU_GATE(CLK_IOPMP_GPU_ACLK, iopmp_gpu_aclk, "iopmp-gpu-aclk",
video_pll_clk_pd, 0x0, BIT(29), 0);
static CCU_GATE(CLK_MIPIDSI0_PIXCLK, mipi_dsi0_pixclk, "mipi-dsi0-pixclk",
video_pll_clk_pd, 0x0, BIT(30), 0);
static CCU_GATE(CLK_MIPIDSI1_PIXCLK, mipi_dsi1_pixclk, "mipi-dsi1-pixclk",
video_pll_clk_pd, 0x0, BIT(31), 0);
static CCU_GATE(CLK_HDMI_PIXCLK, hdmi_pixclk, "hdmi-pixclk", video_pll_clk_pd,
0x4, BIT(0), 0);
static CLK_FIXED_FACTOR_HW(gmac_pll_clk_100m, "gmac-pll-clk-100m",
&gmac_pll_clk.common.hw, 10, 1, 0);
@@ -963,7 +1024,38 @@ static struct ccu_common *th1520_gate_clks[] = {
&sram3_clk.common,
};
#define NR_CLKS (CLK_UART_SCLK + 1)
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_i2s_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 const struct regmap_config th1520_clk_regmap_config = {
.reg_bits = 32,
@@ -972,8 +1064,44 @@ static const struct regmap_config th1520_clk_regmap_config = {
.fast_io = true,
};
struct th1520_plat_data {
struct ccu_common **th1520_pll_clks;
struct ccu_common **th1520_div_clks;
struct ccu_common **th1520_mux_clks;
struct ccu_common **th1520_gate_clks;
int nr_clks;
int nr_pll_clks;
int nr_div_clks;
int nr_mux_clks;
int nr_gate_clks;
};
static const struct th1520_plat_data th1520_ap_platdata = {
.th1520_pll_clks = th1520_pll_clks,
.th1520_div_clks = th1520_div_clks,
.th1520_mux_clks = th1520_mux_clks,
.th1520_gate_clks = th1520_gate_clks,
.nr_clks = CLK_UART_SCLK + 1,
.nr_pll_clks = ARRAY_SIZE(th1520_pll_clks),
.nr_div_clks = ARRAY_SIZE(th1520_div_clks),
.nr_mux_clks = ARRAY_SIZE(th1520_mux_clks),
.nr_gate_clks = ARRAY_SIZE(th1520_gate_clks),
};
static const struct th1520_plat_data th1520_vo_platdata = {
.th1520_gate_clks = th1520_vo_gate_clks,
.nr_clks = CLK_HDMI_PIXCLK + 1,
.nr_gate_clks = ARRAY_SIZE(th1520_vo_gate_clks),
};
static int th1520_clk_probe(struct platform_device *pdev)
{
const struct th1520_plat_data *plat_data;
struct device *dev = &pdev->dev;
struct clk_hw_onecell_data *priv;
@@ -982,11 +1110,16 @@ static int th1520_clk_probe(struct platform_device *pdev)
struct clk_hw *hw;
int ret, i;
priv = devm_kzalloc(dev, struct_size(priv, hws, NR_CLKS), GFP_KERNEL);
plat_data = device_get_match_data(&pdev->dev);
if (!plat_data)
return dev_err_probe(&pdev->dev, -ENODEV,
"No device match data found\n");
priv = devm_kzalloc(dev, struct_size(priv, hws, plat_data->nr_clks), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->num = NR_CLKS;
priv->num = plat_data->nr_clks;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
@@ -996,35 +1129,35 @@ static int th1520_clk_probe(struct platform_device *pdev)
if (IS_ERR(map))
return PTR_ERR(map);
for (i = 0; i < ARRAY_SIZE(th1520_pll_clks); i++) {
struct ccu_pll *cp = hw_to_ccu_pll(&th1520_pll_clks[i]->hw);
for (i = 0; i < plat_data->nr_pll_clks; i++) {
struct ccu_pll *cp = hw_to_ccu_pll(&plat_data->th1520_pll_clks[i]->hw);
th1520_pll_clks[i]->map = map;
plat_data->th1520_pll_clks[i]->map = map;
ret = devm_clk_hw_register(dev, &th1520_pll_clks[i]->hw);
ret = devm_clk_hw_register(dev, &plat_data->th1520_pll_clks[i]->hw);
if (ret)
return ret;
priv->hws[cp->common.clkid] = &cp->common.hw;
}
for (i = 0; i < ARRAY_SIZE(th1520_div_clks); i++) {
struct ccu_div *cd = hw_to_ccu_div(&th1520_div_clks[i]->hw);
for (i = 0; i < plat_data->nr_div_clks; i++) {
struct ccu_div *cd = hw_to_ccu_div(&plat_data->th1520_div_clks[i]->hw);
th1520_div_clks[i]->map = map;
plat_data->th1520_div_clks[i]->map = map;
ret = devm_clk_hw_register(dev, &th1520_div_clks[i]->hw);
ret = devm_clk_hw_register(dev, &plat_data->th1520_div_clks[i]->hw);
if (ret)
return ret;
priv->hws[cd->common.clkid] = &cd->common.hw;
}
for (i = 0; i < ARRAY_SIZE(th1520_mux_clks); i++) {
struct ccu_mux *cm = hw_to_ccu_mux(&th1520_mux_clks[i]->hw);
for (i = 0; i < plat_data->nr_mux_clks; i++) {
struct ccu_mux *cm = hw_to_ccu_mux(&plat_data->th1520_mux_clks[i]->hw);
const struct clk_init_data *init = cm->common.hw.init;
th1520_mux_clks[i]->map = map;
plat_data->th1520_mux_clks[i]->map = map;
hw = devm_clk_hw_register_mux_parent_data_table(dev,
init->name,
init->parent_data,
@@ -1040,10 +1173,10 @@ static int th1520_clk_probe(struct platform_device *pdev)
priv->hws[cm->common.clkid] = hw;
}
for (i = 0; i < ARRAY_SIZE(th1520_gate_clks); i++) {
struct ccu_gate *cg = hw_to_ccu_gate(&th1520_gate_clks[i]->hw);
for (i = 0; i < plat_data->nr_gate_clks; i++) {
struct ccu_gate *cg = hw_to_ccu_gate(&plat_data->th1520_gate_clks[i]->hw);
th1520_gate_clks[i]->map = map;
plat_data->th1520_gate_clks[i]->map = map;
hw = devm_clk_hw_register_gate_parent_data(dev,
cg->common.hw.init->name,
@@ -1057,19 +1190,21 @@ static int th1520_clk_probe(struct platform_device *pdev)
priv->hws[cg->common.clkid] = hw;
}
ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
if (ret)
return ret;
priv->hws[CLK_OSC12M] = &osc12m_clk.hw;
if (plat_data == &th1520_ap_platdata) {
ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
if (ret)
return ret;
priv->hws[CLK_OSC12M] = &osc12m_clk.hw;
ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);
if (ret)
return ret;
priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);
if (ret)
return ret;
priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
if (ret)
return ret;
ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
if (ret)
return ret;
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv);
if (ret)
@@ -1081,6 +1216,11 @@ static int th1520_clk_probe(struct platform_device *pdev)
static const struct of_device_id th1520_clk_match[] = {
{
.compatible = "thead,th1520-clk-ap",
.data = &th1520_ap_platdata,
},
{
.compatible = "thead,th1520-clk-vo",
.data = &th1520_vo_platdata,
},
{ /* sentinel */ },
};
@@ -93,4 +93,38 @@
#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_MEM 1
#define CLK_GPU_CORE 2
#define CLK_GPU_CFG_ACLK 3
#define CLK_DPU_PIXELCLK0 4
#define CLK_DPU_PIXELCLK1 5
#define CLK_DPU_HCLK 6
#define CLK_DPU_ACLK 7
#define CLK_DPU_CCLK 8
#define CLK_HDMI_SFR 9
#define CLK_HDMI_PCLK 10
#define CLK_HDMI_CEC 11
#define CLK_MIPI_DSI0_PCLK 12
#define CLK_MIPI_DSI1_PCLK 13
#define CLK_MIPI_DSI0_CFG 14
#define CLK_MIPI_DSI1_CFG 15
#define CLK_MIPI_DSI0_REFCLK 16
#define CLK_MIPI_DSI1_REFCLK 17
#define CLK_HDMI_I2S 18
#define CLK_X2H_DPU1_ACLK 19
#define CLK_X2H_DPU_ACLK 20
#define CLK_AXI4_VO_PCLK 21
#define CLK_IOPMP_VOSYS_DPU_PCLK 22
#define CLK_IOPMP_VOSYS_DPU1_PCLK 23
#define CLK_IOPMP_VOSYS_GPU_PCLK 24
#define CLK_IOPMP_DPU1_ACLK 25
#define CLK_IOPMP_DPU_ACLK 26
#define CLK_IOPMP_GPU_ACLK 27
#define CLK_MIPIDSI0_PIXCLK 28
#define CLK_MIPIDSI1_PIXCLK 29
#define CLK_HDMI_PIXCLK 30
#endif