[PATCH v2 1/6] clk: mediatek: mt8189: add some VLP clocks

David Lechner dlechner at baylibre.com
Wed Mar 11 01:16:50 CET 2026


Add some VLP clocks needed by the PMIC on MT8189 and similar SoCs.

Signed-off-by: David Lechner <dlechner at baylibre.com>
---
 drivers/clk/mediatek/clk-mt8189.c | 289 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 289 insertions(+)

diff --git a/drivers/clk/mediatek/clk-mt8189.c b/drivers/clk/mediatek/clk-mt8189.c
index 4779735a1cf..39a74180d11 100644
--- a/drivers/clk/mediatek/clk-mt8189.c
+++ b/drivers/clk/mediatek/clk-mt8189.c
@@ -286,11 +286,15 @@
 #define CLK_PAD_CLK32K			0
 #define CLK_PAD_CLK26M			1
 #define CLK_PAD_ULPOSC			2
+#define CLK_PAD_CLK13M			3
+#define CLK_PAD_AUD_ADC_EXT		4
 
 static ulong pad_clks[] = {
 	[CLK_PAD_CLK32K] = 32000,
 	[CLK_PAD_CLK26M] = 26 * MHZ,
 	[CLK_PAD_ULPOSC] = 260 * MHZ,
+	[CLK_PAD_CLK13M] = 13 * MHZ,
+	[CLK_PAD_AUD_ADC_EXT] = 260 * MHZ,
 };
 
 #define MT8189_PLL_FMAX		(3800UL * MHZ)
@@ -1635,6 +1639,258 @@ static const struct mtk_gate mminfra_config_clks[] = {
 	GATE_MMINFRA_CONFIG1(CLK_MMINFRA_GCE_26M, CLK_TOP_MMINFRA_SEL, 17),
 };
 
