diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index e3786fd64726..0163d27e8795 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -7,6 +7,8 @@
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
 
 #include "clk-cpumux.h"
 #include "clk-gate.h"
@@ -15,6 +17,9 @@
 
 #include <dt-bindings/clock/mt8173-clk.h>
 
+#define REGOFF_REF2USB	0x8
+#define REGOFF_HDMI_REF	0x40
+
 /*
  * For some clocks, we don't care what their actual rates are. And these
  * clocks may change their rate on different products or different scenarios.
@@ -24,7 +29,7 @@
 
 static DEFINE_SPINLOCK(mt8173_clk_lock);
 
-static const struct mtk_fixed_clk fixed_clks[] __initconst = {
+static const struct mtk_fixed_clk fixed_clks[] = {
 	FIXED_CLK(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk26m", DUMMY_RATE),
 	FIXED_CLK(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk26m", 125 * MHZ),
 	FIXED_CLK(CLK_TOP_DSI0_DIG, "dsi0_dig", "clk26m", DUMMY_RATE),
@@ -33,7 +38,7 @@ static const struct mtk_fixed_clk fixed_clks[] __initconst = {
 	FIXED_CLK(CLK_TOP_LVDS_CTS, "lvds_cts", "lvdspll", DUMMY_RATE),
 };
 
-static const struct mtk_fixed_factor top_divs[] __initconst = {
+static const struct mtk_fixed_factor top_divs[] = {
 	FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
 	FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
 
@@ -129,7 +134,7 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
 	FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
 };
 
-static const char * const axi_parents[] __initconst = {
+static const char * const axi_parents[] = {
 	"clk26m",
 	"syspll1_d2",
 	"syspll_d5",
@@ -140,17 +145,17 @@ static const char * const axi_parents[] __initconst = {
 	"dmpll_d4"
 };
 
-static const char * const mem_parents[] __initconst = {
+static const char * const mem_parents[] = {
 	"clk26m",
 	"dmpll_ck"
 };
 
-static const char * const ddrphycfg_parents[] __initconst = {
+static const char * const ddrphycfg_parents[] = {
 	"clk26m",
 	"syspll1_d8"
 };
 
-static const char * const mm_parents[] __initconst = {
+static const char * const mm_parents[] = {
 	"clk26m",
 	"vencpll_d2",
 	"main_h364m",
@@ -162,14 +167,14 @@ static const char * const mm_parents[] __initconst = {
 	"dmpll_d2"
 };
 
-static const char * const pwm_parents[] __initconst = {
+static const char * const pwm_parents[] = {
 	"clk26m",
 	"univpll2_d4",
 	"univpll3_d2",
 	"univpll1_d4"
 };
 
-static const char * const vdec_parents[] __initconst = {
+static const char * const vdec_parents[] = {
 	"clk26m",
 	"vcodecpll_ck",
 	"tvdpll_445p5m",
@@ -182,7 +187,7 @@ static const char * const vdec_parents[] __initconst = {
 	"dmpll_d4"
 };
 
-static const char * const venc_parents[] __initconst = {
+static const char * const venc_parents[] = {
 	"clk26m",
 	"vcodecpll_ck",
 	"tvdpll_445p5m",
@@ -195,7 +200,7 @@ static const char * const venc_parents[] __initconst = {
 	"dmpll_d4"
 };
 
-static const char * const mfg_parents[] __initconst = {
+static const char * const mfg_parents[] = {
 	"clk26m",
 	"mmpll_ck",
 	"dmpll_ck",
@@ -214,7 +219,7 @@ static const char * const mfg_parents[] __initconst = {
 	"univpll2_d2"
 };
 
-static const char * const camtg_parents[] __initconst = {
+static const char * const camtg_parents[] = {
 	"clk26m",
 	"univpll_d26",
 	"univpll2_d2",
@@ -223,12 +228,12 @@ static const char * const camtg_parents[] __initconst = {
 	"univpll1_d4"
 };
 
-static const char * const uart_parents[] __initconst = {
+static const char * const uart_parents[] = {
 	"clk26m",
 	"univpll2_d8"
 };
 
-static const char * const spi_parents[] __initconst = {
+static const char * const spi_parents[] = {
 	"clk26m",
 	"syspll3_d2",
 	"syspll1_d4",
@@ -238,20 +243,20 @@ static const char * const spi_parents[] __initconst = {
 	"univpll1_d8"
 };
 
-static const char * const usb20_parents[] __initconst = {
+static const char * const usb20_parents[] = {
 	"clk26m",
 	"univpll1_d8",
 	"univpll3_d4"
 };
 
-static const char * const usb30_parents[] __initconst = {
+static const char * const usb30_parents[] = {
 	"clk26m",
 	"univpll3_d2",
 	"usb_syspll_125m",
 	"univpll2_d4"
 };
 
-static const char * const msdc50_0_h_parents[] __initconst = {
+static const char * const msdc50_0_h_parents[] = {
 	"clk26m",
 	"syspll1_d2",
 	"syspll2_d2",
@@ -260,7 +265,7 @@ static const char * const msdc50_0_h_parents[] __initconst = {
 	"univpll1_d4"
 };
 
-static const char * const msdc50_0_parents[] __initconst = {
+static const char * const msdc50_0_parents[] = {
 	"clk26m",
 	"msdcpll_ck",
 	"msdcpll_d2",
@@ -278,7 +283,7 @@ static const char * const msdc50_0_parents[] __initconst = {
 	"msdcpll2_d4"
 };
 
-static const char * const msdc30_1_parents[] __initconst = {
+static const char * const msdc30_1_parents[] = {
 	"clk26m",
 	"univpll2_d2",
 	"msdcpll_d4",
@@ -289,7 +294,7 @@ static const char * const msdc30_1_parents[] __initconst = {
 	"vencpll_d4"
 };
 
-static const char * const msdc30_2_parents[] __initconst = {
+static const char * const msdc30_2_parents[] = {
 	"clk26m",
 	"univpll2_d2",
 	"msdcpll_d4",
@@ -300,7 +305,7 @@ static const char * const msdc30_2_parents[] __initconst = {
 	"vencpll_d2"
 };
 
-static const char * const msdc30_3_parents[] __initconst = {
+static const char * const msdc30_3_parents[] = {
 	"clk26m",
 	"msdcpll2_ck",
 	"msdcpll2_d2",
@@ -317,14 +322,14 @@ static const char * const msdc30_3_parents[] __initconst = {
 	"msdcpll_d4"
 };
 
-static const char * const audio_parents[] __initconst = {
+static const char * const audio_parents[] = {
 	"clk26m",
 	"syspll3_d4",
 	"syspll4_d4",
 	"syspll1_d16"
 };
 
-static const char * const aud_intbus_parents[] __initconst = {
+static const char * const aud_intbus_parents[] = {
 	"clk26m",
 	"syspll1_d4",
 	"syspll4_d2",
@@ -334,7 +339,7 @@ static const char * const aud_intbus_parents[] __initconst = {
 	"dmpll_d8"
 };
 
-static const char * const pmicspi_parents[] __initconst = {
+static const char * const pmicspi_parents[] = {
 	"clk26m",
 	"syspll1_d8",
 	"syspll3_d4",
@@ -345,7 +350,7 @@ static const char * const pmicspi_parents[] __initconst = {
 	"dmpll_d16"
 };
 
-static const char * const scp_parents[] __initconst = {
+static const char * const scp_parents[] = {
 	"clk26m",
 	"syspll1_d2",
 	"univpll_d5",
@@ -354,14 +359,14 @@ static const char * const scp_parents[] __initconst = {
 	"dmpll_d4"
 };
 
-static const char * const atb_parents[] __initconst = {
+static const char * const atb_parents[] = {
 	"clk26m",
 	"syspll1_d2",
 	"univpll_d5",
 	"dmpll_d2"
 };
 
-static const char * const venc_lt_parents[] __initconst = {
+static const char * const venc_lt_parents[] = {
 	"clk26m",
 	"univpll_d3",
 	"vcodecpll_ck",
@@ -376,7 +381,7 @@ static const char * const venc_lt_parents[] __initconst = {
 	"dmpll_ck"
 };
 
-static const char * const dpi0_parents[] __initconst = {
+static const char * const dpi0_parents[] = {
 	"clk26m",
 	"tvdpll_d2",
 	"tvdpll_d4",
@@ -386,13 +391,13 @@ static const char * const dpi0_parents[] __initconst = {
 	"tvdpll_d16"
 };
 
-static const char * const irda_parents[] __initconst = {
+static const char * const irda_parents[] = {
 	"clk26m",
 	"univpll2_d4",
 	"syspll2_d4"
 };
 
-static const char * const cci400_parents[] __initconst = {
+static const char * const cci400_parents[] = {
 	"clk26m",
 	"vencpll_ck",
 	"armca7pll_754m",
@@ -403,41 +408,41 @@ static const char * const cci400_parents[] __initconst = {
 	"dmpll_ck"
 };
 
-static const char * const aud_1_parents[] __initconst = {
+static const char * const aud_1_parents[] = {
 	"clk26m",
 	"apll1_ck",
 	"univpll2_d4",
 	"univpll2_d8"
 };
 
-static const char * const aud_2_parents[] __initconst = {
+static const char * const aud_2_parents[] = {
 	"clk26m",
 	"apll2_ck",
 	"univpll2_d4",
 	"univpll2_d8"
 };
 
-static const char * const mem_mfg_in_parents[] __initconst = {
+static const char * const mem_mfg_in_parents[] = {
 	"clk26m",
 	"mmpll_ck",
 	"dmpll_ck",
 	"clk26m"
 };
 
-static const char * const axi_mfg_in_parents[] __initconst = {
+static const char * const axi_mfg_in_parents[] = {
 	"clk26m",
 	"axi_sel",
 	"dmpll_d2"
 };
 
-static const char * const scam_parents[] __initconst = {
+static const char * const scam_parents[] = {
 	"clk26m",
 	"syspll3_d2",
 	"univpll2_d4",
 	"dmpll_d4"
 };
 
-static const char * const spinfi_ifr_parents[] __initconst = {
+static const char * const spinfi_ifr_parents[] = {
 	"clk26m",
 	"univpll2_d8",
 	"univpll3_d4",
@@ -448,14 +453,14 @@ static const char * const spinfi_ifr_parents[] __initconst = {
 	"univpll1_d4"
 };
 
-static const char * const hdmi_parents[] __initconst = {
+static const char * const hdmi_parents[] = {
 	"clk26m",
 	"hdmitx_dig_cts",
 	"hdmitxpll_d2",
 	"hdmitxpll_d3"
 };
 
-static const char * const dpilvds_parents[] __initconst = {
+static const char * const dpilvds_parents[] = {
 	"clk26m",
 	"lvdspll",
 	"lvdspll_d2",
@@ -464,7 +469,7 @@ static const char * const dpilvds_parents[] __initconst = {
 	"fpc_ck"
 };
 
-static const char * const msdc50_2_h_parents[] __initconst = {
+static const char * const msdc50_2_h_parents[] = {
 	"clk26m",
 	"syspll1_d2",
 	"syspll2_d2",
@@ -473,72 +478,72 @@ static const char * const msdc50_2_h_parents[] __initconst = {
 	"univpll1_d4"
 };
 
-static const char * const hdcp_parents[] __initconst = {
+static const char * const hdcp_parents[] = {
 	"clk26m",
 	"syspll4_d2",
 	"syspll3_d4",
 	"univpll2_d4"
 };
 
-static const char * const hdcp_24m_parents[] __initconst = {
+static const char * const hdcp_24m_parents[] = {
 	"clk26m",
 	"univpll_d26",
 	"univpll_d52",
 	"univpll2_d8"
 };
 
-static const char * const rtc_parents[] __initconst = {
+static const char * const rtc_parents[] = {
 	"clkrtc_int",
 	"clkrtc_ext",
 	"clk26m",
 	"univpll3_d8"
 };
 
-static const char * const i2s0_m_ck_parents[] __initconst = {
+static const char * const i2s0_m_ck_parents[] = {
 	"apll1_div1",
 	"apll2_div1"
 };
 
-static const char * const i2s1_m_ck_parents[] __initconst = {
+static const char * const i2s1_m_ck_parents[] = {
 	"apll1_div2",
 	"apll2_div2"
 };
 
-static const char * const i2s2_m_ck_parents[] __initconst = {
+static const char * const i2s2_m_ck_parents[] = {
 	"apll1_div3",
 	"apll2_div3"
 };
 
-static const char * const i2s3_m_ck_parents[] __initconst = {
+static const char * const i2s3_m_ck_parents[] = {
 	"apll1_div4",
 	"apll2_div4"
 };
 
-static const char * const i2s3_b_ck_parents[] __initconst = {
+static const char * const i2s3_b_ck_parents[] = {
 	"apll1_div5",
 	"apll2_div5"
 };
 
-static const char * const ca53_parents[] __initconst = {
+static const char * const ca53_parents[] = {
 	"clk26m",
 	"armca7pll",
 	"mainpll",
 	"univpll"
 };
 
-static const char * const ca72_parents[] __initconst = {
+static const char * const ca72_parents[] = {
 	"clk26m",
 	"armca15pll",
 	"mainpll",
 	"univpll"
 };
 
-static const struct mtk_composite cpu_muxes[] __initconst = {
+static const struct mtk_composite cpu_muxes[] = {
 	MUX(CLK_INFRA_CA53SEL, "infra_ca53_sel", ca53_parents, 0x0000, 0, 2),
 	MUX(CLK_INFRA_CA72SEL, "infra_ca72_sel", ca72_parents, 0x0000, 2, 2),
 };
 
-static const struct mtk_composite top_muxes[] __initconst = {
+static const struct mtk_composite top_muxes[] = {
 	/* CLK_CFG_0 */
 	MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
 	MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
