On 25/02/2023 10:42, Yassine Oudjana wrote: > From: Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx> > > Add drivers for MT6735 apmixedsys, topckgen, infracfg and pericfg > clock and reset controllers. These provide the base clocks and resets > on the platform, and should be enough to bring up all essential blocks > including PWRAP, MSDC and peripherals (UART, I2C, SPI). > > Signed-off-by: Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx> > --- > MAINTAINERS | 4 + > drivers/clk/mediatek/Kconfig | 9 + > drivers/clk/mediatek/Makefile | 1 + > drivers/clk/mediatek/clk-mt6735-apmixedsys.c | 139 ++++++ > drivers/clk/mediatek/clk-mt6735-infracfg.c | 78 ++++ > drivers/clk/mediatek/clk-mt6735-pericfg.c | 91 ++++ > drivers/clk/mediatek/clk-mt6735-topckgen.c | 450 +++++++++++++++++++ > 7 files changed, 772 insertions(+) > create mode 100644 drivers/clk/mediatek/clk-mt6735-apmixedsys.c > create mode 100644 drivers/clk/mediatek/clk-mt6735-infracfg.c > create mode 100644 drivers/clk/mediatek/clk-mt6735-pericfg.c > create mode 100644 drivers/clk/mediatek/clk-mt6735-topckgen.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index f617042790ee..d7ec4a36a934 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -13106,6 +13106,10 @@ M: Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx> > L: linux-clk@xxxxxxxxxxxxxxx > L: linux-mediatek@xxxxxxxxxxxxxxxxxxx (moderated for non-subscribers) > S: Maintained > +F: drivers/clk/mediatek/clk-mt6735-apmixedsys.c > +F: drivers/clk/mediatek/clk-mt6735-infracfg.c > +F: drivers/clk/mediatek/clk-mt6735-pericfg.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 > diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig > index 2d14855dd37e..593791c0a7d6 100644 > --- a/drivers/clk/mediatek/Kconfig > +++ b/drivers/clk/mediatek/Kconfig > @@ -124,6 +124,15 @@ config COMMON_CLK_MT2712_VENCSYS > help > This driver supports MediaTek MT2712 vencsys clocks. > > +config COMMON_CLK_MT6735 > + tristate "Main clock drivers for MediaTek MT6735" > + depends on ARCH_MEDIATEK || COMPILE_TEST > + select COMMON_CLK_MEDIATEK > + help > + This enables drivers for clocks and resets provided > + by apmixedsys, topckgen, infracfg and pericfg on the > + MediaTek MT6735 SoC. > + > config COMMON_CLK_MT6765 > bool "Clock driver for MediaTek MT6765" > depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST > diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile > index e5d018270ed0..d2496a8d0467 100644 > --- a/drivers/clk/mediatek/Makefile > +++ b/drivers/clk/mediatek/Makefile > @@ -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_MEDIATEK_FHCTL) += clk-fhctl.o clk-pllfh.o > > +obj-$(CONFIG_COMMON_CLK_MT6735) += clk-mt6735-apmixedsys.o clk-mt6735-infracfg.o clk-mt6735-pericfg.o 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 > diff --git a/drivers/clk/mediatek/clk-mt6735-apmixedsys.c b/drivers/clk/mediatek/clk-mt6735-apmixedsys.c > new file mode 100644 > index 000000000000..5ce395c34d92 > --- /dev/null > +++ b/drivers/clk/mediatek/clk-mt6735-apmixedsys.c > @@ -0,0 +1,139 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2022 Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx> > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/platform_device.h> > + > +#include "clk-mtk.h" > +#include "clk-pll.h" > + > +#include <dt-bindings/clock/mediatek,mt6735-apmixedsys.h> > + > +#define AP_PLL_CON_5 0x014 > +#define ARMPLL_CON0 0x200 > +#define ARMPLL_CON1 0x204 > +#define ARMPLL_PWR_CON0 0x20c > +#define MAINPLL_CON0 0x210 > +#define MAINPLL_CON1 0x214 > +#define MAINPLL_PWR_CON0 0x21c > +#define UNIVPLL_CON0 0x220 > +#define UNIVPLL_CON1 0x224 > +#define UNIVPLL_PWR_CON0 0x22c > +#define MMPLL_CON0 0x230 > +#define MMPLL_CON1 0x234 > +#define MMPLL_PWR_CON0 0x23c > +#define MSDCPLL_CON0 0x240 > +#define MSDCPLL_CON1 0x244 > +#define MSDCPLL_PWR_CON0 0x24c > +#define VENCPLL_CON0 0x250 > +#define VENCPLL_CON1 0x254 > +#define VENCPLL_PWR_CON0 0x25c > +#define TVDPLL_CON0 0x260 > +#define TVDPLL_CON1 0x264 > +#define TVDPLL_PWR_CON0 0x26c > +#define APLL1_CON0 0x270 > +#define APLL1_CON1 0x274 > +#define APLL1_CON2 0x278 > +#define APLL1_PWR_CON0 0x280 > +#define APLL2_CON0 0x284 > +#define APLL2_CON1 0x288 > +#define APLL2_CON2 0x28c > +#define APLL2_PWR_CON0 0x294 > + > +#define CON0_RST_BAR BIT(24) > + > +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _rst_bar_mask, \ > + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ > + _tuner_en_bit, _pcw_reg, _pcwbits, _flags) { \ > + .id = _id, \ > + .name = _name, \ > + .parent_name = "clk26m", \ > + .reg = _reg, \ > + .pwr_reg = _pwr_reg, \ > + .en_mask = _en_mask, \ > + .rst_bar_mask = _rst_bar_mask, \ > + .pd_reg = _pd_reg, \ > + .pd_shift = _pd_shift, \ > + .tuner_reg = _tuner_reg, \ > + .tuner_en_reg = _tuner_en_reg, \ > + .tuner_en_bit = _tuner_en_bit, \ > + .pcw_reg = _pcw_reg, \ > + .pcw_chg_reg = _pcw_reg, \ > + .pcwbits = _pcwbits, \ > + .flags = _flags, \ > + } > + > +static const struct mtk_pll_data apmixedsys_plls[] = { > + PLL(ARMPLL, "armpll", ARMPLL_CON0, ARMPLL_PWR_CON0, 0x00000001, 0, ARMPLL_CON1, 24, 0, 0, 0, ARMPLL_CON1, 21, PLL_AO), > + PLL(MAINPLL, "mainpll", MAINPLL_CON0, MAINPLL_PWR_CON0, 0xf0000101, CON0_RST_BAR, MAINPLL_CON1, 24, 0, 0, 0, MAINPLL_CON1, 21, HAVE_RST_BAR), > + PLL(UNIVPLL, "univpll", UNIVPLL_CON0, UNIVPLL_PWR_CON0, 0xfc000001, CON0_RST_BAR, UNIVPLL_CON1, 24, 0, 0, 0, UNIVPLL_CON1, 21, HAVE_RST_BAR), > + PLL(MMPLL, "mmpll", MMPLL_CON0, MMPLL_PWR_CON0, 0x00000001, 0, MMPLL_CON1, 24, 0, 0, 0, MMPLL_CON1, 21, 0), > + PLL(MSDCPLL, "msdcpll", MSDCPLL_CON0, MSDCPLL_PWR_CON0, 0x00000001, 0, MSDCPLL_CON1, 24, 0, 0, 0, MSDCPLL_CON1, 21, 0), > + PLL(VENCPLL, "vencpll", VENCPLL_CON0, VENCPLL_PWR_CON0, 0x00000001, CON0_RST_BAR, VENCPLL_CON1, 24, 0, 0, 0, VENCPLL_CON1, 21, HAVE_RST_BAR), > + PLL(TVDPLL, "tvdpll", TVDPLL_CON0, TVDPLL_PWR_CON0, 0x00000001, 0, TVDPLL_CON1, 24, 0, 0, 0, TVDPLL_CON1, 21, 0), > + PLL(APLL1, "apll1", APLL1_CON0, APLL1_PWR_CON0, 0x00000001, 0, APLL1_CON0, 4, APLL1_CON2, AP_PLL_CON_5, 0, APLL1_CON1, 31, 0), > + PLL(APLL2, "apll2", APLL2_CON0, APLL2_PWR_CON0, 0x00000001, 0, APLL2_CON0, 4, APLL2_CON2, AP_PLL_CON_5, 1, APLL2_CON1, 31, 0) > +}; > + > +int clk_mt6735_apmixed_probe(struct platform_device *pdev) > +{ > + void __iomem *base; > + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + struct clk_hw_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(apmixedsys_plls)); > + if (!clk_data) > + return -ENOMEM; > + platform_set_drvdata(pdev, clk_data); > + > + ret = mtk_clk_register_plls(pdev->dev.of_node, apmixedsys_plls, > + ARRAY_SIZE(apmixedsys_plls), clk_data); > + if (ret) { > + dev_err(&pdev->dev, "Failed to register PLLs: %d\n", ret); > + return ret; > + } > + > + ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, > + clk_data); > + if (ret) > + dev_err(&pdev->dev, > + "Failed to register clock provider: %d\n", ret); > + > + return ret; > +} > + > +int clk_mt6735_apmixed_remove(struct platform_device *pdev) > +{ > + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); > + > + mtk_clk_unregister_plls(apmixedsys_plls, ARRAY_SIZE(apmixedsys_plls), clk_data); > + mtk_free_clk_data(clk_data); > + > + return 0; > +} > + > +static const struct of_device_id of_match_mt6735_apmixedsys[] = { > + { .compatible = "mediatek,mt6735-apmixedsys" }, > + { /* sentinel */ } > +}; > + > +static struct platform_driver clk_mt6735_apmixedsys = { > + .probe = clk_mt6735_apmixed_probe, > + .remove = clk_mt6735_apmixed_remove, > + .driver = { > + .name = "clk-mt6735-apmixedsys", > + .of_match_table = of_match_mt6735_apmixedsys, > + }, > +}; > +module_platform_driver(clk_mt6735_apmixedsys); > + > +MODULE_AUTHOR("Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx>"); > +MODULE_DESCRIPTION("MediaTek MT6735 apmixedsys clock driver"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/clk/mediatek/clk-mt6735-infracfg.c b/drivers/clk/mediatek/clk-mt6735-infracfg.c > new file mode 100644 > index 000000000000..e9dd3caa5f97 > --- /dev/null > +++ b/drivers/clk/mediatek/clk-mt6735-infracfg.c > @@ -0,0 +1,78 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2022 Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx> > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/platform_device.h> > + > +#include "clk-gate.h" > +#include "clk-mtk.h" > + > +#include <dt-bindings/clock/mediatek,mt6735-infracfg.h> > + > +#define INFRA_RST0 0x30 > +#define INFRA_GLOBALCON_PDN0 0x40 > +#define INFRA_PDN1 0x44 > +#define INFRA_PDN_STA 0x48 > + > +static struct mtk_gate_regs infra_cg_regs = { > + .set_ofs = INFRA_GLOBALCON_PDN0, > + .clr_ofs = INFRA_PDN1, > + .sta_ofs = INFRA_PDN_STA, > +}; > + > +static const struct mtk_gate infracfg_gates[] = { > + GATE_MTK(CLK_DBG, "dbg", "axi_sel", &infra_cg_regs, 0, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_GCE, "gce", "axi_sel", &infra_cg_regs, 1, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_TRBG, "trbg", "axi_sel", &infra_cg_regs, 2, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_CPUM, "cpum", "axi_sel", &infra_cg_regs, 3, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_DEVAPC, "devapc", "axi_sel", &infra_cg_regs, 4, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_AUDIO, "audio", "aud_intbus_sel", &infra_cg_regs, 5, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_GCPU, "gcpu", "axi_sel", &infra_cg_regs, 6, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_L2C_SRAM, "l2csram", "axi_sel", &infra_cg_regs, 7, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_M4U, "m4u", "axi_sel", &infra_cg_regs, 8, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_CLDMA, "cldma", "axi_sel", &infra_cg_regs, 12, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_CONNMCU_BUS, "connmcu_bus", "axi_sel", &infra_cg_regs, 15, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_KP, "kp", "axi_sel", &infra_cg_regs, 16, &mtk_clk_gate_ops_setclr), > + GATE_MTK_FLAGS(CLK_APXGPT, "apxgpt", "axi_sel", &infra_cg_regs, 18, &mtk_clk_gate_ops_setclr, CLK_IS_CRITICAL), > + GATE_MTK(CLK_SEJ, "sej", "axi_sel", &infra_cg_regs, 19, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_CCIF0_AP, "ccif0ap", "axi_sel", &infra_cg_regs, 20, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_CCIF1_AP, "ccif1ap", "axi_sel", &infra_cg_regs, 21, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PMIC_SPI, "pmicspi", "pmicspi_sel", &infra_cg_regs, 22, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PMIC_WRAP, "pmicwrap", "axi_sel", &infra_cg_regs, 23, &mtk_clk_gate_ops_setclr) > +}; > + > +static u16 infracfg_rst_ofs[] = { INFRA_RST0 }; > + > +static const struct mtk_clk_rst_desc infracfg_resets = { > + .version = MTK_RST_SIMPLE, > + .rst_bank_ofs = infracfg_rst_ofs, > + .rst_bank_nr = ARRAY_SIZE(infracfg_rst_ofs) > +}; > + > +static const struct mtk_clk_desc infracfg_clks = { > + .clks = infracfg_gates, > + .num_clks = ARRAY_SIZE(infracfg_gates), > + > + .rst_desc = &infracfg_resets > +}; > + > +static const struct of_device_id of_match_mt6735_infracfg[] = { > + { .compatible = "mediatek,mt6735-infracfg", .data = &infracfg_clks }, > + { /* sentinel */ } > +}; > + > +static struct platform_driver clk_mt6735_infracfg = { > + .probe = mtk_clk_simple_probe, > + .remove = mtk_clk_simple_remove, > + .driver = { > + .name = "clk-mt6735-infracfg", > + .of_match_table = of_match_mt6735_infracfg, > + }, > +}; > +module_platform_driver(clk_mt6735_infracfg); > + > +MODULE_AUTHOR("Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx>"); > +MODULE_DESCRIPTION("MediaTek MT6735 infracfg clock and reset driver"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/clk/mediatek/clk-mt6735-pericfg.c b/drivers/clk/mediatek/clk-mt6735-pericfg.c > new file mode 100644 > index 000000000000..4d74e345509b > --- /dev/null > +++ b/drivers/clk/mediatek/clk-mt6735-pericfg.c > @@ -0,0 +1,91 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2022 Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx> > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/platform_device.h> > + > +#include "clk-gate.h" > +#include "clk-mtk.h" > + > +#include <dt-bindings/clock/mediatek,mt6735-pericfg.h> > + > +#define PERI_GLOBALCON_RST0 0x00 > +#define PERI_GLOBALCON_RST1 0x04 > +#define PERI_GLOBALCON_PDN0_SET 0x08 > +#define PERI_GLOBALCON_PDN0_CLR 0x10 > +#define PERI_GLOBALCON_PDN0_STA 0x18 > + > +static struct mtk_gate_regs peri_cg_regs = { > + .set_ofs = PERI_GLOBALCON_PDN0_SET, > + .clr_ofs = PERI_GLOBALCON_PDN0_CLR, > + .sta_ofs = PERI_GLOBALCON_PDN0_STA, > +}; > + > +static const struct mtk_gate pericfg_gates[] = { > + GATE_MTK(CLK_DISP_PWM, "disp_pwm", "disppwm_sel", &peri_cg_regs, 0, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_THERM, "therm", "axi_sel", &peri_cg_regs, 1, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM1, "pwm1", "axi_sel", &peri_cg_regs, 2, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM2, "pwm2", "axi_sel", &peri_cg_regs, 3, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM3, "pwm3", "axi_sel", &peri_cg_regs, 4, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM4, "pwm4", "axi_sel", &peri_cg_regs, 5, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM5, "pwm5", "axi_sel", &peri_cg_regs, 6, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM6, "pwm6", "axi_sel", &peri_cg_regs, 7, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM7, "pwm7", "axi_sel", &peri_cg_regs, 8, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_PWM, "pwm", "axi_sel", &peri_cg_regs, 9, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_USB0, "usb0", "usb20_sel", &peri_cg_regs, 10, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_IRDA, "irda", "irda_sel", &peri_cg_regs, 11, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_APDMA, "apdma", "axi_sel", &peri_cg_regs, 12, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_MSDC30_0, "msdc30_0", "msdc30_0_sel", &peri_cg_regs, 13, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_MSDC30_1, "msdc30_1", "msdc30_1_sel", &peri_cg_regs, 14, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_MSDC30_2, "msdc30_2", "msdc30_2_sel", &peri_cg_regs, 15, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_MSDC30_3, "msdc30_3", "msdc30_3_sel", &peri_cg_regs, 16, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_UART0, "uart0", "uart_sel", &peri_cg_regs, 17, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_UART1, "uart1", "uart_sel", &peri_cg_regs, 18, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_UART2, "uart2", "uart_sel", &peri_cg_regs, 19, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_UART3, "uart3", "uart_sel", &peri_cg_regs, 20, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_UART4, "uart4", "uart_sel", &peri_cg_regs, 21, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_BTIF, "btif", "axi_sel", &peri_cg_regs, 22, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_I2C0, "i2c0", "axi_sel", &peri_cg_regs, 23, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_I2C1, "i2c1", "axi_sel", &peri_cg_regs, 24, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_I2C2, "i2c2", "axi_sel", &peri_cg_regs, 25, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_I2C3, "i2c3", "axi_sel", &peri_cg_regs, 26, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_AUXADC, "auxadc", "axi_sel", &peri_cg_regs, 27, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_SPI0, "spi0", "spi_sel", &peri_cg_regs, 28, &mtk_clk_gate_ops_setclr), > + GATE_MTK(CLK_IRTX, "irtx", "irtx_sel", &peri_cg_regs, 29, &mtk_clk_gate_ops_setclr) > +}; > + > +static u16 pericfg_rst_ofs[] = { PERI_GLOBALCON_RST0, PERI_GLOBALCON_RST1 }; > + > +static const struct mtk_clk_rst_desc pericfg_resets = { > + .version = MTK_RST_SIMPLE, > + .rst_bank_ofs = pericfg_rst_ofs, > + .rst_bank_nr = ARRAY_SIZE(pericfg_rst_ofs) > +}; > + > +static const struct mtk_clk_desc pericfg_clks = { > + .clks = pericfg_gates, > + .num_clks = ARRAY_SIZE(pericfg_gates), > + > + .rst_desc = &pericfg_resets > +}; > + > +static const struct of_device_id of_match_mt6735_pericfg[] = { > + { .compatible = "mediatek,mt6735-pericfg", .data = &pericfg_clks }, > + { /* sentinel */ } > +}; > + > +static struct platform_driver clk_mt6735_pericfg = { > + .probe = mtk_clk_simple_probe, > + .remove = mtk_clk_simple_remove, > + .driver = { > + .name = "clk-mt6735-pericfg", > + .of_match_table = of_match_mt6735_pericfg, > + }, > +}; > +module_platform_driver(clk_mt6735_pericfg); > + > +MODULE_AUTHOR("Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx>"); > +MODULE_DESCRIPTION("MediaTek MT6735 pericfg clock driver"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/clk/mediatek/clk-mt6735-topckgen.c b/drivers/clk/mediatek/clk-mt6735-topckgen.c > new file mode 100644 > index 000000000000..5fa743e4b0fc > --- /dev/null > +++ b/drivers/clk/mediatek/clk-mt6735-topckgen.c > @@ -0,0 +1,450 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2022 Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx> > + */ > + > +#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 topckgen_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. > + */ > + FIXED_CLK(AD_SYS_26M_CK, "ad_sys_26m_ck", "clk26m", 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. > + */ > + FIXED_CLK(CLKPH_MCK_O, "clkph_mck_o", NULL, 0), > + /* > + * DMPLL clock (dmpll_ck), controlled by DDRPHY. > + */ > + FIXED_CLK(DMPLL, "dmpll", "clkph_mck_o", 0), > + /* > + * MIPI DPI clock. Parent option for dpi0_sel. Unknown parent. > + */ > + FIXED_CLK(DPI_CK, "dpi_ck", NULL, 0), > + /* > + * This clock is a child of WHPLL which is controlled by > + * the modem. > + */ > + FIXED_CLK(WHPLL_AUDIO_CK, "whpll_audio_ck", NULL, 0) > +}; > + > +static const struct mtk_fixed_factor topckgen_factors[] = { > + FACTOR(SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), > + FACTOR(SYSPLL_D3, "syspll_d3", "mainpll", 1, 3), > + FACTOR(SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), > + FACTOR(SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 2), > + FACTOR(SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 4), > + FACTOR(SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 8), > + FACTOR(SYSPLL1_D16, "syspll1_d16", "mainpll", 1, 16), > + FACTOR(SYSPLL2_D2, "syspll2_d2", "mainpll", 1, 2), > + FACTOR(SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 4), > + FACTOR(SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 2), > + FACTOR(SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 4), > + FACTOR(SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 2), > + FACTOR(SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 4), > + FACTOR(UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), > + FACTOR(UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), > + FACTOR(UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), > + FACTOR(UNIVPLL_D26, "univpll_d26", "univpll", 1, 26), > + FACTOR(UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 2), > + FACTOR(UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 4), > + FACTOR(UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 8), > + FACTOR(UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2), > + FACTOR(UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4), > + FACTOR(UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8), > + FACTOR(UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 2), > + FACTOR(UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 4), > + FACTOR(MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), > + FACTOR(MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), > + FACTOR(MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8), > + FACTOR(MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1, 16), > + FACTOR(VENCPLL_D3, "vencpll_d3", "vencpll", 1, 3), > + FACTOR(TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2), > + FACTOR(TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4), > + FACTOR(DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2), > + FACTOR(DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4), > + FACTOR(DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8), > + FACTOR(AD_SYS_26M_D2, "ad_sys_26m_d2", "clk26m", 1, 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 topckgen_muxes[] = { > + MUX_CLR_SET_UPD(AXI_SEL, "axi_sel", axi_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 0, 3, 0, 0), > + MUX_CLR_SET_UPD(MEM_SEL, "mem_sel", mem_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 8, 1, 0, 0), > + MUX_CLR_SET_UPD(DDRPHY_SEL, "ddrphycfg_sel", ddrphycfg_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 1, 0, 0), > + MUX_GATE_CLR_SET_UPD(MM_SEL, "mm_sel", mm_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 24, 3, 31, 0, 0), > + MUX_GATE_CLR_SET_UPD(PWM_SEL, "pwm_sel", pwm_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 0, 2, 7, 0, 0), > + MUX_GATE_CLR_SET_UPD(VDEC_SEL, "vdec_sel", vdec_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 8, 3, 15, 0, 0), > + MUX_GATE_CLR_SET_UPD(MFG_SEL, "mfg_sel", mfg_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 16, 4, 23, 0, 0), > + MUX_GATE_CLR_SET_UPD(CAMTG_SEL, "camtg_sel", camtg_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 24, 3, 31, 0, 0), > + MUX_GATE_CLR_SET_UPD(UART_SEL, "uart_sel", uart_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 0, 1, 7, 0, 0), > + MUX_GATE_CLR_SET_UPD(SPI_SEL, "spi_sel", spi_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 8, 3, 15, 0, 0), > + MUX_GATE_CLR_SET_UPD(USB20_SEL, "usb20_sel", usb20_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 16, 2, 23, 0, 0), > + MUX_GATE_CLR_SET_UPD(MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 3, 31, 0, 0), > + MUX_GATE_CLR_SET_UPD(MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 0, 4, 7, 0, 0), > + MUX_GATE_CLR_SET_UPD(MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_2_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 8, 3, 15, 0, 0), > + MUX_GATE_CLR_SET_UPD(MSDC30_2_SEL, "msdc30_2_sel", msdc30_1_2_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 16, 3, 23, 0, 0), > + MUX_GATE_CLR_SET_UPD(MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 24, 4, 31, 0, 0), > + MUX_GATE_CLR_SET_UPD(AUDIO_SEL, "audio_sel", audio_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 0, 2, 7, 0, 0), > + MUX_GATE_CLR_SET_UPD(AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 8, 2, 15, 0, 0), > + MUX_CLR_SET_UPD(PMICSPI_SEL, "pmicspi_sel", pmicspi_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 16, 3, 0, 0), > + MUX_GATE_CLR_SET_UPD(SCP_SEL, "scp_sel", scp_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 24, 2, 31, 0, 0), > + MUX_GATE_CLR_SET_UPD(ATB_SEL, "atb_sel", atb_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 0, 2, 7, 0, 0), > + MUX_GATE_CLR_SET_UPD(DPI0_SEL, "dpi0_sel", dpi0_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 8, 3, 15, 0, 0), > + MUX_GATE_CLR_SET_UPD(SCAM_SEL, "scam_sel", scam_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 16, 2, 23, 0, 0), > + MUX_GATE_CLR_SET_UPD(MFG13M_SEL, "mfg13m_sel", mfg13m_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 24, 1, 31, 0, 0), > + MUX_GATE_CLR_SET_UPD(AUD1_SEL, "aud_1_sel", aud_1_2_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 0, 1, 7, 0, 0), > + MUX_GATE_CLR_SET_UPD(AUD2_SEL, "aud_2_sel", aud_1_2_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 8, 1, 15, 0, 0), > + MUX_GATE_CLR_SET_UPD(IRDA_SEL, "irda_sel", irda_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 16, 1, 23, 0, 0), > + MUX_GATE_CLR_SET_UPD(IRTX_SEL, "irtx_sel", irtx_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 24, 1, 31, 0, 0), > + MUX_GATE_CLR_SET_UPD(DISPPWM_SEL, "disppwm_sel", disppwm_sel_parents, CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 0, 2, 7, 0, 0), > +}; > + > +int clk_mt6735_topckgen_probe(struct platform_device *pdev) > +{ > + void __iomem *base; > + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + struct clk_hw_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(topckgen_fixed_clks) + > + ARRAY_SIZE(topckgen_factors) + > + ARRAY_SIZE(topckgen_muxes)); > + if (!clk_data) > + return -ENOMEM; > + platform_set_drvdata(pdev, clk_data); > + > + ret = mtk_clk_register_fixed_clks(topckgen_fixed_clks, > + ARRAY_SIZE(topckgen_fixed_clks), > + clk_data); > + if (ret) { > + dev_err(&pdev->dev, "Failed to register fixed clocks: %d\n", > + ret); > + return ret; > + } > + > + ret = mtk_clk_register_factors(topckgen_factors, ARRAY_SIZE(topckgen_factors), > + clk_data); > + if (ret) { > + dev_err(&pdev->dev, "Failed to register dividers: %d\n", ret); > + return ret; > + } > + > + ret = mtk_clk_register_muxes(topckgen_muxes, ARRAY_SIZE(topckgen_muxes), > + pdev->dev.of_node, &mt6735_topckgen_lock, > + clk_data); > + if (ret) { > + dev_err(&pdev->dev, "Failed to register muxes: %d\n", ret); > + return ret; > + } > + > + ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, > + clk_data); > + if (ret) > + dev_err(&pdev->dev, > + "Failed to register clock provider: %d\n", ret); > + > + return ret; > +} > + > +int clk_mt6735_topckgen_remove(struct platform_device *pdev) > +{ > + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); > + > + mtk_clk_unregister_muxes(topckgen_muxes, ARRAY_SIZE(topckgen_muxes), > + clk_data); > + mtk_clk_unregister_factors(topckgen_factors, ARRAY_SIZE(topckgen_factors), > + clk_data); > + mtk_clk_unregister_fixed_clks(topckgen_fixed_clks, > + ARRAY_SIZE(topckgen_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 */ } > +}; Missing module device table. Maybe in other pieces as well. Best regards, Krzysztof