Commit 29c98b13 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

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
parents 0af2f6be 50d4b157
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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,6 +1190,7 @@ static int th1520_clk_probe(struct platform_device *pdev)
		priv->hws[cg->common.clkid] = hw;
	}

	if (plat_data == &th1520_ap_platdata) {
		ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
		if (ret)
			return ret;
@@ -1070,6 +1204,7 @@ static int th1520_clk_probe(struct platform_device *pdev)
		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 */ },
};
+34 −0
Original line number Diff line number Diff line
@@ -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