@@ -614,7 +619,7 @@ static const struct mtk_composite top_muxes[] __initconst = {
 	MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
 };
 
-static const struct mtk_gate_regs infra_cg_regs __initconst = {
+static const struct mtk_gate_regs infra_cg_regs = {
 	.set_ofs = 0x0040,
 	.clr_ofs = 0x0044,
 	.sta_ofs = 0x0048,
@@ -629,7 +634,7 @@ static const struct mtk_gate_regs infra_cg_regs __initconst = {
 		.ops = &mtk_clk_gate_ops_setclr,		\
 	}
 
-static const struct mtk_gate infra_clks[] __initconst = {
+static const struct mtk_gate infra_clks[] = {
 	GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
 	GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
 	GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
@@ -643,17 +648,17 @@ static const struct mtk_gate infra_clks[] __initconst = {
 	GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
 };
 
-static const struct mtk_fixed_factor infra_divs[] __initconst = {
+static const struct mtk_fixed_factor infra_early_divs[] = {
 	FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
 };
 
-static const struct mtk_gate_regs peri0_cg_regs __initconst = {
+static const struct mtk_gate_regs peri0_cg_regs = {
 	.set_ofs = 0x0008,
 	.clr_ofs = 0x0010,
 	.sta_ofs = 0x0018,
 };
 
-static const struct mtk_gate_regs peri1_cg_regs __initconst = {
+static const struct mtk_gate_regs peri1_cg_regs = {
 	.set_ofs = 0x000c,
 	.clr_ofs = 0x0014,
 	.sta_ofs = 0x001c,
@@ -677,7 +682,7 @@ static const struct mtk_gate_regs peri1_cg_regs __initconst = {
 		.ops = &mtk_clk_gate_ops_setclr,		\
 	}
 
-static const struct mtk_gate peri_gates[] __initconst = {
+static const struct mtk_gate peri_gates[] = {
 	/* PERI0 */
 	GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
 	GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
@@ -717,19 +722,19 @@ static const struct mtk_gate peri_gates[] __initconst = {
 	GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
 };
 
-static const char * const uart_ck_sel_parents[] __initconst = {
+static const char * const uart_ck_sel_parents[] = {
 	"clk26m",
 	"uart_sel",
 };
 
-static const struct mtk_composite peri_clks[] __initconst = {
+static const struct mtk_composite peri_clks[] = {
 	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
 	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
 	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
 	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
 };
 
-static const struct mtk_gate_regs cg_regs_4_8_0 __initconst = {
+static const struct mtk_gate_regs cg_regs_4_8_0 = {
 	.set_ofs = 0x0004,
 	.clr_ofs = 0x0008,
 	.sta_ofs = 0x0000,
@@ -744,7 +749,8 @@ static const struct mtk_gate_regs cg_regs_4_8_0 __initconst = {
 		.ops = &mtk_clk_gate_ops_setclr,		\
 	}
 
-static const struct mtk_gate img_clks[] __initconst = {
+static const struct mtk_gate img_clks[] = {
+	GATE_DUMMY(CLK_DUMMY, "img_dummy"),
 	GATE_IMG(CLK_IMG_LARB2_SMI, "img_larb2_smi", "mm_sel", 0),
 	GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "mm_sel", 5),
 	GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "mm_sel", 6),
@@ -754,13 +760,13 @@ static const struct mtk_gate img_clks[] __initconst = {
 	GATE_IMG(CLK_IMG_FD, "img_fd", "mm_sel", 11),
 };
 
-static const struct mtk_gate_regs vdec0_cg_regs __initconst = {
+static const struct mtk_gate_regs vdec0_cg_regs = {
 	.set_ofs = 0x0000,
 	.clr_ofs = 0x0004,
 	.sta_ofs = 0x0000,
 };
 
-static const struct mtk_gate_regs vdec1_cg_regs __initconst = {
+static const struct mtk_gate_regs vdec1_cg_regs = {
 	.set_ofs = 0x0008,
 	.clr_ofs = 0x000c,
 	.sta_ofs = 0x0008,
@@ -784,7 +790,8 @@ static const struct mtk_gate_regs vdec1_cg_regs __initconst = {
 		.ops = &mtk_clk_gate_ops_setclr_inv,		\
 	}
 
-static const struct mtk_gate vdec_clks[] __initconst = {
+static const struct mtk_gate vdec_clks[] = {
+	GATE_DUMMY(CLK_DUMMY, "vdec_dummy"),
 	GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
 	GATE_VDEC1(CLK_VDEC_LARB_CKEN, "vdec_larb_cken", "mm_sel", 0),
 };
@@ -798,7 +805,8 @@ static const struct mtk_gate vdec_clks[] __initconst = {
 		.ops = &mtk_clk_gate_ops_setclr_inv,		\
 	}
 
-static const struct mtk_gate venc_clks[] __initconst = {
+static const struct mtk_gate venc_clks[] = {
+	GATE_DUMMY(CLK_DUMMY, "venc_dummy"),
 	GATE_VENC(CLK_VENC_CKE0, "venc_cke0", "mm_sel", 0),
 	GATE_VENC(CLK_VENC_CKE1, "venc_cke1", "venc_sel", 4),
 	GATE_VENC(CLK_VENC_CKE2, "venc_cke2", "venc_sel", 8),
@@ -814,7 +822,8 @@ static const struct mtk_gate venc_clks[] __initconst = {
 		.ops = &mtk_clk_gate_ops_setclr_inv,		\
 	}
 
-static const struct mtk_gate venclt_clks[] __initconst = {
+static const struct mtk_gate venclt_clks[] = {
+	GATE_DUMMY(CLK_DUMMY, "venclt_dummy"),
 	GATE_VENCLT(CLK_VENCLT_CKE0, "venclt_cke0", "mm_sel", 0),
 	GATE_VENCLT(CLK_VENCLT_CKE1, "venclt_cke1", "venclt_sel", 4),
 };
@@ -837,10 +846,11 @@ static const struct mtk_clk_rst_desc clk_rst_desc[] = {
 	}
 };
 
-static struct clk_hw_onecell_data *mt8173_top_clk_data __initdata;
-static struct clk_hw_onecell_data *mt8173_pll_clk_data __initdata;
+static struct clk_hw_onecell_data *mt8173_top_clk_data;
+static struct clk_hw_onecell_data *mt8173_pll_clk_data;
+static struct clk_hw_onecell_data *infra_clk_data;
 
-static void __init mtk_clk_enable_critical(void)
+static void mtk_clk_enable_critical(void)
 {
 	if (!mt8173_top_clk_data || !mt8173_pll_clk_data)
 		return;
@@ -853,104 +863,152 @@ static void __init mtk_clk_enable_critical(void)
 	clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_RTC_SEL]->clk);
 }
 
-static void __init mtk_topckgen_init(struct device_node *node)
+static int clk_mt8173_topck_probe(struct platform_device *pdev)
 {
+	struct device_node *node = pdev->dev.of_node;
 	struct clk_hw_onecell_data *clk_data;
 	void __iomem *base;
 	int r;
 
-	base = of_iomap(node, 0);
-	if (!base) {
-		pr_err("%s(): ioremap failed\n", __func__);
-		return;
-	}
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+	if (IS_ERR_OR_NULL(clk_data))
+		return -ENOMEM;
 
-	mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data);
-	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
-	mtk_clk_register_composites(NULL, top_muxes,
-				    ARRAY_SIZE(top_muxes), base,
-				    &mt8173_clk_lock, clk_data);
+	r = mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data);
+	if (r)
+		goto free_clk_data;
+
+	r = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	if (r)
+		goto unregister_fixed_clks;
+
+	r = mtk_clk_register_composites(&pdev->dev, top_muxes,
+					ARRAY_SIZE(top_muxes), base,
+					&mt8173_clk_lock, clk_data);
+	if (r)
+		goto unregister_factors;
 
 	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
 	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
+		goto unregister_composites;
 
 	mtk_clk_enable_critical();
+	return 0;
+
+unregister_composites:
+	mtk_clk_unregister_composites(top_muxes, ARRAY_SIZE(top_muxes), clk_data);
+unregister_factors:
+	mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+unregister_fixed_clks:
+	mtk_clk_unregister_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data);
+free_clk_data:
+	mtk_free_clk_data(clk_data);
+	return r;
 }
-CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
 
-static void __init mtk_infrasys_init(struct device_node *node)
+static void clk_mt8173_infra_init_early(struct device_node *node)
 {
-	struct clk_hw_onecell_data *clk_data;
+	int i;
+
+	infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+	if (!infra_clk_data)
+		return;
+
+	for (i = 0; i < CLK_INFRA_NR_CLK; i++)
+		infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+	mtk_clk_register_factors(infra_early_divs,
+				 ARRAY_SIZE(infra_early_divs), infra_clk_data);
+
+	of_clk_add_hw_provider(node, of_clk_hw_onecell_get, infra_clk_data);
+}
+CLK_OF_DECLARE_DRIVER(mtk_infrasys, "mediatek,mt8173-infracfg",
+		      clk_mt8173_infra_init_early);
+
+static int clk_mt8173_infra_probe(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+	r = mtk_clk_register_gates(&pdev->dev, node, infra_clks,
+				   ARRAY_SIZE(infra_clks), infra_clk_data);
+	if (r)
+		return r;
 
-	mtk_clk_register_gates(NULL, node, infra_clks,
-			       ARRAY_SIZE(infra_clks), clk_data);
-	mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
+	r = mtk_clk_register_cpumuxes(&pdev->dev, node, cpu_muxes,
+				      ARRAY_SIZE(cpu_muxes), infra_clk_data);
+	if (r)
+		goto unregister_gates;
 
-	mtk_clk_register_cpumuxes(NULL, node, cpu_muxes,
-				  ARRAY_SIZE(cpu_muxes), clk_data);
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, infra_clk_data);
+	if (r)
+		goto unregister_cpumuxes;
 
-	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	r = mtk_register_reset_controller(node, &clk_rst_desc[0]);
 	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
+		goto unregister_clk_hw;
+
+	return 0;
 
-	mtk_register_reset_controller(node, &clk_rst_desc[0]);
+unregister_clk_hw:
+	of_clk_del_provider(node);
+unregister_cpumuxes:
+	mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), infra_clk_data);
+unregister_gates:
+	mtk_clk_unregister_gates(infra_clks, ARRAY_SIZE(infra_clks), infra_clk_data);
+	return r;
 }
-CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
 
-static void __init mtk_pericfg_init(struct device_node *node)
+static int clk_mt8173_peri_probe(struct platform_device *pdev)
 {
+	struct device_node *node = pdev->dev.of_node;
 	struct clk_hw_onecell_data *clk_data;
 	int r;
 	void __iomem *base;
 
-	base = of_iomap(node, 0);
-	if (!base) {
-		pr_err("%s(): ioremap failed\n", __func__);
-		return;
-	}
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+	if (IS_ERR_OR_NULL(clk_data))
+		return -ENOMEM;
 
-	mtk_clk_register_gates(NULL, node, peri_gates,
-			       ARRAY_SIZE(peri_gates), clk_data);
-	mtk_clk_register_composites(NULL, peri_clks,
-				    ARRAY_SIZE(peri_clks), base,
-				    &mt8173_clk_lock, clk_data);
+	r = mtk_clk_register_gates(&pdev->dev, node, peri_gates,
+				   ARRAY_SIZE(peri_gates), clk_data);
+	if (r)
+		goto free_clk_data;
+
+	r = mtk_clk_register_composites(&pdev->dev, peri_clks,
+					ARRAY_SIZE(peri_clks), base,
+					&mt8173_clk_lock, clk_data);
+	if (r)
+		goto unregister_gates;
 
 	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
 	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
+		goto unregister_composites;
 
-	mtk_register_reset_controller(node, &clk_rst_desc[1]);
+	r = mtk_register_reset_controller(node, &clk_rst_desc[1]);
+	if (r)
+		goto unregister_clk_hw;
+
+	return 0;
+
+unregister_clk_hw:
+	of_clk_del_provider(node);
+unregister_composites:
+	mtk_clk_unregister_composites(peri_clks, ARRAY_SIZE(peri_clks), clk_data);
+unregister_gates:
+	mtk_clk_unregister_gates(peri_gates, ARRAY_SIZE(peri_gates), clk_data);
+free_clk_data:
+	mtk_free_clk_data(clk_data);
+	return r;
 }
-CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
-
-struct mtk_clk_usb {
-	int id;
-	const char *name;
-	const char *parent;
-	u32 reg_ofs;
-};
-
-#define APMIXED_USB(_id, _name, _parent, _reg_ofs) {			\
-		.id = _id,						\
-		.name = _name,						\
-		.parent = _parent,					\
-		.reg_ofs = _reg_ofs,					\
-	}
-
-static const struct mtk_clk_usb apmixed_usb[] __initconst = {
-	APMIXED_USB(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8),
-};
 
 #define MT8173_PLL_FMAX		(3000UL * MHZ)
 
@@ -1009,119 +1067,130 @@ static const struct mtk_pll_data plls[] = {
 	PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
 };
 
-static void __init mtk_apmixedsys_init(struct device_node *node)
+static int clk_mt8173_apmixed_probe(struct platform_device *pdev)
 {
+	struct device_node *node = pdev->dev.of_node;
 	struct clk_hw_onecell_data *clk_data;
 	void __iomem *base;
 	struct clk_hw *hw;
-	int r, i;
+	int r;
 
 	base = of_iomap(node, 0);
-	if (!base) {
-		pr_err("%s(): ioremap failed\n", __func__);
-		return;
-	}
+	if (!base)
+		return PTR_ERR(base);
 
 	mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
-	if (!clk_data) {
-		iounmap(base);
-		return;
-	}
-
-	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+	if (IS_ERR_OR_NULL(clk_data))
+		return -ENOMEM;
 
-	for (i = 0; i < ARRAY_SIZE(apmixed_usb); i++) {
-		const struct mtk_clk_usb *cku = &apmixed_usb[i];
-
-		hw = mtk_clk_register_ref2usb_tx(cku->name, cku->parent, base + cku->reg_ofs);
-		if (IS_ERR(hw)) {
-			pr_err("Failed to register clk %s: %ld\n", cku->name, PTR_ERR(hw));
-			continue;
-		}
+	r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+	if (r)
+		goto free_clk_data;
 
-		clk_data->hws[cku->id] = hw;
+	hw = mtk_clk_register_ref2usb_tx("ref2usb_tx", "clk26m", base + REGOFF_REF2USB);
+	if (IS_ERR(hw)) {
+		r = PTR_ERR(hw);
+		dev_err(&pdev->dev, "Failed to register ref2usb_tx: %d\n", r);
+		goto unregister_plls;
 	}
+	clk_data->hws[CLK_APMIXED_REF2USB_TX] = hw;
 
-	hw = clk_hw_register_divider(NULL, "hdmi_ref", "tvdpll_594m", 0,
-				     base + 0x40, 16, 3, CLK_DIVIDER_POWER_OF_TWO,
-				     NULL);
+	hw = devm_clk_hw_register_divider(&pdev->dev, "hdmi_ref", "tvdpll_594m", 0,
+					  base + REGOFF_HDMI_REF, 16, 3,
+					  CLK_DIVIDER_POWER_OF_TWO, NULL);
 	clk_data->hws[CLK_APMIXED_HDMI_REF] = hw;
 
 	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
 	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
+		goto unregister_ref2usb;
 
 	mtk_clk_enable_critical();
+	return 0;
+
+unregister_ref2usb:
+	mtk_clk_unregister_ref2usb_tx(clk_data->hws[CLK_APMIXED_REF2USB_TX]);
+unregister_plls:
+	mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
+free_clk_data:
+	mtk_free_clk_data(clk_data);
+	return r;
 }
-CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
-		mtk_apmixedsys_init);
-
-static void __init mtk_imgsys_init(struct device_node *node)
-{
-	struct clk_hw_onecell_data *clk_data;
-	int r;
-
-	clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
 
-	mtk_clk_register_gates(NULL, node, img_clks,
-			       ARRAY_SIZE(img_clks), clk_data);
-
-	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+static const struct mtk_clk_desc img_desc = {
+	.clks = img_clks,
+	.num_clks = ARRAY_SIZE(img_clks),
+};
 
-	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
-}
-CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8173-imgsys", mtk_imgsys_init);
+static const struct mtk_clk_desc vdec_desc = {
+	.clks = vdec_clks,
+	.num_clks = ARRAY_SIZE(vdec_clks),
+};
 
-static void __init mtk_vdecsys_init(struct device_node *node)
-{
-	struct clk_hw_onecell_data *clk_data;
-	int r;
+static const struct mtk_clk_desc venc_desc = {
+	.clks = venc_clks,
+	.num_clks = ARRAY_SIZE(venc_clks),
+};
 
-	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
+static const struct mtk_clk_desc venc_lt_desc = {
+	.clks = venclt_clks,
+	.num_clks = ARRAY_SIZE(venclt_clks),
+};
 
-	mtk_clk_register_gates(NULL, node, vdec_clks,
-			       ARRAY_SIZE(vdec_clks), clk_data);
+static const struct of_device_id of_match_clk_mt8173_simple[] = {
+	{ .compatible = "mediatek,mt8173-imgsys", .data = &img_desc },
+	{ .compatible = "mediatek,mt8173-vdecsys", .data = &vdec_desc },
+	{ .compatible = "mediatek,mt8173-vencsys", .data = &venc_desc },
+	{ .compatible = "mediatek,mt8173-vencltsys", .data = &venc_lt_desc },
+	{ /* sentinel */ }
+};
 
-	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
-	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
-}
-CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8173-vdecsys", mtk_vdecsys_init);
+static struct platform_driver clk_mt8173_simple_drv = {
+	.driver = {
+		.name = "clk-mt8173-simple",
+		.of_match_table = of_match_clk_mt8173_simple,
+	},
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+};
 
-static void __init mtk_vencsys_init(struct device_node *node)
+static int clk_mt8173_probe(struct platform_device *pdev)
 {
-	struct clk_hw_onecell_data *clk_data;
+	int (*clk_probe)(struct platform_device *pdev);
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
+	clk_probe = of_device_get_match_data(&pdev->dev);
+	if (!clk_probe)
+		return -EINVAL;
 
-	mtk_clk_register_gates(NULL, node, venc_clks,
-			       ARRAY_SIZE(venc_clks), clk_data);
-
-	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	r = clk_probe(pdev);
 	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
+		dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", pdev->name, r);
+
+	return r;
 }
-CLK_OF_DECLARE(mtk_vencsys, "mediatek,mt8173-vencsys", mtk_vencsys_init);
 
-static void __init mtk_vencltsys_init(struct device_node *node)
-{
-	struct clk_hw_onecell_data *clk_data;
-	int r;
+static const struct of_device_id of_match_clk_mt8173[] = {
+	{ .compatible = "mediatek,mt8173-apmixedsys", .data = clk_mt8173_apmixed_probe },
+	{ .compatible = "mediatek,mt8173-infracfg", .data = clk_mt8173_infra_probe },
+	{ .compatible = "mediatek,mt8173-topckgen", .data = clk_mt8173_topck_probe },
+	{ .compatible = "mediatek,mt8173-pericfg", .data = clk_mt8173_peri_probe },
+	{ /* sentinel */ }
+};
 
-	clk_data = mtk_alloc_clk_data(CLK_VENCLT_NR_CLK);
+static struct platform_driver clk_mt8173_drv = {
+	.probe = clk_mt8173_probe,
+	.driver = {
+		.name = "clk-mt8173",
+		.of_match_table = of_match_clk_mt8173,
+	},
+};
 
-	mtk_clk_register_gates(NULL, node, venclt_clks,
-			       ARRAY_SIZE(venclt_clks), clk_data);
+static int __init clk_mt8173_init(void)
+{
+	int ret = platform_driver_register(&clk_mt8173_drv);
 
-	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
-	if (r)
-		pr_err("%s(): could not register clock provider: %d\n",
-			__func__, r);
+	if (ret)
+		return ret;
+	return platform_driver_register(&clk_mt8173_simple_drv);
 }
-CLK_OF_DECLARE(mtk_vencltsys, "mediatek,mt8173-vencltsys", mtk_vencltsys_init);
+arch_initcall(clk_mt8173_init);
