diff options
Diffstat (limited to 'drivers/clk/thead')
-rw-r--r-- | drivers/clk/thead/clk-th1520-ap.c | 299 |
1 files changed, 213 insertions, 86 deletions
diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th1520-ap.c index 4c9555fc61844..cf1bba58f641e 100644 --- a/drivers/clk/thead/clk-th1520-ap.c +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -42,8 +42,9 @@ struct ccu_common { }; struct ccu_mux { - struct ccu_internal mux; - struct ccu_common common; + int clkid; + u32 reg; + struct clk_mux mux; }; struct ccu_gate { @@ -75,6 +76,17 @@ struct ccu_pll { .flags = _flags, \ } +#define TH_CCU_MUX(_name, _parents, _shift, _width) \ + { \ + .mask = GENMASK(_width - 1, 0), \ + .shift = _shift, \ + .hw.init = CLK_HW_INIT_PARENTS_DATA( \ + _name, \ + _parents, \ + &clk_mux_ops, \ + 0), \ + } + #define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _gate, _flags) \ struct ccu_gate _struct = { \ .enable = _gate, \ @@ -94,13 +106,6 @@ static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw) return container_of(hw, struct ccu_common, hw); } -static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw) -{ - struct ccu_common *common = hw_to_ccu_common(hw); - - return container_of(common, struct ccu_mux, common); -} - static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw) { struct ccu_common *common = hw_to_ccu_common(hw); @@ -415,32 +420,20 @@ static const struct clk_parent_data c910_i0_parents[] = { }; static struct ccu_mux c910_i0_clk = { - .mux = TH_CCU_ARG(1, 1), - .common = { - .clkid = CLK_C910_I0, - .cfg0 = 0x100, - .hw.init = CLK_HW_INIT_PARENTS_DATA("c910-i0", - c910_i0_parents, - &clk_mux_ops, - 0), - } + .clkid = CLK_C910_I0, + .reg = 0x100, + .mux = TH_CCU_MUX("c910-i0", c910_i0_parents, 1, 1), }; static const struct clk_parent_data c910_parents[] = { - { .hw = &c910_i0_clk.common.hw }, + { .hw = &c910_i0_clk.mux.hw }, { .hw = &cpu_pll1_clk.common.hw } }; static struct ccu_mux c910_clk = { - .mux = TH_CCU_ARG(0, 1), - .common = { - .clkid = CLK_C910, - .cfg0 = 0x100, - .hw.init = CLK_HW_INIT_PARENTS_DATA("c910", - c910_parents, - &clk_mux_ops, - 0), - } + .clkid = CLK_C910, + .reg = 0x100, + .mux = TH_CCU_MUX("c910", c910_parents, 0, 1), }; static const struct clk_parent_data ahb2_cpusys_parents[] = { @@ -582,7 +575,14 @@ static const struct clk_parent_data peri2sys_apb_pclk_pd[] = { { .hw = &peri2sys_apb_pclk.common.hw } }; -static CLK_FIXED_FACTOR_FW_NAME(osc12m_clk, "osc_12m", "osc_24m", 2, 1, 0); +static struct clk_fixed_factor osc12m_clk = { + .div = 2, + .mult = 1, + .hw.init = CLK_HW_INIT_PARENTS_DATA("osc_12m", + osc_24m_clk, + &clk_fixed_factor_ops, + 0), +}; static const char * const out_parents[] = { "osc_24m", "osc_12m" }; @@ -792,11 +792,12 @@ static CCU_GATE(CLK_AON2CPU_A2X, aon2cpu_a2x_clk, "aon2cpu-a2x", axi4_cpusys2_ac 0x134, BIT(8), 0); static CCU_GATE(CLK_X2X_CPUSYS, x2x_cpusys_clk, "x2x-cpusys", axi4_cpusys2_aclk_pd, 0x134, BIT(7), 0); -static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", axi_aclk_pd, 0x138, BIT(8), 0); +static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", axi_aclk_pd, + 0x138, BIT(8), CLK_IGNORE_UNUSED); static CCU_GATE(CLK_CPU2PERI_X2H, cpu2peri_x2h_clk, "cpu2peri-x2h", axi4_cpusys2_aclk_pd, 0x140, BIT(9), CLK_IGNORE_UNUSED); static CCU_GATE(CLK_PERISYS_APB1_HCLK, perisys_apb1_hclk, "perisys-apb1-hclk", perisys_ahb_hclk_pd, - 0x150, BIT(9), 0); + 0x150, BIT(9), CLK_IGNORE_UNUSED); static CCU_GATE(CLK_PERISYS_APB2_HCLK, perisys_apb2_hclk, "perisys-apb2-hclk", perisys_ahb_hclk_pd, 0x150, BIT(10), CLK_IGNORE_UNUSED); static CCU_GATE(CLK_PERISYS_APB3_HCLK, perisys_apb3_hclk, "perisys-apb3-hclk", perisys_ahb_hclk_pd, @@ -847,6 +848,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); @@ -856,15 +918,9 @@ static const struct clk_parent_data uart_sclk_parents[] = { }; static struct ccu_mux uart_sclk = { - .mux = TH_CCU_ARG(0, 1), - .common = { - .clkid = CLK_UART_SCLK, - .cfg0 = 0x210, - .hw.init = CLK_HW_INIT_PARENTS_DATA("uart-sclk", - uart_sclk_parents, - &clk_mux_ops, - 0), - } + .clkid = CLK_UART_SCLK, + .reg = 0x210, + .mux = TH_CCU_MUX("uart-sclk", uart_sclk_parents, 0, 1), }; static struct ccu_common *th1520_pll_clks[] = { @@ -901,10 +957,10 @@ static struct ccu_common *th1520_div_clks[] = { &dpu1_clk.common, }; -static struct ccu_common *th1520_mux_clks[] = { - &c910_i0_clk.common, - &c910_clk.common, - &uart_sclk.common, +static struct ccu_mux *th1520_mux_clks[] = { + &c910_i0_clk, + &c910_clk, + &uart_sclk, }; static struct ccu_common *th1520_gate_clks[] = { @@ -963,7 +1019,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 +1059,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_mux **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 +1105,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,54 +1124,46 @@ 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); - const struct clk_init_data *init = cm->common.hw.init; - - th1520_mux_clks[i]->map = map; - hw = devm_clk_hw_register_mux_parent_data_table(dev, - init->name, - init->parent_data, - init->num_parents, - 0, - base + cm->common.cfg0, - cm->mux.shift, - cm->mux.width, - 0, NULL, NULL); - if (IS_ERR(hw)) - return PTR_ERR(hw); + for (i = 0; i < plat_data->nr_mux_clks; i++) { + struct ccu_mux *cm = plat_data->th1520_mux_clks[i]; - priv->hws[cm->common.clkid] = hw; + cm->mux.reg = base + cm->reg; + + ret = devm_clk_hw_register(dev, &cm->mux.hw); + if (ret) + return ret; + + priv->hws[cm->clkid] = &cm->mux.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 +1177,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 +1203,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 */ }, }; |