diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c index 23b9787612a..16c6f024e72 100644 --- a/drivers/clk/mediatek/clk-mt7622.c +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -604,6 +604,8 @@ static const struct mtk_clk_tree mt7622_apmixed_clk_tree = { .plls = apmixed_plls, .gates_offs = CLK_APMIXED_MAIN_CORE_EN, .gates = apmixed_cgs, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_gates = ARRAY_SIZE(apmixed_cgs), }; static const struct mtk_clk_tree mt7622_infra_clk_tree = { @@ -612,6 +614,8 @@ static const struct mtk_clk_tree mt7622_infra_clk_tree = { .gates_offs = CLK_INFRA_DBGCLK_PD, .muxes = infra_muxes, .gates = infra_cgs, + .num_muxes = ARRAY_SIZE(infra_muxes), + .num_gates = ARRAY_SIZE(infra_cgs), }; static const struct mtk_clk_tree mt7622_peri_clk_tree = { @@ -620,6 +624,8 @@ static const struct mtk_clk_tree mt7622_peri_clk_tree = { .gates_offs = CLK_PERI_THERM_PD, .muxes = peri_muxes, .gates = peri_cgs, + .num_muxes = ARRAY_SIZE(peri_muxes), + .num_gates = ARRAY_SIZE(peri_cgs), }; static const struct mtk_clk_tree mt7622_clk_tree = { @@ -629,6 +635,9 @@ static const struct mtk_clk_tree mt7622_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static int mt7622_mcucfg_probe(struct udevice *dev) @@ -683,7 +692,8 @@ static int mt7622_pericfg_probe(struct udevice *dev) static int mt7622_pciesys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, pcie_cgs); + return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, pcie_cgs, + ARRAY_SIZE(pcie_cgs)); } static int mt7622_pciesys_bind(struct udevice *dev) @@ -701,7 +711,8 @@ static int mt7622_pciesys_bind(struct udevice *dev) static int mt7622_ethsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, eth_cgs); + return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, eth_cgs, + ARRAY_SIZE(eth_cgs)); } static int mt7622_ethsys_bind(struct udevice *dev) @@ -719,12 +730,14 @@ static int mt7622_ethsys_bind(struct udevice *dev) static int mt7622_sgmiisys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, sgmii_cgs); + return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, sgmii_cgs, + ARRAY_SIZE(sgmii_cgs)); } static int mt7622_ssusbsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, ssusb_cgs); + return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, ssusb_cgs, + ARRAY_SIZE(ssusb_cgs)); } static const struct udevice_id mt7622_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c index d0b80f48b0a..6ce1d729736 100644 --- a/drivers/clk/mediatek/clk-mt7623.c +++ b/drivers/clk/mediatek/clk-mt7623.c @@ -26,6 +26,7 @@ /* apmixedsys */ static const int pll_id_offs_map[] = { + [0 ... CLK_APMIXED_NR - 1] = -1, [CLK_APMIXED_ARMPLL] = 0, [CLK_APMIXED_MAINPLL] = 1, [CLK_APMIXED_UNIVPLL] = 2, @@ -92,6 +93,7 @@ static const struct mtk_pll_data apmixed_plls[] = { #define CLK_TOP_HDMITX_CLKDIG_CTS CLK_TOP_NR static const int top_id_offs_map[CLK_TOP_NR + 1] = { + [0 ... CLK_TOP_NR] = -1, /* Fixed CLK */ [CLK_TOP_DPI] = 0, [CLK_TOP_DMPLL] = 1, @@ -808,6 +810,7 @@ static const struct mtk_gate infra_cgs[] = { /* pericfg */ static const int peri_id_offs_map[] = { + [0 ... CLK_PERI_NR - 1] = -1, /* MUX CLK */ [CLK_PERI_UART0_SEL] = 1, [CLK_PERI_UART1_SEL] = 2, @@ -996,17 +999,23 @@ static const struct mtk_gate hif_cgs[] = { static const struct mtk_clk_tree mt7623_apmixedsys_clk_tree = { .xtal2_rate = 26 * MHZ, .id_offs_map = pll_id_offs_map, + .id_offs_map_size = ARRAY_SIZE(pll_id_offs_map), .plls = apmixed_plls, + .num_plls = ARRAY_SIZE(apmixed_plls), }; static const struct mtk_clk_tree mt7623_topckgen_clk_tree = { .xtal_rate = 26 * MHZ, .id_offs_map = top_id_offs_map, + .id_offs_map_size = ARRAY_SIZE(top_id_offs_map), .fdivs_offs = top_id_offs_map[CLK_TOP_SYSPLL], .muxes_offs = top_id_offs_map[CLK_TOP_AXI_SEL], .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static int mt7623_mcucfg_probe(struct udevice *dev) @@ -1053,16 +1062,19 @@ static const struct mtk_clk_tree mt7623_clk_gate_tree = { static int mt7623_infracfg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, - infra_cgs); + return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, infra_cgs, + ARRAY_SIZE(infra_cgs)); } static const struct mtk_clk_tree mt7623_clk_peri_tree = { .id_offs_map = peri_id_offs_map, + .id_offs_map_size = ARRAY_SIZE(peri_id_offs_map), .muxes_offs = peri_id_offs_map[CLK_PERI_UART0_SEL], .gates_offs = peri_id_offs_map[CLK_PERI_NFI], .muxes = peri_muxes, .gates = peri_cgs, + .num_muxes = ARRAY_SIZE(peri_muxes), + .num_gates = ARRAY_SIZE(peri_cgs), .xtal_rate = 26 * MHZ, }; @@ -1073,14 +1085,14 @@ static int mt7623_pericfg_probe(struct udevice *dev) static int mt7623_hifsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, - hif_cgs); + return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, hif_cgs, + ARRAY_SIZE(hif_cgs)); } static int mt7623_ethsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, - eth_cgs); + return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, eth_cgs, + ARRAY_SIZE(eth_cgs)); } static int mt7623_ethsys_hifsys_bind(struct udevice *dev) diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index 94fc5e51456..e4132f6195f 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -572,6 +572,10 @@ static const struct mtk_clk_tree mt7629_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static const struct mtk_clk_tree mt7629_peri_clk_tree = { @@ -584,6 +588,10 @@ static const struct mtk_clk_tree mt7629_peri_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static int mt7629_mcucfg_probe(struct udevice *dev) @@ -626,17 +634,20 @@ static int mt7629_topckgen_probe(struct udevice *dev) static int mt7629_infracfg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, infra_cgs); + return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, infra_cgs, + ARRAY_SIZE(infra_cgs)); } static int mt7629_pericfg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7629_peri_clk_tree, peri_cgs); + return mtk_common_clk_gate_init(dev, &mt7629_peri_clk_tree, peri_cgs, + ARRAY_SIZE(peri_cgs)); } static int mt7629_ethsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs); + return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs, + ARRAY_SIZE(eth_cgs)); } static int mt7629_ethsys_bind(struct udevice *dev) @@ -654,12 +665,14 @@ static int mt7629_ethsys_bind(struct udevice *dev) static int mt7629_sgmiisys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs); + return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs, + ARRAY_SIZE(sgmii_cgs)); } static int mt7629_ssusbsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, ssusb_cgs); + return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, ssusb_cgs, + ARRAY_SIZE(ssusb_cgs)); } static const struct udevice_id mt7629_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mt7981.c b/drivers/clk/mediatek/clk-mt7981.c index 2fdb1845e9f..c8090688df0 100644 --- a/drivers/clk/mediatek/clk-mt7981.c +++ b/drivers/clk/mediatek/clk-mt7981.c @@ -513,6 +513,7 @@ static const struct mtk_clk_tree mt7981_fixed_pll_clk_tree = { .fdivs_offs = CLK_APMIXED_NR_CLK, .xtal_rate = 40 * MHZ, .fclks = fixed_pll_clks, + .num_fclks = ARRAY_SIZE(fixed_pll_clks), }; static const struct mtk_clk_tree mt7981_topckgen_clk_tree = { @@ -521,6 +522,9 @@ static const struct mtk_clk_tree mt7981_topckgen_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), .flags = CLK_BYPASS_XTAL | CLK_PARENT_TOPCKGEN, }; @@ -531,6 +535,9 @@ static const struct mtk_clk_tree mt7981_infracfg_clk_tree = { .fdivs = infra_fixed_divs, .muxes = infra_muxes, .gates = infracfg_gates, + .num_fdivs = ARRAY_SIZE(infra_fixed_divs), + .num_muxes = ARRAY_SIZE(infra_muxes), + .num_gates = ARRAY_SIZE(infracfg_gates), .flags = CLK_PARENT_INFRASYS, }; @@ -624,7 +631,7 @@ static const struct mtk_gate sgmii0_cgs[] = { static int mt7981_sgmii0sys_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree, - sgmii0_cgs); + sgmii0_cgs, ARRAY_SIZE(sgmii0_cgs)); } static const struct udevice_id mt7981_sgmii0sys_compat[] = { @@ -651,7 +658,7 @@ static const struct mtk_gate sgmii1_cgs[] = { static int mt7981_sgmii1sys_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree, - sgmii1_cgs); + sgmii1_cgs, ARRAY_SIZE(sgmii1_cgs)); } static const struct udevice_id mt7981_sgmii1sys_compat[] = { @@ -692,7 +699,7 @@ static const struct mtk_gate eth_cgs[] = { static int mt7981_ethsys_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree, - eth_cgs); + eth_cgs, ARRAY_SIZE(eth_cgs)); } static int mt7981_ethsys_bind(struct udevice *dev) diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c index 16db5877056..735e824c874 100644 --- a/drivers/clk/mediatek/clk-mt7986.c +++ b/drivers/clk/mediatek/clk-mt7986.c @@ -519,6 +519,7 @@ static const struct mtk_clk_tree mt7986_fixed_pll_clk_tree = { .fdivs_offs = CLK_APMIXED_NR_CLK, .xtal_rate = 40 * MHZ, .fclks = fixed_pll_clks, + .num_fclks = ARRAY_SIZE(fixed_pll_clks), .flags = CLK_PARENT_APMIXED, }; @@ -528,6 +529,9 @@ static const struct mtk_clk_tree mt7986_topckgen_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), .flags = CLK_BYPASS_XTAL | CLK_PARENT_TOPCKGEN, }; @@ -538,6 +542,9 @@ static const struct mtk_clk_tree mt7986_infracfg_clk_tree = { .fdivs = infra_fixed_divs, .muxes = infra_muxes, .gates = infracfg_gates, + .num_fdivs = ARRAY_SIZE(infra_fixed_divs), + .num_muxes = ARRAY_SIZE(infra_muxes), + .num_gates = ARRAY_SIZE(infracfg_gates), .flags = CLK_PARENT_INFRASYS, }; @@ -629,8 +636,8 @@ static const struct mtk_gate eth_cgs[] = { static int mt7986_ethsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7986_topckgen_clk_tree, - eth_cgs); + return mtk_common_clk_gate_init(dev, &mt7986_topckgen_clk_tree, eth_cgs, + ARRAY_SIZE(eth_cgs)); } static int mt7986_ethsys_bind(struct udevice *dev) diff --git a/drivers/clk/mediatek/clk-mt7987.c b/drivers/clk/mediatek/clk-mt7987.c index caee8bf43e4..99ff57c5dc5 100644 --- a/drivers/clk/mediatek/clk-mt7987.c +++ b/drivers/clk/mediatek/clk-mt7987.c @@ -46,6 +46,7 @@ static const struct mtk_fixed_clk apmixedsys_mtk_plls[] = { static const struct mtk_clk_tree mt7987_fixed_pll_clk_tree = { .fdivs_offs = ARRAY_SIZE(apmixedsys_mtk_plls), .fclks = apmixedsys_mtk_plls, + .num_fclks = ARRAY_SIZE(apmixedsys_mtk_plls), .flags = CLK_PARENT_APMIXED, .xtal_rate = 40 * MHZ, }; @@ -442,6 +443,8 @@ static const struct mtk_clk_tree mt7987_topckgen_clk_tree = { .muxes_offs = CLK_TOP_NETSYS_SEL, .fdivs = topckgen_mtk_fixed_factors, .muxes = topckgen_mtk_muxes, + .num_fdivs = ARRAY_SIZE(topckgen_mtk_fixed_factors), + .num_muxes = ARRAY_SIZE(topckgen_mtk_muxes), .flags = CLK_BYPASS_XTAL | CLK_PARENT_TOPCKGEN, .xtal_rate = MT7987_XTAL_RATE, }; @@ -765,6 +768,8 @@ static const struct mtk_clk_tree mt7987_infracfg_clk_tree = { .gates_offs = CLK_INFRA_66M_GPT_BCK, .muxes = infracfg_mtk_mux, .gates = infracfg_mtk_gates, + .num_muxes = ARRAY_SIZE(infracfg_mtk_mux), + .num_gates = ARRAY_SIZE(infracfg_mtk_gates), .flags = CLK_BYPASS_XTAL, .xtal_rate = MT7987_XTAL_RATE, }; @@ -813,8 +818,8 @@ static const struct mtk_gate eth_cgs[] = { static int mt7987_ethsys_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7987_topckgen_clk_tree, - eth_cgs); + return mtk_common_clk_gate_init(dev, &mt7987_topckgen_clk_tree, eth_cgs, + ARRAY_SIZE(eth_cgs)); } static int mt7987_ethsys_bind(struct udevice *dev) diff --git a/drivers/clk/mediatek/clk-mt7988.c b/drivers/clk/mediatek/clk-mt7988.c index bfbf401eb12..da1d2e89d61 100644 --- a/drivers/clk/mediatek/clk-mt7988.c +++ b/drivers/clk/mediatek/clk-mt7988.c @@ -773,6 +773,7 @@ static const struct mtk_gate infracfg_mtk_gates[] = { static const struct mtk_clk_tree mt7988_fixed_pll_clk_tree = { .fdivs_offs = ARRAY_SIZE(apmixedsys_mtk_plls), .fclks = apmixedsys_mtk_plls, + .num_fclks = ARRAY_SIZE(apmixedsys_mtk_plls), .flags = CLK_PARENT_APMIXED, .xtal_rate = 40 * MHZ, }; @@ -783,6 +784,9 @@ static const struct mtk_clk_tree mt7988_topckgen_clk_tree = { .fclks = topckgen_mtk_fixed_clks, .fdivs = topckgen_mtk_fixed_factors, .muxes = topckgen_mtk_muxes, + .num_fclks = ARRAY_SIZE(topckgen_mtk_fixed_clks), + .num_fdivs = ARRAY_SIZE(topckgen_mtk_fixed_factors), + .num_muxes = ARRAY_SIZE(topckgen_mtk_muxes), .flags = CLK_BYPASS_XTAL | CLK_PARENT_TOPCKGEN, .xtal_rate = 40 * MHZ, }; @@ -792,6 +796,8 @@ static const struct mtk_clk_tree mt7988_infracfg_clk_tree = { .gates_offs = CLK_INFRA_PCIE_PERI_26M_CK_P0, .muxes = infracfg_mtk_mux, .gates = infracfg_mtk_gates, + .num_muxes = ARRAY_SIZE(infracfg_mtk_mux), + .num_gates = ARRAY_SIZE(infracfg_mtk_gates), .flags = CLK_BYPASS_XTAL, .xtal_rate = 40 * MHZ, }; @@ -886,7 +892,8 @@ static const struct mtk_gate ethdma_mtk_gate[] = { static int mt7988_ethdma_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - ethdma_mtk_gate); + ethdma_mtk_gate, + ARRAY_SIZE(ethdma_mtk_gate)); } static int mt7988_ethdma_bind(struct udevice *dev) @@ -944,7 +951,8 @@ static const struct mtk_gate sgmiisys_0_mtk_gate[] = { static int mt7988_sgmiisys_0_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - sgmiisys_0_mtk_gate); + sgmiisys_0_mtk_gate, + ARRAY_SIZE(sgmiisys_0_mtk_gate)); } static const struct udevice_id mt7988_sgmiisys_0_compat[] = { @@ -988,7 +996,8 @@ static const struct mtk_gate sgmiisys_1_mtk_gate[] = { static int mt7988_sgmiisys_1_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - sgmiisys_1_mtk_gate); + sgmiisys_1_mtk_gate, + ARRAY_SIZE(sgmiisys_1_mtk_gate)); } static const struct udevice_id mt7988_sgmiisys_1_compat[] = { @@ -1034,7 +1043,8 @@ static const struct mtk_gate ethwarp_mtk_gate[] = { static int mt7988_ethwarp_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - ethwarp_mtk_gate); + ethwarp_mtk_gate, + ARRAY_SIZE(ethwarp_mtk_gate)); } static int mt7988_ethwarp_bind(struct udevice *dev) diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c index 9612a62e56a..5b41cf4b88c 100644 --- a/drivers/clk/mediatek/clk-mt8183.c +++ b/drivers/clk/mediatek/clk-mt8183.c @@ -599,6 +599,10 @@ static const struct mtk_clk_tree mt8183_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static const struct mtk_gate_regs infra0_cg_regs = { @@ -773,7 +777,8 @@ static int mt8183_topckgen_probe(struct udevice *dev) static int mt8183_infracfg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8183_clk_tree, infra_clks); + return mtk_common_clk_gate_init(dev, &mt8183_clk_tree, infra_clks, + ARRAY_SIZE(infra_clks)); } static const struct udevice_id mt8183_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mt8188.c b/drivers/clk/mediatek/clk-mt8188.c index 55dfadddfe3..a4cbb3213e3 100644 --- a/drivers/clk/mediatek/clk-mt8188.c +++ b/drivers/clk/mediatek/clk-mt8188.c @@ -85,6 +85,7 @@ static const struct mtk_clk_tree mt8188_apmixedsys_clk_tree = { .xtal_rate = 26 * MHZ, .xtal2_rate = 26 * MHZ, .plls = apmixed_plls, + .num_plls = ARRAY_SIZE(apmixed_plls), }; static const struct mtk_fixed_clk top_fixed_clks[] = { @@ -1359,11 +1360,15 @@ static const struct mtk_clk_tree mt8188_topckgen_clk_tree = { .xtal_rate = 26 * MHZ, .xtal2_rate = 26 * MHZ, .id_offs_map = mt8188_id_offs_map, + .id_offs_map_size = ARRAY_SIZE(mt8188_id_offs_map), .fdivs_offs = 8, /* CLK_TOP_MAINPLL_D3 */ .muxes_offs = 87, /* CLK_TOP_AXI */ .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static const struct mtk_gate_regs infra_ao0_cg_regs = { @@ -1690,33 +1695,44 @@ static int mt8188_topckgen_probe(struct udevice *dev) static int mt8188_topckgen_cg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8188_topckgen_cg_clk_tree, topckgen_cg_clks); + return mtk_common_clk_gate_init(dev, &mt8188_topckgen_cg_clk_tree, + topckgen_cg_clks, + ARRAY_SIZE(topckgen_cg_clks)); } static int mt8188_infracfg_ao_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8188_infracfg_ao_clk_tree, infracfg_ao_clks); + return mtk_common_clk_gate_init(dev, &mt8188_infracfg_ao_clk_tree, + infracfg_ao_clks, + ARRAY_SIZE(infracfg_ao_clks)); } static int mt8188_pericfg_ao_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8188_pericfg_ao_clk_tree, pericfg_ao_clks); + return mtk_common_clk_gate_init(dev, &mt8188_pericfg_ao_clk_tree, + pericfg_ao_clks, + ARRAY_SIZE(pericfg_ao_clks)); } static int mt8188_imp_iic_wrap_c_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_c_clk_tree, imp_iic_wrap_c_clks); + return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_c_clk_tree, + imp_iic_wrap_c_clks, + ARRAY_SIZE(imp_iic_wrap_c_clks)); } static int mt8188_imp_iic_wrap_w_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_w_clk_tree, imp_iic_wrap_w_clks); + return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_w_clk_tree, + imp_iic_wrap_w_clks, + ARRAY_SIZE(imp_iic_wrap_w_clks)); } static int mt8188_imp_iic_wrap_en_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_en_clk_tree, - imp_iic_wrap_en_clks); + imp_iic_wrap_en_clks, + ARRAY_SIZE(imp_iic_wrap_en_clks)); } static const struct udevice_id mt8188_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mt8365.c b/drivers/clk/mediatek/clk-mt8365.c index 53eca73b98d..c88545fc7cf 100644 --- a/drivers/clk/mediatek/clk-mt8365.c +++ b/drivers/clk/mediatek/clk-mt8365.c @@ -490,6 +490,10 @@ static const struct mtk_clk_tree mt8365_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_divs, .muxes = top_muxes, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; /* topckgen cg */ @@ -701,12 +705,14 @@ static int mt8365_topckgen_probe(struct udevice *dev) static int mt8365_topckgen_cg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8365_clk_tree, top_clk_gates); + return mtk_common_clk_gate_init(dev, &mt8365_clk_tree, top_clk_gates, + ARRAY_SIZE(top_clk_gates)); } static int mt8365_infracfg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8365_clk_tree, ifr_clks); + return mtk_common_clk_gate_init(dev, &mt8365_clk_tree, ifr_clks, + ARRAY_SIZE(ifr_clks)); } static const struct udevice_id mt8365_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mt8512.c b/drivers/clk/mediatek/clk-mt8512.c index ab270673442..d4f6604c160 100644 --- a/drivers/clk/mediatek/clk-mt8512.c +++ b/drivers/clk/mediatek/clk-mt8512.c @@ -790,6 +790,10 @@ static const struct mtk_clk_tree mt8512_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static int mt8512_apmixedsys_probe(struct udevice *dev) @@ -804,12 +808,14 @@ static int mt8512_topckgen_probe(struct udevice *dev) static int mt8512_topckgen_cg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8512_clk_tree, top_clks); + return mtk_common_clk_gate_init(dev, &mt8512_clk_tree, top_clks, + ARRAY_SIZE(top_clks)); } static int mt8512_infracfg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8512_clk_tree, infra_clks); + return mtk_common_clk_gate_init(dev, &mt8512_clk_tree, infra_clks, + ARRAY_SIZE(infra_clks)); } static const struct udevice_id mt8512_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c index 623f88499f1..d5f922886a3 100644 --- a/drivers/clk/mediatek/clk-mt8516.c +++ b/drivers/clk/mediatek/clk-mt8516.c @@ -739,6 +739,10 @@ static const struct mtk_clk_tree mt8516_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static int mt8516_apmixedsys_probe(struct udevice *dev) @@ -753,7 +757,8 @@ static int mt8516_topckgen_probe(struct udevice *dev) static int mt8516_topckgen_cg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8516_clk_tree, top_clks); + return mtk_common_clk_gate_init(dev, &mt8516_clk_tree, top_clks, + ARRAY_SIZE(top_clks)); } static const struct udevice_id mt8516_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mt8518.c b/drivers/clk/mediatek/clk-mt8518.c index ba8cc584d46..92730f3f06c 100644 --- a/drivers/clk/mediatek/clk-mt8518.c +++ b/drivers/clk/mediatek/clk-mt8518.c @@ -1495,6 +1495,10 @@ static const struct mtk_clk_tree mt8518_clk_tree = { .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, + .num_plls = ARRAY_SIZE(apmixed_plls), + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), }; static int mt8518_apmixedsys_probe(struct udevice *dev) @@ -1509,7 +1513,8 @@ static int mt8518_topckgen_probe(struct udevice *dev) static int mt8518_topckgen_cg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt8518_clk_tree, top_clks); + return mtk_common_clk_gate_init(dev, &mt8518_clk_tree, top_clks, + ARRAY_SIZE(top_clks)); } static const struct udevice_id mt8518_apmixed_compat[] = { diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index f91777e968a..a3dd18363f6 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -35,16 +35,35 @@ /* shared functions */ -static int mtk_clk_get_id(struct clk *clk) +static const int mtk_common_clk_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args, + const struct mtk_clk_tree *tree) { - struct mtk_clk_priv *priv = dev_get_priv(clk->dev); - int id = clk->id; + int id; + + if (args->args_count != 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + id = args->args[0]; /* Remap the clk ID to the one expected by driver */ - if (priv->tree->id_offs_map) - id = priv->tree->id_offs_map[id]; + if (tree->id_offs_map) { + if (id >= tree->id_offs_map_size) + return -ENOENT; - return id; + id = tree->id_offs_map[id]; + } + + /* Some IDs in the map may not be valid. */ + if (id < 0) + return -ENOENT; + + clk->id = id; + clk->data = 0; + + return 0; } static int mtk_dummy_enable(struct clk *clk) @@ -110,13 +129,23 @@ static int mtk_gate_disable(void __iomem *base, const struct mtk_gate *gate) static ulong mtk_clk_find_parent_rate(struct clk *clk, int id, struct udevice *pdev) { - struct clk parent = { .id = id, }; + struct ofnode_phandle_args args = { + .args_count = 1, + .args = { id }, + }; + struct clk parent = { }; + int ret; if (pdev) parent.dev = pdev; else parent.dev = clk->dev; + args.node = dev_ofnode(parent.dev); + ret = ((struct clk_ops *)parent.dev->driver->ops)->of_xlate(&parent, &args); + if (ret) + return ret; + return clk_get_rate(&parent); } @@ -164,8 +193,133 @@ static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent, return 0; } +#if CONFIG_IS_ENABLED(CMD_CLK) +static void mtk_clk_print_dev_parent(struct udevice *parent) +{ + printf("Parent device: %s %s\n", parent->driver->name, parent->name); +} + +static void mtk_clk_print_mapped_id(int unmapped_id, int mapped_id, bool has_map) +{ + /* + * If there is a ID map, then having unmapped and mapped IDs differ is + * expected. On the other hand, if there is no map, then they should be + * the same, and it is a programming error if they differ. + */ + if (has_map) + printf(", (mapped ID: %u)", mapped_id); + else if (unmapped_id != mapped_id) + printf(", (error! should be %u)", mapped_id); +} + +static void mtk_clk_print_rate(struct udevice *dev, int mapped_id) +{ + struct clk clk = { + .dev = dev, + .id = mapped_id, + }; + long rate = clk_get_rate(&clk); + + if (rate < 0) + printf(", error! clk_get_rate() failed: %ld", rate); + else + printf(", Rate: %lu Hz", rate); +} + +static void mtk_clk_print_parent(const char *prefix, int parent, u32 flags) +{ + const char *parent_type_str; + + switch (flags & CLK_PARENT_MASK) { + case CLK_PARENT_APMIXED: + parent_type_str = "apmixedsys"; + break; + case CLK_PARENT_TOPCKGEN: + parent_type_str = "topckgen"; + break; + case CLK_PARENT_INFRASYS: + parent_type_str = "infrasys"; + break; + case CLK_PARENT_XTAL: + parent_type_str = "xtal"; + break; + case CLK_PARENT_MIXED: + parent_type_str = "mixed"; + break; + default: + parent_type_str = "default"; + break; + } + + printf("%s%s-%u", prefix, parent_type_str, parent); +} + +static void mtk_clk_print_single_parent(int parent, u32 flags) +{ + mtk_clk_print_parent(", Parent: ", parent, flags); +} + +static void mtk_clk_print_mux_parents(struct mtk_clk_priv *priv, + const struct mtk_composite *mux) +{ + const char *prefix = ""; + u32 selected; + int i; + + printf(", Parents: "); + + selected = readl(priv->base + mux->mux_reg); + selected &= mux->mux_mask << mux->mux_shift; + selected >>= mux->mux_shift; + + /* Print parents separated by "/" and selected parent enclosed in "*"s */ + for (i = 0; i < mux->num_parents; i++) { + if (i == selected) { + printf("%s", prefix); + prefix = "*"; + } + + if (mux->flags & CLK_PARENT_MIXED) { + const struct mtk_parent *parent = &mux->parent_flags[i]; + + mtk_clk_print_parent(prefix, parent->id, parent->flags); + } else { + mtk_clk_print_parent(prefix, mux->parent[i], mux->flags); + } + + prefix = "/"; + + if (i == selected) + printf("*"); + } +} +#endif + /* apmixedsys functions */ +static const int mtk_apmixedsys_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_clk_tree *tree = priv->tree; + int ret; + + ret = mtk_common_clk_of_xlate(clk, args, tree); + if (ret) + return ret; + + /* apmixedsys only uses plls and gates. */ + + if (tree->plls && clk->id < tree->num_plls) + return 0; + + if (tree->gates && clk->id >= tree->gates_offs && + clk->id < tree->gates_offs + tree->num_gates) + return 0; + + return -ENOENT; +} + static unsigned long __mtk_pll_recalc_rate(const struct mtk_pll_data *pll, u32 fin, u32 pcw, int postdiv) { @@ -274,15 +428,14 @@ static void mtk_pll_calc_values(struct mtk_clk_priv *priv, u32 id, static ulong mtk_apmixedsys_set_rate(struct clk *clk, ulong rate) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); u32 pcw = 0; u32 postdiv; - if (priv->tree->gates && id >= priv->tree->gates_offs) + if (priv->tree->gates && clk->id >= priv->tree->gates_offs) return -EINVAL; - mtk_pll_calc_values(priv, id, &pcw, &postdiv, rate); - mtk_pll_set_rate_regs(priv, id, pcw, postdiv); + mtk_pll_calc_values(priv, clk->id, &pcw, &postdiv, rate); + mtk_pll_set_rate_regs(priv, clk->id, pcw, postdiv); return 0; } @@ -291,18 +444,17 @@ static ulong mtk_apmixedsys_get_rate(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); const struct mtk_pll_data *pll; - int id = mtk_clk_get_id(clk); const struct mtk_gate *gate; u32 postdiv; u32 pcw; /* GATE handling */ - if (priv->tree->gates && id >= priv->tree->gates_offs) { - gate = &priv->tree->gates[id - priv->tree->gates_offs]; + if (priv->tree->gates && clk->id >= priv->tree->gates_offs) { + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; return mtk_clk_find_parent_rate(clk, gate->parent, NULL); } - pll = &priv->tree->plls[id]; + pll = &priv->tree->plls[clk->id]; postdiv = (readl(priv->base + pll->pd_reg) >> pll->pd_shift) & POSTDIV_MASK; @@ -319,17 +471,16 @@ static int mtk_apmixedsys_enable(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); const struct mtk_pll_data *pll; - int id = mtk_clk_get_id(clk); const struct mtk_gate *gate; u32 r; /* GATE handling */ - if (priv->tree->gates && id >= priv->tree->gates_offs) { - gate = &priv->tree->gates[id - priv->tree->gates_offs]; + if (priv->tree->gates && clk->id >= priv->tree->gates_offs) { + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; return mtk_gate_enable(priv->base, gate); } - pll = &priv->tree->plls[id]; + pll = &priv->tree->plls[clk->id]; r = readl(priv->base + pll->pwr_reg) | CON0_PWR_ON; writel(r, priv->base + pll->pwr_reg); @@ -358,17 +509,16 @@ static int mtk_apmixedsys_disable(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); const struct mtk_pll_data *pll; - int id = mtk_clk_get_id(clk); const struct mtk_gate *gate; u32 r; /* GATE handling */ - if (priv->tree->gates && id >= priv->tree->gates_offs) { - gate = &priv->tree->gates[id - priv->tree->gates_offs]; + if (priv->tree->gates && clk->id >= priv->tree->gates_offs) { + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; return mtk_gate_disable(priv->base, gate); } - pll = &priv->tree->plls[id]; + pll = &priv->tree->plls[clk->id]; if (pll->flags & HAVE_RST_BAR) { r = readl(priv->base + pll->reg + REG_CON0); @@ -389,8 +539,65 @@ static int mtk_apmixedsys_disable(struct clk *clk) return 0; } +#if CONFIG_IS_ENABLED(CMD_CLK) +static void mtk_apmixedsys_dump(struct udevice *dev) +{ + struct mtk_clk_priv *priv = dev_get_priv(dev); + const struct mtk_clk_tree *tree = priv->tree; + u32 i; + + mtk_clk_print_dev_parent(priv->parent); + + for (i = 0; i < tree->num_plls; i++) { + const struct mtk_pll_data *pll = &tree->plls[i]; + + printf("[PLL%u] DT: %u", i, pll->id); + mtk_clk_print_mapped_id(pll->id, i, tree->id_offs_map); + mtk_clk_print_rate(dev, i); + printf("\n"); + } + + for (i = 0; i < tree->num_gates; i++) { + const struct mtk_gate *gate = &tree->gates[i]; + + printf("[GATE%u] DT: %u", i, gate->id); + mtk_clk_print_mapped_id(gate->id, i + tree->gates_offs, tree->id_offs_map); + mtk_clk_print_rate(dev, i + tree->gates_offs); + mtk_clk_print_single_parent(gate->parent, gate->flags); + printf("\n"); + } +} +#endif + /* topckgen functions */ +static const int mtk_topckgen_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_clk_tree *tree = priv->tree; + int ret; + + ret = mtk_common_clk_of_xlate(clk, args, tree); + if (ret) + return ret; + + /* topckgen only uses fclks, fdivs and muxes. */ + + if (tree->fclks && clk->id < tree->num_fclks) + return 0; + + if (tree->fdivs && clk->id >= tree->fdivs_offs && + clk->id < tree->fdivs_offs + tree->num_fdivs) + return 0; + + if (tree->muxes && clk->id >= tree->muxes_offs && + clk->id < tree->muxes_offs + tree->num_muxes) + return 0; + + return -ENOENT; +} + static ulong mtk_factor_recalc_rate(const struct mtk_fixed_factor *fdiv, ulong parent_rate) { @@ -421,26 +628,8 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off) rate = priv->tree->xtal_rate; } - return mtk_factor_recalc_rate(fdiv, rate); -} - -static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off) -{ - struct mtk_clk_priv *priv = dev_get_priv(clk->dev); - const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off]; - ulong rate; - - switch (fdiv->flags & CLK_PARENT_MASK) { - case CLK_PARENT_TOPCKGEN: - rate = mtk_clk_find_parent_rate(clk, fdiv->parent, - priv->parent); - break; - case CLK_PARENT_XTAL: - rate = priv->tree->xtal_rate; - break; - default: - rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); - } + if (((long)rate) < 0) + return rate; return mtk_factor_recalc_rate(fdiv, rate); } @@ -504,95 +693,30 @@ static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk, } } -static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off) -{ - struct mtk_clk_priv *priv = dev_get_priv(clk->dev); - const struct mtk_composite *mux = &priv->tree->muxes[off]; - u32 index; - - index = readl(priv->base + mux->mux_reg); - index &= mux->mux_mask << mux->mux_shift; - index = index >> mux->mux_shift; - - /* - * Parents can be either from TOPCKGEN or INFRACFG, - * inspect the mtk_parent struct to check the source - */ - if (mux->flags & CLK_PARENT_MIXED) { - const struct mtk_parent *parent = &mux->parent_flags[index]; - - return mtk_find_parent_rate(priv, clk, parent->id, parent->flags); - } - - if (mux->parent[index] == CLK_XTAL && - !(priv->tree->flags & CLK_BYPASS_XTAL)) - return priv->tree->xtal_rate; - - return mtk_find_parent_rate(priv, clk, mux->parent[index], mux->flags); -} - static ulong mtk_topckgen_get_rate(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); - if (id < priv->tree->fdivs_offs) - return priv->tree->fclks[id].rate; - else if (id < priv->tree->muxes_offs) - return mtk_topckgen_get_factor_rate(clk, id - + if (clk->id < priv->tree->fdivs_offs) + return priv->tree->fclks[clk->id].rate; + else if (clk->id < priv->tree->muxes_offs) + return mtk_topckgen_get_factor_rate(clk, clk->id - priv->tree->fdivs_offs); else - return mtk_topckgen_get_mux_rate(clk, id - + return mtk_topckgen_get_mux_rate(clk, clk->id - priv->tree->muxes_offs); } -static ulong mtk_infrasys_get_rate(struct clk *clk) -{ - struct mtk_clk_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); - ulong rate; - - if (id < priv->tree->fdivs_offs) { - rate = priv->tree->fclks[id].rate; - } else if (id < priv->tree->muxes_offs) { - rate = mtk_infrasys_get_factor_rate(clk, id - - priv->tree->fdivs_offs); - /* No gates defined or ID is a MUX */ - } else if (!priv->tree->gates || id < priv->tree->gates_offs) { - rate = mtk_infrasys_get_mux_rate(clk, id - - priv->tree->muxes_offs); - /* Only valid with muxes + gates implementation */ - } else { - struct udevice *parent = NULL; - const struct mtk_gate *gate; - - gate = &priv->tree->gates[id - priv->tree->gates_offs]; - if (gate->flags & CLK_PARENT_TOPCKGEN) - parent = priv->parent; - /* - * Assume xtal_rate to be declared if some gates have - * XTAL as parent - */ - else if (gate->flags & CLK_PARENT_XTAL) - return priv->tree->xtal_rate; - - rate = mtk_clk_find_parent_rate(clk, gate->parent, parent); - } - - return rate; -} - static int mtk_clk_mux_enable(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); const struct mtk_composite *mux; - int id = mtk_clk_get_id(clk); u32 val; - if (id < priv->tree->muxes_offs) + if (clk->id < priv->tree->muxes_offs) return 0; - mux = &priv->tree->muxes[id - priv->tree->muxes_offs]; + mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs]; if (mux->gate_shift < 0) return 0; @@ -620,13 +744,12 @@ static int mtk_clk_mux_disable(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); const struct mtk_composite *mux; - int id = mtk_clk_get_id(clk); u32 val; - if (id < priv->tree->muxes_offs) + if (clk->id < priv->tree->muxes_offs) return 0; - mux = &priv->tree->muxes[id - priv->tree->muxes_offs]; + mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs]; if (mux->gate_shift < 0) return 0; @@ -647,10 +770,9 @@ static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent) { struct mtk_clk_priv *parent_priv = dev_get_priv(parent->dev); struct mtk_clk_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); u32 parent_type; - if (id < priv->tree->muxes_offs) + if (clk->id < priv->tree->muxes_offs) return 0; if (!parent_priv) @@ -658,62 +780,272 @@ static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent) parent_type = parent_priv->tree->flags & CLK_PARENT_MASK; return mtk_clk_mux_set_parent(priv->base, parent->id, parent_type, - &priv->tree->muxes[id - priv->tree->muxes_offs]); + &priv->tree->muxes[clk->id - priv->tree->muxes_offs]); } -/* CG functions */ - -static int mtk_clk_gate_enable(struct clk *clk) +#if CONFIG_IS_ENABLED(CMD_CLK) +static void mtk_topckgen_dump(struct udevice *dev) { - struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); - const struct mtk_gate *gate; + struct mtk_clk_priv *priv = dev_get_priv(dev); + const struct mtk_clk_tree *tree = priv->tree; + u32 i; - if (id < priv->tree->gates_offs) - return -EINVAL; + mtk_clk_print_dev_parent(priv->parent); - gate = &priv->gates[id - priv->tree->gates_offs]; - return mtk_gate_enable(priv->base, gate); + for (i = 0; i < tree->num_fclks; i++) { + const struct mtk_fixed_clk *fclk = &tree->fclks[i]; + + printf("[FCLK%u] DT: %u", i, fclk->id); + mtk_clk_print_mapped_id(fclk->id, i, tree->id_offs_map); + mtk_clk_print_rate(dev, i); + /* FIXME: fclk needs flags to fully determine parent. */ + mtk_clk_print_single_parent(fclk->parent, 0); + printf("\n"); + } + + for (i = 0; i < tree->num_fdivs; i++) { + const struct mtk_fixed_factor *fdiv = &tree->fdivs[i]; + + printf("[FDIV%u] DT: %u", i, fdiv->id); + mtk_clk_print_mapped_id(fdiv->id, i + tree->fdivs_offs, tree->id_offs_map); + mtk_clk_print_rate(dev, i + tree->fdivs_offs); + mtk_clk_print_single_parent(fdiv->parent, fdiv->flags); + printf(", Mult: %u, Div: %u\n", fdiv->mult, fdiv->div); + } + + for (i = 0; i < tree->num_muxes; i++) { + const struct mtk_composite *mux = &tree->muxes[i]; + + printf("[MUX%u] DT: %u", i, mux->id); + mtk_clk_print_mapped_id(mux->id, i + tree->muxes_offs, tree->id_offs_map); + mtk_clk_print_rate(dev, i + tree->muxes_offs); + mtk_clk_print_mux_parents(priv, mux); + printf("\n"); + } +} +#endif + +/* infrasys functions */ + +static const int mtk_infrasys_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_clk_tree *tree = priv->tree; + int ret; + + ret = mtk_common_clk_of_xlate(clk, args, tree); + if (ret) + return ret; + + /* ifrasys only uses fdivs, muxes and gates. */ + + if (tree->fdivs && clk->id >= tree->fdivs_offs && + clk->id < tree->fdivs_offs + tree->num_fdivs) + return 0; + + if (tree->muxes && clk->id >= tree->muxes_offs && + clk->id < tree->muxes_offs + tree->num_muxes) + return 0; + + if (tree->gates && clk->id >= tree->gates_offs && + clk->id < tree->gates_offs + tree->num_gates) + return 0; + + return -ENOENT; } static int mtk_clk_infrasys_enable(struct clk *clk) { struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); const struct mtk_gate *gate; /* MUX handling */ - if (!priv->tree->gates || id < priv->tree->gates_offs) + if (!priv->tree->gates || clk->id < priv->tree->gates_offs) return mtk_clk_mux_enable(clk); - gate = &priv->tree->gates[id - priv->tree->gates_offs]; + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; + return mtk_gate_enable(priv->base, gate); +} + +static int mtk_clk_infrasys_disable(struct clk *clk) +{ + struct mtk_cg_priv *priv = dev_get_priv(clk->dev); + const struct mtk_gate *gate; + + /* MUX handling */ + if (!priv->tree->gates || clk->id < priv->tree->gates_offs) + return mtk_clk_mux_disable(clk); + + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; + return mtk_gate_disable(priv->base, gate); +} + +static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off]; + ulong rate; + + switch (fdiv->flags & CLK_PARENT_MASK) { + case CLK_PARENT_TOPCKGEN: + rate = mtk_clk_find_parent_rate(clk, fdiv->parent, + priv->parent); + break; + case CLK_PARENT_XTAL: + rate = priv->tree->xtal_rate; + break; + default: + rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); + } + + if (((long)rate) < 0) + return rate; + + return mtk_factor_recalc_rate(fdiv, rate); +} + +static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_composite *mux = &priv->tree->muxes[off]; + u32 index; + + index = readl(priv->base + mux->mux_reg); + index &= mux->mux_mask << mux->mux_shift; + index = index >> mux->mux_shift; + + /* + * Parents can be either from TOPCKGEN or INFRACFG, + * inspect the mtk_parent struct to check the source + */ + if (mux->flags & CLK_PARENT_MIXED) { + const struct mtk_parent *parent = &mux->parent_flags[index]; + + return mtk_find_parent_rate(priv, clk, parent->id, parent->flags); + } + + if (mux->parent[index] == CLK_XTAL && + !(priv->tree->flags & CLK_BYPASS_XTAL)) + return priv->tree->xtal_rate; + + return mtk_find_parent_rate(priv, clk, mux->parent[index], mux->flags); +} + +static ulong mtk_infrasys_get_rate(struct clk *clk) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + ulong rate; + + if (clk->id < priv->tree->fdivs_offs) { + rate = priv->tree->fclks[clk->id].rate; + } else if (clk->id < priv->tree->muxes_offs) { + rate = mtk_infrasys_get_factor_rate(clk, clk->id - + priv->tree->fdivs_offs); + /* No gates defined or ID is a MUX */ + } else if (!priv->tree->gates || clk->id < priv->tree->gates_offs) { + rate = mtk_infrasys_get_mux_rate(clk, clk->id - + priv->tree->muxes_offs); + /* Only valid with muxes + gates implementation */ + } else { + struct udevice *parent = NULL; + const struct mtk_gate *gate; + + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; + if (gate->flags & CLK_PARENT_TOPCKGEN) + parent = priv->parent; + /* + * Assume xtal_rate to be declared if some gates have + * XTAL as parent + */ + else if (gate->flags & CLK_PARENT_XTAL) + return priv->tree->xtal_rate; + + rate = mtk_clk_find_parent_rate(clk, gate->parent, parent); + } + + return rate; +} + +#if CONFIG_IS_ENABLED(CMD_CLK) +static void mtk_infrasys_dump(struct udevice *dev) +{ + struct mtk_clk_priv *priv = dev_get_priv(dev); + const struct mtk_clk_tree *tree = priv->tree; + u32 i; + + mtk_clk_print_dev_parent(priv->parent); + + for (i = 0; i < tree->num_fdivs; i++) { + const struct mtk_fixed_factor *fdiv = &tree->fdivs[i]; + + printf("[FDIV%u] DT: %u", i, fdiv->id); + mtk_clk_print_mapped_id(fdiv->id, i + tree->fdivs_offs, tree->id_offs_map); + mtk_clk_print_single_parent(fdiv->parent, fdiv->flags); + printf(", Mult: %u, Div: %u\n", fdiv->mult, fdiv->div); + } + + for (i = 0; i < tree->num_muxes; i++) { + const struct mtk_composite *mux = &tree->muxes[i]; + + printf("[MUX%u] DT: %u", i, mux->id); + mtk_clk_print_mapped_id(mux->id, i + tree->muxes_offs, tree->id_offs_map); + mtk_clk_print_mux_parents(priv, mux); + printf("\n"); + } + + for (i = 0; i < tree->num_gates; i++) { + const struct mtk_gate *gate = &tree->gates[i]; + + printf("[GATE%u] DT: %u", i, gate->id); + mtk_clk_print_mapped_id(gate->id, i + tree->gates_offs, tree->id_offs_map); + mtk_clk_print_single_parent(gate->parent, gate->flags); + printf("\n"); + } +} +#endif + +/* CG functions */ + +static const int mtk_clk_gate_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + struct mtk_cg_priv *priv = dev_get_priv(clk->dev); + const struct mtk_clk_tree *tree = priv->tree; + int ret; + + ret = mtk_common_clk_of_xlate(clk, args, tree); + if (ret) + return ret; + + if (clk->id >= tree->gates_offs && + clk->id < tree->gates_offs + priv->num_gates) + return 0; + + return -ENOENT; +} + +static int mtk_clk_gate_enable(struct clk *clk) +{ + struct mtk_cg_priv *priv = dev_get_priv(clk->dev); + const struct mtk_gate *gate; + + if (clk->id < priv->tree->gates_offs) + return -EINVAL; + + gate = &priv->gates[clk->id - priv->tree->gates_offs]; return mtk_gate_enable(priv->base, gate); } static int mtk_clk_gate_disable(struct clk *clk) { struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); const struct mtk_gate *gate; - if (id < priv->tree->gates_offs) + if (clk->id < priv->tree->gates_offs) return -EINVAL; - gate = &priv->gates[id - priv->tree->gates_offs]; - return mtk_gate_disable(priv->base, gate); -} - -static int mtk_clk_infrasys_disable(struct clk *clk) -{ - struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - int id = mtk_clk_get_id(clk); - const struct mtk_gate *gate; - - /* MUX handling */ - if (!priv->tree->gates || id < priv->tree->gates_offs) - return mtk_clk_mux_disable(clk); - - gate = &priv->tree->gates[id - priv->tree->gates_offs]; + gate = &priv->gates[clk->id - priv->tree->gates_offs]; return mtk_gate_disable(priv->base, gate); } @@ -721,13 +1053,12 @@ static ulong mtk_clk_gate_get_rate(struct clk *clk) { struct mtk_cg_priv *priv = dev_get_priv(clk->dev); struct udevice *parent = priv->parent; - int id = mtk_clk_get_id(clk); const struct mtk_gate *gate; - if (id < priv->tree->gates_offs) + if (clk->id < priv->tree->gates_offs) return -EINVAL; - gate = &priv->gates[id - priv->tree->gates_offs]; + gate = &priv->gates[clk->id - priv->tree->gates_offs]; /* * With requesting a TOPCKGEN parent, make sure the dev parent * is actually topckgen. This might not be the case for an @@ -750,37 +1081,78 @@ static ulong mtk_clk_gate_get_rate(struct clk *clk) return mtk_clk_find_parent_rate(clk, gate->parent, parent); } +#if CONFIG_IS_ENABLED(CMD_CLK) +static void mtk_clk_gate_dump(struct udevice *dev) +{ + struct mtk_cg_priv *priv = dev_get_priv(dev); + const struct mtk_clk_tree *tree = priv->tree; + u32 i; + + mtk_clk_print_dev_parent(priv->parent); + + for (i = 0; i < priv->num_gates; i++) { + const struct mtk_gate *gate = &priv->gates[i]; + + printf("[GATE%u] DT: %u", i, gate->id); + mtk_clk_print_mapped_id(gate->id, i + tree->gates_offs, tree->id_offs_map); + mtk_clk_print_rate(dev, i + tree->gates_offs); + mtk_clk_print_single_parent(gate->parent, gate->flags); + printf("\n"); + } +} +#endif + const struct clk_ops mtk_clk_apmixedsys_ops = { + .of_xlate = mtk_apmixedsys_of_xlate, .enable = mtk_apmixedsys_enable, .disable = mtk_apmixedsys_disable, .set_rate = mtk_apmixedsys_set_rate, .get_rate = mtk_apmixedsys_get_rate, +#if CONFIG_IS_ENABLED(CMD_CLK) + .dump = mtk_apmixedsys_dump, +#endif }; const struct clk_ops mtk_clk_fixed_pll_ops = { + .of_xlate = mtk_topckgen_of_xlate, .enable = mtk_dummy_enable, .disable = mtk_dummy_enable, .get_rate = mtk_topckgen_get_rate, +#if CONFIG_IS_ENABLED(CMD_CLK) + .dump = mtk_topckgen_dump, +#endif }; const struct clk_ops mtk_clk_topckgen_ops = { + .of_xlate = mtk_topckgen_of_xlate, .enable = mtk_clk_mux_enable, .disable = mtk_clk_mux_disable, .get_rate = mtk_topckgen_get_rate, .set_parent = mtk_common_clk_set_parent, +#if CONFIG_IS_ENABLED(CMD_CLK) + .dump = mtk_topckgen_dump, +#endif }; const struct clk_ops mtk_clk_infrasys_ops = { + .of_xlate = mtk_infrasys_of_xlate, .enable = mtk_clk_infrasys_enable, .disable = mtk_clk_infrasys_disable, .get_rate = mtk_infrasys_get_rate, .set_parent = mtk_common_clk_set_parent, +#if CONFIG_IS_ENABLED(CMD_CLK) + .dump = mtk_infrasys_dump, +#endif }; const struct clk_ops mtk_clk_gate_ops = { + .of_xlate = mtk_clk_gate_of_xlate, .enable = mtk_clk_gate_enable, .disable = mtk_clk_gate_disable, .get_rate = mtk_clk_gate_get_rate, +#if CONFIG_IS_ENABLED(CMD_CLK) + .dump = mtk_clk_gate_dump, +#endif }; static int mtk_common_clk_init_drv(struct udevice *dev, @@ -824,7 +1196,7 @@ int mtk_common_clk_infrasys_init(struct udevice *dev, int mtk_common_clk_gate_init(struct udevice *dev, const struct mtk_clk_tree *tree, - const struct mtk_gate *gates) + const struct mtk_gate *gates, int num_gates) { struct mtk_cg_priv *priv = dev_get_priv(dev); struct udevice *parent; @@ -845,6 +1217,7 @@ int mtk_common_clk_gate_init(struct udevice *dev, priv->parent = parent; priv->tree = tree; priv->gates = gates; + priv->num_gates = num_gates; return 0; } diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 8ce7e52fd60..bd8899193c9 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -45,6 +45,7 @@ /* struct mtk_pll_data - hardware-specific PLLs data */ struct mtk_pll_data { + /* unmapped ID of clock */ const int id; u32 reg; u32 pwr_reg; @@ -65,8 +66,8 @@ struct mtk_pll_data { /** * struct mtk_fixed_clk - fixed clocks * - * @id: index of clocks - * @parent: index of parnet clocks + * @id: unmapped ID of clock + * @parent: unmapped ID of parent clock * @rate: fixed rate */ struct mtk_fixed_clk { @@ -84,8 +85,8 @@ struct mtk_fixed_clk { /** * struct mtk_fixed_factor - fixed multiplier and divider clocks * - * @id: index of clocks - * @parent: index of parnet clocks + * @id: unmapped ID of clock + * @parent: unmapped ID of parent clock * @mult: multiplier * @div: divider * @flag: hardware-specific flags @@ -110,7 +111,7 @@ struct mtk_fixed_factor { * struct mtk_parent - clock parent with flags. Needed for MUX that * parent with mixed infracfg and topckgen. * - * @id: index of parent clocks + * @id: unmapped ID of parent clocks * @flags: hardware-specific flags (parent location, * infracfg, topckgen, APMIXED, xtal ...) */ @@ -127,8 +128,8 @@ struct mtk_parent { /** * struct mtk_composite - aggregate clock of mux, divider and gate clocks * - * @id: index of clocks - * @parent: index of parent clocks + * @id: unmapped ID of clocks + * @parent: unmapped ID of parent clocks * @parent_flags: table of parent clocks with flags * @mux_reg: hardware-specific mux register * @gate_reg: hardware-specific gate register @@ -226,8 +227,8 @@ struct mtk_gate_regs { /** * struct mtk_gate - gate clocks * - * @id: index of gate clocks - * @parent: index of parnet clocks + * @id: unmapped ID of gate clocks + * @parent: unmapped ID of parent clocks * @regs: hardware-specific mux register * @shift: shift to the gate bit field * @flags: hardware-specific flags @@ -245,13 +246,17 @@ struct mtk_clk_tree { unsigned long xtal_rate; unsigned long xtal2_rate; /* - * Clock ID offset are remapped with an auxiliary table. - * Enable this by defining .id_offs_map. - * This is needed for upstream linux kernel -clk.h that - * have mixed clk ID and doesn't have clear distinction between - * ID for factor, mux and gates. + * Clock IDs may be remapped with an auxiliary table. Enable this by + * defining .id_offs_map and .id_offs_map_size. This is needed e.g. when + * the upstream Linux kernel -clk.h has mixed clk IDs and doesn't + * have clear distinction between ID for factor, mux and gates. When + * this is enabled, the struct clk->id will contained the mapped ID that + * is the index in the various arrays in this struct. The .id and + * .parent fields in the various mtk_* structs will contain the + * unmapped IDs as defined in the upstream Linux kernel -clk.h. */ - const int *id_offs_map; /* optional, table clk.h to driver ID */ + const int *id_offs_map; /* optional, maps clk.h ID to array index */ + const int id_offs_map_size; const int fdivs_offs; const int muxes_offs; const int gates_offs; @@ -260,6 +265,11 @@ struct mtk_clk_tree { const struct mtk_fixed_factor *fdivs; const struct mtk_composite *muxes; const struct mtk_gate *gates; + const int num_plls; + const int num_fclks; + const int num_fdivs; + const int num_muxes; + const int num_gates; u32 flags; }; @@ -274,6 +284,7 @@ struct mtk_cg_priv { void __iomem *base; const struct mtk_clk_tree *tree; const struct mtk_gate *gates; + int num_gates; }; extern const struct clk_ops mtk_clk_apmixedsys_ops; @@ -288,6 +299,6 @@ int mtk_common_clk_infrasys_init(struct udevice *dev, const struct mtk_clk_tree *tree); int mtk_common_clk_gate_init(struct udevice *dev, const struct mtk_clk_tree *tree, - const struct mtk_gate *gates); + const struct mtk_gate *gates, int num_gates); #endif /* __DRV_CLK_MTK_H */