@@ -12443,6 +12443,7 @@ L: linux-clk@vger.kernel.org
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/clk/mediatek/clk-mt6735-apmixed.c
+F: drivers/clk/mediatek/clk-mt6735-topckgen.c
F: include/dt-bindings/clock/mediatek,mt6735-apmixedsys.h
F: include/dt-bindings/clock/mediatek,mt6735-infracfg.h
F: include/dt-bindings/clock/mediatek,mt6735-pericfg.h
@@ -124,6 +124,13 @@ config COMMON_CLK_MT6735_APMIXED
help
This driver supports MediaTek MT6735 apmixedsys clocks.
+config COMMON_CLK_MT6735_TOPCKGEN
+ tristate "Clock driver for MediaTek MT6735 topckgen"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ help
+ This driver supports MediaTek MT6735 topckgen clocks.
+
config COMMON_CLK_MT6765
bool "Clock driver for MediaTek MT6765"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
@@ -2,6 +2,7 @@
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
obj-$(CONFIG_COMMON_CLK_MT6735_APMIXED) += clk-mt6735-apmixed.o
+obj-$(CONFIG_COMMON_CLK_MT6735_TOPCKGEN) += clk-mt6735-topckgen.o
obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o
obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o
obj-$(CONFIG_COMMON_CLK_MT6765_CAMSYS) += clk-mt6765-cam.o
new file mode 100644
@@ -0,0 +1,1159 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-topckgen.h>
+
+#define CLK_CFG_0 0x40
+#define CLK_CFG_0_SET 0x44
+#define CLK_CFG_0_CLR 0x48
+#define CLK_CFG_1 0x50
+#define CLK_CFG_1_SET 0x54
+#define CLK_CFG_1_CLR 0x58
+#define CLK_CFG_2 0x60
+#define CLK_CFG_2_SET 0x64
+#define CLK_CFG_2_CLR 0x68
+#define CLK_CFG_3 0x70
+#define CLK_CFG_3_SET 0x74
+#define CLK_CFG_3_CLR 0x78
+#define CLK_CFG_4 0x80
+#define CLK_CFG_4_SET 0x84
+#define CLK_CFG_4_CLR 0x88
+#define CLK_CFG_5 0x90
+#define CLK_CFG_5_SET 0x94
+#define CLK_CFG_5_CLR 0x98
+#define CLK_CFG_6 0xa0
+#define CLK_CFG_6_SET 0xa4
+#define CLK_CFG_6_CLR 0xa8
+#define CLK_CFG_7 0xb0
+#define CLK_CFG_7_SET 0xb4
+#define CLK_CFG_7_CLR 0xb8
+
+static DEFINE_SPINLOCK(mt6735_topckgen_lock);
+
+/* Some clocks with unknown details are modeled as fixed clocks */
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+ {
+ /*
+ * This clock is available as a parent option for multiple
+ * muxes and seems like an alternative name for clk26m at first,
+ * but it appears alongside it in several muxes which should
+ * mean it is a separate clock.
+ */
+ .id = AD_SYS_26M_CK,
+ .name = "ad_sys_26m_ck",
+ .parent = "clk26m",
+ .rate = 26 * MHZ,
+ },
+ {
+ /*
+ * This clock is the parent of DMPLL divisors. It might be MEMPLL
+ * or its parent, as DMPLL appears to be an alternative name for
+ * MEMPLL.
+ */
+ .id = CLKPH_MCK_O,
+ .name = "clkph_mck_o",
+ .parent = NULL
+ },
+ {
+ /*
+ * DMPLL clock (dmpll_ck), controlled by DDRPHY.
+ */
+ .id = DMPLL,
+ .name = "dmpll",
+ .parent = "clkph_mck_o"
+ },
+ {
+ /*
+ * MIPI DPI clock. Parent option for dpi0_sel. Unknown parent.
+ */
+ .id = DPI_CK,
+ .name = "dpi_ck",
+ .parent = NULL
+ },
+ {
+ /*
+ * This clock is a child of WHPLL which is controlled by
+ * the modem.
+ */
+ .id = WHPLL_AUDIO_CK,
+ .name = "whpll_audio_ck",
+ .parent = NULL
+ },
+};
+
+static const struct mtk_fixed_factor top_divs[] = {
+ {
+ .id = SYSPLL_D2,
+ .name = "syspll_d2",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = SYSPLL_D3,
+ .name = "syspll_d3",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 3
+ },
+ {
+ .id = SYSPLL_D5,
+ .name = "syspll_d5",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 5
+ },
+ {
+ .id = SYSPLL1_D2,
+ .name = "syspll1_d2",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = SYSPLL1_D4,
+ .name = "syspll1_d4",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = SYSPLL1_D8,
+ .name = "syspll1_d8",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 8
+ },
+ {
+ .id = SYSPLL1_D16,
+ .name = "syspll1_d16",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 16
+ },
+ {
+ .id = SYSPLL2_D2,
+ .name = "syspll2_d2",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = SYSPLL2_D4,
+ .name = "syspll2_d4",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = SYSPLL3_D2,
+ .name = "syspll3_d2",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = SYSPLL3_D4,
+ .name = "syspll3_d4",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = SYSPLL4_D2,
+ .name = "syspll4_d2",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = SYSPLL4_D4,
+ .name = "syspll4_d4",
+ .parent_name = "mainpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = UNIVPLL_D2,
+ .name = "univpll_d2",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = UNIVPLL_D3,
+ .name = "univpll_d3",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 3
+ },
+ {
+ .id = UNIVPLL_D5,
+ .name = "univpll_d5",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 5
+ },
+ {
+ .id = UNIVPLL_D26,
+ .name = "univpll_d26",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 26
+ },
+ {
+ .id = UNIVPLL1_D2,
+ .name = "univpll1_d2",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = UNIVPLL1_D4,
+ .name = "univpll1_d4",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = UNIVPLL1_D8,
+ .name = "univpll1_d8",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 8
+ },
+ {
+ .id = UNIVPLL2_D2,
+ .name = "univpll2_d2",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = UNIVPLL2_D4,
+ .name = "univpll2_d4",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = UNIVPLL2_D8,
+ .name = "univpll2_d8",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 8
+ },
+ {
+ .id = UNIVPLL3_D2,
+ .name = "univpll3_d2",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = UNIVPLL3_D4,
+ .name = "univpll3_d4",
+ .parent_name = "univpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = MSDCPLL_D2,
+ .name = "msdcpll_d2",
+ .parent_name = "msdcpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = MSDCPLL_D4,
+ .name = "msdcpll_d4",
+ .parent_name = "msdcpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = MSDCPLL_D8,
+ .name = "msdcpll_d8",
+ .parent_name = "msdcpll",
+ .mult = 1,
+ .div = 8
+ },
+ {
+ .id = MSDCPLL_D16,
+ .name = "msdcpll_d16",
+ .parent_name = "msdcpll",
+ .mult = 1,
+ .div = 16
+ },
+ {
+ .id = VENCPLL_D3,
+ .name = "vencpll_d3",
+ .parent_name = "vencpll",
+ .mult = 1,
+ .div = 3
+ },
+ {
+ .id = TVDPLL_D2,
+ .name = "tvdpll_d2",
+ .parent_name = "tvdpll",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = TVDPLL_D4,
+ .name = "tvdpll_d4",
+ .parent_name = "tvdpll",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = DMPLL_D2,
+ .name = "dmpll_d2",
+ .parent_name = "clkph_mck_o",
+ .mult = 1,
+ .div = 2
+ },
+ {
+ .id = DMPLL_D4,
+ .name = "dmpll_d4",
+ .parent_name = "clkph_mck_o",
+ .mult = 1,
+ .div = 4
+ },
+ {
+ .id = DMPLL_D8,
+ .name = "dmpll_d8",
+ .parent_name = "clkph_mck_o",
+ .mult = 1,
+ .div = 8
+ },
+ {
+ .id = AD_SYS_26M_D2,
+ .name = "ad_sys_26m_d2",
+ .parent_name = "clk26m",
+ .mult = 1,
+ .div = 2
+ },
+};
+
+static const char * const axi_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "dmpll",
+ "dmpll_d2"
+};
+
+static const char * const mem_sel_parents[] = {
+ "clk26m",
+ "dmpll"
+};
+
+static const char * const ddrphycfg_parents[] = {
+ "clk26m",
+ "syspll1_d8"
+};
+
+static const char * const mm_sel_parents[] = {
+ "clk26m",
+ "vencpll",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "dmpll"
+};
+
+static const char * const pwm_sel_parents[] = {
+ "clk26m",
+ "univpll2_d4",
+ "univpll3_d2",
+ "univpll1_d4"
+};
+
+static const char * const vdec_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "syspll_d2",
+ "syspll2_d2",
+ "msdcpll_d2"
+};
+
+static const char * const mfg_sel_parents[] = {
+ "clk26m",
+ "mmpll",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "syspll_d3",
+ "syspll1_d2",
+ "syspll_d5",
+ "univpll_d3",
+ "univpll1_d2"
+};
+
+static const char * const camtg_sel_parents[] = {
+ "clk26m",
+ "univpll_d26",
+ "univpll2_d2",
+ "syspll3_d2",
+ "syspll3_d4",
+ "msdcpll_d4"
+};
+
+static const char * const uart_sel_parents[] = {
+ "clk26m",
+ "univpll2_d8"
+};
+
+static const char * const spi_sel_parents[] = {
+ "clk26m",
+ "syspll3_d2",
+ "msdcpll_d8",
+ "syspll2_d4",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8"
+};
+
+static const char * const usb20_sel_parents[] = {
+ "clk26m",
+ "univpll1_d8",
+ "univpll3_d4"
+};
+
+static const char * const msdc50_0_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll2_d2",
+ "syspll4_d2",
+ "univpll_d5",
+ "univpll1_d4"
+};
+
+static const char * const msdc30_0_sel_parents[] = {
+ "clk26m",
+ "msdcpll",
+ "msdcpll_d2",
+ "msdcpll_d4",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll_d3",
+ "univpll_d26",
+ "syspll2_d4",
+ "univpll_d2"
+};
+
+static const char * const msdc30_1_2_sel_parents[] = {
+ "clk26m",
+ "univpll2_d2",
+ "msdcpll_d4",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll_d26",
+ "syspll2_d4"
+};
+
+static const char * const msdc30_3_sel_parents[] = {
+ "clk26m",
+ "univpll2_d2",
+ "msdcpll_d4",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll_d26",
+ "msdcpll_d16",
+ "syspll2_d4"
+};
+
+static const char * const audio_sel_parents[] = {
+ "clk26m",
+ "syspll3_d4",
+ "syspll4_d4",
+ "syspll1_d16"
+};
+
+static const char * const aud_intbus_sel_parents[] = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll4_d2",
+ "dmpll_d4"
+};
+
+static const char * const pmicspi_sel_parents[] = {
+ "clk26m",
+ "syspll1_d8",
+ "syspll3_d4",
+ "syspll1_d16",
+ "univpll3_d4",
+ "univpll_d26",
+ "dmpll_d4",
+ "dmpll_d8"
+};
+
+static const char * const scp_sel_parents[] = {
+ "clk26m",
+ "syspll1_d8",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const atb_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "dmpll"
+};
+
+static const char * const dpi0_sel_parents[] = {
+ "clk26m",
+ "tvdpll",
+ "tvdpll_d2",
+ "tvdpll_d4",
+ "dpi_ck"
+};
+
+static const char * const scam_sel_parents[] = {
+ "clk26m",
+ "syspll3_d2",
+ "univpll2_d4",
+ "vencpll_d3"
+};
+
+static const char * const mfg13m_sel_parents[] = {
+ "clk26m",
+ "ad_sys_26m_d2"
+};
+
+static const char * const aud_1_2_sel_parents[] = {
+ "clk26m",
+ "apll1"
+};
+
+static const char * const irda_sel_parents[] = {
+ "clk26m",
+ "univpll2_d4"
+};
+
+static const char * const irtx_sel_parents[] = {
+ "clk26m",
+ "ad_sys_26m_ck"
+};
+
+static const char * const disppwm_sel_parents[] = {
+ "clk26m",
+ "univpll2_d4",
+ "syspll4_d2_d8",
+ "ad_sys_26m_ck"
+};
+
+static const struct mtk_mux top_muxes[] = {
+ {
+ .id = AXI_SEL,
+ .name = "axi_sel",
+ .parent_names = axi_sel_parents,
+ .num_parents = ARRAY_SIZE(axi_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_0,
+ .set_ofs = CLK_CFG_0_SET,
+ .clr_ofs = CLK_CFG_0_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 3,
+
+ .ops = &mtk_mux_clr_set_upd_ops,
+ },
+ {
+ .id = MEM_SEL,
+ .name = "mem_sel",
+ .parent_names = mem_sel_parents,
+ .num_parents = ARRAY_SIZE(mem_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_0,
+ .set_ofs = CLK_CFG_0_SET,
+ .clr_ofs = CLK_CFG_0_CLR,
+
+ .mux_shift = 8,
+ .mux_width = 1,
+
+ .ops = &mtk_mux_clr_set_upd_ops,
+ },
+ {
+ .id = DDRPHY_SEL,
+ .name = "ddrphycfg_sel",
+ .parent_names = ddrphycfg_parents,
+ .num_parents = ARRAY_SIZE(ddrphycfg_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_0,
+ .set_ofs = CLK_CFG_0_SET,
+ .clr_ofs = CLK_CFG_0_CLR,
+
+ .mux_shift = 16,
+ .mux_width = 1,
+
+ .ops = &mtk_mux_clr_set_upd_ops,
+ },
+ {
+ .id = MM_SEL,
+ .name = "mm_sel",
+ .parent_names = mm_sel_parents,
+ .num_parents = ARRAY_SIZE(mm_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_0,
+ .set_ofs = CLK_CFG_0_SET,
+ .clr_ofs = CLK_CFG_0_CLR,
+
+ .mux_shift = 24,
+ .mux_width = 3,
+ .gate_shift = 31,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = PWM_SEL,
+ .name = "pwm_sel",
+ .parent_names = pwm_sel_parents,
+ .num_parents = ARRAY_SIZE(pwm_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_1,
+ .set_ofs = CLK_CFG_1_SET,
+ .clr_ofs = CLK_CFG_1_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 2,
+ .gate_shift = 7,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = VDEC_SEL,
+ .name = "vdec_sel",
+ .parent_names = vdec_sel_parents,
+ .num_parents = ARRAY_SIZE(vdec_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_1,
+ .set_ofs = CLK_CFG_1_SET,
+ .clr_ofs = CLK_CFG_1_CLR,
+
+ .mux_shift = 8,
+ .mux_width = 3,
+ .gate_shift = 15,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = MFG_SEL,
+ .name = "mfg_sel",
+ .parent_names = mfg_sel_parents,
+ .num_parents = ARRAY_SIZE(mfg_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_1,
+ .set_ofs = CLK_CFG_1_SET,
+ .clr_ofs = CLK_CFG_1_CLR,
+
+ .mux_shift = 16,
+ .mux_width = 4,
+ .gate_shift = 23,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = CAMTG_SEL,
+ .name = "camtg_sel",
+ .parent_names = camtg_sel_parents,
+ .num_parents = ARRAY_SIZE(camtg_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_1,
+ .set_ofs = CLK_CFG_1_SET,
+ .clr_ofs = CLK_CFG_1_CLR,
+
+ .mux_shift = 24,
+ .mux_width = 3,
+ .gate_shift = 31,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = UART_SEL,
+ .name = "uart_sel",
+ .parent_names = uart_sel_parents,
+ .num_parents = ARRAY_SIZE(uart_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_2,
+ .set_ofs = CLK_CFG_2_SET,
+ .clr_ofs = CLK_CFG_2_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 1,
+ .gate_shift = 7,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = SPI_SEL,
+ .name = "spi_sel",
+ .parent_names = spi_sel_parents,
+ .num_parents = ARRAY_SIZE(spi_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_2,
+ .set_ofs = CLK_CFG_2_SET,
+ .clr_ofs = CLK_CFG_2_CLR,
+
+ .mux_shift = 8,
+ .mux_width = 3,
+ .gate_shift = 15,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = USB20_SEL,
+ .name = "usb20_sel",
+ .parent_names = usb20_sel_parents,
+ .num_parents = ARRAY_SIZE(usb20_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_2,
+ .set_ofs = CLK_CFG_2_SET,
+ .clr_ofs = CLK_CFG_2_CLR,
+
+ .mux_shift = 16,
+ .mux_width = 2,
+ .gate_shift = 23,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = MSDC50_0_SEL,
+ .name = "msdc50_0_sel",
+ .parent_names = msdc50_0_sel_parents,
+ .num_parents = ARRAY_SIZE(msdc50_0_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_2,
+ .set_ofs = CLK_CFG_2_SET,
+ .clr_ofs = CLK_CFG_2_CLR,
+
+ .mux_shift = 24,
+ .mux_width = 3,
+ .gate_shift = 31,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = MSDC30_0_SEL,
+ .name = "msdc30_0_sel",
+ .parent_names = msdc30_0_sel_parents,
+ .num_parents = ARRAY_SIZE(msdc30_0_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_3,
+ .set_ofs = CLK_CFG_3_SET,
+ .clr_ofs = CLK_CFG_3_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 4,
+ .gate_shift = 7,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = MSDC30_1_SEL,
+ .name = "msdc30_1_sel",
+ .parent_names = msdc30_1_2_sel_parents,
+ .num_parents = ARRAY_SIZE(msdc30_1_2_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_3,
+ .set_ofs = CLK_CFG_3_SET,
+ .clr_ofs = CLK_CFG_3_CLR,
+
+ .mux_shift = 8,
+ .mux_width = 3,
+ .gate_shift = 15,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = MSDC30_2_SEL,
+ .name = "msdc30_2_sel",
+ .parent_names = msdc30_1_2_sel_parents,
+ .num_parents = ARRAY_SIZE(msdc30_1_2_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_3,
+ .set_ofs = CLK_CFG_3_SET,
+ .clr_ofs = CLK_CFG_3_CLR,
+
+ .mux_shift = 16,
+ .mux_width = 3,
+ .gate_shift = 23,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = MSDC30_3_SEL,
+ .name = "msdc30_3_sel",
+ .parent_names = msdc30_3_sel_parents,
+ .num_parents = ARRAY_SIZE(msdc30_3_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_3,
+ .set_ofs = CLK_CFG_3_SET,
+ .clr_ofs = CLK_CFG_3_CLR,
+
+ .mux_shift = 24,
+ .mux_width = 4,
+ .gate_shift = 31,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = AUDIO_SEL,
+ .name = "audio_sel",
+ .parent_names = audio_sel_parents,
+ .num_parents = ARRAY_SIZE(audio_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_4,
+ .set_ofs = CLK_CFG_4_SET,
+ .clr_ofs = CLK_CFG_4_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 2,
+ .gate_shift = 7,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = AUDINTBUS_SEL,
+ .name = "aud_intbus_sel",
+ .parent_names = aud_intbus_sel_parents,
+ .num_parents = ARRAY_SIZE(aud_intbus_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_4,
+ .set_ofs = CLK_CFG_4_SET,
+ .clr_ofs = CLK_CFG_4_CLR,
+
+ .mux_shift = 8,
+ .mux_width = 2,
+ .gate_shift = 15,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = PMICSPI_SEL,
+ .name = "pmicspi_sel",
+ .parent_names = pmicspi_sel_parents,
+ .num_parents = ARRAY_SIZE(pmicspi_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_4,
+ .set_ofs = CLK_CFG_4_SET,
+ .clr_ofs = CLK_CFG_4_CLR,
+
+ .mux_shift = 16,
+ .mux_width = 3,
+
+ .ops = &mtk_mux_clr_set_upd_ops,
+ },
+ {
+ .id = SCP_SEL,
+ .name = "scp_sel",
+ .parent_names = scp_sel_parents,
+ .num_parents = ARRAY_SIZE(scp_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_4,
+ .set_ofs = CLK_CFG_4_SET,
+ .clr_ofs = CLK_CFG_4_CLR,
+
+ .mux_shift = 24,
+ .mux_width = 2,
+ .gate_shift = 31,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = ATB_SEL,
+ .name = "atb_sel",
+ .parent_names = atb_sel_parents,
+ .num_parents = ARRAY_SIZE(atb_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_5,
+ .set_ofs = CLK_CFG_5_SET,
+ .clr_ofs = CLK_CFG_5_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 2,
+ .gate_shift = 7,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = DPI0_SEL,
+ .name = "dpi0_sel",
+ .parent_names = dpi0_sel_parents,
+ .num_parents = ARRAY_SIZE(dpi0_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_5,
+ .set_ofs = CLK_CFG_5_SET,
+ .clr_ofs = CLK_CFG_5_CLR,
+
+ .mux_shift = 8,
+ .mux_width = 3,
+ .gate_shift = 15,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = SCAM_SEL,
+ .name = "scam_sel",
+ .parent_names = scam_sel_parents,
+ .num_parents = ARRAY_SIZE(scam_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_5,
+ .set_ofs = CLK_CFG_5_SET,
+ .clr_ofs = CLK_CFG_5_CLR,
+
+ .mux_shift = 16,
+ .mux_width = 2,
+ .gate_shift = 23,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = MFG13M_SEL,
+ .name = "mfg13m_sel",
+ .parent_names = mfg13m_sel_parents,
+ .num_parents = ARRAY_SIZE(mfg13m_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_5,
+ .set_ofs = CLK_CFG_5_SET,
+ .clr_ofs = CLK_CFG_5_CLR,
+
+ .mux_shift = 24,
+ .mux_width = 1,
+ .gate_shift = 31,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = AUD1_SEL,
+ .name = "aud_1_sel",
+ .parent_names = aud_1_2_sel_parents,
+ .num_parents = ARRAY_SIZE(aud_1_2_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_6,
+ .set_ofs = CLK_CFG_6_SET,
+ .clr_ofs = CLK_CFG_6_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 1,
+ .gate_shift = 7,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = AUD2_SEL,
+ .name = "aud_2_sel",
+ .parent_names = aud_1_2_sel_parents,
+ .num_parents = ARRAY_SIZE(aud_1_2_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_6,
+ .set_ofs = CLK_CFG_6_SET,
+ .clr_ofs = CLK_CFG_6_CLR,
+
+ .mux_shift = 8,
+ .mux_width = 1,
+ .gate_shift = 15,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = IRDA_SEL,
+ .name = "irda_sel",
+ .parent_names = irda_sel_parents,
+ .num_parents = ARRAY_SIZE(irda_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_6,
+ .set_ofs = CLK_CFG_6_SET,
+ .clr_ofs = CLK_CFG_6_CLR,
+
+ .mux_shift = 16,
+ .mux_width = 1,
+ .gate_shift = 23,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = IRTX_SEL,
+ .name = "irtx_sel",
+ .parent_names = irtx_sel_parents,
+ .num_parents = ARRAY_SIZE(irtx_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_6,
+ .set_ofs = CLK_CFG_6_SET,
+ .clr_ofs = CLK_CFG_6_CLR,
+
+ .mux_shift = 24,
+ .mux_width = 1,
+ .gate_shift = 31,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+ {
+ .id = DISPPWM_SEL,
+ .name = "disppwm_sel",
+ .parent_names = disppwm_sel_parents,
+ .num_parents = ARRAY_SIZE(disppwm_sel_parents),
+ .flags = CLK_SET_RATE_PARENT,
+
+ .mux_ofs = CLK_CFG_7,
+ .set_ofs = CLK_CFG_7_SET,
+ .clr_ofs = CLK_CFG_7_CLR,
+
+ .mux_shift = 0,
+ .mux_width = 2,
+ .gate_shift = 7,
+
+ .ops = &mtk_mux_gate_clr_set_upd_ops,
+ },
+};
+
+int clk_mt6735_topckgen_probe(struct platform_device *pdev)
+{
+ void __iomem *base;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct clk_onecell_data *clk_data;
+ int ret;
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(ARRAY_SIZE(top_fixed_clks) +
+ ARRAY_SIZE(top_divs) +
+ ARRAY_SIZE(top_muxes));
+ if (!clk_data)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, clk_data);
+
+ ret = mtk_clk_register_fixed_clks(top_fixed_clks,
+ ARRAY_SIZE(top_fixed_clks), clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register fixed clocks: %pe\n",
+ ERR_PTR(ret));
+ goto free_clk_data;
+ }
+
+ ret = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register dividers: %pe\n",
+ ERR_PTR(ret));
+ goto unregister_fixed_clks;
+ }
+
+ ret = mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes),
+ pdev->dev.of_node, &mt6735_topckgen_lock,
+ clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register muxes: %pe\n",
+ ERR_PTR(ret));
+ goto unregister_factors;
+ }
+
+ ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+ clk_data);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to register clock provider: %pe\n",
+ ERR_PTR(ret));
+ goto unregister_muxes;
+ }
+
+ return 0;
+unregister_muxes:
+ mtk_clk_unregister_muxes(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(top_fixed_clks,
+ ARRAY_SIZE(top_fixed_clks), clk_data);
+free_clk_data:
+ mtk_free_clk_data(clk_data);
+
+ return ret;
+}
+
+int clk_mt6735_topckgen_remove(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+ mtk_clk_unregister_muxes(top_muxes, ARRAY_SIZE(top_muxes), clk_data);
+ mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+ mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+ clk_data);
+ mtk_free_clk_data(clk_data);
+
+ return 0;
+}
+
+static const struct of_device_id of_match_mt6735_topckgen[] = {
+ { .compatible = "mediatek,mt6735-topckgen" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt6735_topckgen = {
+ .probe = clk_mt6735_topckgen_probe,
+ .remove = clk_mt6735_topckgen_remove,
+ .driver = {
+ .name = "clk-mt6735-topckgen",
+ .of_match_table = of_match_mt6735_topckgen,
+ },
+};
+module_platform_driver(clk_mt6735_topckgen);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Mediatek MT6735 topckgen clock driver");
+MODULE_LICENSE("GPL");