+static const struct mtk_parent vlp_26m_oscd10_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+};
+
+static const struct mtk_parent vlp_vadsp_vowpll_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_VOWPLL),
+};
+
+static const struct mtk_parent vlp_sspm_ulposc_parents[] = {
+	EXT_PARENT(CLK_PAD_ULPOSC),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D5_D2),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+};
+
+static const struct mtk_parent vlp_aud_adc_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_VOWPLL),
+	EXT_PARENT(CLK_PAD_AUD_ADC_EXT),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+};
+
+static const struct mtk_parent vlp_scp_iic_spi_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_MAINPLL_D5_D4),
+	TOP_PARENT(CLK_TOP_MAINPLL_D7_D2),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+};
+
+static const struct mtk_parent vlp_vadsp_uarthub_b_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D6_D4),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D6_D2),
+};
+
+static const struct mtk_parent vlp_axi_kp_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_OSC_D2),
+	TOP_PARENT(CLK_TOP_MAINPLL_D7_D4),
+	TOP_PARENT(CLK_TOP_MAINPLL_D7_D2),
+};
+
+static const struct mtk_parent vlp_sspm_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_MAINPLL_D5_D2),
+	EXT_PARENT(CLK_PAD_ULPOSC),
+	TOP_PARENT(CLK_TOP_MAINPLL_D6),
+};
+
+static const struct mtk_parent vlp_pwm_vlp_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_OSC_D4),
+	EXT_PARENT(CLK_PAD_CLK32K),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_MAINPLL_D4_D8),
+};
+
+static const struct mtk_parent vlp_pwrap_ulposc_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_OSC_D7),
+	TOP_PARENT(CLK_TOP_OSC_D8),
+	TOP_PARENT(CLK_TOP_OSC_D16),
+	TOP_PARENT(CLK_TOP_MAINPLL_D7_D8),
+};
+
+static const struct mtk_parent vlp_vadsp_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_OSC_D20),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_OSC_D2),
+	EXT_PARENT(CLK_PAD_ULPOSC),
+	TOP_PARENT(CLK_TOP_MAINPLL_D4_D2),
+};
+
+static const struct mtk_parent vlp_scp_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D4),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D3),
+	TOP_PARENT(CLK_TOP_MAINPLL_D3),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D6),
+	APMIXED_PARENT(CLK_APMIXED_APLL1),
+	TOP_PARENT(CLK_TOP_MAINPLL_D4),
+	TOP_PARENT(CLK_TOP_MAINPLL_D6),
+	TOP_PARENT(CLK_TOP_MAINPLL_D7),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+};
+
+static const struct mtk_parent vlp_spmi_p_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_F26M_CK_D2),
+	TOP_PARENT(CLK_TOP_OSC_D8),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_OSC_D16),
+	TOP_PARENT(CLK_TOP_OSC_D7),
+	EXT_PARENT(CLK_PAD_CLK32K),
+	TOP_PARENT(CLK_TOP_MAINPLL_D7_D8),
+	TOP_PARENT(CLK_TOP_MAINPLL_D6_D8),
+	TOP_PARENT(CLK_TOP_MAINPLL_D5_D8),
+};
+
+static const struct mtk_parent vlp_camtg_parents[] = {
+	EXT_PARENT(CLK_PAD_CLK26M),
+	TOP_PARENT(CLK_TOP_UNIVPLL_192M_D8),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D6_D8),
+	TOP_PARENT(CLK_TOP_UNIVPLL_192M_D4),
+	TOP_PARENT(CLK_TOP_OSC_D16),
+	TOP_PARENT(CLK_TOP_OSC_D20),
+	TOP_PARENT(CLK_TOP_OSC_D10),
+	TOP_PARENT(CLK_TOP_UNIVPLL_D6_D16),
+	TOP_PARENT(CLK_TOP_TVDPLL1_D16),
+	TOP_PARENT(CLK_TOP_F26M_CK_D2),
+	TOP_PARENT(CLK_TOP_UNIVPLL_192M_D10),
+	TOP_PARENT(CLK_TOP_UNIVPLL_192M_D16),
+	TOP_PARENT(CLK_TOP_UNIVPLL_192M_D32),
+};
+
+static const struct mtk_composite vlp_ck_muxes[] = {
+	/* VLP_CLK_CFG_0 */
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_SCP_SEL, vlp_scp_parents,
+			     0x008, 0x00c, 0x010, 0, 4, 7, 0x04, 0),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_PWRAP_ULPOSC_SEL, vlp_pwrap_ulposc_parents,
+			0x008, 0x00c, 0x010, 8, 3, 0x04, 1),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SPMI_P_MST_SEL, vlp_spmi_p_parents,
+			0x008, 0x00c, 0x010, 16, 4, 0x04, 2),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_DVFSRC_SEL, vlp_26m_oscd10_parents,
+			0x008, 0x00c, 0x010, 24, 1, 0x04, 3),
+	/* VLP_CLK_CFG_1 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_PWM_VLP_SEL, vlp_pwm_vlp_parents,
+			0x014, 0x018, 0x01c, 0, 3, 0x04, 4),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_AXI_VLP_SEL, vlp_axi_kp_parents,
+			0x014, 0x018, 0x01c, 8, 3, 0x04, 5),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SYSTIMER_26M_SEL, vlp_26m_oscd10_parents,
+			0x014, 0x018, 0x01c, 16, 1, 0x04, 6),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_SEL, vlp_sspm_parents,
+			0x014, 0x018, 0x01c, 24, 3, 0x04, 7),
+	/* VLP_CLK_CFG_2 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_F26M_SEL, vlp_26m_oscd10_parents,
+			0x020, 0x024, 0x028, 0, 1, 0x04, 8),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SRCK_SEL, vlp_26m_oscd10_parents,
+			0x020, 0x024, 0x028, 8, 1, 0x04, 9),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_SPI_SEL, vlp_scp_iic_spi_parents,
+			0x020, 0x024, 0x028, 16, 2, 0x04, 10),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_IIC_SEL, vlp_scp_iic_spi_parents,
+			0x020, 0x024, 0x028, 24, 2, 0x04, 11),
+	/* VLP_CLK_CFG_3 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_SPI_HIGH_SPD_SEL,
+			vlp_scp_iic_spi_parents,
+			0x02c, 0x030, 0x034, 0, 2, 0x04, 12),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_IIC_HIGH_SPD_SEL,
+			vlp_scp_iic_spi_parents,
+			0x02c, 0x030, 0x034, 8, 2, 0x04, 13),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_ULPOSC_SEL, vlp_sspm_ulposc_parents,
+			0x02c, 0x030, 0x034, 16, 2, 0x04, 14),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_APXGPT_26M_SEL, vlp_26m_oscd10_parents,
+			0x02c, 0x030, 0x034, 24, 1, 0x04, 15),
+	/* VLP_CLK_CFG_4 */
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_VADSP_SEL, vlp_vadsp_parents,
+			     0x038, 0x03c, 0x040, 0, 3, 7, 0x04, 16),
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_VADSP_VOWPLL_SEL,
+			     vlp_vadsp_vowpll_parents,
+			     0x038, 0x03c, 0x040, 8, 1, 15, 0x04, 17),
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_VADSP_UARTHUB_BCLK_SEL,
+			     vlp_vadsp_uarthub_b_parents,
+			     0x038, 0x03c, 0x040, 16, 2, 23, 0x04, 18),
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_CAMTG0_SEL, vlp_camtg_parents,
+			     0x038, 0x03c, 0x040, 24, 4, 31, 0x04, 19),
+	/* VLP_CLK_CFG_5 */
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_CAMTG1_SEL, vlp_camtg_parents,
+			     0x044, 0x048, 0x04c, 0, 4, 7, 0x04, 20),
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_CAMTG2_SEL, vlp_camtg_parents,
+			     0x044, 0x048, 0x04c, 8, 4, 15, 0x04, 21),
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_AUD_ADC_SEL, vlp_aud_adc_parents,
+			     0x044, 0x048, 0x04c, 16, 2, 23, 0x04, 22),
+	MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_KP_IRQ_GEN_SEL, vlp_axi_kp_parents,
+			     0x044, 0x048, 0x04c, 24, 3, 31, 0x04, 23),
+};
+
+static const struct mtk_gate_regs vlp_ck_gate_regs = {
+	.set_ofs = 0x1f4,
+	.clr_ofs = 0x1f8,
+	.sta_ofs = 0x1f0,
+};
+
+#define GATE_VLP_CK(id, parent, shift, flags) \
+	GATE_FLAGS(id, parent, &vlp_ck_gate_regs, shift, flags | CLK_GATE_NO_SETCLR_INV)
+
+#define GATE_VLP_CK_EXT(id, parent, shift) \
+	GATE_VLP_CK(id, parent, shift, CLK_PARENT_EXT)
+
+#define GATE_VLP_CK_TOP(id, parent, shift) \
+	GATE_VLP_CK(id, parent, shift, CLK_PARENT_TOPCKGEN)
+
+static const struct mtk_gate vlp_ck_gates[] = {
+	GATE_VLP_CK_EXT(CLK_VLP_CK_VADSYS_VLP_26M_EN, CLK_PAD_CLK26M, 1),
+	GATE_VLP_CK_EXT(CLK_VLP_CK_SEJ_13M_EN, CLK_PAD_CLK13M, 4),
+	GATE_VLP_CK_EXT(CLK_VLP_CK_SEJ_26M_EN, CLK_PAD_CLK26M, 5),
+	GATE_VLP_CK_TOP(CLK_VLP_CK_FMIPI_CSI_UP26M_CK_EN, CLK_TOP_OSC_D10, 11),
+};
+
+static const struct mtk_gate_regs vlpcfg_ao_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x4,
+	.sta_ofs = 0x4,
+};
+
+/*
+ * REVISIT: this is currently the only clock tree using the infrasys ops so we
+ * are using it instead of introducing a new parent in the core code. Instead,
+ * we should eventually rework the core code to do a better job of supporting
+ * arbitrary parent trees.
+ */
+#define CLK_PARENT_VLP_CK CLK_PARENT_INFRASYS
+
+#define GATE_VLPCFG_AO(id, parent, shift, flags) \
+	GATE_FLAGS(id, parent, &vlpcfg_ao_regs, shift, flags | CLK_GATE_NO_SETCLR_INV)
+
+#define GATE_VLPCFG_AO_EXT(id, parent, shift) \
+	GATE_VLPCFG_AO(id, parent, shift, CLK_PARENT_EXT)
+
+#define GATE_VLPCFG_AO_TOP(id, parent, shift) \
+	GATE_VLPCFG_AO(id, parent, shift, CLK_PARENT_TOPCKGEN)
+
+#define GATE_VLPCFG_AO_VLP(id, parent, shift) \
+	GATE_VLPCFG_AO(id, parent, shift, CLK_PARENT_VLP_CK)
+
+static const struct mtk_gate vlpcfg_ao_clks[] = {
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_SCP, CLK_VLP_CK_SCP_SEL, 28),
+	GATE_VLPCFG_AO_EXT(CLK_VLPCFG_REG_RG_R_APXGPT_26M, CLK_PAD_CLK26M, 24),
+	GATE_VLPCFG_AO_EXT(CLK_VLPCFG_REG_DPMSRCK_TEST, CLK_PAD_CLK26M, 23),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_RG_DPMSRRTC_TEST, CLK_PAD_CLK32K, 22),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_DPMSRULP_TEST, CLK_TOP_OSC_D10, 21),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_SPMI_P_MST, CLK_VLP_CK_SPMI_P_MST_SEL, 20),
+	GATE_VLPCFG_AO_EXT(CLK_VLPCFG_REG_SPMI_P_MST_32K, CLK_PAD_CLK32K, 18),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_PMIF_SPMI_P_SYS, CLK_VLP_CK_PWRAP_ULPOSC_SEL, 13),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_PMIF_SPMI_P_TMR, CLK_VLP_CK_PWRAP_ULPOSC_SEL, 12),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_PMIF_SPMI_M_SYS, CLK_VLP_CK_PWRAP_ULPOSC_SEL, 11),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_PMIF_SPMI_M_TMR, CLK_VLP_CK_PWRAP_ULPOSC_SEL, 10),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_DVFSRC, CLK_VLP_CK_DVFSRC_SEL, 9),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_PWM_VLP, CLK_VLP_CK_PWM_VLP_SEL, 8),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_SRCK, CLK_VLP_CK_SRCK_SEL, 7),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_SSPM_F26M, CLK_VLP_CK_SSPM_F26M_SEL, 4),
+	GATE_VLPCFG_AO_EXT(CLK_VLPCFG_REG_SSPM_F32K, CLK_PAD_CLK32K, 3),
+	GATE_VLPCFG_AO_VLP(CLK_VLPCFG_REG_SSPM_ULPOSC, CLK_VLP_CK_SSPM_ULPOSC_SEL, 2),
+	GATE_VLPCFG_AO_EXT(CLK_VLPCFG_REG_VLP_32K_COM, CLK_PAD_CLK32K, 1),
+	GATE_VLPCFG_AO_EXT(CLK_VLPCFG_REG_VLP_26M_COM, CLK_PAD_CLK26M, 0),
+};
+
 static const struct mtk_clk_tree mt8189_apmixedsys_clk_tree = {
 	.pll_parent = EXT_PARENT(CLK_PAD_CLK26M),
 	.ext_clk_rates = pad_clks,
@@ -1657,6 +1913,17 @@ static const struct mtk_clk_tree mt8189_topckgen_clk_tree = {
 	.num_gates = ARRAY_SIZE(top_gates),
 };
 
+static const struct mtk_clk_tree mt8189_vlpckgen_clk_tree = {
+	.ext_clk_rates = pad_clks,
+	.num_ext_clks = ARRAY_SIZE(pad_clks),
+	.muxes_offs = CLK_VLP_CK_SCP_SEL,
+	.gates_offs = CLK_VLP_CK_VADSYS_VLP_26M_EN,
+	.muxes = vlp_ck_muxes,
+	.gates = vlp_ck_gates,
+	.num_muxes = ARRAY_SIZE(vlp_ck_muxes),
+	.num_gates = ARRAY_SIZE(vlp_ck_gates),
+};
+
 static const struct udevice_id mt8189_apmixed[] = {
 	{ .compatible = "mediatek,mt8189-apmixedsys", },
 	{ }
@@ -1667,6 +1934,11 @@ static const struct udevice_id mt8189_topckgen_compat[] = {
 	{ }
 };
 
+static const struct udevice_id mt8189_vlpckgen[] = {
+	{ .compatible = "mediatek,mt8189-vlpckgen", },
+	{ }
+};
+
 struct mt8189_gate_clk_data {
 	const struct mtk_gate *gates;
 	int num_gates;
@@ -1681,12 +1953,14 @@ GATE_CLK_DATA(perao_clks);
 GATE_CLK_DATA(imp_clks);
 GATE_CLK_DATA(mm_clks);
 GATE_CLK_DATA(mminfra_config_clks);
+GATE_CLK_DATA(vlpcfg_ao_clks);
 
 static const struct udevice_id of_match_mt8189_clk_gate[] = {
 	{ .compatible = "mediatek,mt8189-peri-ao", .data = (ulong)&perao_clks_data },
 	{ .compatible = "mediatek,mt8189-iic-wrap", .data = (ulong)&imp_clks_data },
 	{ .compatible = "mediatek,mt8189-dispsys", .data = (ulong)&mm_clks_data },
 	{ .compatible = "mediatek,mt8189-mm-infra", .data = (ulong)&mminfra_config_clks_data },
+	{ .compatible = "mediatek,mt8189-vlpcfg-ao", .data = (ulong)&vlpcfg_ao_clks_data },
 	{ }
 };
 
@@ -1700,6 +1974,11 @@ static int mt8189_topckgen_probe(struct udevice *dev)
 	return mtk_common_clk_init(dev, &mt8189_topckgen_clk_tree);
 }
 
+static int mt8189_infrasys_probe(struct udevice *dev)
+{
+	return mtk_common_clk_infrasys_init(dev, &mt8189_vlpckgen_clk_tree);
+}
+
 static int mt8189_clk_gate_probe(struct udevice *dev)
 {
 	struct mt8189_gate_clk_data *data;
@@ -1731,6 +2010,16 @@ U_BOOT_DRIVER(mtk_clk_topckgen) = {
 	.flags = DM_FLAG_PRE_RELOC,
 };
 
+U_BOOT_DRIVER(mtk_clk_vlpckgen) = {
+	.name = "mt8189-vlpckgen",
+	.id = UCLASS_CLK,
+	.of_match = mt8189_vlpckgen,
+	.probe = mt8189_infrasys_probe,
+	.priv_auto = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_infrasys_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
 U_BOOT_DRIVER(mtk_clk_gate) = {
 	.name = "mt8189-gate-clk",
 	.id = UCLASS_CLK,

-- 
2.43.0



More information about the U-Boot mailing list