clk: mediatek: fix gate-less mux definitions
Subsystems (2)
v2 cover clk: mediatek: fix gate-less mux definitions
Some MediaTek clock drivers define gate-less muxes without an update register using MUX_GATE_CLR_SET_UPD, passing -1 as a sentinel for the absent gate and update fields. Since those fields are stored in u8 and u32 struct members, the -1 truncates to unexpected values.
Add MUX_CLR_SET, a wrapper around MUX_CLR_SET_UPD that hardcodes the absent fields, and convert the affected mux definitions in mt8192 and mt7988 to use it.
Daniel Golle (3):
clk: mediatek: add MUX_CLR_SET macro
clk: mediatek: mt8192: use MUX_CLR_SET
clk: mediatek: mt7988: use MUX_CLR_SET for gate-less muxes
drivers/clk/mediatek/clk-mt7988-infracfg.c | 80 ++++++++++------------ drivers/clk/mediatek/clk-mt8192.c | 4 +- drivers/clk/mediatek/clk-mux.h | 6 ++ 3 files changed, 46 insertions(+), 44 deletions(-)
Signature · 1 line
2.53.0
PATCH v2 1/3 clk: mediatek: add MUX_CLR_SET macro
Some MediaTek SoCs (e.g. MT7988) define infra muxes that have neither a clock gate nor an update register.
Add a MUX_CLR_SET convenience macro that takes only the mux register offsets, bit shift, and width, hardcoding upd_ofs = 0 and upd_shift = -1 so callers cannot accidentally pass bogus sentinel values to wrongly-typed fields.
--- drivers/clk/mediatek/clk-mux.h | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/clk/mediatek/clk-mux.h +5 -0
@@ -126,6 +126,11 @@ extern const struct clk_ops mtk_mux_gate_hwv_fenc_clr_set_upd_ops; 0, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \ mtk_mux_clr_set_upd_ops) +#define MUX_CLR_SET (_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width) \ + MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width, 0, -1) + #define MUX_GATE_HWV_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents, \ _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \ _hwv_sta_ofs, _hwv_set_ofs, _hwv_clr_ofs, \
Signature · 1 line
2.53.0
Re: [PATCH v2 1/3] clk: mediatek: add MUX_CLR_SET macro
Quoted 10 lines · Daniel Golle
Some MediaTek SoCs (e.g. MT7988) define infra muxes that have neither a clock gate nor an update register.
Add a
MUX_CLR_SETconvenience macro that takes only the mux register offsets, bit shift, and width, hardcodingupd_ofs= 0 andupd_shift= -1 so callers cannot accidentally pass bogus sentinel values to wrongly-typed fields.Signed-off-by Daniel Golle <[email protected]>
Re: [PATCH v2 1/3] clk: mediatek: add MUX_CLR_SET macro
In reply to Daniel GolleQuoting Daniel Golle (2026-03-25 22:09:35)
Quoted 10 lines
Some MediaTek SoCs (e.g. MT7988) define infra muxes that have neither a clock gate nor an update register.
Add a
MUX_CLR_SETconvenience macro that takes only the mux register offsets, bit shift, and width, hardcodingupd_ofs= 0 andupd_shift= -1 so callers cannot accidentally pass bogus sentinel values to wrongly-typed fields.Signed-off-by Daniel Golle <[email protected]>---
Applied to clk-next
PATCH v2 2/3 clk: mediatek: mt8192: use MUX_CLR_SET
In reply to Daniel GolleThe mfg_pll_sel mux has neither a clock gate nor an update register, and upd_ofs is stored as u32, so the -1 truncates to 0xFFFFFFFF.
While upd_shift being -1 (as s8) prevents the update path from executing at runtime, the bogus upd_ofs value is still stored in the struct.
Use MUX_CLR_SET to avoid passing sentinel values to wrongly-typed fields.
--- drivers/clk/mediatek/clk-mt8192.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/mediatek/clk-mt8192.c +2 -2
@@ -579,8 +579,8 @@ static const struct mtk_mux top_mtk_muxes[] = { dsp7_parents, 0x050, 0x054, 0x058, 0, 3, 7, 0x004, 16),MUX_GATE_CLR_SET_UPD (CLK_TOP_MFG_REF_SEL ,"mfg_ref_sel" , mfg_ref_parents,0x050 ,0x054 ,0x058 ,16 ,2 ,23 ,0x004 ,18 ), -MUX_CLR_SET_UPD (CLK_TOP_MFG_PLL_SEL ,"mfg_pll_sel" , - mfg_pll_parents,0x050 ,0x054 ,0x058 ,18 ,1 ,-1 ,-1 ), +MUX_CLR_SET (CLK_TOP_MFG_PLL_SEL ,"mfg_pll_sel" , mfg_pll_parents, +0x050 ,0x054 ,0x058 ,18 ,1 ),MUX_GATE_CLR_SET_UPD (CLK_TOP_CAMTG_SEL ,"camtg_sel" , camtg_parents, 0x050, 0x054, 0x058, 24, 3, 31, 0x004, 19),/* CLK_CFG_5 */
Signature · 1 line
2.53.0
Re: [PATCH v2 2/3] clk: mediatek: mt8192: use MUX_CLR_SET
Quoted 8 lines · Daniel Golle
The
mfg_pll_selmux has neither a clock gate nor an update register, andupd_ofsis stored as u32, so the -1 truncates to0xFFFFFFFF.While
upd_shiftbeing -1 (as s8) prevents the update path from executing at runtime, the bogusupd_ofsvalue is still stored in the struct.
Quoted 5 lines
Use
MUX_CLR_SETto avoid passing sentinel values to wrongly-typed fields.Fixes 710573dee31b4 ("clk: mediatek: Add MT8192 basic clocks support")Signed-off-by Daniel Golle <[email protected]>
Re: [PATCH v2 2/3] clk: mediatek: mt8192: use MUX_CLR_SET
In reply to Daniel GolleQuoting Daniel Golle (2026-03-25 22:10:47)
Quoted 7 lines
The
mfg_pll_selmux has neither a clock gate nor an update register, andupd_ofsis stored as u32, so the -1 truncates to0xFFFFFFFF.While
upd_shiftbeing -1 (as s8) prevents the update path from executing at runtime, the bogusupd_ofsvalue is still stored in the struct.
Quoted 6 lines
Use
MUX_CLR_SETto avoid passing sentinel values to wrongly-typed fields.Fixes 710573dee31b4 ("clk: mediatek: Add MT8192 basic clocks support")Signed-off-by Daniel Golle <[email protected]>---
Applied to clk-next
PATCH v2 3/3 clk: mediatek: mt7988: use MUX_CLR_SET for gate-less muxes
In reply to Daniel GolleAll 19 muxes in the infra_muxes[] array are pure mux selectors without a clock gate or update register, yet they were defined using MUX_GATE_CLR_SET_UPD with gate_shift = -1.
This macro assigns mtk_mux_gate_clr_set_upd_ops, whose enable/disable/is_enabled callbacks perform BIT(gate_shift). Since gate_shift is stored as u8, the -1 truncates to 255, causing a shift-out-of-bounds at runtime:
UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:76:8
shift exponent 255 is too large for 64-bit type 'long unsigned int'
UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:102:4
shift exponent 255 is too large for 64-bit type 'long unsigned int'
UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:122:16
shift exponent 255 is too large for 64-bit type 'long unsigned int'
Switch these definitions to MUX_CLR_SET, which uses mtk_mux_clr_set_upd_ops (no gate callbacks) and does not require callers to pass sentinel values for unused update register fields. The actual clock gating for these peripherals is handled by the separate GATE_INFRA* definitions further down.
--- drivers/clk/mediatek/clk-mt7988-infracfg.c | 80 ++++++++++------------ 1 file changed, 38 insertions(+), 42 deletions(-)
drivers/clk/mediatek/clk-mt7988-infracfg.c +38 -42
@@ -56,49 +56,45 @@ static const char *const infra_pcie_gfmux_tl_ck_o_p3_parents[] __initconst = {static const struct mtk_mux infra_muxes[] = {/* MODULE_CLK_SEL_0 */ -MUX_GATE_CLR_SET_UPD (CLK_INFRA_MUX_UART0_SEL ,"infra_mux_uart0_sel" , - infra_mux_uart0_parents,0x0018 ,0x0010 ,0x0014 ,0 ,1 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_MUX_UART1_SEL ,"infra_mux_uart1_sel" , - infra_mux_uart1_parents,0x0018 ,0x0010 ,0x0014 ,1 ,1 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_MUX_UART2_SEL ,"infra_mux_uart2_sel" , - infra_mux_uart2_parents,0x0018 ,0x0010 ,0x0014 ,2 ,1 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_MUX_SPI0_SEL ,"infra_mux_spi0_sel" , infra_mux_spi0_parents, -0x0018 ,0x0010 ,0x0014 ,4 ,1 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_MUX_SPI1_SEL ,"infra_mux_spi1_sel" , infra_mux_spi1_parents, -0x0018 ,0x0010 ,0x0014 ,5 ,1 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_MUX_SPI2_SEL ,"infra_mux_spi2_sel" , infra_mux_spi0_parents, -0x0018 ,0x0010 ,0x0014 ,6 ,1 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_SEL ,"infra_pwm_sel" , infra_pwm_bck_parents,0x0018 , -0x0010 ,0x0014 ,14 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK1_SEL ,"infra_pwm_ck1_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,16 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK2_SEL ,"infra_pwm_ck2_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,18 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK3_SEL ,"infra_pwm_ck3_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,20 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK4_SEL ,"infra_pwm_ck4_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,22 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK5_SEL ,"infra_pwm_ck5_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,24 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK6_SEL ,"infra_pwm_ck6_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,26 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK7_SEL ,"infra_pwm_ck7_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,28 ,2 ,-1 ,-1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PWM_CK8_SEL ,"infra_pwm_ck8_sel" , infra_pwm_bck_parents, -0x0018 ,0x0010 ,0x0014 ,30 ,2 ,-1 ,-1 ,-1 ), +MUX_CLR_SET (CLK_INFRA_MUX_UART0_SEL ,"infra_mux_uart0_sel" , + infra_mux_uart0_parents,0x0018 ,0x0010 ,0x0014 ,0 ,1 ), +MUX_CLR_SET (CLK_INFRA_MUX_UART1_SEL ,"infra_mux_uart1_sel" , + infra_mux_uart1_parents,0x0018 ,0x0010 ,0x0014 ,1 ,1 ), +MUX_CLR_SET (CLK_INFRA_MUX_UART2_SEL ,"infra_mux_uart2_sel" , + infra_mux_uart2_parents,0x0018 ,0x0010 ,0x0014 ,2 ,1 ), +MUX_CLR_SET (CLK_INFRA_MUX_SPI0_SEL ,"infra_mux_spi0_sel" , + infra_mux_spi0_parents,0x0018 ,0x0010 ,0x0014 ,4 ,1 ), +MUX_CLR_SET (CLK_INFRA_MUX_SPI1_SEL ,"infra_mux_spi1_sel" , + infra_mux_spi1_parents,0x0018 ,0x0010 ,0x0014 ,5 ,1 ), +MUX_CLR_SET (CLK_INFRA_MUX_SPI2_SEL ,"infra_mux_spi2_sel" , + infra_mux_spi0_parents,0x0018 ,0x0010 ,0x0014 ,6 ,1 ), +MUX_CLR_SET (CLK_INFRA_PWM_SEL ,"infra_pwm_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,14 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK1_SEL ,"infra_pwm_ck1_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,16 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK2_SEL ,"infra_pwm_ck2_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,18 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK3_SEL ,"infra_pwm_ck3_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,20 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK4_SEL ,"infra_pwm_ck4_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,22 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK5_SEL ,"infra_pwm_ck5_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,24 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK6_SEL ,"infra_pwm_ck6_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,26 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK7_SEL ,"infra_pwm_ck7_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,28 ,2 ), +MUX_CLR_SET (CLK_INFRA_PWM_CK8_SEL ,"infra_pwm_ck8_sel" , + infra_pwm_bck_parents,0x0018 ,0x0010 ,0x0014 ,30 ,2 ),/* MODULE_CLK_SEL_1 */ -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL ,"infra_pcie_gfmux_tl_o_p0_sel" , - infra_pcie_gfmux_tl_ck_o_p0_parents,0x0028 ,0x0020 ,0x0024 ,0 ,2 ,-1 , --1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL ,"infra_pcie_gfmux_tl_o_p1_sel" , - infra_pcie_gfmux_tl_ck_o_p1_parents,0x0028 ,0x0020 ,0x0024 ,2 ,2 ,-1 , --1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL ,"infra_pcie_gfmux_tl_o_p2_sel" , - infra_pcie_gfmux_tl_ck_o_p2_parents,0x0028 ,0x0020 ,0x0024 ,4 ,2 ,-1 , --1 ,-1 ), -MUX_GATE_CLR_SET_UPD (CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL ,"infra_pcie_gfmux_tl_o_p3_sel" , - infra_pcie_gfmux_tl_ck_o_p3_parents,0x0028 ,0x0020 ,0x0024 ,6 ,2 ,-1 , --1 ,-1 ), +MUX_CLR_SET (CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL ,"infra_pcie_gfmux_tl_o_p0_sel" , + infra_pcie_gfmux_tl_ck_o_p0_parents,0x0028 ,0x0020 ,0x0024 ,0 ,2 ), +MUX_CLR_SET (CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL ,"infra_pcie_gfmux_tl_o_p1_sel" , + infra_pcie_gfmux_tl_ck_o_p1_parents,0x0028 ,0x0020 ,0x0024 ,2 ,2 ), +MUX_CLR_SET (CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL ,"infra_pcie_gfmux_tl_o_p2_sel" , + infra_pcie_gfmux_tl_ck_o_p2_parents,0x0028 ,0x0020 ,0x0024 ,4 ,2 ), +MUX_CLR_SET (CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL ,"infra_pcie_gfmux_tl_o_p3_sel" , + infra_pcie_gfmux_tl_ck_o_p3_parents,0x0028 ,0x0020 ,0x0024 ,6 ,2 ), };static const struct mtk_gate_regs infra0_cg_regs = {
Signature · 1 line
2.53.0
Re: [PATCH v2 3/3] clk: mediatek: mt7988: use MUX_CLR_SET for gate-less muxes
Quoted 19 lines · Daniel Golle
All 19 muxes in the infra_muxes[] array are pure mux selectors without a clock gate or update register, yet they were defined using
MUX_GATE_CLR_SET_UPDwithgate_shift= -1.This macro assigns
mtk_mux_gate_clr_set_upd_ops, whose enable/disable/is_enabled callbacks performBIT(gate_shift). Sincegate_shiftis stored as u8, the -1 truncates to 255, causing a shift-out-of-bounds at runtime:UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:76:8shift exponent 255 is too large for 64-bit type 'long unsigned int'
UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:102:4shift exponent 255 is too large for 64-bit type 'long unsigned int'
UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:122:16shift exponent 255 is too large for 64-bit type 'long unsigned int'
Quoted 8 lines
Switch these definitions to
MUX_CLR_SET, which usesmtk_mux_clr_set_upd_ops(no gate callbacks) and does not require callers to pass sentinel values for unused update register fields. The actual clock gating for these peripherals is handled by the separate GATE_INFRA* definitions further down.Fixes 4b4719437d85f ("clk: mediatek: add drivers for MT7988 SoC")Signed-off-by Daniel Golle <[email protected]>
Re: [PATCH v2 3/3] clk: mediatek: mt7988: use MUX_CLR_SET for gate-less muxes
In reply to Daniel GolleQuoting Daniel Golle (2026-03-25 22:11:12)
Quoted 24 lines
All 19 muxes in the infra_muxes[] array are pure mux selectors without a clock gate or update register, yet they were defined using
MUX_GATE_CLR_SET_UPDwithgate_shift= -1.This macro assigns
mtk_mux_gate_clr_set_upd_ops, whose enable/disable/is_enabled callbacks performBIT(gate_shift). Sincegate_shiftis stored as u8, the -1 truncates to 255, causing a shift-out-of-bounds at runtime:UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:76:8shift exponent 255 is too large for 64-bit type 'long unsigned int'
UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:102:4shift exponent 255 is too large for 64-bit type 'long unsigned int'
UBSAN: shift-out-of-bounds in drivers/clk/mediatek/clk-mux.c:122:16shift exponent 255 is too large for 64-bit type 'long unsigned int'
Switch these definitions to
MUX_CLR_SET, which usesmtk_mux_clr_set_upd_ops(no gate callbacks) and does not require callers to pass sentinel values for unused update register fields. The actual clock gating for these peripherals is handled by the separate GATE_INFRA* definitions further down.
Quoted 3 lines
Fixes 4b4719437d85f ("clk: mediatek: add drivers for MT7988 SoC")Signed-off-by Daniel Golle <[email protected]>---
Applied to clk-next