From 3d54f47ae50b737e4f577ab2d41df51f67e975ed Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:11 -0600 Subject: [PATCH 1/8] clk: mediatek: add array size fields to clk trees Add num_plls, num_fclks, num_fdivs, num_muxes, and num_gates fields to the mtk_clk_tree struct and populate them in the clk trees for all existing drivers. Currently, there is no bounds checking when accessing the arrays in the clk tree structs. Adding these fields will allow for bounds checking in the future. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mt7622.c | 9 +++++++++ drivers/clk/mediatek/clk-mt7623.c | 6 ++++++ drivers/clk/mediatek/clk-mt7629.c | 8 ++++++++ drivers/clk/mediatek/clk-mt7981.c | 7 +++++++ drivers/clk/mediatek/clk-mt7986.c | 7 +++++++ drivers/clk/mediatek/clk-mt7987.c | 5 +++++ drivers/clk/mediatek/clk-mt7988.c | 6 ++++++ drivers/clk/mediatek/clk-mt8183.c | 4 ++++ drivers/clk/mediatek/clk-mt8188.c | 4 ++++ drivers/clk/mediatek/clk-mt8365.c | 4 ++++ drivers/clk/mediatek/clk-mt8512.c | 4 ++++ drivers/clk/mediatek/clk-mt8516.c | 4 ++++ drivers/clk/mediatek/clk-mt8518.c | 4 ++++ drivers/clk/mediatek/clk-mtk.h | 5 +++++ 14 files changed, 77 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c index 23b9787612a..ccad3820c1b 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) diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c index d0b80f48b0a..cfc711ad216 100644 --- a/drivers/clk/mediatek/clk-mt7623.c +++ b/drivers/clk/mediatek/clk-mt7623.c @@ -997,6 +997,7 @@ static const struct mtk_clk_tree mt7623_apmixedsys_clk_tree = { .xtal2_rate = 26 * MHZ, .id_offs_map = pll_id_offs_map, .plls = apmixed_plls, + .num_plls = ARRAY_SIZE(apmixed_plls), }; static const struct mtk_clk_tree mt7623_topckgen_clk_tree = { @@ -1007,6 +1008,9 @@ static const struct mtk_clk_tree mt7623_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), }; static int mt7623_mcucfg_probe(struct udevice *dev) @@ -1063,6 +1067,8 @@ static const struct mtk_clk_tree mt7623_clk_peri_tree = { .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, }; diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index 94fc5e51456..e0eff01561c 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) diff --git a/drivers/clk/mediatek/clk-mt7981.c b/drivers/clk/mediatek/clk-mt7981.c index 2fdb1845e9f..f854f079c67 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, }; diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c index 16db5877056..257f89b7daa 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, }; diff --git a/drivers/clk/mediatek/clk-mt7987.c b/drivers/clk/mediatek/clk-mt7987.c index caee8bf43e4..b559152c045 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, }; diff --git a/drivers/clk/mediatek/clk-mt7988.c b/drivers/clk/mediatek/clk-mt7988.c index bfbf401eb12..56f3e5ebdff 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, }; diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c index 9612a62e56a..7a1953ef6fd 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 = { diff --git a/drivers/clk/mediatek/clk-mt8188.c b/drivers/clk/mediatek/clk-mt8188.c index 55dfadddfe3..186638fcb66 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[] = { @@ -1364,6 +1365,9 @@ static const struct mtk_clk_tree mt8188_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), }; static const struct mtk_gate_regs infra_ao0_cg_regs = { diff --git a/drivers/clk/mediatek/clk-mt8365.c b/drivers/clk/mediatek/clk-mt8365.c index 53eca73b98d..7897044e1ad 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 */ diff --git a/drivers/clk/mediatek/clk-mt8512.c b/drivers/clk/mediatek/clk-mt8512.c index ab270673442..6d98403bc45 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) diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c index 623f88499f1..c21b9894ad6 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) diff --git a/drivers/clk/mediatek/clk-mt8518.c b/drivers/clk/mediatek/clk-mt8518.c index ba8cc584d46..48ef209ebbd 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) diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 8ce7e52fd60..a4a3307e576 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -260,6 +260,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; }; From 538f72f4038652be5bbb907f23fbc74dad682a19 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:12 -0600 Subject: [PATCH 2/8] clk: mediatek: add array size fields to cg gates Add num_gates field to struct mtk_cg_priv and populate it for all existing drivers. Currently, there is no bounds checking when accessing the gates array. Adding this field will allow for bounds checking in the future. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mt7622.c | 12 ++++++++---- drivers/clk/mediatek/clk-mt7623.c | 12 ++++++------ drivers/clk/mediatek/clk-mt7629.c | 15 ++++++++++----- drivers/clk/mediatek/clk-mt7981.c | 6 +++--- drivers/clk/mediatek/clk-mt7986.c | 4 ++-- drivers/clk/mediatek/clk-mt7987.c | 4 ++-- drivers/clk/mediatek/clk-mt7988.c | 12 ++++++++---- drivers/clk/mediatek/clk-mt8183.c | 3 ++- drivers/clk/mediatek/clk-mt8188.c | 23 +++++++++++++++++------ drivers/clk/mediatek/clk-mt8365.c | 6 ++++-- drivers/clk/mediatek/clk-mt8512.c | 6 ++++-- drivers/clk/mediatek/clk-mt8516.c | 3 ++- drivers/clk/mediatek/clk-mt8518.c | 3 ++- drivers/clk/mediatek/clk-mtk.c | 3 ++- drivers/clk/mediatek/clk-mtk.h | 3 ++- 15 files changed, 74 insertions(+), 41 deletions(-) diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c index ccad3820c1b..16c6f024e72 100644 --- a/drivers/clk/mediatek/clk-mt7622.c +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -692,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) @@ -710,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) @@ -728,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 cfc711ad216..5a60a86233e 100644 --- a/drivers/clk/mediatek/clk-mt7623.c +++ b/drivers/clk/mediatek/clk-mt7623.c @@ -1057,8 +1057,8 @@ 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 = { @@ -1079,14 +1079,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 e0eff01561c..e4132f6195f 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -634,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) @@ -662,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 f854f079c67..c8090688df0 100644 --- a/drivers/clk/mediatek/clk-mt7981.c +++ b/drivers/clk/mediatek/clk-mt7981.c @@ -631,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[] = { @@ -658,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[] = { @@ -699,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 257f89b7daa..735e824c874 100644 --- a/drivers/clk/mediatek/clk-mt7986.c +++ b/drivers/clk/mediatek/clk-mt7986.c @@ -636,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 b559152c045..99ff57c5dc5 100644 --- a/drivers/clk/mediatek/clk-mt7987.c +++ b/drivers/clk/mediatek/clk-mt7987.c @@ -818,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 56f3e5ebdff..da1d2e89d61 100644 --- a/drivers/clk/mediatek/clk-mt7988.c +++ b/drivers/clk/mediatek/clk-mt7988.c @@ -892,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) @@ -950,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[] = { @@ -994,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[] = { @@ -1040,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 7a1953ef6fd..5b41cf4b88c 100644 --- a/drivers/clk/mediatek/clk-mt8183.c +++ b/drivers/clk/mediatek/clk-mt8183.c @@ -777,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 186638fcb66..f7c04047f4d 100644 --- a/drivers/clk/mediatek/clk-mt8188.c +++ b/drivers/clk/mediatek/clk-mt8188.c @@ -1694,33 +1694,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 7897044e1ad..c88545fc7cf 100644 --- a/drivers/clk/mediatek/clk-mt8365.c +++ b/drivers/clk/mediatek/clk-mt8365.c @@ -705,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 6d98403bc45..d4f6604c160 100644 --- a/drivers/clk/mediatek/clk-mt8512.c +++ b/drivers/clk/mediatek/clk-mt8512.c @@ -808,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 c21b9894ad6..d5f922886a3 100644 --- a/drivers/clk/mediatek/clk-mt8516.c +++ b/drivers/clk/mediatek/clk-mt8516.c @@ -757,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 48ef209ebbd..92730f3f06c 100644 --- a/drivers/clk/mediatek/clk-mt8518.c +++ b/drivers/clk/mediatek/clk-mt8518.c @@ -1513,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..ffaecbfd306 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -824,7 +824,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 +845,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 a4a3307e576..7bd432cb93d 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -279,6 +279,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; @@ -293,6 +294,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 */ From 6094f0a040765932dd7820941fd77e25c6dd4e34 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:13 -0600 Subject: [PATCH 3/8] clk: mediatek: add array size field for id_offs_map Add id_offs_map_size field to struct mtk_clk_tree and populate it for all existing drivers. Currently, there is no bounds checking when accessing the id_offs_map array. Adding this field will allow for bounds checking in the future. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mt7623.c | 3 +++ drivers/clk/mediatek/clk-mt8188.c | 1 + drivers/clk/mediatek/clk-mtk.h | 1 + 3 files changed, 5 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c index 5a60a86233e..eca8352d8e6 100644 --- a/drivers/clk/mediatek/clk-mt7623.c +++ b/drivers/clk/mediatek/clk-mt7623.c @@ -996,6 +996,7 @@ 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), }; @@ -1003,6 +1004,7 @@ static const struct mtk_clk_tree mt7623_apmixedsys_clk_tree = { 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, @@ -1063,6 +1065,7 @@ static int mt7623_infracfg_probe(struct udevice *dev) 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, diff --git a/drivers/clk/mediatek/clk-mt8188.c b/drivers/clk/mediatek/clk-mt8188.c index f7c04047f4d..a4cbb3213e3 100644 --- a/drivers/clk/mediatek/clk-mt8188.c +++ b/drivers/clk/mediatek/clk-mt8188.c @@ -1360,6 +1360,7 @@ 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, diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 7bd432cb93d..8a1cb0839a0 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -252,6 +252,7 @@ struct mtk_clk_tree { * ID for factor, mux and gates. */ const int *id_offs_map; /* optional, table clk.h to driver ID */ + const int id_offs_map_size; const int fdivs_offs; const int muxes_offs; const int gates_offs; From 159825bdd5ec63cd443c855adeceb3adf29e4655 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:14 -0600 Subject: [PATCH 4/8] clk: mediatek: organize infrasys functions Move all infrasys ops and related functions next to each other in the file for better organization. Generally all ops functions are grouped together like this for the other ops types (apmixedsys, topckgen, etc). However the infrasys functions were mixed in with the other sections making them harder to find. This will also give a logical place to add any future infrasys-specific functions. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mtk.c | 224 +++++++++++++++++---------------- 1 file changed, 113 insertions(+), 111 deletions(-) diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index ffaecbfd306..6ed0f23f685 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -424,27 +424,6 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off) 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); - } - - return mtk_factor_recalc_rate(fdiv, rate); -} - static ulong mtk_topckgen_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk, const int parent, u16 flags) { @@ -504,33 +483,6 @@ 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); @@ -546,42 +498,6 @@ static ulong mtk_topckgen_get_rate(struct clk *clk) 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); @@ -661,20 +577,7 @@ static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent) &priv->tree->muxes[id - priv->tree->muxes_offs]); } -/* CG functions */ - -static int mtk_clk_gate_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; - - if (id < priv->tree->gates_offs) - return -EINVAL; - - gate = &priv->gates[id - priv->tree->gates_offs]; - return mtk_gate_enable(priv->base, gate); -} +/* infrasys functions */ static int mtk_clk_infrasys_enable(struct clk *clk) { @@ -690,19 +593,6 @@ static int mtk_clk_infrasys_enable(struct clk *clk) 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) - 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); @@ -717,6 +607,118 @@ static int mtk_clk_infrasys_disable(struct clk *clk) 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); + } + + 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); + 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; +} + +/* CG functions */ + +static int mtk_clk_gate_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; + + if (id < priv->tree->gates_offs) + return -EINVAL; + + gate = &priv->gates[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) + return -EINVAL; + + gate = &priv->gates[id - priv->tree->gates_offs]; + return mtk_gate_disable(priv->base, gate); +} + static ulong mtk_clk_gate_get_rate(struct clk *clk) { struct mtk_cg_priv *priv = dev_get_priv(clk->dev); From b1358915728b9c38c0d8c4ef11a3a6f5ab5687bb Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:15 -0600 Subject: [PATCH 5/8] clk: mediatek: add of_xlate ops Add driver-specific of_xlate ops for MediaTek clocks. This provides better checking of the args passed from the devicetree. Compared to the default of_xlate implementation, this will return -EINVAL if there are zero args (id is always required) and -ENOENT if the id is out of range for the clock type. This will protect against out of bounds array accesses later on when the clk->id is used to index into the clock data arrays. If there is a id_offs_map, then we have to do that translation first before checking the id to see if it is in range. There is no sense in doing the mapping multiple times, so we save the mapped ID in clk->id and remove mtk_clk_get_id(). mtk_clk_find_parent_rate() also had to be updated since it creates a temporary struct clk to represent the parent clock. It now has do the translation in case the parent clock also uses an id_offs_map. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mtk.c | 244 ++++++++++++++++++++++++--------- 1 file changed, 183 insertions(+), 61 deletions(-) diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 6ed0f23f685..1539dc6cbcc 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); } @@ -166,6 +195,29 @@ static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent, /* 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 +326,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 +342,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 +369,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 +407,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); @@ -391,6 +439,33 @@ static int mtk_apmixedsys_disable(struct clk *clk) /* 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,6 +496,9 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off) rate = priv->tree->xtal_rate; } + if (((long)rate) < 0) + return rate; + return mtk_factor_recalc_rate(fdiv, rate); } @@ -486,15 +564,14 @@ static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk, 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); } @@ -502,13 +579,12 @@ 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; @@ -536,13 +612,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; @@ -563,10 +638,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) @@ -574,36 +648,62 @@ 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]); } /* 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); - 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_disable(clk); - gate = &priv->tree->gates[id - priv->tree->gates_offs]; + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; return mtk_gate_disable(priv->base, gate); } @@ -625,6 +725,9 @@ static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off) rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); } + if (((long)rate) < 0) + return rate; + return mtk_factor_recalc_rate(fdiv, rate); } @@ -658,24 +761,23 @@ static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off) 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 - + 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 || id < priv->tree->gates_offs) { - rate = mtk_infrasys_get_mux_rate(clk, id - + } 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[id - priv->tree->gates_offs]; + gate = &priv->tree->gates[clk->id - priv->tree->gates_offs]; if (gate->flags & CLK_PARENT_TOPCKGEN) parent = priv->parent; /* @@ -693,29 +795,45 @@ static ulong mtk_infrasys_get_rate(struct clk *clk) /* 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); - 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]; 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]; + gate = &priv->gates[clk->id - priv->tree->gates_offs]; return mtk_gate_disable(priv->base, gate); } @@ -723,13 +841,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 @@ -753,6 +870,7 @@ static ulong mtk_clk_gate_get_rate(struct clk *clk) } 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, @@ -760,12 +878,14 @@ const struct clk_ops mtk_clk_apmixedsys_ops = { }; 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, }; 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, @@ -773,6 +893,7 @@ const struct clk_ops mtk_clk_topckgen_ops = { }; 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, @@ -780,6 +901,7 @@ const struct clk_ops mtk_clk_infrasys_ops = { }; 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, From cc1a458a3d315bd94ed2b5faf7e74baf8f667d9b Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:16 -0600 Subject: [PATCH 6/8] clk: mediatek: clarify mapped vs. unmapped ID Update documentation comments to clarify the difference between which .id fields are mapped (only struct clk.id) vs. unmapped (all struct mtk_*.id and .parent fields). The unmapped IDs are the ones defined in the devicetree bindings, while the mapped IDs are the ones used as the index into the various clk arrays. Also fix spelling of "parent" while we are touching this. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mtk.h | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 8a1cb0839a0..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,16 @@ 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; From eb2bf2bc832d34440204ad90795ca7475ede4402 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:17 -0600 Subject: [PATCH 7/8] clk: mediatek: mt7623: set unmapped IDs to -1 Add range initializers to the id_offs_map arrays in the mt7623 clk driver to set unmapped IDs to -1. This prevents accidental usage of unmapped IDs that would otherwise map to 0. mtk_common_clk_of_xlate() checks these values for < 0 and returns -ENOENT in that case. A range initializer covering the entire array is used since it is less error-prone than manually looking up the value of each macro in the existing initializers and checking for gaps. It is placed first so that the specific initializers override it. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mt7623.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c index eca8352d8e6..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, From c8ebe42b3f5f753f2c84266e289a31e85e257110 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Jan 2026 09:50:18 -0600 Subject: [PATCH 8/8] clk: mediatek: implement dump callbacks Implement dump callbacks for Mediatek clocks. On these platforms, there are 100s of clocks, so it can be easy to miss mistakes. The dump callbacks will be useful for debugging and verifying clock configs. Signed-off-by: David Lechner --- drivers/clk/mediatek/clk-mtk.c | 248 +++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 1539dc6cbcc..a3dd18363f6 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -193,6 +193,108 @@ 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, @@ -437,6 +539,36 @@ 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, @@ -651,6 +783,48 @@ static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent) &priv->tree->muxes[clk->id - priv->tree->muxes_offs]); } +#if CONFIG_IS_ENABLED(CMD_CLK) +static void mtk_topckgen_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_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, @@ -793,6 +967,44 @@ static ulong mtk_infrasys_get_rate(struct clk *clk) 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, @@ -869,12 +1081,36 @@ 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 = { @@ -882,6 +1118,9 @@ const struct clk_ops mtk_clk_fixed_pll_ops = { .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 = { @@ -890,6 +1129,9 @@ const struct clk_ops mtk_clk_topckgen_ops = { .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 = { @@ -898,6 +1140,9 @@ const struct clk_ops mtk_clk_infrasys_ops = { .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 = { @@ -905,6 +1150,9 @@ const struct clk_ops mtk_clk_gate_ops = { .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,