diff options
Diffstat (limited to 'drivers/clk')
32 files changed, 4609 insertions, 1102 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e69b0543817..47da49c8314 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -215,6 +215,13 @@ config CLK_HSDK Enable this to support the cgu clocks on Synopsys ARC HSDK and Synopsys ARC HSDK-4xD boards +config CLK_RS9_PCIE + tristate "Clock driver for Renesas 9-series PCIe clock generators" + depends on CLK + help + This driver supports the Renesas 9-series PCIe clock generator + models 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ. + config CLK_VERSACLOCK bool "Enable VersaClock 5/6 devices" depends on CLK @@ -277,11 +284,12 @@ source "drivers/clk/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" -source "drivers/clk/sophgo/Kconfig" -source "drivers/clk/sunxi/Kconfig" source "drivers/clk/sifive/Kconfig" +source "drivers/clk/sophgo/Kconfig" +source "drivers/clk/spacemit/Kconfig" source "drivers/clk/starfive/Kconfig" source "drivers/clk/stm32/Kconfig" +source "drivers/clk/sunxi/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" source "drivers/clk/thead/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c37ef75d420..4b241a9240a 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -45,9 +45,11 @@ obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_QCOM) += qcom/ obj-$(CONFIG_CLK_RENESAS) += renesas/ +obj-$(CONFIG_$(PHASE_)CLK_RS9_PCIE) += clk-renesas-pcie.o obj-$(CONFIG_$(PHASE_)CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-$(CONFIG_CLK_SOPHGO) += sophgo/ +obj-$(CONFIG_CLK_SPACEMIT) += spacemit/ obj-$(CONFIG_CLK_SUNXI) += sunxi/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c new file mode 100644 index 00000000000..ad57cd4fd28 --- /dev/null +++ b/drivers/clk/clk-renesas-pcie.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Renesas 9-series PCIe clock generator driver + * + * The following series can be supported: + * - 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ + * Currently supported: + * - 9FGV0241 + * - 9FGV0441 + * - 9FGV0841 + * + * Copyright (C) 2022-2026 Marek Vasut + */ + +#include <clk-uclass.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <errno.h> +#include <i2c.h> +#include <linux/bitops.h> + +#define RS9_REG_OE 0x0 +#define RS9_REG_SS 0x1 +#define RS9_REG_SS_AMP_0V6 0x0 +#define RS9_REG_SS_AMP_0V7 0x1 +#define RS9_REG_SS_AMP_0V8 0x2 +#define RS9_REG_SS_AMP_0V9 0x3 +#define RS9_REG_SS_AMP_DEFAULT RS9_REG_SS_AMP_0V8 +#define RS9_REG_SS_AMP_MASK 0x3 +#define RS9_REG_SS_SSC_100 0 +#define RS9_REG_SS_SSC_M025 (1 << 3) +#define RS9_REG_SS_SSC_M050 (3 << 3) +#define RS9_REG_SS_SSC_DEFAULT RS9_REG_SS_SSC_100 +#define RS9_REG_SS_SSC_MASK (3 << 3) +#define RS9_REG_SS_SSC_LOCK BIT(5) +#define RS9_REG_SR 0x2 +#define RS9_REG_REF 0x3 +#define RS9_REG_REF_OE BIT(4) +#define RS9_REG_REF_OD BIT(5) +#define RS9_REG_REF_SR_SLOWEST 0 +#define RS9_REG_REF_SR_SLOW (1 << 6) +#define RS9_REG_REF_SR_FAST (2 << 6) +#define RS9_REG_REF_SR_FASTER (3 << 6) +#define RS9_REG_VID 0x5 +#define RS9_REG_DID 0x6 +#define RS9_REG_BCP 0x7 + +#define RS9_REG_VID_MASK GENMASK(3, 0) +#define RS9_REG_VID_IDT 0x01 + +#define RS9_REG_DID_TYPE_FGV (0x0 << RS9_REG_DID_TYPE_SHIFT) +#define RS9_REG_DID_TYPE_DBV (0x1 << RS9_REG_DID_TYPE_SHIFT) +#define RS9_REG_DID_TYPE_DMV (0x2 << RS9_REG_DID_TYPE_SHIFT) +#define RS9_REG_DID_TYPE_SHIFT 0x6 + +/* Structure to describe features of a particular 9-series model */ +struct rs9_chip_info { + unsigned int num_clks; + u8 outshift; + u8 did; +}; + +struct rs9_driver_data { + struct udevice *i2c; + struct rs9_chip_info *chip_info; + unsigned long rate; + u8 pll_amplitude; + u8 pll_ssc; + u8 clk_dif_sr; +}; + +static int clk_rs9_request(struct clk *clk) +{ + struct rs9_driver_data *rs9 = dev_get_priv(clk->dev); + + if (clk->id > rs9->chip_info->num_clks) + return -EINVAL; + + return 0; +} + +static ulong clk_rs9_get_rate(struct clk *clk) +{ + struct rs9_driver_data *rs9 = dev_get_priv(clk->dev); + + return rs9->rate * 4; +} + +static const struct clk_ops clk_rs9_ops = { + .request = clk_rs9_request, + .get_rate = clk_rs9_get_rate, +}; + +static int rs9_write(struct udevice *dev, u8 reg, u8 val) +{ + u8 data[2] = { 1, val }; + + return dm_i2c_write(dev, reg, data, 2); +} + +static int rs9_read(struct udevice *dev, u8 reg, u8 *val) +{ + struct dm_i2c_chip *chip = dev_get_parent_plat(dev); + struct i2c_msg xfer[2]; + u8 txdata = reg; + u8 rxdata[2]; + int ret; + + xfer[0].addr = chip->chip_addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = (void *)&txdata; + + xfer[1].addr = chip->chip_addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 2; + xfer[1].buf = (void *)rxdata; + + ret = dm_i2c_xfer(dev, xfer, 2); + if (ret < 0) + return ret; + + /* + * Byte 0 is transfer length, which is always 1 due + * to BCP register programming to 1 in rs9_probe(), + * ignore it and use data from Byte 1. + */ + *val = rxdata[1]; + return 0; +} + +static u8 rs9_calc_dif(const struct rs9_driver_data *rs9, int idx) +{ + /* + * On 9FGV0241, the DIF OE0 is BIT(1) and DIF OE(1) is BIT(2), + * on 9FGV0441 and 9FGV0841 the DIF OE0 is BIT(0) and so on. + * Increment the index in the 9FGV0241 special case here. + */ + return BIT(idx + rs9->chip_info->outshift); +} + +static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx) +{ + struct udevice *dev = rs9->i2c; + u8 dif = rs9_calc_dif(rs9, idx); + unsigned char name[5] = "DIF0"; + ofnode np; + u32 sr; + + /* Set defaults */ + rs9->clk_dif_sr |= dif; + + snprintf(name, 5, "DIF%d", idx); + np = dev_read_subnode(dev, name); + if (!ofnode_valid(np)) + return 0; + + /* Output clock slew rate */ + sr = ofnode_read_u32_default(np, "renesas,slew-rate", 3000000); + if (sr == 2000000) { /* 2V/ns */ + rs9->clk_dif_sr &= ~dif; + } else if (sr == 3000000) { /* 3V/ns (default) */ + rs9->clk_dif_sr |= dif; + } else { + dev_err(dev, "Invalid renesas,slew-rate value\n"); + return -EINVAL; + } + + return 0; +} + +static int rs9_get_common_config(struct rs9_driver_data *rs9) +{ + struct udevice *dev = rs9->i2c; + unsigned int amp, ssc; + + /* Set defaults */ + rs9->pll_amplitude = RS9_REG_SS_AMP_DEFAULT; + rs9->pll_ssc = RS9_REG_SS_SSC_DEFAULT; + + /* Output clock amplitude */ + amp = dev_read_u32_default(dev, "renesas,out-amplitude-microvolt", 700000); + if (amp == 600000) { /* 0.6V */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V6; + } else if (amp == 700000) { /* 0.7V (default) */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V7; + } else if (amp == 800000) { /* 0.8V */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V8; + } else if (amp == 900000) { /* 0.9V */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V9; + } else { + dev_err(dev, "Invalid renesas,out-amplitude-microvolt value\n"); + return -EINVAL; + } + + /* Output clock spread spectrum */ + ssc = dev_read_u32_default(dev, "renesas,out-spread-spectrum", 100000); + if (ssc == 100000) { /* 100% ... no spread (default) */ + rs9->pll_ssc = RS9_REG_SS_SSC_100; + } else if (ssc == 99750) { /* -0.25% ... down spread */ + rs9->pll_ssc = RS9_REG_SS_SSC_M025; + } else if (ssc == 99500) { /* -0.50% ... down spread */ + rs9->pll_ssc = RS9_REG_SS_SSC_M050; + } else { + dev_err(dev, "Invalid renesas,out-spread-spectrum value\n"); + return -EINVAL; + } + + return 0; +} + +static void rs9_update_config(struct rs9_driver_data *rs9) +{ + struct udevice *dev = rs9->i2c; + int i; + + /* If amplitude is non-default, update it. */ + if (rs9->pll_amplitude != RS9_REG_SS_AMP_DEFAULT) { + dm_i2c_reg_clrset(dev, RS9_REG_SS, RS9_REG_SS_AMP_MASK, + rs9->pll_amplitude); + } + + /* If SSC is non-default, update it. */ + if (rs9->pll_ssc != RS9_REG_SS_SSC_DEFAULT) { + dm_i2c_reg_clrset(dev, RS9_REG_SS, RS9_REG_SS_SSC_MASK, + rs9->pll_ssc); + } + + for (i = 0; i < rs9->chip_info->num_clks; i++) { + u8 dif = rs9_calc_dif(rs9, i); + + if (rs9->clk_dif_sr & dif) + continue; + + dm_i2c_reg_clrset(dev, RS9_REG_SR, dif, + rs9->clk_dif_sr & dif); + } +} + +static int clk_rs9_probe(struct udevice *dev) +{ + struct rs9_driver_data *rs9 = dev_get_priv(dev); + struct clk *clk; + u8 vid, did; + int i, ret; + + rs9->i2c = dev; + rs9->chip_info = (struct rs9_chip_info *)dev_get_driver_data(dev); + if (!rs9->chip_info) + return -EINVAL; + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + rs9->rate = clk_get_rate(clk); + + /* Fetch common configuration from DT (if specified) */ + ret = rs9_get_common_config(rs9); + if (ret) + return ret; + + /* Fetch DIFx output configuration from DT (if specified) */ + for (i = 0; i < rs9->chip_info->num_clks; i++) { + ret = rs9_get_output_config(rs9, i); + if (ret) + return ret; + } + + /* Always read back 1 Byte via I2C */ + ret = rs9_write(dev, RS9_REG_BCP, 1); + if (ret < 0) + return ret; + + ret = rs9_read(dev, RS9_REG_VID, &vid); + if (ret < 0) + return ret; + + ret = rs9_read(dev, RS9_REG_DID, &did); + if (ret < 0) + return ret; + + vid &= RS9_REG_VID_MASK; + if (vid != RS9_REG_VID_IDT || did != rs9->chip_info->did) { + dev_err(dev, "Incorrect VID/DID: %#02x, %#02x. Expected %#02x, %#02x\n", + vid, did, RS9_REG_VID_IDT, rs9->chip_info->did); + return -ENODEV; + } + + rs9_update_config(rs9); + + return 0; +} + +static const struct rs9_chip_info renesas_9fgv0241_info = { + .num_clks = 2, + .outshift = 1, + .did = RS9_REG_DID_TYPE_FGV | 0x02, +}; + +static const struct rs9_chip_info renesas_9fgv0441_info = { + .num_clks = 4, + .outshift = 0, + .did = RS9_REG_DID_TYPE_FGV | 0x04, +}; + +static const struct rs9_chip_info renesas_9fgv0841_info = { + .num_clks = 8, + .outshift = 0, + .did = RS9_REG_DID_TYPE_FGV | 0x08, +}; + +static const struct udevice_id clk_rs9_of_match[] = { + { .compatible = "renesas,9fgv0241", .data = (ulong)&renesas_9fgv0241_info }, + { .compatible = "renesas,9fgv0441", .data = (ulong)&renesas_9fgv0441_info }, + { .compatible = "renesas,9fgv0841", .data = (ulong)&renesas_9fgv0841_info }, + { /* sentinel */ }, +}; + +U_BOOT_DRIVER(clk_rs9) = { + .name = "clk-renesas-pcie-9series", + .id = UCLASS_CLK, + .of_match = clk_rs9_of_match, + .ops = &clk_rs9_ops, + .probe = clk_rs9_probe, + .priv_auto = sizeof(struct rs9_driver_data), +}; diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c index 79315912fd4..d66200f1938 100644 --- a/drivers/clk/mediatek/clk-mt7622.c +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -85,7 +85,7 @@ static const struct mtk_gate_regs apmixed_cg_regs = { .parent = _parent, \ .regs = &apmixed_cg_regs, \ .shift = _shift, \ - .flags = CLK_GATE_NO_SETCLR_INV, \ + .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_APMIXED, \ } static const struct mtk_gate apmixed_cgs[] = { @@ -613,6 +613,21 @@ static const struct mtk_clk_tree mt7622_apmixed_clk_tree = { .gates = apmixed_cgs, .num_plls = ARRAY_SIZE(apmixed_plls), .num_gates = ARRAY_SIZE(apmixed_cgs), + .type = MTK_CLK_TREE_APMIXED, +}; + +static const struct mtk_clk_tree mt7622_topckgen_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .fdivs_offs = CLK_TOP_TO_USB3_SYS, + .muxes_offs = CLK_TOP_AXI_SEL, + .fclks = top_fixed_clks, + .fdivs = top_fixed_divs, + .muxes = top_muxes, + .num_fclks = ARRAY_SIZE(top_fixed_clks), + .num_fdivs = ARRAY_SIZE(top_fixed_divs), + .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_clk_tree mt7622_infra_clk_tree = { @@ -637,17 +652,32 @@ static const struct mtk_clk_tree mt7622_peri_clk_tree = { .num_gates = ARRAY_SIZE(peri_cgs), }; -static const struct mtk_clk_tree mt7622_clk_tree = { +static const struct mtk_clk_tree mt7622_pcie_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), - .fdivs_offs = CLK_TOP_TO_USB3_SYS, - .muxes_offs = CLK_TOP_AXI_SEL, - .fclks = top_fixed_clks, - .fdivs = top_fixed_divs, - .muxes = top_muxes, - .num_fclks = ARRAY_SIZE(top_fixed_clks), - .num_fdivs = ARRAY_SIZE(top_fixed_divs), - .num_muxes = ARRAY_SIZE(top_muxes), + .gates = pcie_cgs, + .num_gates = ARRAY_SIZE(pcie_cgs), +}; + +static const struct mtk_clk_tree mt7622_eth_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = eth_cgs, + .num_gates = ARRAY_SIZE(eth_cgs), +}; + +static const struct mtk_clk_tree mt7622_sgmii_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = sgmii_cgs, + .num_gates = ARRAY_SIZE(sgmii_cgs), +}; + +static const struct mtk_clk_tree mt7622_ssusb_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = ssusb_cgs, + .num_gates = ARRAY_SIZE(ssusb_cgs), }; static int mt7622_mcucfg_probe(struct udevice *dev) @@ -671,7 +701,7 @@ static int mt7622_apmixedsys_probe(struct udevice *dev) struct mtk_clk_priv *priv = dev_get_priv(dev); int ret; - ret = mtk_common_clk_init(dev, &mt7622_apmixed_clk_tree); + ret = mtk_clk_probe(dev); if (ret) return ret; @@ -685,103 +715,68 @@ static int mt7622_apmixedsys_probe(struct udevice *dev) return 0; } -static int mt7622_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt7622_clk_tree); -} - -static int mt7622_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_infrasys_init(dev, &mt7622_infra_clk_tree); -} - -static int mt7622_pericfg_probe(struct udevice *dev) -{ - return mtk_common_clk_infrasys_init(dev, &mt7622_peri_clk_tree); -} - -static int mt7622_pciesys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, pcie_cgs, - ARRAY_SIZE(pcie_cgs), 0); -} - -static int mt7622_pciesys_bind(struct udevice *dev) +static int mt7622_reset_bind(struct udevice *dev) { int ret = 0; - if (IS_ENABLED(CONFIG_RESET_MEDIATEK)) { - ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1); - if (ret) - debug("Warning: failed to bind reset controller\n"); + if (CONFIG_IS_ENABLED(RESET_MEDIATEK)) { + ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1); + if (ret) + debug("Warning: failed to bind reset controller\n"); } return ret; } -static int mt7622_ethsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, eth_cgs, - ARRAY_SIZE(eth_cgs), 0); -} - -static int mt7622_ethsys_bind(struct udevice *dev) -{ - int ret = 0; - -#if CONFIG_IS_ENABLED(RESET_MEDIATEK) - ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1); - if (ret) - debug("Warning: failed to bind reset controller\n"); -#endif - - return ret; -} - -static int mt7622_sgmiisys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, sgmii_cgs, - ARRAY_SIZE(sgmii_cgs), 0); -} - -static int mt7622_ssusbsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7622_clk_tree, ssusb_cgs, - ARRAY_SIZE(ssusb_cgs), 0); -} - static const struct udevice_id mt7622_apmixed_compat[] = { - { .compatible = "mediatek,mt7622-apmixedsys" }, + { + .compatible = "mediatek,mt7622-apmixedsys", + .data = (ulong)&mt7622_apmixed_clk_tree, + }, { } }; static const struct udevice_id mt7622_topckgen_compat[] = { - { .compatible = "mediatek,mt7622-topckgen" }, - { } -}; - -static const struct udevice_id mt7622_infracfg_compat[] = { - { .compatible = "mediatek,mt7622-infracfg", }, - { } -}; - -static const struct udevice_id mt7622_pericfg_compat[] = { - { .compatible = "mediatek,mt7622-pericfg", }, + { + .compatible = "mediatek,mt7622-topckgen", + .data = (ulong)&mt7622_topckgen_clk_tree, + }, { } }; -static const struct udevice_id mt7622_pciesys_compat[] = { - { .compatible = "mediatek,mt7622-pciesys", }, +static const struct udevice_id of_match_mt7622_infracfg[] = { + { + .compatible = "mediatek,mt7622-infracfg", + .data = (ulong)&mt7622_infra_clk_tree, + }, + { + .compatible = "mediatek,mt7622-pericfg", + .data = (ulong)&mt7622_peri_clk_tree, + }, { } }; -static const struct udevice_id mt7622_ethsys_compat[] = { - { .compatible = "mediatek,mt7622-ethsys", }, +static const struct udevice_id of_match_mt7622_clk_eth[] = { + { + .compatible = "mediatek,mt7622-pciesys", + .data = (ulong)&mt7622_pcie_clk_tree, + }, + { + .compatible = "mediatek,mt7622-ethsys", + .data = (ulong)&mt7622_eth_clk_tree, + }, { } }; -static const struct udevice_id mt7622_sgmiisys_compat[] = { - { .compatible = "mediatek,mt7622-sgmiisys", }, +static const struct udevice_id of_match_mt7622_clk[] = { + { + .compatible = "mediatek,mt7622-sgmiisys", + .data = (ulong)&mt7622_sgmii_clk_tree, + }, + { + .compatible = "mediatek,mt7622-ssusbsys", + .data = (ulong)&mt7622_ssusb_clk_tree, + }, { } }; @@ -790,12 +785,7 @@ static const struct udevice_id mt7622_mcucfg_compat[] = { { } }; -static const struct udevice_id mt7622_ssusbsys_compat[] = { - { .compatible = "mediatek,mt7622-ssusbsys" }, - { } -}; - -U_BOOT_DRIVER(mtk_mcucfg) = { +U_BOOT_DRIVER(mt7622_mcucfg) = { .name = "mt7622-mcucfg", .id = UCLASS_SYSCON, .of_match = mt7622_mcucfg_compat, @@ -803,7 +793,7 @@ U_BOOT_DRIVER(mtk_mcucfg) = { .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt7622_clk_apmixedsys) = { .name = "mt7622-clock-apmixedsys", .id = UCLASS_CLK, .of_match = mt7622_apmixed_compat, @@ -813,70 +803,41 @@ U_BOOT_DRIVER(mtk_clk_apmixedsys) = { .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt7622_clk_topckgen) = { .name = "mt7622-clock-topckgen", .id = UCLASS_CLK, .of_match = mt7622_topckgen_compat, - .probe = mt7622_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt7622_clk_infracfg) = { .name = "mt7622-clock-infracfg", .id = UCLASS_CLK, - .of_match = mt7622_infracfg_compat, - .probe = mt7622_infracfg_probe, + .of_match = of_match_mt7622_infracfg, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_infrasys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_pericfg) = { - .name = "mt7622-clock-pericfg", +U_BOOT_DRIVER(mt7622_clk_eth) = { + .name = "mt7622-clk-eth", .id = UCLASS_CLK, - .of_match = mt7622_pericfg_compat, - .probe = mt7622_pericfg_probe, + .of_match = of_match_mt7622_clk_eth, + .probe = mtk_clk_probe, + .bind = mt7622_reset_bind, .priv_auto = sizeof(struct mtk_clk_priv), - .ops = &mtk_clk_infrasys_ops, - .flags = DM_FLAG_PRE_RELOC, -}; - -U_BOOT_DRIVER(mtk_clk_pciesys) = { - .name = "mt7622-clock-pciesys", - .id = UCLASS_CLK, - .of_match = mt7622_pciesys_compat, - .probe = mt7622_pciesys_probe, - .bind = mt7622_pciesys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, -}; - -U_BOOT_DRIVER(mtk_clk_ethsys) = { - .name = "mt7622-clock-ethsys", - .id = UCLASS_CLK, - .of_match = mt7622_ethsys_compat, - .probe = mt7622_ethsys_probe, - .bind = mt7622_ethsys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, -}; - -U_BOOT_DRIVER(mtk_clk_sgmiisys) = { - .name = "mt7622-clock-sgmiisys", - .id = UCLASS_CLK, - .of_match = mt7622_sgmiisys_compat, - .probe = mt7622_sgmiisys_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .ops = &mtk_clk_topckgen_ops, }; -U_BOOT_DRIVER(mtk_clk_ssusbsys) = { - .name = "mt7622-clock-ssusbsys", +U_BOOT_DRIVER(mt7622_clk) = { + .name = "mt7622-clk", .id = UCLASS_CLK, - .of_match = mt7622_ssusbsys_compat, - .probe = mt7622_ssusbsys_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .of_match = of_match_mt7622_clk, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c index 0a302b405e2..cc075495b09 100644 --- a/drivers/clk/mediatek/clk-mt7623.c +++ b/drivers/clk/mediatek/clk-mt7623.c @@ -1009,6 +1009,7 @@ static const struct mtk_clk_tree mt7623_apmixedsys_clk_tree = { .id_offs_map_size = ARRAY_SIZE(pll_id_offs_map), .plls = apmixed_plls, .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, }; static const struct mtk_clk_tree mt7623_topckgen_clk_tree = { @@ -1024,6 +1025,7 @@ static const struct mtk_clk_tree mt7623_topckgen_clk_tree = { .num_fclks = ARRAY_SIZE(top_fixed_clks), .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_TOPCKGEN, }; static int mt7623_mcucfg_probe(struct udevice *dev) @@ -1045,7 +1047,7 @@ static int mt7623_apmixedsys_probe(struct udevice *dev) struct mtk_clk_priv *priv = dev_get_priv(dev); int ret; - ret = mtk_common_clk_init(dev, &mt7623_apmixedsys_clk_tree); + ret = mtk_clk_probe(dev); if (ret) return ret; @@ -1057,21 +1059,29 @@ static int mt7623_apmixedsys_probe(struct udevice *dev) return 0; } -static int mt7623_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt7623_topckgen_clk_tree); -} +static const struct mtk_clk_tree mt7623_infracfg_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates_offs = 1, + .gates = infra_cgs, + .num_gates = ARRAY_SIZE(infra_cgs), +}; -static const struct mtk_clk_tree mt7623_clk_gate_tree = { +static const struct mtk_clk_tree mt7623_hifsys_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates_offs = 1, + .gates = hif_cgs, + .num_gates = ARRAY_SIZE(hif_cgs), }; -static int mt7623_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, infra_cgs, - ARRAY_SIZE(infra_cgs), 1); -} +static const struct mtk_clk_tree mt7623_ethsys_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates_offs = 1, + .gates = eth_cgs, + .num_gates = ARRAY_SIZE(eth_cgs), +}; static const struct mtk_clk_tree mt7623_clk_peri_tree = { .ext_clk_rates = ext_clock_rates, @@ -1086,23 +1096,6 @@ static const struct mtk_clk_tree mt7623_clk_peri_tree = { .num_gates = ARRAY_SIZE(peri_cgs), }; -static int mt7623_pericfg_probe(struct udevice *dev) -{ - return mtk_common_clk_infrasys_init(dev, &mt7623_clk_peri_tree); -} - -static int mt7623_hifsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, hif_cgs, - ARRAY_SIZE(hif_cgs), 1); -} - -static int mt7623_ethsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7623_clk_gate_tree, eth_cgs, - ARRAY_SIZE(eth_cgs), 1); -} - static int mt7623_ethsys_hifsys_bind(struct udevice *dev) { int ret = 0; @@ -1117,32 +1110,46 @@ static int mt7623_ethsys_hifsys_bind(struct udevice *dev) } static const struct udevice_id mt7623_apmixed_compat[] = { - { .compatible = "mediatek,mt7623-apmixedsys" }, + { + .compatible = "mediatek,mt7623-apmixedsys", + .data = (ulong)&mt7623_apmixedsys_clk_tree, + }, { } }; static const struct udevice_id mt7623_topckgen_compat[] = { - { .compatible = "mediatek,mt7623-topckgen" }, + { + .compatible = "mediatek,mt7623-topckgen", + .data = (ulong)&mt7623_topckgen_clk_tree, + }, { } }; static const struct udevice_id mt7623_infracfg_compat[] = { - { .compatible = "mediatek,mt7623-infracfg", }, + { + .compatible = "mediatek,mt7623-infracfg", + .data = (ulong)&mt7623_infracfg_tree, + }, { } }; static const struct udevice_id mt7623_pericfg_compat[] = { - { .compatible = "mediatek,mt7623-pericfg", }, + { + .compatible = "mediatek,mt7623-pericfg", + .data = (ulong)&mt7623_clk_peri_tree, + }, { } }; -static const struct udevice_id mt7623_ethsys_compat[] = { - { .compatible = "mediatek,mt7623-ethsys" }, - { } -}; - -static const struct udevice_id mt7623_hifsys_compat[] = { - { .compatible = "mediatek,mt7623-hifsys" }, +static const struct udevice_id of_match_mt7623_clk_eth[] = { + { + .compatible = "mediatek,mt7623-ethsys", + .data = (ulong)&mt7623_ethsys_tree, + }, + { + .compatible = "mediatek,mt7623-hifsys", + .data = (ulong)&mt7623_hifsys_tree, + }, { } }; @@ -1151,7 +1158,7 @@ static const struct udevice_id mt7623_mcucfg_compat[] = { { } }; -U_BOOT_DRIVER(mtk_mcucfg) = { +U_BOOT_DRIVER(mt7623_mcucfg) = { .name = "mt7623-mcucfg", .id = UCLASS_SYSCON, .of_match = mt7623_mcucfg_compat, @@ -1159,7 +1166,7 @@ U_BOOT_DRIVER(mtk_mcucfg) = { .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt7623_clk_apmixedsys) = { .name = "mt7623-clock-apmixedsys", .id = UCLASS_CLK, .of_match = mt7623_apmixed_compat, @@ -1169,52 +1176,42 @@ U_BOOT_DRIVER(mtk_clk_apmixedsys) = { .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt7623_clk_topckgen) = { .name = "mt7623-clock-topckgen", .id = UCLASS_CLK, .of_match = mt7623_topckgen_compat, - .probe = mt7623_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt7623_clk_infracfg) = { .name = "mt7623-infracfg", .id = UCLASS_CLK, .of_match = mt7623_infracfg_compat, - .probe = mt7623_infracfg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_pericfg) = { +U_BOOT_DRIVER(mt7623_clk_pericfg) = { .name = "mt7623-pericfg", .id = UCLASS_CLK, .of_match = mt7623_pericfg_compat, - .probe = mt7623_pericfg_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_infrasys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_hifsys) = { - .name = "mt7623-clock-hifsys", +U_BOOT_DRIVER(mt7623_clk_eth) = { + .name = "mt7623-clk-eth", .id = UCLASS_CLK, - .of_match = mt7623_hifsys_compat, - .probe = mt7623_hifsys_probe, + .of_match = of_match_mt7623_clk_eth, + .probe = mtk_clk_probe, .bind = mt7623_ethsys_hifsys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, -}; - -U_BOOT_DRIVER(mtk_clk_ethsys) = { - .name = "mt7623-clock-ethsys", - .id = UCLASS_CLK, - .of_match = mt7623_ethsys_compat, - .probe = mt7623_ethsys_probe, - .bind = mt7623_ethsys_hifsys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index 74510ee36a9..b271b96ebf3 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -575,36 +575,64 @@ static const struct mtk_gate ssusb_cgs[] = { GATE_SSUSB(CLK_SSUSB_DMA_EN, CLK_TOP_TO_USB3_DMA, 8), }; -static const struct mtk_clk_tree mt7629_clk_tree = { +static const struct mtk_clk_tree mt7629_apmixed_clk_tree = { .pll_parent = EXT_PARENT(CLK_PAD_CLK20M), .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), - .fdivs_offs = CLK_TOP_TO_USB3_SYS, - .muxes_offs = CLK_TOP_AXI_SEL, .plls = apmixed_plls, - .fclks = top_fixed_clks, - .fdivs = top_fixed_divs, - .muxes = top_muxes, .num_plls = ARRAY_SIZE(apmixed_plls), - .num_fclks = ARRAY_SIZE(top_fixed_clks), - .num_fdivs = ARRAY_SIZE(top_fixed_divs), - .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_APMIXED, }; -static const struct mtk_clk_tree mt7629_peri_clk_tree = { - .pll_parent = EXT_PARENT(CLK_PAD_CLK20M), +static const struct mtk_clk_tree mt7629_topckgen_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .fdivs_offs = CLK_TOP_TO_USB3_SYS, .muxes_offs = CLK_TOP_AXI_SEL, - .plls = apmixed_plls, .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, - .num_plls = ARRAY_SIZE(apmixed_plls), .num_fclks = ARRAY_SIZE(top_fixed_clks), .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_TOPCKGEN, +}; + +static const struct mtk_clk_tree mt7629_infracfg_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates_offs = CLK_INFRA_DBGCLK_PD, + .gates = infra_cgs, + .num_gates = ARRAY_SIZE(infra_cgs), +}; + +static const struct mtk_clk_tree mt7629_pericfg_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates_offs = CLK_PERI_PWM1_PD, + .gates = peri_cgs, + .num_gates = ARRAY_SIZE(peri_cgs), +}; + +static const struct mtk_clk_tree mt7629_ethsys_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = eth_cgs, + .num_gates = ARRAY_SIZE(eth_cgs), +}; + +static const struct mtk_clk_tree mt7629_sgmii_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = sgmii_cgs, + .num_gates = ARRAY_SIZE(sgmii_cgs), +}; + +static const struct mtk_clk_tree mt7629_ssusb_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = ssusb_cgs, + .num_gates = ARRAY_SIZE(ssusb_cgs), }; static int mt7629_mcucfg_probe(struct udevice *dev) @@ -628,7 +656,7 @@ static int mt7629_apmixedsys_probe(struct udevice *dev) struct mtk_clk_priv *priv = dev_get_priv(dev); int ret; - ret = mtk_common_clk_init(dev, &mt7629_clk_tree); + ret = mtk_clk_probe(dev); if (ret) return ret; @@ -640,29 +668,6 @@ static int mt7629_apmixedsys_probe(struct udevice *dev) return 0; } -static int mt7629_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt7629_clk_tree); -} - -static int mt7629_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, infra_cgs, - ARRAY_SIZE(infra_cgs), 0); -} - -static int mt7629_pericfg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7629_peri_clk_tree, peri_cgs, - ARRAY_SIZE(peri_cgs), CLK_PERI_PWM1_PD); -} - -static int mt7629_ethsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs, - ARRAY_SIZE(eth_cgs), 0); -} - static int mt7629_ethsys_bind(struct udevice *dev) { int ret = 0; @@ -676,50 +681,51 @@ static int mt7629_ethsys_bind(struct udevice *dev) return ret; } -static int mt7629_sgmiisys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs, - ARRAY_SIZE(sgmii_cgs), 0); -} - -static int mt7629_ssusbsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, ssusb_cgs, - ARRAY_SIZE(ssusb_cgs), 0); -} - static const struct udevice_id mt7629_apmixed_compat[] = { - { .compatible = "mediatek,mt7629-apmixedsys" }, + { + .compatible = "mediatek,mt7629-apmixedsys", + .data = (ulong)&mt7629_apmixed_clk_tree, + }, { } }; static const struct udevice_id mt7629_topckgen_compat[] = { - { .compatible = "mediatek,mt7629-topckgen" }, + { + .compatible = "mediatek,mt7629-topckgen", + .data = (ulong)&mt7629_topckgen_clk_tree, + }, { } }; -static const struct udevice_id mt7629_infracfg_compat[] = { - { .compatible = "mediatek,mt7629-infracfg", }, - { } -}; - -static const struct udevice_id mt7629_pericfg_compat[] = { - { .compatible = "mediatek,mt7629-pericfg", }, +static const struct udevice_id of_match_mt7629_infracfg[] = { + { + .compatible = "mediatek,mt7629-infracfg", + .data = (ulong)&mt7629_infracfg_tree, + }, + { + .compatible = "mediatek,mt7629-pericfg", + .data = (ulong)&mt7629_pericfg_tree, + }, { } }; static const struct udevice_id mt7629_ethsys_compat[] = { - { .compatible = "mediatek,mt7629-ethsys", }, - { } -}; - -static const struct udevice_id mt7629_sgmiisys_compat[] = { - { .compatible = "mediatek,mt7629-sgmiisys", }, + { + .compatible = "mediatek,mt7629-ethsys", + .data = (ulong)&mt7629_ethsys_tree, + }, { } }; -static const struct udevice_id mt7629_ssusbsys_compat[] = { - { .compatible = "mediatek,mt7629-ssusbsys" }, +static const struct udevice_id of_match_mt7629_clk[] = { + { + .compatible = "mediatek,mt7629-sgmiisys", + .data = (ulong)&mt7629_sgmii_clk_tree, + }, + { + .compatible = "mediatek,mt7629-ssusbsys", + .data = (ulong)&mt7629_ssusb_clk_tree, + }, { } }; @@ -728,7 +734,7 @@ static const struct udevice_id mt7629_mcucfg_compat[] = { { } }; -U_BOOT_DRIVER(mtk_mcucfg) = { +U_BOOT_DRIVER(mt7629_mcucfg) = { .name = "mt7629-mcucfg", .id = UCLASS_SYSCON, .of_match = mt7629_mcucfg_compat, @@ -736,7 +742,7 @@ U_BOOT_DRIVER(mtk_mcucfg) = { .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt7629_clk_apmixedsys) = { .name = "mt7629-clock-apmixedsys", .id = UCLASS_CLK, .of_match = mt7629_apmixed_compat, @@ -746,60 +752,41 @@ U_BOOT_DRIVER(mtk_clk_apmixedsys) = { .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt7629_clk_topckgen) = { .name = "mt7629-clock-topckgen", .id = UCLASS_CLK, .of_match = mt7629_topckgen_compat, - .probe = mt7629_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt7629_clk_infracfg) = { .name = "mt7629-clock-infracfg", .id = UCLASS_CLK, - .of_match = mt7629_infracfg_compat, - .probe = mt7629_infracfg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, - .flags = DM_FLAG_PRE_RELOC, -}; - -U_BOOT_DRIVER(mtk_clk_pericfg) = { - .name = "mt7629-clock-pericfg", - .id = UCLASS_CLK, - .of_match = mt7629_pericfg_compat, - .probe = mt7629_pericfg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .of_match = of_match_mt7629_infracfg, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_ethsys) = { +U_BOOT_DRIVER(mt7629_clk_ethsys) = { .name = "mt7629-clock-ethsys", .id = UCLASS_CLK, .of_match = mt7629_ethsys_compat, - .probe = mt7629_ethsys_probe, + .probe = mtk_clk_probe, .bind = mt7629_ethsys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, -}; - -U_BOOT_DRIVER(mtk_clk_sgmiisys) = { - .name = "mt7629-clock-sgmiisys", - .id = UCLASS_CLK, - .of_match = mt7629_sgmiisys_compat, - .probe = mt7629_sgmiisys_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; -U_BOOT_DRIVER(mtk_clk_ssusbsys) = { - .name = "mt7629-clock-ssusbsys", +U_BOOT_DRIVER(mt7629_clk) = { + .name = "mt7629-clk", .id = UCLASS_CLK, - .of_match = mt7629_ssusbsys_compat, - .probe = mt7629_ssusbsys_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .of_match = of_match_mt7629_clk, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; diff --git a/drivers/clk/mediatek/clk-mt7981.c b/drivers/clk/mediatek/clk-mt7981.c index 8c2944b7fb3..7e3e60477d9 100644 --- a/drivers/clk/mediatek/clk-mt7981.c +++ b/drivers/clk/mediatek/clk-mt7981.c @@ -622,6 +622,7 @@ static const struct mtk_clk_tree mt7981_fixed_pll_clk_tree = { .fdivs_offs = CLK_APMIXED_NR_CLK, .fclks = fixed_pll_clks, .num_fclks = ARRAY_SIZE(fixed_pll_clks), + .type = MTK_CLK_TREE_APMIXED, }; static const struct mtk_clk_tree mt7981_topckgen_clk_tree = { @@ -636,6 +637,7 @@ static const struct mtk_clk_tree mt7981_topckgen_clk_tree = { .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), .flags = CLK_PARENT_TOPCKGEN, + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_clk_tree mt7981_infracfg_clk_tree = { @@ -651,24 +653,29 @@ static const struct mtk_clk_tree mt7981_infracfg_clk_tree = { .num_muxes = ARRAY_SIZE(infra_muxes), .num_gates = ARRAY_SIZE(infracfg_gates), .flags = CLK_PARENT_INFRASYS, + .type = MTK_CLK_TREE_INFRASYS, }; static const struct udevice_id mt7981_fixed_pll_compat[] = { - { .compatible = "mediatek,mt7981-fixed-plls" }, - { .compatible = "mediatek,mt7981-apmixedsys" }, + { + .compatible = "mediatek,mt7981-fixed-plls", + .data = (ulong)&mt7981_fixed_pll_clk_tree, + }, + { + .compatible = "mediatek,mt7981-apmixedsys", + .data = (ulong)&mt7981_fixed_pll_clk_tree, + }, {} }; static const struct udevice_id mt7981_topckgen_compat[] = { - { .compatible = "mediatek,mt7981-topckgen" }, + { + .compatible = "mediatek,mt7981-topckgen", + .data = (ulong)&mt7981_topckgen_clk_tree, + }, {} }; -static int mt7981_fixed_pll_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt7981_fixed_pll_clk_tree); -} - static int mt7981_topckgen_probe(struct udevice *dev) { struct mtk_clk_priv *priv = dev_get_priv(dev); @@ -676,20 +683,20 @@ static int mt7981_topckgen_probe(struct udevice *dev) priv->base = dev_read_addr_ptr(dev); writel(MT7981_CLK_PDN_EN_WRITE, priv->base + MT7981_CLK_PDN); - return mtk_common_clk_init(dev, &mt7981_topckgen_clk_tree); + return mtk_clk_probe(dev); } -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt7981_clk_apmixedsys) = { .name = "mt7981-clock-fixed-pll", .id = UCLASS_CLK, .of_match = mt7981_fixed_pll_compat, - .probe = mt7981_fixed_pll_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt7981_clk_topckgen) = { .name = "mt7981-clock-topckgen", .id = UCLASS_CLK, .of_match = mt7981_topckgen_compat, @@ -700,20 +707,18 @@ U_BOOT_DRIVER(mtk_clk_topckgen) = { }; static const struct udevice_id mt7981_infracfg_compat[] = { - { .compatible = "mediatek,mt7981-infracfg" }, + { + .compatible = "mediatek,mt7981-infracfg", + .data = (ulong)&mt7981_infracfg_clk_tree, + }, {} }; -static int mt7981_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_infrasys_init(dev, &mt7981_infracfg_clk_tree); -} - -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt7981_clk_infracfg) = { .name = "mt7981-clock-infracfg", .id = UCLASS_CLK, .of_match = mt7981_infracfg_compat, - .probe = mt7981_infracfg_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_infrasys_ops, .flags = DM_FLAG_PRE_RELOC, @@ -740,24 +745,11 @@ static const struct mtk_gate sgmii0_cgs[] = { GATE_SGMII(CLK_SGM0_CDR_CK0_EN, "sgm0_cdr_ck0_en", CLK_TOP_USB_CDR_CK, 5), }; -static int mt7981_sgmii0sys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree, - sgmii0_cgs, ARRAY_SIZE(sgmii0_cgs), 0); -} - -static const struct udevice_id mt7981_sgmii0sys_compat[] = { - { .compatible = "mediatek,mt7981-sgmiisys_0", }, - {} -}; - -U_BOOT_DRIVER(mtk_clk_sgmii0sys) = { - .name = "mt7981-clock-sgmii0sys", - .id = UCLASS_CLK, - .of_match = mt7981_sgmii0sys_compat, - .probe = mt7981_sgmii0sys_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, +static const struct mtk_clk_tree mt7981_sgmii0_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = sgmii0_cgs, + .num_gates = ARRAY_SIZE(sgmii0_cgs), }; static const struct mtk_gate sgmii1_cgs[] = { @@ -767,24 +759,32 @@ static const struct mtk_gate sgmii1_cgs[] = { GATE_SGMII(CLK_SGM1_CDR_CK1_EN, "sgm1_cdr_ck1_en", CLK_TOP_USB_CDR_CK, 5), }; -static int mt7981_sgmii1sys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree, - sgmii1_cgs, ARRAY_SIZE(sgmii1_cgs), 0); -} +static const struct mtk_clk_tree mt7981_sgmii1_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = sgmii1_cgs, + .num_gates = ARRAY_SIZE(sgmii1_cgs), +}; -static const struct udevice_id mt7981_sgmii1sys_compat[] = { - { .compatible = "mediatek,mt7981-sgmiisys_1", }, +static const struct udevice_id of_match_mt7981_sgmiisys[] = { + { + .compatible = "mediatek,mt7981-sgmiisys_0", + .data = (ulong)&mt7981_sgmii0_clk_tree, + }, + { + .compatible = "mediatek,mt7981-sgmiisys_1", + .data = (ulong)&mt7981_sgmii1_clk_tree, + }, {} }; -U_BOOT_DRIVER(mtk_clk_sgmii1sys) = { - .name = "mt7981-clock-sgmii1sys", +U_BOOT_DRIVER(mt7981_clk_sgmiisys) = { + .name = "mt7981-clock-sgmiisys", .id = UCLASS_CLK, - .of_match = mt7981_sgmii1sys_compat, - .probe = mt7981_sgmii1sys_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .of_match = of_match_mt7981_sgmiisys, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; /* ethsys */ @@ -808,11 +808,12 @@ static const struct mtk_gate eth_cgs[] = { GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", CLK_TOP_NETSYS_WED_MCU, 15), }; -static int mt7981_ethsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree, - eth_cgs, ARRAY_SIZE(eth_cgs), 0); -} +static const struct mtk_clk_tree mt7981_eth_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = eth_cgs, + .num_gates = ARRAY_SIZE(eth_cgs), +}; static int mt7981_ethsys_bind(struct udevice *dev) { @@ -828,16 +829,19 @@ static int mt7981_ethsys_bind(struct udevice *dev) } static const struct udevice_id mt7981_ethsys_compat[] = { - { .compatible = "mediatek,mt7981-ethsys", }, + { + .compatible = "mediatek,mt7981-ethsys", + .data = (ulong)&mt7981_eth_clk_tree, + }, {} }; -U_BOOT_DRIVER(mtk_clk_ethsys) = { +U_BOOT_DRIVER(mt7981_clk_ethsys) = { .name = "mt7981-clock-ethsys", .id = UCLASS_CLK, .of_match = mt7981_ethsys_compat, - .probe = mt7981_ethsys_probe, + .probe = mtk_clk_probe, .bind = mt7981_ethsys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c index 9c6514120a6..e4abddbd515 100644 --- a/drivers/clk/mediatek/clk-mt7986.c +++ b/drivers/clk/mediatek/clk-mt7986.c @@ -530,6 +530,7 @@ static const struct mtk_clk_tree mt7986_fixed_pll_clk_tree = { .fclks = fixed_pll_clks, .num_fclks = ARRAY_SIZE(fixed_pll_clks), .flags = CLK_PARENT_APMIXED, + .type = MTK_CLK_TREE_APMIXED, }; static const struct mtk_clk_tree mt7986_topckgen_clk_tree = { @@ -544,6 +545,7 @@ static const struct mtk_clk_tree mt7986_topckgen_clk_tree = { .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), .flags = CLK_PARENT_TOPCKGEN, + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_clk_tree mt7986_infracfg_clk_tree = { @@ -559,24 +561,29 @@ static const struct mtk_clk_tree mt7986_infracfg_clk_tree = { .num_muxes = ARRAY_SIZE(infra_muxes), .num_gates = ARRAY_SIZE(infracfg_gates), .flags = CLK_PARENT_INFRASYS, + .type = MTK_CLK_TREE_INFRASYS, }; static const struct udevice_id mt7986_fixed_pll_compat[] = { - { .compatible = "mediatek,mt7986-fixed-plls" }, - { .compatible = "mediatek,mt7986-apmixedsys" }, + { + .compatible = "mediatek,mt7986-fixed-plls", + .data = (ulong)&mt7986_fixed_pll_clk_tree, + }, + { + .compatible = "mediatek,mt7986-apmixedsys", + .data = (ulong)&mt7986_fixed_pll_clk_tree, + }, {} }; static const struct udevice_id mt7986_topckgen_compat[] = { - { .compatible = "mediatek,mt7986-topckgen" }, + { + .compatible = "mediatek,mt7986-topckgen", + .data = (ulong)&mt7986_topckgen_clk_tree, + }, {} }; -static int mt7986_fixed_pll_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt7986_fixed_pll_clk_tree); -} - static int mt7986_topckgen_probe(struct udevice *dev) { struct mtk_clk_priv *priv = dev_get_priv(dev); @@ -584,20 +591,20 @@ static int mt7986_topckgen_probe(struct udevice *dev) priv->base = dev_read_addr_ptr(dev); writel(MT7986_CLK_PDN_EN_WRITE, priv->base + MT7986_CLK_PDN); - return mtk_common_clk_init(dev, &mt7986_topckgen_clk_tree); + return mtk_clk_probe(dev); } -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt7986_clk_apmixedsys) = { .name = "mt7986-clock-fixed-pll", .id = UCLASS_CLK, .of_match = mt7986_fixed_pll_compat, - .probe = mt7986_fixed_pll_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt7986_clk_topckgen) = { .name = "mt7986-clock-topckgen", .id = UCLASS_CLK, .of_match = mt7986_topckgen_compat, @@ -608,20 +615,18 @@ U_BOOT_DRIVER(mtk_clk_topckgen) = { }; static const struct udevice_id mt7986_infracfg_compat[] = { - { .compatible = "mediatek,mt7986-infracfg" }, + { + .compatible = "mediatek,mt7986-infracfg", + .data = (ulong)&mt7986_infracfg_clk_tree, + }, {} }; -static int mt7986_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_infrasys_init(dev, &mt7986_infracfg_clk_tree); -} - -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt7986_clk_infracfg) = { .name = "mt7986-clock-infracfg", .id = UCLASS_CLK, .of_match = mt7986_infracfg_compat, - .probe = mt7986_infracfg_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_infrasys_ops, .flags = DM_FLAG_PRE_RELOC, @@ -647,11 +652,12 @@ static const struct mtk_gate eth_cgs[] = { GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", CLK_TOP_NETSYS_MCU_SEL, 15), }; -static int mt7986_ethsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7986_topckgen_clk_tree, eth_cgs, - ARRAY_SIZE(eth_cgs), 0); -} +static const struct mtk_clk_tree mt7986_eth_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = eth_cgs, + .num_gates = ARRAY_SIZE(eth_cgs), +}; static int mt7986_ethsys_bind(struct udevice *dev) { @@ -667,16 +673,19 @@ static int mt7986_ethsys_bind(struct udevice *dev) } static const struct udevice_id mt7986_ethsys_compat[] = { - { .compatible = "mediatek,mt7986-ethsys" }, + { + .compatible = "mediatek,mt7986-ethsys", + .data = (ulong)&mt7986_eth_clk_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_ethsys) = { +U_BOOT_DRIVER(mt7986_clk_ethsys) = { .name = "mt7986-clock-ethsys", .id = UCLASS_CLK, .of_match = mt7986_ethsys_compat, - .probe = mt7986_ethsys_probe, + .probe = mtk_clk_probe, .bind = mt7986_ethsys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; diff --git a/drivers/clk/mediatek/clk-mt7987.c b/drivers/clk/mediatek/clk-mt7987.c index 5f102636079..6f2fe12a186 100644 --- a/drivers/clk/mediatek/clk-mt7987.c +++ b/drivers/clk/mediatek/clk-mt7987.c @@ -60,24 +60,26 @@ static const struct mtk_clk_tree mt7987_fixed_pll_clk_tree = { .fclks = apmixedsys_mtk_plls, .num_fclks = ARRAY_SIZE(apmixedsys_mtk_plls), .flags = CLK_PARENT_APMIXED, + .type = MTK_CLK_TREE_APMIXED, }; static const struct udevice_id mt7987_fixed_pll_compat[] = { - { .compatible = "mediatek,mt7987-fixed-plls" }, - { .compatible = "mediatek,mt7987-apmixedsys" }, + { + .compatible = "mediatek,mt7987-fixed-plls", + .data = (ulong)&mt7987_fixed_pll_clk_tree, + }, + { + .compatible = "mediatek,mt7987-apmixedsys", + .data = (ulong)&mt7987_fixed_pll_clk_tree, + }, {} }; -static int mt7987_fixed_pll_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt7987_fixed_pll_clk_tree); -} - -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt7987_clk_apmixedsys) = { .name = "mt7987-clock-fixed-pll", .id = UCLASS_CLK, .of_match = mt7987_fixed_pll_compat, - .probe = mt7987_fixed_pll_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, @@ -457,10 +459,14 @@ static const struct mtk_clk_tree mt7987_topckgen_clk_tree = { .num_fdivs = ARRAY_SIZE(topckgen_mtk_fixed_factors), .num_muxes = ARRAY_SIZE(topckgen_mtk_muxes), .flags = CLK_PARENT_TOPCKGEN, + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct udevice_id mt7987_topckgen_compat[] = { - { .compatible = "mediatek,mt7987-topckgen" }, + { + .compatible = "mediatek,mt7987-topckgen", + .data = (ulong)&mt7987_topckgen_clk_tree, + }, {} }; @@ -473,10 +479,10 @@ static int mt7987_topckgen_probe(struct udevice *dev) return -ENOENT; writel(MT7987_CLK_PDN_EN_WRITE, priv->base + MT7987_CLK_PDN); - return mtk_common_clk_init(dev, &mt7987_topckgen_clk_tree); + return mtk_clk_probe(dev); } -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt7987_clk_topckgen) = { .name = "mt7987-clock-topckgen", .id = UCLASS_CLK, .of_match = mt7987_topckgen_compat, @@ -783,24 +789,26 @@ static const struct mtk_clk_tree mt7987_infracfg_clk_tree = { .gates = infracfg_mtk_gates, .num_muxes = ARRAY_SIZE(infracfg_mtk_mux), .num_gates = ARRAY_SIZE(infracfg_mtk_gates), + .type = MTK_CLK_TREE_INFRASYS, }; static const struct udevice_id mt7987_infracfg_compat[] = { - { .compatible = "mediatek,mt7987-infracfg_ao" }, - { .compatible = "mediatek,mt7987-infracfg" }, + { + .compatible = "mediatek,mt7987-infracfg_ao", + .data = (ulong)&mt7987_infracfg_clk_tree, + }, + { + .compatible = "mediatek,mt7987-infracfg", + .data = (ulong)&mt7987_infracfg_clk_tree, + }, {} }; -static int mt7987_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_infrasys_init(dev, &mt7987_infracfg_clk_tree); -} - -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt7987_clk_infracfg) = { .name = "mt7987-clock-infracfg", .id = UCLASS_CLK, .of_match = mt7987_infracfg_compat, - .probe = mt7987_infracfg_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_infrasys_ops, .flags = DM_FLAG_PRE_RELOC, @@ -827,11 +835,12 @@ static const struct mtk_gate eth_cgs[] = { GATE_ETH_TOP(CLK_ETHDMA_GP3_EN, "ethdma_gp3_en", CLK_TOP_NETSYS_500M_SEL, 10), }; -static int mt7987_ethsys_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7987_topckgen_clk_tree, eth_cgs, - ARRAY_SIZE(eth_cgs), 0); -} +static const struct mtk_clk_tree mt7987_eth_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = eth_cgs, + .num_gates = ARRAY_SIZE(eth_cgs), +}; static int mt7987_ethsys_bind(struct udevice *dev) { @@ -849,16 +858,17 @@ static int mt7987_ethsys_bind(struct udevice *dev) static const struct udevice_id mt7987_ethsys_compat[] = { { .compatible = "mediatek,mt7987-ethsys", + .data = (ulong)&mt7987_eth_clk_tree, }, {} }; -U_BOOT_DRIVER(mtk_clk_ethsys) = { +U_BOOT_DRIVER(mt7987_clk_ethsys) = { .name = "mt7987-clock-ethsys", .id = UCLASS_CLK, .of_match = mt7987_ethsys_compat, - .probe = mt7987_ethsys_probe, + .probe = mtk_clk_probe, .bind = mt7987_ethsys_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; diff --git a/drivers/clk/mediatek/clk-mt7988.c b/drivers/clk/mediatek/clk-mt7988.c index 4e19f285da0..4728ca3e25a 100644 --- a/drivers/clk/mediatek/clk-mt7988.c +++ b/drivers/clk/mediatek/clk-mt7988.c @@ -808,6 +808,7 @@ static const struct mtk_clk_tree mt7988_fixed_pll_clk_tree = { .fclks = apmixedsys_mtk_plls, .num_fclks = ARRAY_SIZE(apmixedsys_mtk_plls), .flags = CLK_PARENT_APMIXED, + .type = MTK_CLK_TREE_APMIXED, }; static const struct mtk_clk_tree mt7988_topckgen_clk_tree = { @@ -822,6 +823,7 @@ static const struct mtk_clk_tree mt7988_topckgen_clk_tree = { .num_fdivs = ARRAY_SIZE(topckgen_mtk_fixed_factors), .num_muxes = ARRAY_SIZE(topckgen_mtk_muxes), .flags = CLK_PARENT_TOPCKGEN, + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_clk_tree mt7988_infracfg_clk_tree = { @@ -833,24 +835,29 @@ static const struct mtk_clk_tree mt7988_infracfg_clk_tree = { .gates = infracfg_mtk_gates, .num_muxes = ARRAY_SIZE(infracfg_mtk_mux), .num_gates = ARRAY_SIZE(infracfg_mtk_gates), + .type = MTK_CLK_TREE_INFRASYS, }; static const struct udevice_id mt7988_fixed_pll_compat[] = { - { .compatible = "mediatek,mt7988-fixed-plls" }, - { .compatible = "mediatek,mt7988-apmixedsys" }, + { + .compatible = "mediatek,mt7988-fixed-plls", + .data = (ulong)&mt7988_fixed_pll_clk_tree, + }, + { + .compatible = "mediatek,mt7988-apmixedsys", + .data = (ulong)&mt7988_fixed_pll_clk_tree, + }, {} }; static const struct udevice_id mt7988_topckgen_compat[] = { - { .compatible = "mediatek,mt7988-topckgen" }, + { + .compatible = "mediatek,mt7988-topckgen", + .data = (ulong)&mt7988_topckgen_clk_tree, + }, {} }; -static int mt7988_fixed_pll_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt7988_fixed_pll_clk_tree); -} - static int mt7988_topckgen_probe(struct udevice *dev) { struct mtk_clk_priv *priv = dev_get_priv(dev); @@ -860,20 +867,20 @@ static int mt7988_topckgen_probe(struct udevice *dev) return -ENOENT; writel(MT7988_CLK_PDN_EN_WRITE, priv->base + MT7988_CLK_PDN); - return mtk_common_clk_init(dev, &mt7988_topckgen_clk_tree); + return mtk_clk_probe(dev); } -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt7988_clk_apmixedsys) = { .name = "mt7988-clock-fixed-pll", .id = UCLASS_CLK, .of_match = mt7988_fixed_pll_compat, - .probe = mt7988_fixed_pll_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt7988_clk_topckgen) = { .name = "mt7988-clock-topckgen", .id = UCLASS_CLK, .of_match = mt7988_topckgen_compat, @@ -884,20 +891,18 @@ U_BOOT_DRIVER(mtk_clk_topckgen) = { }; static const struct udevice_id mt7988_infracfg_compat[] = { - { .compatible = "mediatek,mt7988-infracfg" }, + { + .compatible = "mediatek,mt7988-infracfg", + .data = (ulong)&mt7988_infracfg_clk_tree, + }, {} }; -static int mt7988_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_infrasys_init(dev, &mt7988_infracfg_clk_tree); -} - -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt7988_clk_infracfg) = { .name = "mt7988-clock-infracfg", .id = UCLASS_CLK, .of_match = mt7988_infracfg_compat, - .probe = mt7988_infracfg_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_infrasys_ops, .flags = DM_FLAG_PRE_RELOC, @@ -922,12 +927,12 @@ static const struct mtk_gate ethdma_mtk_gate[] = { GATE_ETHDMA(CLK_ETHDMA_FE_EN, "ethdma_fe_en", CLK_TOP_NETSYS_2X_SEL, 6), }; -static int mt7988_ethdma_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - ethdma_mtk_gate, - ARRAY_SIZE(ethdma_mtk_gate), 0); -} +static const struct mtk_clk_tree mt7988_ethdma_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = ethdma_mtk_gate, + .num_gates = ARRAY_SIZE(ethdma_mtk_gate), +}; static int mt7988_ethdma_bind(struct udevice *dev) { @@ -945,18 +950,19 @@ static int mt7988_ethdma_bind(struct udevice *dev) static const struct udevice_id mt7988_ethdma_compat[] = { { .compatible = "mediatek,mt7988-ethdma", + .data = (ulong)&mt7988_ethdma_clk_tree, }, {} }; -U_BOOT_DRIVER(mtk_clk_ethdma) = { +U_BOOT_DRIVER(mt7988_clk_ethdma) = { .name = "mt7988-clock-ethdma", .id = UCLASS_CLK, .of_match = mt7988_ethdma_compat, - .probe = mt7988_ethdma_probe, + .probe = mtk_clk_probe, .bind = mt7988_ethdma_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; /* SGMIISYS_0 */ @@ -981,27 +987,11 @@ static const struct mtk_gate sgmiisys_0_mtk_gate[] = { GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", CLK_TOP_XTAL, 3), }; -static int mt7988_sgmiisys_0_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - sgmiisys_0_mtk_gate, - ARRAY_SIZE(sgmiisys_0_mtk_gate), 0); -} - -static const struct udevice_id mt7988_sgmiisys_0_compat[] = { - { - .compatible = "mediatek,mt7988-sgmiisys_0", - }, - {} -}; - -U_BOOT_DRIVER(mtk_clk_sgmiisys_0) = { - .name = "mt7988-clock-sgmiisys_0", - .id = UCLASS_CLK, - .of_match = mt7988_sgmiisys_0_compat, - .probe = mt7988_sgmiisys_0_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, +static const struct mtk_clk_tree mt7988_sgmiisys_0_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = sgmiisys_0_mtk_gate, + .num_gates = ARRAY_SIZE(sgmiisys_0_mtk_gate), }; /* SGMIISYS_1 */ @@ -1026,27 +1016,32 @@ static const struct mtk_gate sgmiisys_1_mtk_gate[] = { GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", CLK_TOP_XTAL, 3), }; -static int mt7988_sgmiisys_1_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - sgmiisys_1_mtk_gate, - ARRAY_SIZE(sgmiisys_1_mtk_gate), 0); -} +static const struct mtk_clk_tree mt7988_sgmiisys_1_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = sgmiisys_1_mtk_gate, + .num_gates = ARRAY_SIZE(sgmiisys_1_mtk_gate), +}; -static const struct udevice_id mt7988_sgmiisys_1_compat[] = { +static const struct udevice_id of_match_mt7988_sgmiisys[] = { + { + .compatible = "mediatek,mt7988-sgmiisys_0", + .data = (ulong)&mt7988_sgmiisys_0_clk_tree, + }, { .compatible = "mediatek,mt7988-sgmiisys_1", + .data = (ulong)&mt7988_sgmiisys_1_clk_tree, }, {} }; -U_BOOT_DRIVER(mtk_clk_sgmiisys_1) = { - .name = "mt7988-clock-sgmiisys_1", +U_BOOT_DRIVER(mt7988_clk_sgmiisys) = { + .name = "mt7988-clock-sgmiisys", .id = UCLASS_CLK, - .of_match = mt7988_sgmiisys_1_compat, - .probe = mt7988_sgmiisys_1_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .of_match = of_match_mt7988_sgmiisys, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; /* ETHWARP */ @@ -1073,12 +1068,12 @@ static const struct mtk_gate ethwarp_mtk_gate[] = { CLK_TOP_NETSYS_MCU_SEL, 15), }; -static int mt7988_ethwarp_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt7988_topckgen_clk_tree, - ethwarp_mtk_gate, - ARRAY_SIZE(ethwarp_mtk_gate), 0); -} +static const struct mtk_clk_tree mt7988_ethwarp_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = ethwarp_mtk_gate, + .num_gates = ARRAY_SIZE(ethwarp_mtk_gate), +}; static int mt7988_ethwarp_bind(struct udevice *dev) { @@ -1096,16 +1091,17 @@ static int mt7988_ethwarp_bind(struct udevice *dev) static const struct udevice_id mt7988_ethwarp_compat[] = { { .compatible = "mediatek,mt7988-ethwarp", + .data = (ulong)&mt7988_ethwarp_clk_tree, }, {} }; -U_BOOT_DRIVER(mtk_clk_ethwarp) = { +U_BOOT_DRIVER(mt7988_clk_ethwarp) = { .name = "mt7988-clock-ethwarp", .id = UCLASS_CLK, .of_match = mt7988_ethwarp_compat, - .probe = mt7988_ethwarp_probe, + .probe = mtk_clk_probe, .bind = mt7988_ethwarp_bind, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, }; diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c index 7b2d796bc6c..5a4863049c5 100644 --- a/drivers/clk/mediatek/clk-mt8183.c +++ b/drivers/clk/mediatek/clk-mt8183.c @@ -604,20 +604,27 @@ static const struct mtk_composite top_muxes[] = { MUX(CLK_TOP_MUX_AUD_2, aud_2_parents, 0xe0, 8, 1), }; -static const struct mtk_clk_tree mt8183_clk_tree = { +static const struct mtk_clk_tree mt8183_apmixed_clk_tree = { .pll_parent = EXT_PARENT(CLK_PAD_CLK26M), .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .plls = apmixed_plls, + .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, +}; + +static const struct mtk_clk_tree mt8183_topckgen_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .fdivs_offs = CLK_TOP_CLK13M, .muxes_offs = CLK_TOP_MUX_AXI, - .plls = apmixed_plls, .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, - .num_plls = ARRAY_SIZE(apmixed_plls), .num_fclks = ARRAY_SIZE(top_fixed_clks), .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_gate_regs infra0_cg_regs = { @@ -780,63 +787,63 @@ static const struct mtk_gate infra_clks[] = { GATE_INFRA3(CLK_INFRA_FBIST2FPC, CLK_TOP_MUX_MSDC50_0, 24), }; -static int mt8183_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8183_clk_tree); -} - -static int mt8183_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8183_clk_tree); -} - -static int mt8183_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8183_clk_tree, infra_clks, - ARRAY_SIZE(infra_clks), 0); -} +static const struct mtk_clk_tree mt8183_infracfg_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = infra_clks, + .num_gates = ARRAY_SIZE(infra_clks), +}; static const struct udevice_id mt8183_apmixed_compat[] = { - { .compatible = "mediatek,mt8183-apmixedsys", }, + { + .compatible = "mediatek,mt8183-apmixedsys", + .data = (ulong)&mt8183_apmixed_clk_tree, + }, { } }; static const struct udevice_id mt8183_topckgen_compat[] = { - { .compatible = "mediatek,mt8183-topckgen", }, + { + .compatible = "mediatek,mt8183-topckgen", + .data = (ulong)&mt8183_topckgen_clk_tree, + }, { } }; static const struct udevice_id mt8183_infracfg_compat[] = { - { .compatible = "mediatek,mt8183-infracfg", }, + { + .compatible = "mediatek,mt8183-infracfg", + .data = (ulong)&mt8183_infracfg_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8183_clk_apmixedsys) = { .name = "mt8183-apmixedsys", .id = UCLASS_CLK, .of_match = mt8183_apmixed_compat, - .probe = mt8183_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8183_clk_topckgen) = { .name = "mt8183-topckgen", .id = UCLASS_CLK, .of_match = mt8183_topckgen_compat, - .probe = mt8183_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt8183_clk_infracfg) = { .name = "mt8183-infracfg", .id = UCLASS_CLK, .of_match = mt8183_infracfg_compat, - .probe = mt8183_infracfg_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), - .ops = &mtk_clk_gate_ops, + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt8188.c b/drivers/clk/mediatek/clk-mt8188.c index 3e413e111f1..0829ebf4f9a 100644 --- a/drivers/clk/mediatek/clk-mt8188.c +++ b/drivers/clk/mediatek/clk-mt8188.c @@ -89,6 +89,7 @@ static const struct mtk_clk_tree mt8188_apmixedsys_clk_tree = { .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .plls = apmixed_plls, .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, }; #define FIXED_CLK0(_id, _rate) \ @@ -1362,7 +1363,7 @@ static const struct mtk_gate_regs top1_cg_regs = { .parent = _parent, \ .regs = &top0_cg_regs, \ .shift = _shift, \ - .flags = CLK_GATE_NO_SETCLR | CLK_PARENT_TOPCKGEN, \ + .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN, \ } #define GATE_TOP0E(_id, _parent, _shift) { \ @@ -1370,7 +1371,7 @@ static const struct mtk_gate_regs top1_cg_regs = { .parent = _parent, \ .regs = &top0_cg_regs, \ .shift = _shift, \ - .flags = CLK_GATE_NO_SETCLR | CLK_PARENT_EXT, \ + .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_EXT, \ } #define GATE_TOP1(_id, _parent, _shift) { \ @@ -1422,6 +1423,7 @@ static const struct mtk_clk_tree mt8188_topckgen_clk_tree = { .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), .num_gates = ARRAY_SIZE(topckgen_cg_clks), + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_gate_regs infra_ao0_cg_regs = { @@ -1620,6 +1622,8 @@ static const struct mtk_gate infracfg_ao_clks[] = { static const struct mtk_clk_tree mt8188_infracfg_ao_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = infracfg_ao_clks, + .num_gates = ARRAY_SIZE(infracfg_ao_clks), }; static const struct mtk_gate_regs peri_ao_cg_regs = { @@ -1657,11 +1661,14 @@ static const struct mtk_gate pericfg_ao_clks[] = { GATE_PERI_AO(CLK_PERI_AO_SSUSB_BUS, CLK_TOP_USB_TOP, 13), GATE_PERI_AO(CLK_PERI_AO_SSUSB_XHCI, CLK_TOP_SSUSB_XHCI, 14), GATE_PERI_AO(CLK_PERI_AO_ETHERNET_MAC, CLK_TOP_SNPS_ETH_250M, 16), + GATE_PERI_AO(CLK_PERI_AO_PCIE_P0_FMEM, CLK_TOP_466M_FMEM, 24), }; static const struct mtk_clk_tree mt8188_pericfg_ao_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = pericfg_ao_clks, + .num_gates = ARRAY_SIZE(pericfg_ao_clks), }; static const struct mtk_gate_regs imp_iic_wrap_cg_regs = { @@ -1697,164 +1704,492 @@ static const struct mtk_gate imp_iic_wrap_en_clks[] = { const struct mtk_clk_tree mt8188_imp_iic_wrap_c_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = imp_iic_wrap_c_clks, + .num_gates = ARRAY_SIZE(imp_iic_wrap_c_clks), }; const struct mtk_clk_tree mt8188_imp_iic_wrap_w_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = imp_iic_wrap_w_clks, + .num_gates = ARRAY_SIZE(imp_iic_wrap_w_clks), }; const struct mtk_clk_tree mt8188_imp_iic_wrap_en_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = imp_iic_wrap_en_clks, + .num_gates = ARRAY_SIZE(imp_iic_wrap_en_clks), }; -static int mt8188_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8188_apmixedsys_clk_tree); -} +static const struct mtk_gate_regs vdo0_0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; -static int mt8188_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8188_topckgen_clk_tree); -} +static const struct mtk_gate_regs vdo0_1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; -static int mt8188_infracfg_ao_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8188_infracfg_ao_clk_tree, - infracfg_ao_clks, - ARRAY_SIZE(infracfg_ao_clks), 0); -} +static const struct mtk_gate_regs vdo0_2_cg_regs = { + .set_ofs = 0x124, + .clr_ofs = 0x128, + .sta_ofs = 0x120, +}; -static int mt8188_pericfg_ao_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8188_pericfg_ao_clk_tree, - pericfg_ao_clks, - ARRAY_SIZE(pericfg_ao_clks), 0); -} +static const struct mtk_gate_regs vpp0_0_cg_regs = { + .set_ofs = 0x24, + .clr_ofs = 0x28, + .sta_ofs = 0x20, +}; -static int mt8188_imp_iic_wrap_c_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_c_clk_tree, - imp_iic_wrap_c_clks, - ARRAY_SIZE(imp_iic_wrap_c_clks), 0); -} +static const struct mtk_gate_regs vpp0_1_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x34, + .sta_ofs = 0x2c, +}; -static int mt8188_imp_iic_wrap_w_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_w_clk_tree, - imp_iic_wrap_w_clks, - ARRAY_SIZE(imp_iic_wrap_w_clks), 0); -} +static const struct mtk_gate_regs vpp0_2_cg_regs = { + .set_ofs = 0x3c, + .clr_ofs = 0x40, + .sta_ofs = 0x38, +}; -static int mt8188_imp_iic_wrap_en_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8188_imp_iic_wrap_en_clk_tree, - imp_iic_wrap_en_clks, - ARRAY_SIZE(imp_iic_wrap_en_clks), 0); -} +#define GATE_VPP0_0(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vpp0_0_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) -static const struct udevice_id mt8188_apmixed_compat[] = { - { .compatible = "mediatek,mt8188-apmixedsys", }, - { } +#define GATE_VPP0_1(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vpp0_1_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VPP0_2(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vpp0_2_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +static const struct mtk_gate vpp0_clks[] = { + /* VPP0_0 */ + GATE_VPP0_0(CLK_VPP0_MDP_FG, CLK_TOP_VPP, 1), + GATE_VPP0_0(CLK_VPP0_STITCH, CLK_TOP_VPP, 2), + GATE_VPP0_0(CLK_VPP0_PADDING, CLK_TOP_VPP, 7), + GATE_VPP0_0(CLK_VPP0_MDP_TCC, CLK_TOP_VPP, 8), + GATE_VPP0_0(CLK_VPP0_WARP0_ASYNC_TX, CLK_TOP_VPP, 10), + GATE_VPP0_0(CLK_VPP0_WARP1_ASYNC_TX, CLK_TOP_VPP, 11), + GATE_VPP0_0(CLK_VPP0_MUTEX, CLK_TOP_VPP, 13), + GATE_VPP0_0(CLK_VPP02VPP1_RELAY, CLK_TOP_VPP, 14), + GATE_VPP0_0(CLK_VPP0_VPP12VPP0_ASYNC, CLK_TOP_VPP, 15), + GATE_VPP0_0(CLK_VPP0_MMSYSRAM_TOP, CLK_TOP_VPP, 16), + GATE_VPP0_0(CLK_VPP0_MDP_AAL, CLK_TOP_VPP, 17), + GATE_VPP0_0(CLK_VPP0_MDP_RSZ, CLK_TOP_VPP, 18), + /* VPP0_1 */ + GATE_VPP0_1(CLK_VPP0_SMI_COMMON_MMSRAM, CLK_TOP_VPP, 0), + GATE_VPP0_1(CLK_VPP0_GALS_VDO0_LARB0_MMSRAM, CLK_TOP_VPP, 1), + GATE_VPP0_1(CLK_VPP0_GALS_VDO0_LARB1_MMSRAM, CLK_TOP_VPP, 2), + GATE_VPP0_1(CLK_VPP0_GALS_VENCSYS_MMSRAM, CLK_TOP_VPP, 3), + GATE_VPP0_1(CLK_VPP0_GALS_VENCSYS_CORE1_MMSRAM, CLK_TOP_VPP, 4), + GATE_VPP0_1(CLK_VPP0_GALS_INFRA_MMSRAM, CLK_TOP_VPP, 5), + GATE_VPP0_1(CLK_VPP0_GALS_CAMSYS_MMSRAM, CLK_TOP_VPP, 6), + GATE_VPP0_1(CLK_VPP0_GALS_VPP1_LARB5_MMSRAM, CLK_TOP_VPP, 7), + GATE_VPP0_1(CLK_VPP0_GALS_VPP1_LARB6_MMSRAM, CLK_TOP_VPP, 8), + GATE_VPP0_1(CLK_VPP0_SMI_REORDER_MMSRAM, CLK_TOP_VPP, 9), + GATE_VPP0_1(CLK_VPP0_SMI_IOMMU, CLK_TOP_VPP, 10), + GATE_VPP0_1(CLK_VPP0_GALS_IMGSYS_CAMSYS, CLK_TOP_VPP, 11), + GATE_VPP0_1(CLK_VPP0_MDP_RDMA, CLK_TOP_VPP, 12), + GATE_VPP0_1(CLK_VPP0_MDP_WROT, CLK_TOP_VPP, 13), + GATE_VPP0_1(CLK_VPP0_GALS_EMI0_EMI1, CLK_TOP_VPP, 16), + GATE_VPP0_1(CLK_VPP0_SMI_SUB_COMMON_REORDER, CLK_TOP_VPP, 17), + GATE_VPP0_1(CLK_VPP0_SMI_RSI, CLK_TOP_VPP, 18), + GATE_VPP0_1(CLK_VPP0_SMI_COMMON_LARB4, CLK_TOP_VPP, 19), + GATE_VPP0_1(CLK_VPP0_GALS_VDEC_VDEC_CORE1, CLK_TOP_VPP, 20), + GATE_VPP0_1(CLK_VPP0_GALS_VPP1_WPESYS, CLK_TOP_VPP, 21), + GATE_VPP0_1(CLK_VPP0_GALS_VDO0_VDO1_VENCSYS_CORE1, CLK_TOP_VPP, 22), + GATE_VPP0_1(CLK_VPP0_FAKE_ENG, CLK_TOP_VPP, 23), + GATE_VPP0_1(CLK_VPP0_MDP_HDR, CLK_TOP_VPP, 24), + GATE_VPP0_1(CLK_VPP0_MDP_TDSHP, CLK_TOP_VPP, 25), + GATE_VPP0_1(CLK_VPP0_MDP_COLOR, CLK_TOP_VPP, 26), + GATE_VPP0_1(CLK_VPP0_MDP_OVL, CLK_TOP_VPP, 27), + GATE_VPP0_1(CLK_VPP0_DSIP_RDMA, CLK_TOP_VPP, 28), + GATE_VPP0_1(CLK_VPP0_DISP_WDMA, CLK_TOP_VPP, 29), + GATE_VPP0_1(CLK_VPP0_MDP_HMS, CLK_TOP_VPP, 30), + /* VPP0_2 */ + GATE_VPP0_2(CLK_VPP0_WARP0_RELAY, CLK_TOP_WPE_VPP, 0), + GATE_VPP0_2(CLK_VPP0_WARP0_ASYNC, CLK_TOP_WPE_VPP, 1), + GATE_VPP0_2(CLK_VPP0_WARP1_RELAY, CLK_TOP_WPE_VPP, 2), + GATE_VPP0_2(CLK_VPP0_WARP1_ASYNC, CLK_TOP_WPE_VPP, 3), }; -static const struct udevice_id mt8188_topckgen_compat[] = { - { .compatible = "mediatek,mt8188-topckgen", }, - { } +static const struct mtk_gate_regs vpp1_0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, }; -static const struct udevice_id mt8188_infracfg_ao_compat[] = { - { .compatible = "mediatek,mt8188-infracfg-ao", }, - { } +static const struct mtk_gate_regs vpp1_1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, }; -static const struct udevice_id mt8188_pericfg_ao_compat[] = { - { .compatible = "mediatek,mt8188-pericfg-ao", }, - { } +#define GATE_VPP1_0(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vpp1_0_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VPP1_1(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vpp1_1_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +static const struct mtk_gate vpp1_clks[] = { + /* VPP1_0 */ + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_OVL, CLK_TOP_VPP, 0), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_TCC, CLK_TOP_VPP, 1), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_WROT, CLK_TOP_VPP, 2), + GATE_VPP1_0(CLK_VPP1_SVPP1_VPP_PAD, CLK_TOP_VPP, 3), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_WROT, CLK_TOP_VPP, 4), + GATE_VPP1_0(CLK_VPP1_SVPP2_VPP_PAD, CLK_TOP_VPP, 5), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_WROT, CLK_TOP_VPP, 6), + GATE_VPP1_0(CLK_VPP1_SVPP3_VPP_PAD, CLK_TOP_VPP, 7), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_RDMA, CLK_TOP_VPP, 8), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_FG, CLK_TOP_VPP, 9), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_RDMA, CLK_TOP_VPP, 10), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_FG, CLK_TOP_VPP, 11), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_RDMA, CLK_TOP_VPP, 12), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_FG, CLK_TOP_VPP, 13), + GATE_VPP1_0(CLK_VPP1_VPP_SPLIT, CLK_TOP_VPP, 14), + GATE_VPP1_0(CLK_VPP1_SVPP2_VDO0_DL_RELAY, CLK_TOP_VPP, 15), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_RSZ, CLK_TOP_VPP, 16), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_TDSHP, CLK_TOP_VPP, 17), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_COLOR, CLK_TOP_VPP, 18), + GATE_VPP1_0(CLK_VPP1_SVPP3_VDO1_DL_RELAY, CLK_TOP_VPP, 19), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_RSZ, CLK_TOP_VPP, 20), + GATE_VPP1_0(CLK_VPP1_SVPP2_VPP_MERGE, CLK_TOP_VPP, 21), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_TDSHP, CLK_TOP_VPP, 22), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_COLOR, CLK_TOP_VPP, 23), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_RSZ, CLK_TOP_VPP, 24), + GATE_VPP1_0(CLK_VPP1_SVPP3_VPP_MERGE, CLK_TOP_VPP, 25), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_TDSHP, CLK_TOP_VPP, 26), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_COLOR, CLK_TOP_VPP, 27), + GATE_VPP1_0(CLK_VPP1_GALS5, CLK_TOP_VPP, 28), + GATE_VPP1_0(CLK_VPP1_GALS6, CLK_TOP_VPP, 29), + GATE_VPP1_0(CLK_VPP1_LARB5, CLK_TOP_VPP, 30), + GATE_VPP1_0(CLK_VPP1_LARB6, CLK_TOP_VPP, 31), + /* VPP1_1 */ + GATE_VPP1_1(CLK_VPP1_SVPP1_MDP_HDR, CLK_TOP_VPP, 0), + GATE_VPP1_1(CLK_VPP1_SVPP1_MDP_AAL, CLK_TOP_VPP, 1), + GATE_VPP1_1(CLK_VPP1_SVPP2_MDP_HDR, CLK_TOP_VPP, 2), + GATE_VPP1_1(CLK_VPP1_SVPP2_MDP_AAL, CLK_TOP_VPP, 3), + GATE_VPP1_1(CLK_VPP1_SVPP3_MDP_HDR, CLK_TOP_VPP, 4), + GATE_VPP1_1(CLK_VPP1_SVPP3_MDP_AAL, CLK_TOP_VPP, 5), + GATE_VPP1_1(CLK_VPP1_DISP_MUTEX, CLK_TOP_VPP, 7), + GATE_VPP1_1(CLK_VPP1_SVPP2_VDO1_DL_RELAY, CLK_TOP_VPP, 8), + GATE_VPP1_1(CLK_VPP1_SVPP3_VDO0_DL_RELAY, CLK_TOP_VPP, 9), + GATE_VPP1_1(CLK_VPP1_VPP0_DL_ASYNC, CLK_TOP_VPP, 10), + GATE_VPP1_1(CLK_VPP1_VPP0_DL1_RELAY, CLK_TOP_VPP, 11), + GATE_VPP1_1(CLK_VPP1_LARB5_FAKE_ENG, CLK_TOP_VPP, 12), + GATE_VPP1_1(CLK_VPP1_LARB6_FAKE_ENG, CLK_TOP_VPP, 13), + GATE_VPP1_1(CLK_VPP1_HDMI_META, CLK_TOP_VPP, 16), + GATE_VPP1_1(CLK_VPP1_VPP_SPLIT_HDMI, CLK_TOP_VPP, 17), + GATE_VPP1_1(CLK_VPP1_DGI_IN, CLK_TOP_VPP, 18), + GATE_VPP1_1(CLK_VPP1_DGI_OUT, CLK_TOP_VPP, 19), + GATE_VPP1_1(CLK_VPP1_VPP_SPLIT_DGI, CLK_TOP_VPP, 20), + GATE_VPP1_1(CLK_VPP1_DL_CON_OCC, CLK_TOP_VPP, 21), + GATE_VPP1_1(CLK_VPP1_VPP_SPLIT_26M, CLK_TOP_VPP, 26), +}; + +#define GATE_VDO0_0(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo0_0_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VDO0_1(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo0_1_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VDO0_2(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo0_2_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +static const struct mtk_gate vdo0_clks[] = { + /* VDO0_0 */ + GATE_VDO0_0(CLK_VDO0_DISP_OVL0, CLK_TOP_VPP, 0), + GATE_VDO0_0(CLK_VDO0_FAKE_ENG0, CLK_TOP_VPP, 2), + GATE_VDO0_0(CLK_VDO0_DISP_CCORR0, CLK_TOP_VPP, 4), + GATE_VDO0_0(CLK_VDO0_DISP_MUTEX0, CLK_TOP_VPP, 6), + GATE_VDO0_0(CLK_VDO0_DISP_GAMMA0, CLK_TOP_VPP, 8), + GATE_VDO0_0(CLK_VDO0_DISP_DITHER0, CLK_TOP_VPP, 10), + GATE_VDO0_0(CLK_VDO0_DISP_WDMA0, CLK_TOP_VPP, 17), + GATE_VDO0_0(CLK_VDO0_DISP_RDMA0, CLK_TOP_VPP, 19), + GATE_VDO0_0(CLK_VDO0_DSI0, CLK_TOP_VPP, 21), + GATE_VDO0_0(CLK_VDO0_DSI1, CLK_TOP_VPP, 22), + GATE_VDO0_0(CLK_VDO0_DSC_WRAP0, CLK_TOP_VPP, 23), + GATE_VDO0_0(CLK_VDO0_VPP_MERGE0, CLK_TOP_VPP, 24), + GATE_VDO0_0(CLK_VDO0_DP_INTF0, CLK_TOP_VPP, 25), + GATE_VDO0_0(CLK_VDO0_DISP_AAL0, CLK_TOP_VPP, 26), + GATE_VDO0_0(CLK_VDO0_INLINEROT0, CLK_TOP_VPP, 27), + GATE_VDO0_0(CLK_VDO0_APB_BUS, CLK_TOP_VPP, 28), + GATE_VDO0_0(CLK_VDO0_DISP_COLOR0, CLK_TOP_VPP, 29), + GATE_VDO0_0(CLK_VDO0_MDP_WROT0, CLK_TOP_VPP, 30), + GATE_VDO0_0(CLK_VDO0_DISP_RSZ0, CLK_TOP_VPP, 31), + /* VDO0_1 */ + GATE_VDO0_1(CLK_VDO0_DISP_POSTMASK0, CLK_TOP_VPP, 0), + GATE_VDO0_1(CLK_VDO0_FAKE_ENG1, CLK_TOP_VPP, 1), + GATE_VDO0_1(CLK_VDO0_DL_ASYNC2, CLK_TOP_VPP, 5), + GATE_VDO0_1(CLK_VDO0_DL_RELAY3, CLK_TOP_VPP, 6), + GATE_VDO0_1(CLK_VDO0_DL_RELAY4, CLK_TOP_VPP, 7), + GATE_VDO0_1(CLK_VDO0_SMI_GALS, CLK_TOP_VPP, 10), + GATE_VDO0_1(CLK_VDO0_SMI_COMMON, CLK_TOP_VPP, 11), + GATE_VDO0_1(CLK_VDO0_SMI_EMI, CLK_TOP_VPP, 12), + GATE_VDO0_1(CLK_VDO0_SMI_IOMMU, CLK_TOP_VPP, 13), + GATE_VDO0_1(CLK_VDO0_SMI_LARB, CLK_TOP_VPP, 14), + GATE_VDO0_1(CLK_VDO0_SMI_RSI, CLK_TOP_VPP, 15), + /* VDO0_2 */ + GATE_VDO0_2(CLK_VDO0_DSI0_DSI, CLK_TOP_DSI_OCC, 0), + GATE_VDO0_2(CLK_VDO0_DSI1_DSI, CLK_TOP_DSI_OCC, 8), + GATE_VDO0_2(CLK_VDO0_DP_INTF0_DP_INTF, CLK_TOP_EDP, 16), +}; + +static const struct mtk_gate_regs vdo1_0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs vdo1_1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +static const struct mtk_gate_regs vdo1_2_cg_regs = { + .set_ofs = 0x124, + .clr_ofs = 0x128, + .sta_ofs = 0x120, +}; + +static const struct mtk_gate_regs vdo1_3_cg_regs = { + .set_ofs = 0x134, + .clr_ofs = 0x138, + .sta_ofs = 0x130, +}; + +static const struct mtk_gate_regs vdo1_4_cg_regs = { + .set_ofs = 0x144, + .clr_ofs = 0x148, + .sta_ofs = 0x140, +}; + +static const struct mtk_gate_regs vdo1_5_cg_regs = { + .set_ofs = 0x400, + .clr_ofs = 0x400, + .sta_ofs = 0x400, +}; + +#define GATE_VDO1_0(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo1_0_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VDO1_1(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo1_1_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VDO1_2(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo1_2_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VDO1_3(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo1_3_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VDO1_4(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo1_4_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +#define GATE_VDO1_5(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &vdo1_5_cg_regs, _shift, \ + CLK_PARENT_TOPCKGEN | CLK_GATE_SETCLR) + +static const struct mtk_gate vdo1_clks[] = { + /* VDO1_0 */ + GATE_VDO1_0(CLK_VDO1_SMI_LARB2, CLK_TOP_VPP, 0), + GATE_VDO1_0(CLK_VDO1_SMI_LARB3, CLK_TOP_VPP, 1), + GATE_VDO1_0(CLK_VDO1_GALS, CLK_TOP_VPP, 2), + GATE_VDO1_0(CLK_VDO1_FAKE_ENG0, CLK_TOP_VPP, 3), + GATE_VDO1_0(CLK_VDO1_FAKE_ENG1, CLK_TOP_VPP, 4), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA0, CLK_TOP_VPP, 5), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA1, CLK_TOP_VPP, 6), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA2, CLK_TOP_VPP, 7), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA3, CLK_TOP_VPP, 8), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE0, CLK_TOP_VPP, 9), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE1, CLK_TOP_VPP, 10), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE2, CLK_TOP_VPP, 11), + /* VDO1_1 */ + GATE_VDO1_1(CLK_VDO1_VPP_MERGE3, CLK_TOP_VPP, 0), + GATE_VDO1_1(CLK_VDO1_VPP_MERGE4, CLK_TOP_VPP, 1), + GATE_VDO1_1(CLK_VDO1_VPP2_TO_VDO1_DL_ASYNC, CLK_TOP_VPP, 2), + GATE_VDO1_1(CLK_VDO1_VPP3_TO_VDO1_DL_ASYNC, CLK_TOP_VPP, 3), + GATE_VDO1_1(CLK_VDO1_DISP_MUTEX, CLK_TOP_VPP, 4), + GATE_VDO1_1(CLK_VDO1_MDP_RDMA4, CLK_TOP_VPP, 5), + GATE_VDO1_1(CLK_VDO1_MDP_RDMA5, CLK_TOP_VPP, 6), + GATE_VDO1_1(CLK_VDO1_MDP_RDMA6, CLK_TOP_VPP, 7), + GATE_VDO1_1(CLK_VDO1_MDP_RDMA7, CLK_TOP_VPP, 8), + GATE_VDO1_1(CLK_VDO1_DP_INTF0_MMCK, CLK_TOP_VPP, 9), + GATE_VDO1_1(CLK_VDO1_DPI0_MM, CLK_TOP_VPP, 10), + GATE_VDO1_1(CLK_VDO1_DPI1_MM, CLK_TOP_VPP, 11), + GATE_VDO1_1(CLK_VDO1_MERGE0_DL_ASYNC, CLK_TOP_VPP, 13), + GATE_VDO1_1(CLK_VDO1_MERGE1_DL_ASYNC, CLK_TOP_VPP, 14), + GATE_VDO1_1(CLK_VDO1_MERGE2_DL_ASYNC, CLK_TOP_VPP, 15), + GATE_VDO1_1(CLK_VDO1_MERGE3_DL_ASYNC, CLK_TOP_VPP, 16), + GATE_VDO1_1(CLK_VDO1_MERGE4_DL_ASYNC, CLK_TOP_VPP, 17), + GATE_VDO1_1(CLK_VDO1_DSC_VDO1_DL_ASYNC, CLK_TOP_VPP, 18), + GATE_VDO1_1(CLK_VDO1_MERGE_VDO1_DL_ASYNC, CLK_TOP_VPP, 19), + GATE_VDO1_1(CLK_VDO1_PADDING0, CLK_TOP_VPP, 20), + GATE_VDO1_1(CLK_VDO1_PADDING1, CLK_TOP_VPP, 21), + GATE_VDO1_1(CLK_VDO1_PADDING2, CLK_TOP_VPP, 22), + GATE_VDO1_1(CLK_VDO1_PADDING3, CLK_TOP_VPP, 23), + GATE_VDO1_1(CLK_VDO1_PADDING4, CLK_TOP_VPP, 24), + GATE_VDO1_1(CLK_VDO1_PADDING5, CLK_TOP_VPP, 25), + GATE_VDO1_1(CLK_VDO1_PADDING6, CLK_TOP_VPP, 26), + GATE_VDO1_1(CLK_VDO1_PADDING7, CLK_TOP_VPP, 27), + GATE_VDO1_1(CLK_VDO1_DISP_RSZ0, CLK_TOP_VPP, 28), + GATE_VDO1_1(CLK_VDO1_DISP_RSZ1, CLK_TOP_VPP, 29), + GATE_VDO1_1(CLK_VDO1_DISP_RSZ2, CLK_TOP_VPP, 30), + GATE_VDO1_1(CLK_VDO1_DISP_RSZ3, CLK_TOP_VPP, 31), + /* VDO1_2 */ + GATE_VDO1_2(CLK_VDO1_HDR_VDO_FE0, CLK_TOP_VPP, 0), + GATE_VDO1_2(CLK_VDO1_HDR_GFX_FE0, CLK_TOP_VPP, 1), + GATE_VDO1_2(CLK_VDO1_HDR_VDO_BE, CLK_TOP_VPP, 2), + GATE_VDO1_2(CLK_VDO1_HDR_VDO_FE1, CLK_TOP_VPP, 16), + GATE_VDO1_2(CLK_VDO1_HDR_GFX_FE1, CLK_TOP_VPP, 17), + GATE_VDO1_2(CLK_VDO1_DISP_MIXER, CLK_TOP_VPP, 18), + GATE_VDO1_2(CLK_VDO1_HDR_VDO_FE0_DL_ASYNC, CLK_TOP_VPP, 19), + GATE_VDO1_2(CLK_VDO1_HDR_VDO_FE1_DL_ASYNC, CLK_TOP_VPP, 20), + GATE_VDO1_2(CLK_VDO1_HDR_GFX_FE0_DL_ASYNC, CLK_TOP_VPP, 21), + GATE_VDO1_2(CLK_VDO1_HDR_GFX_FE1_DL_ASYNC, CLK_TOP_VPP, 22), + GATE_VDO1_2(CLK_VDO1_HDR_VDO_BE_DL_ASYNC, CLK_TOP_VPP, 23), + /* VDO1_3 */ + GATE_VDO1_3(CLK_VDO1_DPI0, CLK_TOP_VPP, 0), + GATE_VDO1_3(CLK_VDO1_DISP_MONITOR_DPI0, CLK_TOP_VPP, 1), + GATE_VDO1_3(CLK_VDO1_DPI1, CLK_TOP_VPP, 8), + GATE_VDO1_3(CLK_VDO1_DISP_MONITOR_DPI1, CLK_TOP_VPP, 9), + GATE_VDO1_3(CLK_VDO1_DPINTF, CLK_TOP_VPP, 16), + GATE_VDO1_3(CLK_VDO1_DISP_MONITOR_DPINTF, CLK_TOP_VPP, 17), + /* VDO1_4 */ + GATE_VDO1_4(CLK_VDO1_26M_SLOW, CLK_PAD_CLK26M, 8), + /* VDO1_5 */ + GATE_VDO1_5(CLK_VDO1_DPI1_HDMI, CLK_TOP_VPP, 0), +}; + +const struct mtk_clk_tree mt8188_vpp0_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = vpp0_clks, + .num_gates = ARRAY_SIZE(vpp0_clks), +}; + +const struct mtk_clk_tree mt8188_vpp1_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = vpp1_clks, + .num_gates = ARRAY_SIZE(vpp1_clks), +}; + +const struct mtk_clk_tree mt8188_vdo0_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = vdo0_clks, + .num_gates = ARRAY_SIZE(vdo0_clks), +}; + +const struct mtk_clk_tree mt8188_vdo1_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = vdo1_clks, + .num_gates = ARRAY_SIZE(vdo1_clks), }; -static const struct udevice_id mt8188_imp_iic_wrap_c_compat[] = { - { .compatible = "mediatek,mt8188-imp-iic-wrap-c", }, +static const struct udevice_id mt8188_apmixed_compat[] = { + { + .compatible = "mediatek,mt8188-apmixedsys", + .data = (ulong)&mt8188_apmixedsys_clk_tree, + }, { } }; -static const struct udevice_id mt8188_imp_iic_wrap_w_compat[] = { - { .compatible = "mediatek,mt8188-imp-iic-wrap-w", }, +static const struct udevice_id mt8188_topckgen_compat[] = { + { + .compatible = "mediatek,mt8188-topckgen", + .data = (ulong)&mt8188_topckgen_clk_tree, + }, { } }; -static const struct udevice_id mt8188_imp_iic_wrap_en_compat[] = { - { .compatible = "mediatek,mt8188-imp-iic-wrap-en", }, +static const struct udevice_id of_match_mt8188_clk[] = { + { + .compatible = "mediatek,mt8188-infracfg-ao", + .data = (ulong)&mt8188_infracfg_ao_clk_tree, + }, + { + .compatible = "mediatek,mt8188-pericfg-ao", + .data = (ulong)&mt8188_pericfg_ao_clk_tree, + }, + { + .compatible = "mediatek,mt8188-imp-iic-wrap-c", + .data = (ulong)&mt8188_imp_iic_wrap_c_clk_tree, + }, + { + .compatible = "mediatek,mt8188-imp-iic-wrap-w", + .data = (ulong)&mt8188_imp_iic_wrap_w_clk_tree, + }, + { + .compatible = "mediatek,mt8188-imp-iic-wrap-en", + .data = (ulong)&mt8188_imp_iic_wrap_en_clk_tree, + }, + { + .compatible = "mediatek,mt8188-vppsys0", + .data = (ulong)&mt8188_vpp0_clk_tree, + }, + { + .compatible = "mediatek,mt8188-vppsys1", + .data = (ulong)&mt8188_vpp1_clk_tree, + }, + { + .compatible = "mediatek,mt8188-vdosys0", + .data = (ulong)&mt8188_vdo0_clk_tree, + }, + { + .compatible = "mediatek,mt8188-vdosys1", + .data = (ulong)&mt8188_vdo1_clk_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8188_clk_apmixedsys) = { .name = "mt8188-apmixedsys", .id = UCLASS_CLK, .of_match = mt8188_apmixed_compat, - .probe = mt8188_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8188_clk_topckgen) = { .name = "mt8188-topckgen", .id = UCLASS_CLK, .of_match = mt8188_topckgen_compat, - .probe = mt8188_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_infracfg_ao) = { - .name = "mt8188-infracfg-ao", - .id = UCLASS_CLK, - .of_match = mt8188_infracfg_ao_compat, - .probe = mt8188_infracfg_ao_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, - .flags = DM_FLAG_PRE_RELOC, -}; - -U_BOOT_DRIVER(mtk_clk_pericfg_ao) = { - .name = "mt8188-pericfg-ao", - .id = UCLASS_CLK, - .of_match = mt8188_pericfg_ao_compat, - .probe = mt8188_pericfg_ao_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, - .flags = DM_FLAG_PRE_RELOC, -}; - -U_BOOT_DRIVER(mtk_clk_imp_iic_wrap_c) = { - .name = "mt8188-imp_iic_wrap_c", +U_BOOT_DRIVER(mt8188_clk) = { + .name = "mt8188-clk", .id = UCLASS_CLK, - .of_match = mt8188_imp_iic_wrap_c_compat, - .probe = mt8188_imp_iic_wrap_c_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, - .flags = DM_FLAG_PRE_RELOC, -}; - -U_BOOT_DRIVER(mtk_clk_imp_iic_wrap_w) = { - .name = "mt8188-imp_iic_wrap_w", - .id = UCLASS_CLK, - .of_match = mt8188_imp_iic_wrap_w_compat, - .probe = mt8188_imp_iic_wrap_w_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, - .flags = DM_FLAG_PRE_RELOC, -}; - -U_BOOT_DRIVER(mtk_clk_imp_iic_wrap_en) = { - .name = "mt8188-imp_iic_wrap_en", - .id = UCLASS_CLK, - .of_match = mt8188_imp_iic_wrap_en_compat, - .probe = mt8188_imp_iic_wrap_en_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .of_match = of_match_mt8188_clk, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt8189.c b/drivers/clk/mediatek/clk-mt8189.c index d11947ee461..15e040569e7 100644 --- a/drivers/clk/mediatek/clk-mt8189.c +++ b/drivers/clk/mediatek/clk-mt8189.c @@ -1898,6 +1898,7 @@ static const struct mtk_gate_regs vlpcfg_ao_regs = { * arbitrary parent trees. */ #define CLK_PARENT_VLP_CK CLK_PARENT_INFRASYS +#define MTK_CLK_TREE_VLP_CK MTK_CLK_TREE_INFRASYS #define GATE_VLPCFG_AO(id, parent, shift, flags) \ GATE_FLAGS(id, parent, &vlpcfg_ao_regs, shift, flags | CLK_GATE_NO_SETCLR_INV) @@ -1915,8 +1916,8 @@ 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_EXT(CLK_VLPCFG_REG_RG_DPMSRRTC_TEST, CLK_PAD_CLK32K, 22), + GATE_VLPCFG_AO_TOP(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), @@ -1939,6 +1940,7 @@ static const struct mtk_clk_tree mt8189_apmixedsys_clk_tree = { .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .plls = apmixed_plls, .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, }; static const struct mtk_clk_tree mt8189_topckgen_clk_tree = { @@ -1953,6 +1955,7 @@ static const struct mtk_clk_tree mt8189_topckgen_clk_tree = { .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), .num_gates = ARRAY_SIZE(top_gates), + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_clk_tree mt8189_vlpckgen_clk_tree = { @@ -1964,114 +1967,97 @@ static const struct mtk_clk_tree mt8189_vlpckgen_clk_tree = { .gates = vlp_ck_gates, .num_muxes = ARRAY_SIZE(vlp_ck_muxes), .num_gates = ARRAY_SIZE(vlp_ck_gates), + .type = MTK_CLK_TREE_VLP_CK, }; static const struct udevice_id mt8189_apmixed[] = { - { .compatible = "mediatek,mt8189-apmixedsys", }, + { + .compatible = "mediatek,mt8189-apmixedsys", + .data = (ulong)&mt8189_apmixedsys_clk_tree, + }, { } }; static const struct udevice_id mt8189_topckgen_compat[] = { - { .compatible = "mediatek,mt8189-topckgen", }, + { + .compatible = "mediatek,mt8189-topckgen", + .data = (ulong)&mt8189_topckgen_clk_tree, + }, { } }; static const struct udevice_id mt8189_vlpckgen[] = { - { .compatible = "mediatek,mt8189-vlpckgen", }, + { + .compatible = "mediatek,mt8189-vlpckgen", + .data = (ulong)&mt8189_vlpckgen_clk_tree, + }, { } }; -struct mt8189_gate_clk_data { - const struct mtk_gate *gates; - int num_gates; -}; - -#define GATE_CLK_DATA(name) \ -static const struct mt8189_gate_clk_data name##_data = { \ - .gates = name, .num_gates = ARRAY_SIZE(name) \ +#define GATE_CLK_TREE(_name) \ +static const struct mtk_clk_tree _name##_tree = { \ + .ext_clk_rates = ext_clock_rates, \ + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), \ + .gates = _name, \ + .num_gates = ARRAY_SIZE(_name), \ + .gates_offs = _name[0].id, \ } -GATE_CLK_DATA(perao_clks); -GATE_CLK_DATA(imp_clks); -GATE_CLK_DATA(mm_clks); -GATE_CLK_DATA(mminfra_config_clks); -GATE_CLK_DATA(ufs_config_ao_clks); -GATE_CLK_DATA(ufs_config_pdn_clks); -GATE_CLK_DATA(vlpcfg_ao_clks); +GATE_CLK_TREE(perao_clks); +GATE_CLK_TREE(imp_clks); +GATE_CLK_TREE(mm_clks); +GATE_CLK_TREE(mminfra_config_clks); +GATE_CLK_TREE(ufs_config_ao_clks); +GATE_CLK_TREE(ufs_config_pdn_clks); +GATE_CLK_TREE(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-ufscfg-ao", .data = (ulong)&ufs_config_ao_clks_data }, - { .compatible = "mediatek,mt8189-ufscfg-pdn", .data = (ulong)&ufs_config_pdn_clks_data }, - { .compatible = "mediatek,mt8189-vlpcfg-ao", .data = (ulong)&vlpcfg_ao_clks_data }, + { .compatible = "mediatek,mt8189-peri-ao", .data = (ulong)&perao_clks_tree }, + { .compatible = "mediatek,mt8189-iic-wrap", .data = (ulong)&imp_clks_tree }, + { .compatible = "mediatek,mt8189-dispsys", .data = (ulong)&mm_clks_tree }, + { .compatible = "mediatek,mt8189-mm-infra", .data = (ulong)&mminfra_config_clks_tree }, + { .compatible = "mediatek,mt8189-ufscfg-ao", .data = (ulong)&ufs_config_ao_clks_tree }, + { .compatible = "mediatek,mt8189-ufscfg-pdn", .data = (ulong)&ufs_config_pdn_clks_tree }, + { .compatible = "mediatek,mt8189-vlpcfg-ao", .data = (ulong)&vlpcfg_ao_clks_tree }, { } }; -static int mt8189_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8189_apmixedsys_clk_tree); -} - -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; - - data = (void *)dev_get_driver_data(dev); - - return mtk_common_clk_gate_init(dev, &mt8189_topckgen_clk_tree, - data->gates, data->num_gates, - data->gates[0].id); -} - -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8189_clk_apmixedsys) = { .name = "mt8189-apmixedsys", .id = UCLASS_CLK, .of_match = mt8189_apmixed, - .probe = mt8189_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8189_clk_topckgen) = { .name = "mt8189-topckgen", .id = UCLASS_CLK, .of_match = mt8189_topckgen_compat, - .probe = mt8189_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_vlpckgen) = { +U_BOOT_DRIVER(mt8189_clk_vlpckgen) = { .name = "mt8189-vlpckgen", .id = UCLASS_CLK, .of_match = mt8189_vlpckgen, - .probe = mt8189_infrasys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_infrasys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_gate) = { +U_BOOT_DRIVER(mt8189_clk_gate) = { .name = "mt8189-gate-clk", .id = UCLASS_CLK, .of_match = of_match_mt8189_clk_gate, - .probe = mt8189_clk_gate_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt8195.c b/drivers/clk/mediatek/clk-mt8195.c index 37cceb5f32b..de40821100e 100644 --- a/drivers/clk/mediatek/clk-mt8195.c +++ b/drivers/clk/mediatek/clk-mt8195.c @@ -101,6 +101,7 @@ static const struct mtk_clk_tree mt8195_apmixedsys_clk_tree = { .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .plls = apmixed_plls, .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, }; #define FIXED_CLK0(_id, _rate) \ @@ -1423,6 +1424,7 @@ static const struct mtk_clk_tree mt8195_topckgen_clk_tree = { .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), .num_gates = ARRAY_SIZE(top_cg_clks), + .type = MTK_CLK_TREE_TOPCKGEN, }; static const struct mtk_gate_regs infra_ao0_cg_regs = { @@ -1597,66 +1599,60 @@ static const struct mtk_gate infra_ao_clks[] = { static const struct mtk_clk_tree mt8195_infracfg_ao_clk_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = infra_ao_clks, + .num_gates = ARRAY_SIZE(infra_ao_clks), }; -static int mt8195_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8195_apmixedsys_clk_tree); -} - -static int mt8195_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8195_topckgen_clk_tree); -} - -static int mt8195_infra_ao_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8195_infracfg_ao_clk_tree, - infra_ao_clks, - ARRAY_SIZE(infra_ao_clks), 0); -} - static const struct udevice_id mt8195_apmixed[] = { - { .compatible = "mediatek,mt8195-apmixedsys", }, + { + .compatible = "mediatek,mt8195-apmixedsys", + .data = (ulong)&mt8195_apmixedsys_clk_tree, + }, { } }; static const struct udevice_id mt8195_topckgen_compat[] = { - { .compatible = "mediatek,mt8195-topckgen", }, + { + .compatible = "mediatek,mt8195-topckgen", + .data = (ulong)&mt8195_topckgen_clk_tree, + }, { } }; static const struct udevice_id of_match_clk_mt8195_infra_ao[] = { - { .compatible = "mediatek,mt8195-infracfg_ao", }, + { + .compatible = "mediatek,mt8195-infracfg_ao", + .data = (ulong)&mt8195_infracfg_ao_clk_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8195_clk_apmixedsys) = { .name = "mt8195-apmixedsys", .id = UCLASS_CLK, .of_match = mt8195_apmixed, - .probe = mt8195_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8195_clk_topckgen) = { .name = "mt8195-topckgen", .id = UCLASS_CLK, .of_match = mt8195_topckgen_compat, - .probe = mt8195_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_infra_ao) = { +U_BOOT_DRIVER(mt8195_clk_infra_ao) = { .name = "mt8195-infra_ao", .id = UCLASS_CLK, .of_match = of_match_clk_mt8195_infra_ao, - .probe = mt8195_infra_ao_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt8365.c b/drivers/clk/mediatek/clk-mt8365.c index eb94b86622c..3fa030d7218 100644 --- a/drivers/clk/mediatek/clk-mt8365.c +++ b/drivers/clk/mediatek/clk-mt8365.c @@ -79,6 +79,7 @@ static const struct mtk_clk_tree mt8365_apmixed_tree = { .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .plls = apmixed_plls, .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, }; /* topckgen */ @@ -595,6 +596,7 @@ static const struct mtk_clk_tree mt8365_topckgen_tree = { .num_fdivs = ARRAY_SIZE(top_divs), .num_muxes = ARRAY_SIZE(top_muxes), .num_gates = ARRAY_SIZE(top_clk_gates), + .type = MTK_CLK_TREE_TOPCKGEN, }; /* infracfg */ @@ -755,65 +757,60 @@ static const struct mtk_gate ifr_clks[] = { static const struct mtk_clk_tree mt8365_infracfg_tree = { .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = ifr_clks, + .num_gates = ARRAY_SIZE(ifr_clks), }; -static int mt8365_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8365_apmixed_tree); -} - -static int mt8365_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8365_topckgen_tree); -} - -static int mt8365_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8365_infracfg_tree, ifr_clks, - ARRAY_SIZE(ifr_clks), 0); -} - static const struct udevice_id mt8365_apmixed_compat[] = { - { .compatible = "mediatek,mt8365-apmixedsys", }, + { + .compatible = "mediatek,mt8365-apmixedsys", + .data = (ulong)&mt8365_apmixed_tree, + }, { } }; static const struct udevice_id mt8365_topckgen_compat[] = { - { .compatible = "mediatek,mt8365-topckgen", }, + { + .compatible = "mediatek,mt8365-topckgen", + .data = (ulong)&mt8365_topckgen_tree, + }, { } }; static const struct udevice_id mt8365_infracfg_compat[] = { - { .compatible = "mediatek,mt8365-infracfg", }, + { + .compatible = "mediatek,mt8365-infracfg", + .data = (ulong)&mt8365_infracfg_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8365_clk_apmixedsys) = { .name = "mt8365-apmixedsys", .id = UCLASS_CLK, .of_match = mt8365_apmixed_compat, - .probe = mt8365_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8365_clk_topckgen) = { .name = "mt8365-topckgen", .id = UCLASS_CLK, .of_match = mt8365_topckgen_compat, - .probe = mt8365_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_infracfg) = { +U_BOOT_DRIVER(mt8365_clk_infracfg) = { .name = "mt8365-infracfg", .id = UCLASS_CLK, .of_match = mt8365_infracfg_compat, - .probe = mt8365_infracfg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt8512.c b/drivers/clk/mediatek/clk-mt8512.c index d6e58be8e22..a0beae8fa5f 100644 --- a/drivers/clk/mediatek/clk-mt8512.c +++ b/drivers/clk/mediatek/clk-mt8512.c @@ -792,100 +792,97 @@ static const struct mtk_gate infra_clks[] = { GATE_INFRA5(CLK_INFRA_USB_XHCI, CLK_TOP_SSUSB_XHCI_SEL, 11), }; -static const struct mtk_clk_tree mt8512_clk_tree = { +static const struct mtk_clk_tree mt8512_apmixed_clk_tree = { .pll_parent = EXT_PARENT(CLK_PAD_CLK26M), .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .plls = apmixed_plls, + .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, +}; + +static const struct mtk_clk_tree mt8512_topckgen_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .fdivs_offs = CLK_TOP_SYSPLL1_D2, .muxes_offs = CLK_TOP_AXI_SEL, - .plls = apmixed_plls, .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, - .num_plls = ARRAY_SIZE(apmixed_plls), .num_fclks = ARRAY_SIZE(top_fixed_clks), .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_TOPCKGEN, }; -static int mt8512_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8512_clk_tree); -} - -static int mt8512_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8512_clk_tree); -} - -static int mt8512_topckgen_cg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8512_clk_tree, top_clks, - ARRAY_SIZE(top_clks), 0); -} +static const struct mtk_clk_tree mt8512_topckgen_cg_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = top_clks, + .num_gates = ARRAY_SIZE(top_clks), +}; -static int mt8512_infracfg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8512_clk_tree, infra_clks, - ARRAY_SIZE(infra_clks), 0); -} +static const struct mtk_clk_tree mt8512_infracfg_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = infra_clks, + .num_gates = ARRAY_SIZE(infra_clks), +}; static const struct udevice_id mt8512_apmixed_compat[] = { - { .compatible = "mediatek,mt8512-apmixedsys", }, + { + .compatible = "mediatek,mt8512-apmixedsys", + .data = (ulong)&mt8512_apmixed_clk_tree, + }, { } }; static const struct udevice_id mt8512_topckgen_compat[] = { - { .compatible = "mediatek,mt8512-topckgen", }, - { } -}; - -static const struct udevice_id mt8512_topckgen_cg_compat[] = { - { .compatible = "mediatek,mt8512-topckgen-cg", }, + { + .compatible = "mediatek,mt8512-topckgen", + .data = (ulong)&mt8512_topckgen_clk_tree, + }, { } }; -static const struct udevice_id mt8512_infracfg_compat[] = { - { .compatible = "mediatek,mt8512-infracfg", }, +static const struct udevice_id of_match_mt8512_clk_gate[] = { + { + .compatible = "mediatek,mt8512-topckgen-cg", + .data = (ulong)&mt8512_topckgen_cg_tree, + }, + { + .compatible = "mediatek,mt8512-infracfg", + .data = (ulong)&mt8512_infracfg_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8512_clk_apmixedsys) = { .name = "mt8512-apmixedsys", .id = UCLASS_CLK, .of_match = mt8512_apmixed_compat, - .probe = mt8512_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8512_clk_topckgen) = { .name = "mt8512-topckgen", .id = UCLASS_CLK, .of_match = mt8512_topckgen_compat, - .probe = mt8512_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen_cg) = { - .name = "mt8512-topckgen-cg", - .id = UCLASS_CLK, - .of_match = mt8512_topckgen_cg_compat, - .probe = mt8512_topckgen_cg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, - .flags = DM_FLAG_PRE_RELOC, -}; - -U_BOOT_DRIVER(mtk_clk_infracfg) = { - .name = "mt8512-infracfg", +U_BOOT_DRIVER(mt8512_clk_gate) = { + .name = "mt8512-clk-gate", .id = UCLASS_CLK, - .of_match = mt8512_infracfg_compat, - .probe = mt8512_infracfg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .of_match = of_match_mt8512_clk_gate, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c index 1070dd1551b..ea00b8dbca1 100644 --- a/drivers/clk/mediatek/clk-mt8516.c +++ b/drivers/clk/mediatek/clk-mt8516.c @@ -744,79 +744,86 @@ static const struct mtk_gate top_clks[] = { GATE_TOP5(CLK_TOP_APLL12_DIV6, CLK_TOP_APLL12_CK_DIV6, 8), }; -static const struct mtk_clk_tree mt8516_clk_tree = { +static const struct mtk_clk_tree mt8516_apmixed_clk_tree = { .pll_parent = EXT_PARENT(CLK_PAD_CLK26M), .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .plls = apmixed_plls, + .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, +}; + +static const struct mtk_clk_tree mt8516_topckgen_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .fdivs_offs = CLK_TOP_DMPLL, .muxes_offs = CLK_TOP_UART0_SEL, - .plls = apmixed_plls, .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, - .num_plls = ARRAY_SIZE(apmixed_plls), .num_fclks = ARRAY_SIZE(top_fixed_clks), .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_TOPCKGEN, }; -static int mt8516_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8516_clk_tree); -} - -static int mt8516_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8516_clk_tree); -} - -static int mt8516_topckgen_cg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8516_clk_tree, top_clks, - ARRAY_SIZE(top_clks), 0); -} +static const struct mtk_clk_tree mt8516_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = top_clks, + .num_gates = ARRAY_SIZE(top_clks), +}; static const struct udevice_id mt8516_apmixed_compat[] = { - { .compatible = "mediatek,mt8516-apmixedsys", }, + { + .compatible = "mediatek,mt8516-apmixedsys", + .data = (ulong)&mt8516_apmixed_clk_tree, + }, { } }; static const struct udevice_id mt8516_topckgen_compat[] = { - { .compatible = "mediatek,mt8516-topckgen", }, + { + .compatible = "mediatek,mt8516-topckgen", + .data = (ulong)&mt8516_topckgen_clk_tree, + }, { } }; static const struct udevice_id mt8516_topckgen_cg_compat[] = { - { .compatible = "mediatek,mt8516-topckgen-cg", }, + { + .compatible = "mediatek,mt8516-topckgen-cg", + .data = (ulong)&mt8516_clk_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8516_clk_apmixedsys) = { .name = "mt8516-apmixedsys", .id = UCLASS_CLK, .of_match = mt8516_apmixed_compat, - .probe = mt8516_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8516_clk_topckgen) = { .name = "mt8516-topckgen", .id = UCLASS_CLK, .of_match = mt8516_topckgen_compat, - .probe = mt8516_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen_cg) = { +U_BOOT_DRIVER(mt8516_clk_topckgen_cg) = { .name = "mt8516-topckgen-cg", .id = UCLASS_CLK, .of_match = mt8516_topckgen_cg_compat, - .probe = mt8516_topckgen_cg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt8518.c b/drivers/clk/mediatek/clk-mt8518.c index 2b213e720a0..4fef36f458a 100644 --- a/drivers/clk/mediatek/clk-mt8518.c +++ b/drivers/clk/mediatek/clk-mt8518.c @@ -1500,79 +1500,86 @@ static const struct mtk_gate top_clks[] = { GATE_TOP7(CLK_TOP_DISP_DPI, CLK_TOP_DISP_DPI_CK_SEL, 0), }; -static const struct mtk_clk_tree mt8518_clk_tree = { +static const struct mtk_clk_tree mt8518_apmixed_clk_tree = { .pll_parent = EXT_PARENT(CLK_PAD_CLK26M), .ext_clk_rates = ext_clock_rates, .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .plls = apmixed_plls, + .num_plls = ARRAY_SIZE(apmixed_plls), + .type = MTK_CLK_TREE_APMIXED, +}; + +static const struct mtk_clk_tree mt8518_topckgen_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), .fdivs_offs = CLK_TOP_DMPLL, .muxes_offs = CLK_TOP_UART0_SEL, - .plls = apmixed_plls, .fclks = top_fixed_clks, .fdivs = top_fixed_divs, .muxes = top_muxes, - .num_plls = ARRAY_SIZE(apmixed_plls), .num_fclks = ARRAY_SIZE(top_fixed_clks), .num_fdivs = ARRAY_SIZE(top_fixed_divs), .num_muxes = ARRAY_SIZE(top_muxes), + .type = MTK_CLK_TREE_TOPCKGEN, }; -static int mt8518_apmixedsys_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8518_clk_tree); -} - -static int mt8518_topckgen_probe(struct udevice *dev) -{ - return mtk_common_clk_init(dev, &mt8518_clk_tree); -} - -static int mt8518_topckgen_cg_probe(struct udevice *dev) -{ - return mtk_common_clk_gate_init(dev, &mt8518_clk_tree, top_clks, - ARRAY_SIZE(top_clks), 0); -} +static const struct mtk_clk_tree mt8518_clk_tree = { + .ext_clk_rates = ext_clock_rates, + .num_ext_clks = ARRAY_SIZE(ext_clock_rates), + .gates = top_clks, + .num_gates = ARRAY_SIZE(top_clks), +}; static const struct udevice_id mt8518_apmixed_compat[] = { - { .compatible = "mediatek,mt8518-apmixedsys", }, + { + .compatible = "mediatek,mt8518-apmixedsys", + .data = (ulong)&mt8518_apmixed_clk_tree, + }, { } }; static const struct udevice_id mt8518_topckgen_compat[] = { - { .compatible = "mediatek,mt8518-topckgen", }, + { + .compatible = "mediatek,mt8518-topckgen", + .data = (ulong)&mt8518_topckgen_clk_tree, + }, { } }; static const struct udevice_id mt8518_topckgen_cg_compat[] = { - { .compatible = "mediatek,mt8518-topckgen-cg", }, + { + .compatible = "mediatek,mt8518-topckgen-cg", + .data = (ulong)&mt8518_clk_tree, + }, { } }; -U_BOOT_DRIVER(mtk_clk_apmixedsys) = { +U_BOOT_DRIVER(mt8518_clk_apmixedsys) = { .name = "mt8518-apmixedsys", .id = UCLASS_CLK, .of_match = mt8518_apmixed_compat, - .probe = mt8518_apmixedsys_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_apmixedsys_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen) = { +U_BOOT_DRIVER(mt8518_clk_topckgen) = { .name = "mt8518-topckgen", .id = UCLASS_CLK, .of_match = mt8518_topckgen_compat, - .probe = mt8518_topckgen_probe, + .probe = mtk_clk_probe, .priv_auto = sizeof(struct mtk_clk_priv), .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; -U_BOOT_DRIVER(mtk_clk_topckgen_cg) = { +U_BOOT_DRIVER(mt8518_clk_topckgen_cg) = { .name = "mt8518-topckgen-cg", .id = UCLASS_CLK, .of_match = mt8518_topckgen_cg_compat, - .probe = mt8518_topckgen_cg_probe, - .priv_auto = sizeof(struct mtk_cg_priv), - .ops = &mtk_clk_gate_ops, + .probe = mtk_clk_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 9d0a6cd79cf..13c248c93a6 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -9,6 +9,7 @@ #include <clk-uclass.h> #include <div64.h> #include <dm.h> +#include <dm/device-internal.h> #include <asm/io.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -34,6 +35,88 @@ #define SCP_AXICK_DCM_DIS_EN BIT(0) #define SCP_AXICK_26M_SEL_EN BIT(4) +static struct udevice *mtk_clk_providers[MTK_CLK_TREE_NUM_TYPES]; + +static bool mtk_clk_tree_type_is_provider(enum mtk_clk_tree_type type) +{ + return type != MTK_CLK_TREE_NONE && type < MTK_CLK_TREE_NUM_TYPES; +} + +static enum mtk_clk_tree_type mtk_clk_tree_type_from_parent_flags(u16 flags) +{ + switch (flags & CLK_PARENT_MASK) { + case CLK_PARENT_APMIXED: + return MTK_CLK_TREE_APMIXED; + case CLK_PARENT_TOPCKGEN: + return MTK_CLK_TREE_TOPCKGEN; + case CLK_PARENT_INFRASYS: + return MTK_CLK_TREE_INFRASYS; + default: + return MTK_CLK_TREE_NONE; + } +} + +static struct udevice *mtk_clk_tree_get_provider(enum mtk_clk_tree_type type) +{ + if (!mtk_clk_tree_type_is_provider(type)) + return NULL; + + if (!mtk_clk_providers[type]) { + struct udevice *dev; + struct uclass *uc; + int ret; + + /* Lazily probe and register the requested provider. */ + ret = uclass_get(UCLASS_CLK, &uc); + if (ret) + return ERR_PTR(ret); + + uclass_foreach_dev(dev, uc) { + const struct mtk_clk_tree *tree; + const void *ops; + + ops = dev_get_driver_ops(dev); + if (ops != &mtk_clk_apmixedsys_ops && + ops != &mtk_clk_fixed_pll_ops && + ops != &mtk_clk_topckgen_ops && + ops != &mtk_clk_infrasys_ops) + continue; + + tree = (const void *)dev_get_driver_data(dev); + if (tree->type != type) + continue; + + /* Probe will add it to mtk_clk_providers[type]. */ + ret = device_probe(dev); + if (ret) + return ERR_PTR(ret); + + break; + } + } + + return mtk_clk_providers[type] ?: ERR_PTR(-ENOENT); +} + +static struct udevice *mtk_clk_parent_get_provider(u16 flags) +{ + return mtk_clk_tree_get_provider(mtk_clk_tree_type_from_parent_flags(flags)); +} + +static int mtk_clk_tree_register_provider(struct udevice *dev, + const struct mtk_clk_tree *tree) +{ + if (!mtk_clk_tree_type_is_provider(tree->type)) + return 0; + + if (mtk_clk_providers[tree->type]) + return -EEXIST; + + mtk_clk_providers[tree->type] = dev; + + return 0; +} + /* shared functions */ static const int mtk_common_clk_of_xlate(struct clk *clk, @@ -207,50 +290,16 @@ static ulong mtk_clk_find_parent_rate(struct clk *clk, int id, static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk, const int parent, u16 flags) { - struct udevice *parent_dev; - - switch (flags & CLK_PARENT_MASK) { - case CLK_PARENT_APMIXED: - /* APMIXEDSYS can be parent or grandparent. */ - if (dev_get_driver_ops(clk->dev) == &mtk_clk_apmixedsys_ops || - dev_get_driver_ops(clk->dev) == &mtk_clk_fixed_pll_ops) { - parent_dev = clk->dev; - } else if (dev_get_driver_ops(priv->parent) == &mtk_clk_apmixedsys_ops || - dev_get_driver_ops(priv->parent) == &mtk_clk_fixed_pll_ops) { - parent_dev = priv->parent; - } else { - struct udevice *grandparent_dev = dev_get_parent(priv->parent); - - if (dev_get_driver_ops(grandparent_dev) == &mtk_clk_apmixedsys_ops || - dev_get_driver_ops(grandparent_dev) == &mtk_clk_fixed_pll_ops) - parent_dev = grandparent_dev; - else - return -EINVAL; - } - break; - case CLK_PARENT_TOPCKGEN: - if (dev_get_driver_ops(clk->dev) == &mtk_clk_topckgen_ops) - parent_dev = clk->dev; - else if (dev_get_driver_ops(priv->parent) == &mtk_clk_topckgen_ops) - parent_dev = priv->parent; - else - return -EINVAL; + struct udevice *pdev; - break; - case CLK_PARENT_INFRASYS: - if (dev_get_driver_ops(clk->dev) != &mtk_clk_infrasys_ops) - return -EINVAL; - - parent_dev = clk->dev; - break; - case CLK_PARENT_EXT: + if ((flags & CLK_PARENT_MASK) == CLK_PARENT_EXT) return mtk_ext_clock_get_rate(priv->tree, parent); - default: - parent_dev = NULL; - break; - } - return mtk_clk_find_parent_rate(clk, parent, parent_dev); + pdev = mtk_clk_parent_get_provider(flags); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return mtk_clk_find_parent_rate(clk, parent, pdev); } static ulong mtk_clk_mux_get_rate(struct clk *clk, u32 off) @@ -306,11 +355,6 @@ static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent, } #if CONFIG_IS_ENABLED(CMD_CLK) -static void mtk_clk_print_dev_parent(struct udevice *parent) -{ - printf("Parent device: %s %s\n", parent->driver->name, parent->name); -} - static void mtk_clk_print_mapped_id(int unmapped_id, int mapped_id, bool has_map) { /* @@ -663,8 +707,6 @@ static void mtk_apmixedsys_dump(struct udevice *dev) const struct mtk_clk_tree *tree = priv->tree; u32 i; - mtk_clk_print_dev_parent(priv->parent); - for (i = 0; i < tree->num_plls; i++) { const struct mtk_pll_data *pll = &tree->plls[i]; @@ -869,8 +911,6 @@ static void mtk_topckgen_dump(struct udevice *dev) const struct mtk_clk_tree *tree = priv->tree; u32 i; - mtk_clk_print_dev_parent(priv->parent); - for (i = 0; i < tree->num_fclks; i++) { const struct mtk_fixed_clk *fclk = &tree->fclks[i]; @@ -1005,8 +1045,6 @@ static void mtk_infrasys_dump(struct udevice *dev) const struct mtk_clk_tree *tree = priv->tree; u32 i; - mtk_clk_print_dev_parent(priv->parent); - for (i = 0; i < tree->num_fdivs; i++) { const struct mtk_fixed_factor *fdiv = &tree->fdivs[i]; @@ -1036,99 +1074,6 @@ static void mtk_infrasys_dump(struct udevice *dev) } #endif -/* CG functions */ - -static const int mtk_clk_gate_of_xlate(struct clk *clk, - struct ofnode_phandle_args *args) -{ - struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - const struct mtk_clk_tree *tree = priv->tree; - int ret; - - ret = mtk_common_clk_of_xlate(clk, args, tree); - if (ret) - return ret; - - if (clk->id >= priv->gates_offs && - clk->id < priv->gates_offs + priv->num_gates) - return 0; - - return -ENOENT; -} - -static int mtk_clk_gate_enable(struct clk *clk) -{ - struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - const struct mtk_gate *gate; - - if (clk->id < priv->gates_offs) - return -EINVAL; - - gate = &priv->gates[clk->id - priv->gates_offs]; - return mtk_gate_enable(priv->base, gate); -} - -static int mtk_clk_gate_disable(struct clk *clk) -{ - struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - const struct mtk_gate *gate; - - if (clk->id < priv->gates_offs) - return -EINVAL; - - gate = &priv->gates[clk->id - priv->gates_offs]; - return mtk_gate_disable(priv->base, gate); -} - -static ulong mtk_clk_gate_get_rate(struct clk *clk) -{ - struct mtk_cg_priv *priv = dev_get_priv(clk->dev); - struct udevice *parent = priv->parent; - const struct mtk_gate *gate; - - if (clk->id < priv->gates_offs) - return -EINVAL; - - gate = &priv->gates[clk->id - priv->gates_offs]; - /* - * With requesting a TOPCKGEN parent, make sure the dev parent - * is actually topckgen. This might not be the case for an - * infracfg-ao implementation where: - * parent = infracfg - * parent->parent = topckgen - */ - if (gate->flags & CLK_PARENT_TOPCKGEN && - parent->driver != DM_DRIVER_GET(mtk_clk_topckgen)) { - priv = dev_get_priv(parent); - parent = priv->parent; - } else if (gate->flags & CLK_PARENT_EXT) { - return mtk_ext_clock_get_rate(priv->tree, gate->parent); - } - - return mtk_clk_find_parent_rate(clk, gate->parent, parent); -} - -#if CONFIG_IS_ENABLED(CMD_CLK) -static void mtk_clk_gate_dump(struct udevice *dev) -{ - struct mtk_cg_priv *priv = dev_get_priv(dev); - const struct mtk_clk_tree *tree = priv->tree; - u32 i; - - mtk_clk_print_dev_parent(priv->parent); - - for (i = 0; i < priv->num_gates; i++) { - const struct mtk_gate *gate = &priv->gates[i]; - - printf("[GATE%u] DT: %u", i, gate->id); - mtk_clk_print_mapped_id(gate->id, i + priv->gates_offs, tree->id_offs_map); - mtk_clk_print_rate(dev, i + priv->gates_offs); - mtk_clk_print_single_parent(gate->parent, gate->flags); - printf("\n"); - } -} -#endif - const struct clk_ops mtk_clk_apmixedsys_ops = { .of_xlate = mtk_apmixedsys_of_xlate, .enable = mtk_apmixedsys_enable, @@ -1172,81 +1117,16 @@ const struct clk_ops mtk_clk_infrasys_ops = { #endif }; -const struct clk_ops mtk_clk_gate_ops = { - .of_xlate = mtk_clk_gate_of_xlate, - .enable = mtk_clk_gate_enable, - .disable = mtk_clk_gate_disable, - .get_rate = mtk_clk_gate_get_rate, -#if CONFIG_IS_ENABLED(CMD_CLK) - .dump = mtk_clk_gate_dump, -#endif -}; - -static int mtk_common_clk_init_drv(struct udevice *dev, - const struct mtk_clk_tree *tree, - const struct driver *drv) +int mtk_clk_probe(struct udevice *dev) { struct mtk_clk_priv *priv = dev_get_priv(dev); - struct udevice *parent; - int ret; + const struct mtk_clk_tree *tree = (void *)dev_get_driver_data(dev); priv->base = dev_read_addr_ptr(dev); if (!priv->base) return -ENOENT; - ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent); - if (ret || !parent) { - ret = uclass_get_device_by_driver(UCLASS_CLK, drv, &parent); - if (ret || !parent) - return -ENOENT; - } - - priv->parent = parent; priv->tree = tree; - return 0; -} - -int mtk_common_clk_init(struct udevice *dev, - const struct mtk_clk_tree *tree) -{ - return mtk_common_clk_init_drv(dev, tree, - DM_DRIVER_GET(mtk_clk_apmixedsys)); -} - -int mtk_common_clk_infrasys_init(struct udevice *dev, - const struct mtk_clk_tree *tree) -{ - return mtk_common_clk_init_drv(dev, tree, - DM_DRIVER_GET(mtk_clk_topckgen)); -} - -int mtk_common_clk_gate_init(struct udevice *dev, - const struct mtk_clk_tree *tree, - const struct mtk_gate *gates, int num_gates, - int gates_offs) -{ - struct mtk_cg_priv *priv = dev_get_priv(dev); - struct udevice *parent; - int ret; - - priv->base = dev_read_addr_ptr(dev); - if (!priv->base) - return -ENOENT; - - ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent); - if (ret || !parent) { - ret = uclass_get_device_by_driver(UCLASS_CLK, - DM_DRIVER_GET(mtk_clk_topckgen), &parent); - if (ret || !parent) - return -ENOENT; - } - - priv->parent = parent; - priv->tree = tree; - priv->gates = gates; - priv->num_gates = num_gates; - priv->gates_offs = gates_offs; - - return 0; + return mtk_clk_tree_register_provider(dev, tree); } diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index b39a62edc43..9244542a2a5 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -32,6 +32,15 @@ #define ETHSYS_HIFSYS_RST_CTRL_OFS 0x34 +/* These get matched to CLK_PARENT_* when looking up parent clocks. */ +enum mtk_clk_tree_type { + MTK_CLK_TREE_NONE, + MTK_CLK_TREE_APMIXED, + MTK_CLK_TREE_TOPCKGEN, + MTK_CLK_TREE_INFRASYS, + MTK_CLK_TREE_NUM_TYPES +}; + /* struct mtk_pll_data - hardware-specific PLLs data */ struct mtk_pll_data { /* unmapped ID of clock */ @@ -261,36 +270,20 @@ struct mtk_clk_tree { const int num_muxes; const int num_gates; u32 flags; + /* Set this if this tree provides a specific type for parent lookup. */ + enum mtk_clk_tree_type type; }; struct mtk_clk_priv { - struct udevice *parent; void __iomem *base; const struct mtk_clk_tree *tree; }; -struct mtk_cg_priv { - struct udevice *parent; - void __iomem *base; - const struct mtk_clk_tree *tree; - const struct mtk_gate *gates; - int num_gates; - int gates_offs; -}; - extern const struct clk_ops mtk_clk_apmixedsys_ops; extern const struct clk_ops mtk_clk_fixed_pll_ops; extern const struct clk_ops mtk_clk_topckgen_ops; extern const struct clk_ops mtk_clk_infrasys_ops; -extern const struct clk_ops mtk_clk_gate_ops; -int mtk_common_clk_init(struct udevice *dev, - const struct mtk_clk_tree *tree); -int mtk_common_clk_infrasys_init(struct udevice *dev, - const struct mtk_clk_tree *tree); -int mtk_common_clk_gate_init(struct udevice *dev, - const struct mtk_clk_tree *tree, - const struct mtk_gate *gates, int num_gates, - int gates_offs); +int mtk_clk_probe(struct udevice *dev); #endif /* __DRV_CLK_MTK_H */ diff --git a/drivers/clk/renesas/r8a78000-cpg.c b/drivers/clk/renesas/r8a78000-cpg.c index e9ca06476f6..67d820bbde8 100644 --- a/drivers/clk/renesas/r8a78000-cpg.c +++ b/drivers/clk/renesas/r8a78000-cpg.c @@ -105,6 +105,7 @@ struct clk_map_in { #define GEN5_SCMI_SDK_4_30 0x010c0000 #define GEN5_SCMI_SDK_4_31 0x010d0000 #define GEN5_SCMI_SDK_4_32 0x010e0000 +#define GEN5_SCMI_SDK_4_36 0x01100000 static const struct clk_map_in gen5_clk_map_dt_sdk_4_28[] = { { SCP_CLOCK_ID_MDLC_UFS0, 202 }, @@ -186,7 +187,8 @@ static int gen5_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) map = gen5_clk_map_dt_sdk_4_28; map_size = ARRAY_SIZE(gen5_clk_map_dt_sdk_4_28); } else if (priv->basever == GEN5_SCMI_SDK_4_31 || - priv->basever == GEN5_SCMI_SDK_4_32) { + priv->basever == GEN5_SCMI_SDK_4_32 || + priv->basever == GEN5_SCMI_SDK_4_36) { map = gen5_clk_map_dt_sdk_4_31; map_size = ARRAY_SIZE(gen5_clk_map_dt_sdk_4_31); } else { diff --git a/drivers/clk/spacemit/Kconfig b/drivers/clk/spacemit/Kconfig new file mode 100644 index 00000000000..25a3c1e4a45 --- /dev/null +++ b/drivers/clk/spacemit/Kconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2025, Junhui Liu <[email protected]> + +config CLK_SPACEMIT + bool "Clock support for SpacemiT SoCs" + depends on CLK || COMPILE_TEST + select REGMAP + select LIB_RATIONAL + help + This enables support clock driver for Spacemit SoC + family. + +if CLK_SPACEMIT + +config CLK_SPACEMIT_K1 + bool "SpacemiT K1 clock support" + select CLK_CCF + help + This enables support clock driver for Spacemit K1 SoC. + It's based on Common Clock Framework. + +endif diff --git a/drivers/clk/spacemit/Makefile b/drivers/clk/spacemit/Makefile new file mode 100644 index 00000000000..824e94d1f74 --- /dev/null +++ b/drivers/clk/spacemit/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2025 Junhui Liu <[email protected]> + +obj-$(CONFIG_CLK_SPACEMIT) += clk_ddn.o clk_mix.o clk_pll.o + +obj-$(CONFIG_CLK_SPACEMIT_K1) += clk-k1.o diff --git a/drivers/clk/spacemit/clk-k1.c b/drivers/clk/spacemit/clk-k1.c new file mode 100644 index 00000000000..07adc126ee3 --- /dev/null +++ b/drivers/clk/spacemit/clk-k1.c @@ -0,0 +1,1878 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/lists.h> +#include <regmap.h> +#include <linux/clk-provider.h> +#include <soc/spacemit/k1-reset.h> +#include <soc/spacemit/k1-syscon.h> + +#include "clk_common.h" +#include "clk_ddn.h" +#include "clk_mix.h" +#include "clk_pll.h" + +#include <dt-bindings/clock/spacemit,k1-syscon.h> + +#define K1_PLL_ID 100 +#define K1_MPMU_ID 200 +#define K1_APBC_ID 300 +#define K1_APMU_ID 400 + +struct spacemit_ccu_data { + struct clk **clks; + size_t num; + unsigned long offset; +}; + +/* APBS clocks start, APBS region contains and only contains all PLL clocks */ + +/* + * PLL{1,2} must run at fixed frequencies to provide clocks in correct rates for + * peripherals. + */ +static const struct ccu_pll_rate_tbl pll1_rate_tbl[] = { + CCU_PLL_RATE(2457600000UL, 0x0050dd64, 0x330ccccd), +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +CCU_PLL_DEFINE(CLK_PLL1, pll1, pll1, "clock-24m", pll1_rate_tbl, + APBS_PLL1_SWCR1, APBS_PLL1_SWCR3, MPMU_POSR, POSR_PLL1_LOCK, + CLK_SET_RATE_GATE); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D4, pll1_d4, pll1_d4, "pll1", APBS_PLL1_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D6, pll1_d6, pll1_d6, "pll1", APBS_PLL1_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_FLAGS_DEFINE(CLK_PLL1_D8, pll1_d8, pll1_d8, "pll1", + APBS_PLL1_SWCR2, BIT(7), 8, 1, CLK_IS_CRITICAL); +#else +static const struct ccu_pll_rate_tbl pll2_rate_tbl[] = { + CCU_PLL_RATE(3000000000UL, 0x0050dd66, 0x3fe00000), +}; + +static const struct ccu_pll_rate_tbl pll3_rate_tbl[] = { + CCU_PLL_RATE(1600000000UL, 0x0050cd61, 0x43eaaaab), + CCU_PLL_RATE(1800000000UL, 0x0050cd61, 0x4b000000), + CCU_PLL_RATE(2000000000UL, 0x0050dd62, 0x2aeaaaab), + CCU_PLL_RATE(2457600000UL, 0x0050dd64, 0x330ccccd), + CCU_PLL_RATE(3000000000UL, 0x0050dd66, 0x3fe00000), + CCU_PLL_RATE(3200000000UL, 0x0050dd67, 0x43eaaaab), +}; + +CCU_PLL_DEFINE(CLK_PLL1, pll1, pll1, "clock-24m", pll1_rate_tbl, + APBS_PLL1_SWCR1, APBS_PLL1_SWCR3, MPMU_POSR, POSR_PLL1_LOCK, + CLK_SET_RATE_GATE); +CCU_PLL_DEFINE(CLK_PLL2, pll2, pll2, "clock-24m", pll2_rate_tbl, + APBS_PLL2_SWCR1, APBS_PLL2_SWCR3, MPMU_POSR, POSR_PLL2_LOCK, + CLK_SET_RATE_GATE); +CCU_PLL_DEFINE(CLK_PLL3, pll3, pll3, "clock-24m", pll3_rate_tbl, + APBS_PLL3_SWCR1, APBS_PLL3_SWCR3, MPMU_POSR, POSR_PLL3_LOCK, + CLK_SET_RATE_GATE); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D2, pll1_d2, pll1_d2, "pll1", APBS_PLL1_SWCR2, + BIT(1), 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D3, pll1_d3, pll1_d3, "pll1", APBS_PLL1_SWCR2, + BIT(2), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D4, pll1_d4, pll1_d4, "pll1", APBS_PLL1_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D5, pll1_d5, pll1_d5, "pll1", APBS_PLL1_SWCR2, + BIT(4), 5, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D6, pll1_d6, pll1_d6, "pll1", APBS_PLL1_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D7, pll1_d7, pll1_d7, "pll1", APBS_PLL1_SWCR2, + BIT(6), 7, 1); +CCU_FACTOR_GATE_FLAGS_DEFINE(CLK_PLL1_D8, pll1_d8, pll1_d8, "pll1", + APBS_PLL1_SWCR2, BIT(7), 8, 1, CLK_IS_CRITICAL); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D11, pll1_d11_223p4, pll1_d11_223p4, "pll1", + APBS_PLL1_SWCR2, BIT(15), 11, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D13, pll1_d13_189, pll1_d13_189, "pll1", + APBS_PLL1_SWCR2, BIT(16), 13, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D23, pll1_d23_106p8, pll1_d23_106p8, "pll1", + APBS_PLL1_SWCR2, BIT(20), 23, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D64, pll1_d64_38p4, pll1_d64_38p4, "pll1", + APBS_PLL1_SWCR2, BIT(0), 64, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D10_AUD, pll1_aud_245p7, pll1_aud_245p7, "pll1", + APBS_PLL1_SWCR2, BIT(10), 10, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D100_AUD, pll1_aud_24p5, pll1_aud_24p5, "pll1", + APBS_PLL1_SWCR2, BIT(11), 100, 1); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D1, pll2_d1, pll2_d1, "pll2", APBS_PLL2_SWCR2, + BIT(0), 1, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D2, pll2_d2, pll2_d2, "pll2", APBS_PLL2_SWCR2, + BIT(1), 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D3, pll2_d3, pll2_d3, "pll2", APBS_PLL2_SWCR2, + BIT(2), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D4, pll2_d4, pll2_d4, "pll2", APBS_PLL2_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D5, pll2_d5, pll2_d5, "pll2", APBS_PLL2_SWCR2, + BIT(4), 5, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D6, pll2_d6, pll2_d6, "pll2", APBS_PLL2_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D7, pll2_d7, pll2_d7, "pll2", APBS_PLL2_SWCR2, + BIT(6), 7, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D8, pll2_d8, pll2_d8, "pll2", APBS_PLL2_SWCR2, + BIT(7), 8, 1); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D1, pll3_d1, pll3_d1, "pll3", APBS_PLL3_SWCR2, + BIT(0), 1, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D2, pll3_d2, pll3_d2, "pll3", APBS_PLL3_SWCR2, + BIT(1), 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D3, pll3_d3, pll3_d3, "pll3", APBS_PLL3_SWCR2, + BIT(2), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D4, pll3_d4, pll3_d4, "pll3", APBS_PLL3_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D5, pll3_d5, pll3_d5, "pll3", APBS_PLL3_SWCR2, + BIT(4), 5, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D6, pll3_d6, pll3_d6, "pll3", APBS_PLL3_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D7, pll3_d7, pll3_d7, "pll3", APBS_PLL3_SWCR2, + BIT(6), 7, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D8, pll3_d8, pll3_d8, "pll3", APBS_PLL3_SWCR2, + BIT(7), 8, 1); + +CCU_FACTOR_DEFINE(CLK_PLL3_20, pll3_20, pll3_20, "pll3_d8", 20, 1); +CCU_FACTOR_DEFINE(CLK_PLL3_40, pll3_40, pll3_40, "pll3_d8", 10, 1); +CCU_FACTOR_DEFINE(CLK_PLL3_80, pll3_80, pll3_80, "pll3_d8", 5, 1); +#endif +/* APBS clocks end */ + +/* MPMU clocks start */ +#if IS_ENABLED(CONFIG_SPL_BUILD) +CCU_GATE_DEFINE(CLK_PLL1_614, pll1_d4_614p4, pll1_d4_614p4, "pll1_d4", + MPMU_ACGR, BIT(15), 0); +CCU_GATE_DEFINE(CLK_PLL1_409P6, pll1_d6_409p6, pll1_d6_409p6, "pll1_d6", + MPMU_ACGR, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8", + MPMU_ACGR, BIT(13), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_31P5, pll1_d78_31p5, pll1_d78_31p5, + "pll1_d4", MPMU_ACGR, BIT(6), 39, 2); +CCU_DDN_DEFINE(CLK_SLOW_UART2, slow_uart2_48, slow_uart2_48, + "pll1_d4_614p4", MPMU_SUCCR_1, + CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0); +#else +CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8", + MPMU_ACGR, BIT(13), 0); + +CCU_FACTOR_DEFINE(CLK_PLL1_76P8, pll1_d32_76p8, pll1_d32_76p8, "pll1_d8_307p2", + 4, 1); + +CCU_FACTOR_DEFINE(CLK_PLL1_61P44, pll1_d40_61p44, pll1_d40_61p44, + "pll1_d8_307p2", 5, 1); + +CCU_FACTOR_DEFINE(CLK_PLL1_153P6, pll1_d16_153p6, pll1_d16_153p6, + "pll1_d8", 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_102P4, pll1_d24_102p4, pll1_d24_102p4, + "pll1_d8", MPMU_ACGR, BIT(12), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_51P2, pll1_d48_51p2, pll1_d48_51p2, + "pll1_d8", MPMU_ACGR, BIT(7), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_51P2_AP, pll1_d48_51p2_ap, pll1_d48_51p2_ap, + "pll1_d8", MPMU_ACGR, BIT(11), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_57P6, pll1_m3d128_57p6, pll1_m3d128_57p6, + "pll1_d8", MPMU_ACGR, BIT(8), 16, 3); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_25P6, pll1_d96_25p6, pll1_d96_25p6, + "pll1_d8", MPMU_ACGR, BIT(4), 12, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_12P8, pll1_d192_12p8, pll1_d192_12p8, + "pll1_d8", MPMU_ACGR, BIT(3), 24, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_12P8_WDT, pll1_d192_12p8_wdt, pll1_d192_12p8_wdt, + "pll1_d8", MPMU_ACGR, BIT(19), 24, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_6P4, pll1_d384_6p4, pll1_d384_6p4, + "pll1_d8", MPMU_ACGR, BIT(2), 48, 1); + +CCU_FACTOR_DEFINE(CLK_PLL1_3P2, pll1_d768_3p2, pll1_d768_3p2, + "pll1_d384_6p4", 2, 1); +CCU_FACTOR_DEFINE(CLK_PLL1_1P6, pll1_d1536_1p6, pll1_d1536_1p6, + "pll1_d384_6p4", 4, 1); +CCU_FACTOR_DEFINE(CLK_PLL1_0P8, pll1_d3072_0p8, pll1_d3072_0p8, + "pll1_d384_6p4", 8, 1); + +CCU_GATE_DEFINE(CLK_PLL1_409P6, pll1_d6_409p6, pll1_d6_409p6, "pll1_d6", + MPMU_ACGR, BIT(0), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_204P8, pll1_d12_204p8, pll1_d12_204p8, + "pll1_d6", MPMU_ACGR, BIT(5), 2, 1); + +CCU_GATE_DEFINE(CLK_PLL1_491, pll1_d5_491p52, pll1_d5_491p52, "pll1_d5", + MPMU_ACGR, BIT(21), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_245P76, pll1_d10_245p76, pll1_d10_245p76, + "pll1_d5", MPMU_ACGR, BIT(18), 2, 1); + +CCU_GATE_DEFINE(CLK_PLL1_614, pll1_d4_614p4, pll1_d4_614p4, "pll1_d4", + MPMU_ACGR, BIT(15), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_47P26, pll1_d52_47p26, pll1_d52_47p26, + "pll1_d4", MPMU_ACGR, BIT(10), 13, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_31P5, pll1_d78_31p5, pll1_d78_31p5, + "pll1_d4", MPMU_ACGR, BIT(6), 39, 2); + +CCU_GATE_DEFINE(CLK_PLL1_819, pll1_d3_819p2, pll1_d3_819p2, "pll1_d3", + MPMU_ACGR, BIT(14), 0); + +CCU_GATE_DEFINE(CLK_PLL1_1228, pll1_d2_1228p8, pll1_d2_1228p8, "pll1_d2", + MPMU_ACGR, BIT(16), 0); + +CCU_GATE_DEFINE(CLK_SLOW_UART, slow_uart, slow_uart, "clock-32k", MPMU_ACGR, + BIT(1), CLK_IGNORE_UNUSED); +CCU_DDN_DEFINE(CLK_SLOW_UART1, slow_uart1_14p74, slow_uart1_14p74, + "pll1_d16_153p6", MPMU_SUCCR, + CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0); +CCU_DDN_DEFINE(CLK_SLOW_UART2, slow_uart2_48, slow_uart2_48, + "pll1_d4_614p4", MPMU_SUCCR_1, + CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0); + +CCU_GATE_DEFINE(CLK_WDT, wdt_clk, wdt_clk, "pll1_d96_25p6", MPMU_WDTPCR, + BIT(1), 0); + +CCU_FACTOR_DEFINE(CLK_I2S_153P6, i2s_153p6, i2s_153p6, "pll1_d8_307p2", 2, 1); + +static const char * const i2s_153p6_base_parents[] = { + "i2s_153p6", + "pll1_d8_307p2", +}; + +CCU_MUX_DEFINE(CLK_I2S_153P6_BASE, i2s_153p6_base, i2s_153p6_base, + i2s_153p6_base_parents, ARRAY_SIZE(i2s_153p6_base_parents), + MPMU_FCCR, 29, 1, 0); + +static const char * const i2s_sysclk_src_parents[] = { + "pll1_d96_25p6", + "i2s_153p6_base" +}; + +CCU_MUX_GATE_DEFINE(CLK_I2S_SYSCLK_SRC, i2s_sysclk_src, i2s_sysclk_src, + i2s_sysclk_src_parents, ARRAY_SIZE(i2s_sysclk_src_parents), + MPMU_ISCCR, 30, 1, BIT(31), 0); + +CCU_DDN_DEFINE(CLK_I2S_SYSCLK, i2s_sysclk, i2s_sysclk, "i2s_sysclk_src", + MPMU_ISCCR, CCU_DDN_MASK(0, 15), 0, CCU_DDN_MASK(15, 12), + 15, 1, 0); + +CCU_FACTOR_DEFINE(CLK_I2S_BCLK_FACTOR, i2s_bclk_factor, i2s_bclk_factor, + "i2s_sysclk", 2, 1); +/* + * Divider of i2s_bclk always implies a 1/2 factor, which is + * described by i2s_bclk_factor. + */ +CCU_DIV_GATE_DEFINE(CLK_I2S_BCLK, i2s_bclk, i2s_bclk, "i2s_bclk_factor", + MPMU_ISCCR, 27, 2, BIT(29), 0); + +static const char * const apb_parents[] = { + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d96_25p6", + "pll1_d24_102p4", +}; + +CCU_MUX_DEFINE(CLK_APB, apb_clk, apb_clk, apb_parents, ARRAY_SIZE(apb_parents), + MPMU_APBCSCR, 0, 2, 0); + +CCU_GATE_DEFINE(CLK_WDT_BUS, wdt_bus_clk, wdt_bus_clk, "apb_clk", MPMU_WDTPCR, + BIT(0), 0); + +CCU_GATE_DEFINE(CLK_RIPC, ripc_clk, ripc_clk, "apb_clk", MPMU_RIPCCR, 0x1, 0); +#endif +/* MPMU clocks end */ + +/* APBC clocks start */ +#if IS_ENABLED(CONFIG_SPL_BUILD) +static const char * const uart_clk_parents[] = { + "clock-dummy", + "clock-dummy", + "slow_uart2_48", +}; + +CCU_MUX_GATE_DEFINE(CLK_UART0, uart0_clk, uart0_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART1_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +static const char * const twsi_parents[] = { + "pll1_d78_31p5", +}; + +CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI2_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +/* + * APBC_TWSI8_CLK_RST has a quirk that reading always results in zero. + * Combine functional and bus bits together as a gate to avoid sharing the + * write-only register between different clock hardwares. + */ +CCU_GATE_DEFINE(CLK_TWSI8, twsi8_clk, twsi8_clk, "pll1_d78_31p5", + APBC_TWSI8_CLK_RST, BIT(1) | BIT(0), 0); + +#else +static const char * const uart_clk_parents[] = { + "pll1_m3d128_57p6", + "slow_uart1_14p74", + "slow_uart2_48", +}; + +CCU_MUX_GATE_DEFINE(CLK_UART0, uart0_clk, uart0_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART1_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +static const char * const twsi_parents[] = { + "pll1_d78_31p5", + "pll1_d48_51p2", + "pll1_d40_61p44", +}; + +CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI2_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +/* + * APBC_TWSI8_CLK_RST has a quirk that reading always results in zero. + * Combine functional and bus bits together as a gate to avoid sharing the + * write-only register between different clock hardwares. + */ +CCU_GATE_DEFINE(CLK_TWSI8, twsi8_clk, twsi8_clk, "pll1_d78_31p5", + APBC_TWSI8_CLK_RST, BIT(1) | BIT(0), 0); + +CCU_MUX_GATE_DEFINE(CLK_UART2, uart2_clk, uart2_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART2_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART3, uart3_clk, uart3_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART3_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART4, uart4_clk, uart4_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART4_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART5, uart5_clk, uart5_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART5_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART6, uart6_clk, uart6_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART6_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART7, uart7_clk, uart7_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART7_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART8, uart8_clk, uart8_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART8_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART9, uart9_clk, uart9_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART9_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +CCU_GATE_DEFINE(CLK_GPIO, gpio_clk, gpio_clk, "clock-24m", APBC_GPIO_CLK_RST, + BIT(1) | BIT(0), 0); + +static const char * const pwm_parents[] = { + "pll1_d192_12p8", + "clock-32k", +}; + +CCU_MUX_GATE_DEFINE(CLK_PWM0, pwm0_clk, pwm0_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM0_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM1, pwm1_clk, pwm1_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM1_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM2, pwm2_clk, pwm2_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM2_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM3, pwm3_clk, pwm3_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM3_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM4, pwm4_clk, pwm4_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM4_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM5, pwm5_clk, pwm5_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM5_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM6, pwm6_clk, pwm6_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM6_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM7, pwm7_clk, pwm7_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM7_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM8, pwm8_clk, pwm8_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM8_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM9, pwm9_clk, pwm9_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM9_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM10, pwm10_clk, pwm10_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM10_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM11, pwm11_clk, pwm11_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM11_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM12, pwm12_clk, pwm12_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM12_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM13, pwm13_clk, pwm13_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM13_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM14, pwm14_clk, pwm14_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM14_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM15, pwm15_clk, pwm15_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM15_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM16, pwm16_clk, pwm16_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM16_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM17, pwm17_clk, pwm17_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM17_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM18, pwm18_clk, pwm18_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM18_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM19, pwm19_clk, pwm19_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM19_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); + +static const char * const ssp_parents[] = { + "pll1_d384_6p4", + "pll1_d192_12p8", + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d768_3p2", + "pll1_d1536_1p6", + "pll1_d3072_0p8", +}; + +CCU_MUX_GATE_DEFINE(CLK_SSP3, ssp3_clk, ssp3_clk, ssp_parents, + ARRAY_SIZE(ssp_parents), APBC_SSP3_CLK_RST, 4, 3, + BIT(1), 0); + +CCU_GATE_DEFINE(CLK_RTC, rtc_clk, rtc_clk, "clock-32k", APBC_RTC_CLK_RST, + BIT(7) | BIT(1) | BIT(0), 0); + +CCU_MUX_GATE_DEFINE(CLK_TWSI0, twsi0_clk, twsi0_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI0_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI1, twsi1_clk, twsi1_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI1_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI4, twsi4_clk, twsi4_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI4_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI5, twsi5_clk, twsi5_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI5_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI6, twsi6_clk, twsi6_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI6_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI7, twsi7_clk, twsi7_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI7_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +static const char * const timer_parents[] = { + "pll1_d192_12p8", + "clock-32k", + "pll1_d384_6p4", + "clock-3m", + "clock-1m", +}; + +CCU_MUX_GATE_DEFINE(CLK_TIMERS1, timers1_clk, timers1_clk, timer_parents, + ARRAY_SIZE(timer_parents), APBC_TIMERS1_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TIMERS2, timers2_clk, timers2_clk, timer_parents, + ARRAY_SIZE(timer_parents), APBC_TIMERS2_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); + +CCU_GATE_DEFINE(CLK_AIB, aib_clk, aib_clk, "clock-24m", APBC_AIB_CLK_RST, + BIT(1) | BIT(0), 0); + +CCU_GATE_DEFINE(CLK_ONEWIRE, onewire_clk, onewire_clk, "clock-24m", + APBC_ONEWIRE_CLK_RST, BIT(1) | BIT(0), 0); + +/* + * When i2s_bclk is selected as the parent clock of sspa, + * the hardware requires bit3 to be set + */ +CCU_GATE_DEFINE(CLK_SSPA0_I2S_BCLK, sspa0_i2s_bclk, sspa0_i2s_bclk, "i2s_bclk", + APBC_SSPA0_CLK_RST, BIT(3), 0); +CCU_GATE_DEFINE(CLK_SSPA1_I2S_BCLK, sspa1_i2s_bclk, sspa1_i2s_bclk, "i2s_bclk", + APBC_SSPA1_CLK_RST, BIT(3), 0); + +static const char * const sspa0_parents[] = { + "pll1_d384_6p4", + "pll1_d192_12p8", + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d768_3p2", + "pll1_d1536_1p6", + "pll1_d3072_0p8", + "sspa0_i2s_bclk", +}; + +CCU_MUX_GATE_DEFINE(CLK_SSPA0, sspa0_clk, sspa0_clk, sspa0_parents, + ARRAY_SIZE(sspa0_parents), APBC_SSPA0_CLK_RST, 4, 3, + BIT(1), 0); + +static const char * const sspa1_parents[] = { + "pll1_d384_6p4", + "pll1_d192_12p8", + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d768_3p2", + "pll1_d1536_1p6", + "pll1_d3072_0p8", + "sspa1_i2s_bclk", +}; + +CCU_MUX_GATE_DEFINE(CLK_SSPA1, sspa1_clk, sspa1_clk, sspa1_parents, + ARRAY_SIZE(sspa1_parents), APBC_SSPA1_CLK_RST, 4, 3, + BIT(1), 0); + +CCU_GATE_DEFINE(CLK_DRO, dro_clk, dro_clk, "apb_clk", APBC_DRO_CLK_RST, + BIT(1) | BIT(0), 0); +CCU_GATE_DEFINE(CLK_IR, ir_clk, ir_clk, "apb_clk", APBC_IR_CLK_RST, + BIT(1) | BIT(0), 0); +CCU_GATE_DEFINE(CLK_TSEN, tsen_clk, tsen_clk, "apb_clk", APBC_TSEN_CLK_RST, + BIT(1) | BIT(0), 0); +CCU_GATE_DEFINE(CLK_IPC_AP2AUD, ipc_ap2aud_clk, ipc_ap2aud_clk, "apb_clk", + APBC_IPC_AP2AUD_CLK_RST, BIT(1) | BIT(0), 0); + +static const char * const can_parents[] = { + "pll3_20", + "pll3_40", + "pll3_80", +}; + +CCU_MUX_GATE_DEFINE(CLK_CAN0, can0_clk, can0_clk, can_parents, + ARRAY_SIZE(can_parents), APBC_CAN0_CLK_RST, 4, 3, + BIT(1), 0); +CCU_GATE_DEFINE(CLK_CAN0_BUS, can0_bus_clk, can0_bus_clk, "clock-24m", + APBC_CAN0_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_UART0_BUS, uart0_bus_clk, uart0_bus_clk, "apb_clk", + APBC_UART1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART2_BUS, uart2_bus_clk, uart2_bus_clk, "apb_clk", + APBC_UART2_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART3_BUS, uart3_bus_clk, uart3_bus_clk, "apb_clk", + APBC_UART3_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART4_BUS, uart4_bus_clk, uart4_bus_clk, "apb_clk", + APBC_UART4_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART5_BUS, uart5_bus_clk, uart5_bus_clk, "apb_clk", + APBC_UART5_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART6_BUS, uart6_bus_clk, uart6_bus_clk, "apb_clk", + APBC_UART6_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART7_BUS, uart7_bus_clk, uart7_bus_clk, "apb_clk", + APBC_UART7_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART8_BUS, uart8_bus_clk, uart8_bus_clk, "apb_clk", + APBC_UART8_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART9_BUS, uart9_bus_clk, uart9_bus_clk, "apb_clk", + APBC_UART9_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_GPIO_BUS, gpio_bus_clk, gpio_bus_clk, "apb_clk", + APBC_GPIO_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PWM0_BUS, pwm0_bus_clk, pwm0_bus_clk, "apb_clk", + APBC_PWM0_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM1_BUS, pwm1_bus_clk, pwm1_bus_clk, "apb_clk", + APBC_PWM1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM2_BUS, pwm2_bus_clk, pwm2_bus_clk, "apb_clk", + APBC_PWM2_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM3_BUS, pwm3_bus_clk, pwm3_bus_clk, "apb_clk", + APBC_PWM3_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM4_BUS, pwm4_bus_clk, pwm4_bus_clk, "apb_clk", + APBC_PWM4_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM5_BUS, pwm5_bus_clk, pwm5_bus_clk, "apb_clk", + APBC_PWM5_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM6_BUS, pwm6_bus_clk, pwm6_bus_clk, "apb_clk", + APBC_PWM6_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM7_BUS, pwm7_bus_clk, pwm7_bus_clk, "apb_clk", + APBC_PWM7_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM8_BUS, pwm8_bus_clk, pwm8_bus_clk, "apb_clk", + APBC_PWM8_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM9_BUS, pwm9_bus_clk, pwm9_bus_clk, "apb_clk", + APBC_PWM9_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM10_BUS, pwm10_bus_clk, pwm10_bus_clk, "apb_clk", + APBC_PWM10_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM11_BUS, pwm11_bus_clk, pwm11_bus_clk, "apb_clk", + APBC_PWM11_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM12_BUS, pwm12_bus_clk, pwm12_bus_clk, "apb_clk", + APBC_PWM12_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM13_BUS, pwm13_bus_clk, pwm13_bus_clk, "apb_clk", + APBC_PWM13_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM14_BUS, pwm14_bus_clk, pwm14_bus_clk, "apb_clk", + APBC_PWM14_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM15_BUS, pwm15_bus_clk, pwm15_bus_clk, "apb_clk", + APBC_PWM15_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM16_BUS, pwm16_bus_clk, pwm16_bus_clk, "apb_clk", + APBC_PWM16_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM17_BUS, pwm17_bus_clk, pwm17_bus_clk, "apb_clk", + APBC_PWM17_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM18_BUS, pwm18_bus_clk, pwm18_bus_clk, "apb_clk", + APBC_PWM18_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM19_BUS, pwm19_bus_clk, pwm19_bus_clk, "apb_clk", + APBC_PWM19_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_SSP3_BUS, ssp3_bus_clk, ssp3_bus_clk, "apb_clk", + APBC_SSP3_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_RTC_BUS, rtc_bus_clk, rtc_bus_clk, "apb_clk", + APBC_RTC_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_TWSI0_BUS, twsi0_bus_clk, twsi0_bus_clk, "apb_clk", + APBC_TWSI0_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI1_BUS, twsi1_bus_clk, twsi1_bus_clk, "apb_clk", + APBC_TWSI1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI2_BUS, twsi2_bus_clk, twsi2_bus_clk, "apb_clk", + APBC_TWSI2_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI4_BUS, twsi4_bus_clk, twsi4_bus_clk, "apb_clk", + APBC_TWSI4_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI5_BUS, twsi5_bus_clk, twsi5_bus_clk, "apb_clk", + APBC_TWSI5_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI6_BUS, twsi6_bus_clk, twsi6_bus_clk, "apb_clk", + APBC_TWSI6_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI7_BUS, twsi7_bus_clk, twsi7_bus_clk, "apb_clk", + APBC_TWSI7_CLK_RST, BIT(0), 0); +CCU_FACTOR_DEFINE(CLK_TWSI8_BUS, twsi8_bus_clk, twsi8_bus_clk, "apb_clk", 1, 1); + +CCU_GATE_DEFINE(CLK_TIMERS1_BUS, timers1_bus_clk, timers1_bus_clk, "apb_clk", + APBC_TIMERS1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TIMERS2_BUS, timers2_bus_clk, timers2_bus_clk, "apb_clk", + APBC_TIMERS2_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_AIB_BUS, aib_bus_clk, aib_bus_clk, "apb_clk", + APBC_AIB_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_ONEWIRE_BUS, onewire_bus_clk, onewire_bus_clk, "apb_clk", + APBC_ONEWIRE_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_SSPA0_BUS, sspa0_bus_clk, sspa0_bus_clk, "apb_clk", + APBC_SSPA0_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_SSPA1_BUS, sspa1_bus_clk, sspa1_bus_clk, "apb_clk", + APBC_SSPA1_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_TSEN_BUS, tsen_bus_clk, tsen_bus_clk, "apb_clk", + APBC_TSEN_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_IPC_AP2AUD_BUS, ipc_ap2aud_bus_clk, ipc_ap2aud_bus_clk, + "apb_clk", APBC_IPC_AP2AUD_CLK_RST, BIT(0), 0); +#endif +/* APBC clocks end */ + +/* APMU clocks start */ +#if IS_ENABLED(CONFIG_SPL_BUILD) +static const char * const pmua_aclk_parents[] = { + "clock-dummy", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_FC_DEFINE(CLK_PMUA_ACLK, pmua_aclk, pmua_aclk, pmua_aclk_parents, + ARRAY_SIZE(pmua_aclk_parents), + APMU_ACLK_CLK_CTRL, APMU_ACLK_CLK_CTRL, 1, 2, BIT(4), + 0, 1, 0); + +CCU_GATE_DEFINE(CLK_SDH_AXI, sdh_axi_aclk, sdh_axi_aclk, "pmua_aclk", + APMU_SDH0_CLK_RES_CTRL, BIT(3), 0); + +static const char * const sdh01_parents[] = { + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH0, sdh0_clk, sdh0_clk, sdh01_parents, + ARRAY_SIZE(sdh01_parents), + APMU_SDH0_CLK_RES_CTRL, + APMU_SDH0_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); + +static const char * const sdh2_parents[] = { + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH2, sdh2_clk, sdh2_clk, sdh2_parents, + ARRAY_SIZE(sdh2_parents), + APMU_SDH2_CLK_RES_CTRL, + APMU_SDH2_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); +#else +static const char * const pmua_aclk_parents[] = { + "pll1_d10_245p76", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_FC_DEFINE(CLK_PMUA_ACLK, pmua_aclk, pmua_aclk, pmua_aclk_parents, + ARRAY_SIZE(pmua_aclk_parents), + APMU_ACLK_CLK_CTRL, APMU_ACLK_CLK_CTRL, 1, 2, BIT(4), + 0, 1, 0); + +static const char * const emmc_parents[] = { + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll1_d52_47p26", + "pll1_d3_819p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_EMMC, emmc_clk, emmc_clk, emmc_parents, + ARRAY_SIZE(emmc_parents), + APMU_PMUA_EM_CLK_RES_CTRL, + APMU_PMUA_EM_CLK_RES_CTRL, 8, 3, BIT(11), + 6, 2, BIT(4), 0); +CCU_DIV_GATE_DEFINE(CLK_EMMC_X, emmc_x_clk, emmc_x_clk, "pll1_d2_1228p8", + APMU_PMUA_EM_CLK_RES_CTRL, 12, + 3, BIT(15), 0); + +CCU_GATE_DEFINE(CLK_EMMC_BUS, emmc_bus_clk, emmc_bus_clk, "pmua_aclk", + APMU_PMUA_EM_CLK_RES_CTRL, BIT(3), 0); + +static const char * const cci550_clk_parents[] = { + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll2_d3", +}; + +CCU_MUX_DIV_FC_DEFINE(CLK_CCI550, cci550_clk, cci550_clk, cci550_clk_parents, + ARRAY_SIZE(cci550_clk_parents), + APMU_CCI550_CLK_CTRL, APMU_CCI550_CLK_CTRL, 8, 3, + BIT(12), 0, 2, CLK_IS_CRITICAL); + +static const char * const cpu_c0_hi_clk_parents[] = { + "pll3_d2", + "pll3_d1", +}; + +CCU_MUX_DEFINE(CLK_CPU_C0_HI, cpu_c0_hi_clk, cpu_c0_hi_clk, + cpu_c0_hi_clk_parents, ARRAY_SIZE(cpu_c0_hi_clk_parents), + APMU_CPU_C0_CLK_CTRL, 13, 1, 0); +static const char * const cpu_c0_clk_parents[] = { + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d2_1228p8", + "pll3_d3", + "pll2_d3", + "cpu_c0_hi_clk", +}; + +CCU_MUX_FC_DEFINE(CLK_CPU_C0_CORE, cpu_c0_core_clk, cpu_c0_core_clk, + cpu_c0_clk_parents, ARRAY_SIZE(cpu_c0_clk_parents), + APMU_CPU_C0_CLK_CTRL, APMU_CPU_C0_CLK_CTRL, + BIT(12), 0, 3, CLK_IS_CRITICAL); +CCU_DIV_DEFINE(CLK_CPU_C0_ACE, cpu_c0_ace_clk, cpu_c0_ace_clk, + "cpu_c0_core_clk", APMU_CPU_C0_CLK_CTRL, 6, 3, CLK_IS_CRITICAL); +CCU_DIV_DEFINE(CLK_CPU_C0_TCM, cpu_c0_tcm_clk, cpu_c0_tcm_clk, + "cpu_c0_core_clk", APMU_CPU_C0_CLK_CTRL, 9, 3, CLK_IS_CRITICAL); + +static const char * const cpu_c1_hi_clk_parents[] = { + "pll3_d2", + "pll3_d1", +}; + +CCU_MUX_DEFINE(CLK_CPU_C1_HI, cpu_c1_hi_clk, cpu_c1_hi_clk, + cpu_c1_hi_clk_parents, ARRAY_SIZE(cpu_c1_hi_clk_parents), + APMU_CPU_C1_CLK_CTRL, 13, 1, 0); +static const char * const cpu_c1_clk_parents[] = { + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d2_1228p8", + "pll3_d3", + "pll2_d3", + "cpu_c1_hi_clk", +}; + +CCU_MUX_FC_DEFINE(CLK_CPU_C1_CORE, cpu_c1_core_clk, cpu_c1_core_clk, + cpu_c1_clk_parents, ARRAY_SIZE(cpu_c1_clk_parents), + APMU_CPU_C1_CLK_CTRL, APMU_CPU_C1_CLK_CTRL, + BIT(12), 0, 3, CLK_IS_CRITICAL); +CCU_DIV_DEFINE(CLK_CPU_C1_ACE, cpu_c1_ace_clk, cpu_c1_ace_clk, + "cpu_c1_core_clk", APMU_CPU_C1_CLK_CTRL, 6, 3, CLK_IS_CRITICAL); + +static const char * const jpg_parents[] = { + "pll1_d4_614p4", + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d3_819p2", + "pll1_d2_1228p8", + "pll2_d4", + "pll2_d3", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_JPG, jpg_clk, jpg_clk, jpg_parents, + ARRAY_SIZE(jpg_parents), + APMU_JPG_CLK_RES_CTRL, + APMU_JPG_CLK_RES_CTRL, + 5, 3, BIT(15), 2, 3, BIT(1), 0); + +static const char * const ccic2phy_parents[] = { + "pll1_d24_102p4", + "pll1_d48_51p2_ap", +}; + +CCU_MUX_GATE_DEFINE(CLK_CCIC2PHY, ccic2phy_clk, ccic2phy_clk, ccic2phy_parents, + ARRAY_SIZE(ccic2phy_parents), APMU_CSI_CCIC2_CLK_RES_CTRL, + 7, 1, BIT(5), 0); + +static const char * const ccic3phy_parents[] = { + "pll1_d24_102p4", + "pll1_d48_51p2_ap", +}; + +CCU_MUX_GATE_DEFINE(CLK_CCIC3PHY, ccic3phy_clk, ccic3phy_clk, ccic3phy_parents, + ARRAY_SIZE(ccic3phy_parents), APMU_CSI_CCIC2_CLK_RES_CTRL, + 31, 1, BIT(30), 0); + +static const char * const csi_parents[] = { + "pll1_d5_491p52", + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll2_d2", + "pll2_d3", + "pll2_d4", + "pll1_d2_1228p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_CSI, csi_clk, csi_clk, csi_parents, + ARRAY_SIZE(csi_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, + APMU_CSI_CCIC2_CLK_RES_CTRL, 20, 3, BIT(15), + 16, 3, BIT(4), 0); + +static const char * const camm_parents[] = { + "pll1_d8_307p2", + "pll2_d5", + "pll1_d6_409p6", + "clock-24m", +}; + +CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM0, camm0_clk, camm0_clk, camm_parents, + ARRAY_SIZE(camm_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2, + BIT(28), 0); +CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM1, camm1_clk, camm1_clk, camm_parents, + ARRAY_SIZE(camm_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2, + BIT(6), 0); +CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM2, camm2_clk, camm2_clk, camm_parents, + ARRAY_SIZE(camm_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2, + BIT(3), 0); + +static const char * const isp_cpp_parents[] = { + "pll1_d8_307p2", + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_DEFINE(CLK_ISP_CPP, isp_cpp_clk, isp_cpp_clk, isp_cpp_parents, + ARRAY_SIZE(isp_cpp_parents), + APMU_ISP_CLK_RES_CTRL, 24, 2, 26, 1, + BIT(28), 0); +static const char * const isp_bus_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d8_307p2", + "pll1_d10_245p76", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_ISP_BUS, isp_bus_clk, isp_bus_clk, + isp_bus_parents, ARRAY_SIZE(isp_cpp_parents), + APMU_ISP_CLK_RES_CTRL, + APMU_ISP_CLK_RES_CTRL, 18, 3, BIT(23), + 21, 2, BIT(17), 0); +static const char * const isp_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_ISP, isp_clk, isp_clk, isp_parents, + ARRAY_SIZE(isp_parents), + APMU_ISP_CLK_RES_CTRL, + APMU_ISP_CLK_RES_CTRL, + 4, 3, BIT(7), 8, 2, BIT(1), 0); + +static const char * const dpumclk_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_MCLK, dpu_mclk, dpu_mclk, + dpumclk_parents, ARRAY_SIZE(dpumclk_parents), + APMU_LCD_CLK_RES_CTRL2, APMU_LCD_CLK_RES_CTRL1, + 1, 4, BIT(29), 5, 3, BIT(0), 0); + +static const char * const dpuesc_parents[] = { + "pll1_d48_51p2_ap", + "pll1_d52_47p26", + "pll1_d96_25p6", + "pll1_d32_76p8", +}; + +CCU_MUX_GATE_DEFINE(CLK_DPU_ESC, dpu_esc_clk, dpu_esc_clk, dpuesc_parents, + ARRAY_SIZE(dpuesc_parents), APMU_LCD_CLK_RES_CTRL1, 0, 2, + BIT(2), 0); + +static const char * const dpubit_parents[] = { + "pll1_d3_819p2", + "pll2_d2", + "pll2_d3", + "pll1_d2_1228p8", + "pll2_d4", + "pll2_d5", + "pll2_d7", + "pll2_d8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_BIT, dpu_bit_clk, dpu_bit_clk, + dpubit_parents, ARRAY_SIZE(dpubit_parents), + APMU_LCD_CLK_RES_CTRL1, + APMU_LCD_CLK_RES_CTRL1, 17, 3, BIT(31), + 20, 3, BIT(16), 0); + +static const char * const dpupx_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", + "pll2_d7", + "pll2_d8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_PXCLK, dpu_pxclk, dpu_pxclk, + dpupx_parents, ARRAY_SIZE(dpupx_parents), + APMU_LCD_CLK_RES_CTRL2, APMU_LCD_CLK_RES_CTRL1, + 17, 4, BIT(30), 21, 3, BIT(16), 0); + +CCU_GATE_DEFINE(CLK_DPU_HCLK, dpu_hclk, dpu_hclk, "pmua_aclk", + APMU_LCD_CLK_RES_CTRL1, BIT(5), 0); + +static const char * const dpu_spi_parents[] = { + "pll1_d8_307p2", + "pll1_d6_409p6", + "pll1_d10_245p76", + "pll1_d11_223p4", + "pll1_d13_189", + "pll1_d23_106p8", + "pll2_d3", + "pll2_d5", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_SPI, dpu_spi_clk, dpu_spi_clk, + dpu_spi_parents, ARRAY_SIZE(dpu_spi_parents), + APMU_LCD_SPI_CLK_RES_CTRL, + APMU_LCD_SPI_CLK_RES_CTRL, 8, 3, + BIT(7), 12, 3, BIT(1), 0); +CCU_GATE_DEFINE(CLK_DPU_SPI_HBUS, dpu_spi_hbus_clk, dpu_spi_hbus_clk, + "pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(3), 0); +CCU_GATE_DEFINE(CLK_DPU_SPIBUS, dpu_spi_bus_clk, dpu_spi_bus_clk, + "pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(5), 0); +CCU_GATE_DEFINE(CLK_DPU_SPI_ACLK, dpu_spi_aclk, dpu_spi_aclk, + "pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(6), 0); + +static const char * const v2d_parents[] = { + "pll1_d5_491p52", + "pll1_d6_409p6", + "pll1_d8_307p2", + "pll1_d4_614p4", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_V2D, v2d_clk, v2d_clk, v2d_parents, + ARRAY_SIZE(v2d_parents), + APMU_LCD_CLK_RES_CTRL1, + APMU_LCD_CLK_RES_CTRL1, 9, 3, BIT(28), 12, 2, + BIT(8), 0); + +static const char * const ccic_4x_parents[] = { + "pll1_d5_491p52", + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll2_d2", + "pll2_d3", + "pll2_d4", + "pll1_d2_1228p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_CCIC_4X, ccic_4x_clk, ccic_4x_clk, + ccic_4x_parents, ARRAY_SIZE(ccic_4x_parents), + APMU_CCIC_CLK_RES_CTRL, + APMU_CCIC_CLK_RES_CTRL, 18, 3, + BIT(15), 23, 2, BIT(4), 0); + +static const char * const ccic1phy_parents[] = { + "pll1_d24_102p4", + "pll1_d48_51p2_ap", +}; + +CCU_MUX_GATE_DEFINE(CLK_CCIC1PHY, ccic1phy_clk, ccic1phy_clk, ccic1phy_parents, + ARRAY_SIZE(ccic1phy_parents), APMU_CCIC_CLK_RES_CTRL, 7, 1, + BIT(5), 0); + +CCU_GATE_DEFINE(CLK_SDH_AXI, sdh_axi_aclk, sdh_axi_aclk, "pmua_aclk", + APMU_SDH0_CLK_RES_CTRL, BIT(3), 0); +static const char * const sdh01_parents[] = { + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll2_d8", + "pll2_d5", + "pll1_d11_223p4", + "pll1_d13_189", + "pll1_d23_106p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH0, sdh0_clk, sdh0_clk, sdh01_parents, + ARRAY_SIZE(sdh01_parents), + APMU_SDH0_CLK_RES_CTRL, + APMU_SDH0_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH1, sdh1_clk, sdh1_clk, sdh01_parents, + ARRAY_SIZE(sdh01_parents), + APMU_SDH1_CLK_RES_CTRL, + APMU_SDH1_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); +static const char * const sdh2_parents[] = { + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll2_d8", + "pll1_d3_819p2", + "pll1_d11_223p4", + "pll1_d13_189", + "pll1_d23_106p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH2, sdh2_clk, sdh2_clk, sdh2_parents, + ARRAY_SIZE(sdh2_parents), + APMU_SDH2_CLK_RES_CTRL, + APMU_SDH2_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); + +CCU_GATE_DEFINE(CLK_USB_AXI, usb_axi_clk, usb_axi_clk, "pmua_aclk", + APMU_USB_CLK_RES_CTRL, BIT(1), 0); +CCU_GATE_DEFINE(CLK_USB_P1, usb_p1_aclk, usb_p1_aclk, "pmua_aclk", + APMU_USB_CLK_RES_CTRL, BIT(5), 0); +CCU_GATE_DEFINE(CLK_USB30, usb30_clk, usb30_clk, "pmua_aclk", + APMU_USB_CLK_RES_CTRL, BIT(8), 0); + +static const char * const qspi_parents[] = { + "pll1_d6_409p6", + "pll2_d8", + "pll1_d8_307p2", + "pll1_d10_245p76", + "pll1_d11_223p4", + "pll1_d23_106p8", + "pll1_d5_491p52", + "pll1_d13_189", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_QSPI, qspi_clk, qspi_clk, qspi_parents, + ARRAY_SIZE(qspi_parents), + APMU_QSPI_CLK_RES_CTRL, + APMU_QSPI_CLK_RES_CTRL, 9, 3, BIT(12), 6, 3, + BIT(4), 0); +CCU_GATE_DEFINE(CLK_QSPI_BUS, qspi_bus_clk, qspi_bus_clk, "pmua_aclk", + APMU_QSPI_CLK_RES_CTRL, BIT(3), 0); +CCU_GATE_DEFINE(CLK_DMA, dma_clk, dma_clk, "pmua_aclk", APMU_DMA_CLK_RES_CTRL, + BIT(3), 0); + +static const char * const aes_parents[] = { + "pll1_d12_204p8", + "pll1_d24_102p4", +}; + +CCU_MUX_GATE_DEFINE(CLK_AES, aes_clk, aes_clk, aes_parents, + ARRAY_SIZE(aes_parents), APMU_AES_CLK_RES_CTRL, 6, 1, + BIT(5), 0); + +static const char * const vpu_parents[] = { + "pll1_d4_614p4", + "pll1_d5_491p52", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll3_d6", + "pll2_d3", + "pll2_d4", + "pll2_d5", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_VPU, vpu_clk, vpu_clk, vpu_parents, + ARRAY_SIZE(vpu_parents), APMU_VPU_CLK_RES_CTRL, + APMU_VPU_CLK_RES_CTRL, 13, 3, BIT(21), 10, 3, + BIT(3), 0); + +static const char * const gpu_parents[] = { + "pll1_d4_614p4", + "pll1_d5_491p52", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll3_d6", + "pll2_d3", + "pll2_d4", + "pll2_d5", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_GPU, gpu_clk, gpu_clk, gpu_parents, + ARRAY_SIZE(gpu_parents), APMU_GPU_CLK_RES_CTRL, + APMU_GPU_CLK_RES_CTRL, 12, 3, BIT(15), 18, 3, + BIT(4), 0); + +static const char * const audio_parents[] = { + "pll1_aud_245p7", + "pll1_d8_307p2", + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_AUDIO, audio_clk, audio_clk, audio_parents, + ARRAY_SIZE(audio_parents), + APMU_AUDIO_CLK_RES_CTRL, + APMU_AUDIO_CLK_RES_CTRL, 4, 3, BIT(15), + 7, 3, BIT(12), 0); + +static const char * const hdmi_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_HDMI, hdmi_mclk, hdmi_mclk, hdmi_parents, + ARRAY_SIZE(hdmi_parents), + APMU_HDMI_CLK_RES_CTRL, + APMU_HDMI_CLK_RES_CTRL, 1, 4, BIT(29), 5, + 3, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PCIE0_MASTER, pcie0_master_clk, pcie0_master_clk, + "pmua_aclk", APMU_PCIE_CLK_RES_CTRL_0, BIT(2), 0); +CCU_GATE_DEFINE(CLK_PCIE0_SLAVE, pcie0_slave_clk, pcie0_slave_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_0, BIT(1), 0); +CCU_GATE_DEFINE(CLK_PCIE0_DBI, pcie0_dbi_clk, pcie0_dbi_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_0, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PCIE1_MASTER, pcie1_master_clk, pcie1_master_clk, + "pmua_aclk", APMU_PCIE_CLK_RES_CTRL_1, BIT(2), 0); +CCU_GATE_DEFINE(CLK_PCIE1_SLAVE, pcie1_slave_clk, pcie1_slave_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_1, BIT(1), 0); +CCU_GATE_DEFINE(CLK_PCIE1_DBI, pcie1_dbi_clk, pcie1_dbi_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_1, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PCIE2_MASTER, pcie2_master_clk, pcie2_master_clk, + "pmua_aclk", APMU_PCIE_CLK_RES_CTRL_2, BIT(2), 0); +CCU_GATE_DEFINE(CLK_PCIE2_SLAVE, pcie2_slave_clk, pcie2_slave_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_2, BIT(1), 0); +CCU_GATE_DEFINE(CLK_PCIE2_DBI, pcie2_dbi_clk, pcie2_dbi_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_2, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_EMAC0_BUS, emac0_bus_clk, emac0_bus_clk, "pmua_aclk", + APMU_EMAC0_CLK_RES_CTRL, BIT(0), 0); +CCU_GATE_DEFINE(CLK_EMAC0_PTP, emac0_ptp_clk, emac0_ptp_clk, "pll2_d6", + APMU_EMAC0_CLK_RES_CTRL, BIT(15), 0); +CCU_GATE_DEFINE(CLK_EMAC1_BUS, emac1_bus_clk, emac1_bus_clk, "pmua_aclk", + APMU_EMAC1_CLK_RES_CTRL, BIT(0), 0); +CCU_GATE_DEFINE(CLK_EMAC1_PTP, emac1_ptp_clk, emac1_ptp_clk, "pll2_d6", + APMU_EMAC1_CLK_RES_CTRL, BIT(15), 0); + +#endif +/* APMU clocks end */ + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_pll_clks[] = { + &pll1.common.clk, + &pll1_d4.common.clk, + &pll1_d6.common.clk, + &pll1_d8.common.clk, +}; +#else +static struct clk *k1_ccu_pll_clks[] = { + &pll1.common.clk, + &pll2.common.clk, + &pll3.common.clk, + &pll1_d2.common.clk, + &pll1_d3.common.clk, + &pll1_d4.common.clk, + &pll1_d5.common.clk, + &pll1_d6.common.clk, + &pll1_d7.common.clk, + &pll1_d8.common.clk, + &pll1_d11_223p4.common.clk, + &pll1_d13_189.common.clk, + &pll1_d23_106p8.common.clk, + &pll1_d64_38p4.common.clk, + &pll1_aud_245p7.common.clk, + &pll1_aud_24p5.common.clk, + &pll2_d1.common.clk, + &pll2_d2.common.clk, + &pll2_d3.common.clk, + &pll2_d4.common.clk, + &pll2_d5.common.clk, + &pll2_d6.common.clk, + &pll2_d7.common.clk, + &pll2_d8.common.clk, + &pll3_d1.common.clk, + &pll3_d2.common.clk, + &pll3_d3.common.clk, + &pll3_d4.common.clk, + &pll3_d5.common.clk, + &pll3_d6.common.clk, + &pll3_d7.common.clk, + &pll3_d8.common.clk, + &pll3_80.common.clk, + &pll3_40.common.clk, + &pll3_20.common.clk, +}; +#endif + +static const struct spacemit_ccu_data k1_ccu_pll_data = { + .clks = k1_ccu_pll_clks, + .num = ARRAY_SIZE(k1_ccu_pll_clks), + .offset = K1_PLL_ID, +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_mpmu_clks[] = { + &pll1_d4_614p4.common.clk, + &pll1_d6_409p6.common.clk, + &pll1_d8_307p2.common.clk, + &pll1_d78_31p5.common.clk, + &slow_uart2_48.common.clk, +}; +#else +static struct clk *k1_ccu_mpmu_clks[] = { + &pll1_d8_307p2.common.clk, + &pll1_d32_76p8.common.clk, + &pll1_d40_61p44.common.clk, + &pll1_d16_153p6.common.clk, + &pll1_d24_102p4.common.clk, + &pll1_d48_51p2.common.clk, + &pll1_d48_51p2_ap.common.clk, + &pll1_m3d128_57p6.common.clk, + &pll1_d96_25p6.common.clk, + &pll1_d192_12p8.common.clk, + &pll1_d192_12p8_wdt.common.clk, + &pll1_d384_6p4.common.clk, + &pll1_d768_3p2.common.clk, + &pll1_d1536_1p6.common.clk, + &pll1_d3072_0p8.common.clk, + &pll1_d6_409p6.common.clk, + &pll1_d12_204p8.common.clk, + &pll1_d5_491p52.common.clk, + &pll1_d10_245p76.common.clk, + &pll1_d4_614p4.common.clk, + &pll1_d52_47p26.common.clk, + &pll1_d78_31p5.common.clk, + &pll1_d3_819p2.common.clk, + &pll1_d2_1228p8.common.clk, + &slow_uart.common.clk, + &slow_uart1_14p74.common.clk, + &slow_uart2_48.common.clk, + &wdt_clk.common.clk, + &apb_clk.common.clk, + &ripc_clk.common.clk, + &i2s_153p6.common.clk, + &i2s_153p6_base.common.clk, + &i2s_sysclk_src.common.clk, + &i2s_sysclk.common.clk, + &i2s_bclk_factor.common.clk, + &i2s_bclk.common.clk, + &wdt_bus_clk.common.clk, +}; +#endif + +static const struct spacemit_ccu_data k1_ccu_mpmu_data = { + .clks = k1_ccu_mpmu_clks, + .num = ARRAY_SIZE(k1_ccu_mpmu_clks), + .offset = K1_MPMU_ID, +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_apbc_clks[] = { + &uart0_clk.common.clk, + &twsi2_clk.common.clk, + &twsi8_clk.common.clk, +}; +#else +static struct clk *k1_ccu_apbc_clks[] = { + &uart0_clk.common.clk, + &uart2_clk.common.clk, + &uart3_clk.common.clk, + &uart4_clk.common.clk, + &uart5_clk.common.clk, + &uart6_clk.common.clk, + &uart7_clk.common.clk, + &uart8_clk.common.clk, + &uart9_clk.common.clk, + &gpio_clk.common.clk, + &pwm0_clk.common.clk, + &pwm1_clk.common.clk, + &pwm2_clk.common.clk, + &pwm3_clk.common.clk, + &pwm4_clk.common.clk, + &pwm5_clk.common.clk, + &pwm6_clk.common.clk, + &pwm7_clk.common.clk, + &pwm8_clk.common.clk, + &pwm9_clk.common.clk, + &pwm10_clk.common.clk, + &pwm11_clk.common.clk, + &pwm12_clk.common.clk, + &pwm13_clk.common.clk, + &pwm14_clk.common.clk, + &pwm15_clk.common.clk, + &pwm16_clk.common.clk, + &pwm17_clk.common.clk, + &pwm18_clk.common.clk, + &pwm19_clk.common.clk, + &ssp3_clk.common.clk, + &rtc_clk.common.clk, + &twsi0_clk.common.clk, + &twsi1_clk.common.clk, + &twsi2_clk.common.clk, + &twsi4_clk.common.clk, + &twsi5_clk.common.clk, + &twsi6_clk.common.clk, + &twsi7_clk.common.clk, + &twsi8_clk.common.clk, + &timers1_clk.common.clk, + &timers2_clk.common.clk, + &aib_clk.common.clk, + &onewire_clk.common.clk, + &sspa0_clk.common.clk, + &sspa1_clk.common.clk, + &dro_clk.common.clk, + &ir_clk.common.clk, + &tsen_clk.common.clk, + &ipc_ap2aud_clk.common.clk, + &can0_clk.common.clk, + &can0_bus_clk.common.clk, + &uart0_bus_clk.common.clk, + &uart2_bus_clk.common.clk, + &uart3_bus_clk.common.clk, + &uart4_bus_clk.common.clk, + &uart5_bus_clk.common.clk, + &uart6_bus_clk.common.clk, + &uart7_bus_clk.common.clk, + &uart8_bus_clk.common.clk, + &uart9_bus_clk.common.clk, + &gpio_bus_clk.common.clk, + &pwm0_bus_clk.common.clk, + &pwm1_bus_clk.common.clk, + &pwm2_bus_clk.common.clk, + &pwm3_bus_clk.common.clk, + &pwm4_bus_clk.common.clk, + &pwm5_bus_clk.common.clk, + &pwm6_bus_clk.common.clk, + &pwm7_bus_clk.common.clk, + &pwm8_bus_clk.common.clk, + &pwm9_bus_clk.common.clk, + &pwm10_bus_clk.common.clk, + &pwm11_bus_clk.common.clk, + &pwm12_bus_clk.common.clk, + &pwm13_bus_clk.common.clk, + &pwm14_bus_clk.common.clk, + &pwm15_bus_clk.common.clk, + &pwm16_bus_clk.common.clk, + &pwm17_bus_clk.common.clk, + &pwm18_bus_clk.common.clk, + &pwm19_bus_clk.common.clk, + &ssp3_bus_clk.common.clk, + &rtc_bus_clk.common.clk, + &twsi0_bus_clk.common.clk, + &twsi1_bus_clk.common.clk, + &twsi2_bus_clk.common.clk, + &twsi4_bus_clk.common.clk, + &twsi5_bus_clk.common.clk, + &twsi6_bus_clk.common.clk, + &twsi7_bus_clk.common.clk, + &twsi8_bus_clk.common.clk, + &timers1_bus_clk.common.clk, + &timers2_bus_clk.common.clk, + &aib_bus_clk.common.clk, + &onewire_bus_clk.common.clk, + &sspa0_bus_clk.common.clk, + &sspa1_bus_clk.common.clk, + &tsen_bus_clk.common.clk, + &ipc_ap2aud_bus_clk.common.clk, + &sspa0_i2s_bclk.common.clk, + &sspa1_i2s_bclk.common.clk, +}; +#endif + +static const struct spacemit_ccu_data k1_ccu_apbc_data = { + .clks = k1_ccu_apbc_clks, + .num = ARRAY_SIZE(k1_ccu_apbc_clks), + .offset = K1_APBC_ID, +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_apmu_clks[] = { + &pmua_aclk.common.clk, + &sdh_axi_aclk.common.clk, + &sdh0_clk.common.clk, + &sdh2_clk.common.clk, +}; +#else +static struct clk *k1_ccu_apmu_clks[] = { + &cci550_clk.common.clk, + &cpu_c0_hi_clk.common.clk, + &cpu_c0_core_clk.common.clk, + &cpu_c0_ace_clk.common.clk, + &cpu_c0_tcm_clk.common.clk, + &cpu_c1_hi_clk.common.clk, + &cpu_c1_core_clk.common.clk, + &cpu_c1_ace_clk.common.clk, + &ccic_4x_clk.common.clk, + &ccic1phy_clk.common.clk, + &pmua_aclk.common.clk, + &sdh_axi_aclk.common.clk, + &sdh0_clk.common.clk, + &sdh1_clk.common.clk, + &sdh2_clk.common.clk, + &usb_p1_aclk.common.clk, + &usb_axi_clk.common.clk, + &usb30_clk.common.clk, + &qspi_clk.common.clk, + &qspi_bus_clk.common.clk, + &dma_clk.common.clk, + &aes_clk.common.clk, + &vpu_clk.common.clk, + &gpu_clk.common.clk, + &emmc_clk.common.clk, + &emmc_x_clk.common.clk, + &audio_clk.common.clk, + &hdmi_mclk.common.clk, + &pcie0_master_clk.common.clk, + &pcie0_slave_clk.common.clk, + &pcie0_dbi_clk.common.clk, + &pcie1_master_clk.common.clk, + &pcie1_slave_clk.common.clk, + &pcie1_dbi_clk.common.clk, + &pcie2_master_clk.common.clk, + &pcie2_slave_clk.common.clk, + &pcie2_dbi_clk.common.clk, + &emac0_bus_clk.common.clk, + &emac0_ptp_clk.common.clk, + &emac1_bus_clk.common.clk, + &emac1_ptp_clk.common.clk, + &jpg_clk.common.clk, + &ccic2phy_clk.common.clk, + &ccic3phy_clk.common.clk, + &csi_clk.common.clk, + &camm0_clk.common.clk, + &camm1_clk.common.clk, + &camm2_clk.common.clk, + &isp_cpp_clk.common.clk, + &isp_bus_clk.common.clk, + &isp_clk.common.clk, + &dpu_mclk.common.clk, + &dpu_esc_clk.common.clk, + &dpu_bit_clk.common.clk, + &dpu_pxclk.common.clk, + &dpu_hclk.common.clk, + &dpu_spi_clk.common.clk, + &dpu_spi_hbus_clk.common.clk, + &dpu_spi_bus_clk.common.clk, + &dpu_spi_aclk.common.clk, + &v2d_clk.common.clk, + &emmc_bus_clk.common.clk, +}; +#endif + +static int clk_k1_enable(struct clk *clk) +{ + const struct spacemit_ccu_data *data; + struct clk *c; + struct clk *pclk; + int ret, i; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(clk->dev); + for (i = 0; i < data->num; i++) { + if (clk->id == data->clks[i]->id) { + c = data->clks[i]; + break; + } + } + if (i == data->num) + c = clk; + + pclk = clk_get_parent(c); + if (!IS_ERR_OR_NULL(pclk)) { + ret = ccf_clk_enable(pclk); + if (ret) + return ret; + } + ret = ccu_gate_enable(c); + return ret; +} + +static int clk_k1_disable(struct clk *clk) +{ + const struct spacemit_ccu_data *data; + struct clk *c; + struct clk *pclk; + int ret, i; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(clk->dev); + for (i = 0; i < data->num; i++) { + if (clk->id == data->clks[i]->id) { + c = data->clks[i]; + break; + } + } + if (i == data->num) + c = clk; + + pclk = clk_get_parent(c); + if (!IS_ERR_OR_NULL(pclk)) { + ret = ccf_clk_disable(pclk); + if (ret) + return ret; + } + ret = ccu_gate_disable(c); + return ret; +} + +#define K1_CLK_OPS(name) \ +static const struct clk_ops k1_##name##_clk_ops = { \ + .set_rate = ccf_clk_set_rate, \ + .get_rate = ccf_clk_get_rate, \ + .enable = clk_k1_enable, \ + .disable = clk_k1_disable, \ + .set_parent = ccf_clk_set_parent, \ + .of_xlate = k1_##name##_clk_of_xlate, \ +} + +static const struct spacemit_ccu_data k1_ccu_apmu_data = { + .clks = k1_ccu_apmu_clks, + .num = ARRAY_SIZE(k1_ccu_apmu_clks), + .offset = K1_APMU_ID, +}; + +/* + * The K1 clock providers are split across separate syscon devices (PLL, + * MPMU, APMU, APBC) whose clocks parent across device boundaries. U-Boot's + * CCF resolves a parent by name at registration time and silently binds an + * orphan if the parent is not registered yet, so a controller must not + * register its clocks before the controllers owning its parents have probed. + * Force the parent controller to probe by its driver: this is robust against + * device tree node/phandle ordering and needs no helper "clocks" wiring in + * the syscon nodes. + */ +static int k1_clk_force_probe(const struct driver *drv) +{ + struct udevice *dev; + + return uclass_get_device_by_driver(UCLASS_CLK, drv, &dev); +} + +static int k1_clk_register(struct udevice *dev, struct regmap *regmap, + struct regmap *lock_regmap, + const struct spacemit_ccu_data *data) +{ + int i, ret; + + for (i = 0; i < data->num; i++) { + struct clk *clk = data->clks[i]; + struct ccu_common *common; + + if (!clk) + continue; + + common = clk_to_ccu_common(clk); + common->regmap = regmap; + common->lock_regmap = lock_regmap; + + if (common->clk.id < K1_PLL_ID) + clk->id = common->clk.id + data->offset; + else + clk->id = common->clk.id; + + ret = common->init(common); + if (ret) + return ret; + } + + return 0; +} + +static int k1_pll_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + clk_register_fixed_rate(NULL, "clock-dummy", 0); + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + /* + * The lock status of PLLs locate in MPMU region, while PLLs themselves + * are in APBS region. Reference to MPMU syscon is required to check PLL + * status. + */ + if (device_is_compatible(dev, "spacemit,k1-pll")) { + struct ofnode_phandle_args mpmu_args; + + ret = dev_read_phandle_with_args(dev, "spacemit,mpmu", NULL, 0, 0, + &mpmu_args); + if (ret) + return ret; + + ret = regmap_init_mem(mpmu_args.node, &lock_regmap); + if (ret) + return ret; + } + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_mpmu_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + /* MPMU clocks parent off the PLL controller */ + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_pll_clk)); + if (ret) + return ret; + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_apmu_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + /* APMU clocks parent off the PLL and MPMU controllers */ + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_pll_clk)); + if (ret) + return ret; + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_mpmu_clk)); + if (ret) + return ret; + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_apbc_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + /* APBC clocks parent off the PLL, MPMU and APMU controllers */ + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_pll_clk)); + if (ret) + return ret; + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_mpmu_clk)); + if (ret) + return ret; + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_apmu_clk)); + if (ret) + return ret; + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_pll_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_PLL_ID + args->args[0]; + else + clk->id = K1_PLL_ID; + + return 0; +} + +static int k1_mpmu_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_MPMU_ID + args->args[0]; + else + clk->id = K1_MPMU_ID; + + return 0; +} + +static int k1_apbc_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_APBC_ID + args->args[0]; + else + clk->id = K1_APBC_ID; + + return 0; +} + +static int k1_apmu_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_APMU_ID + args->args[0]; + else + clk->id = K1_APMU_ID; + + return 0; +} + +static const struct udevice_id k1_pll_clk_match[] = { + { .compatible = "spacemit,k1-pll", + .data = (ulong)&k1_ccu_pll_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(pll); + +U_BOOT_DRIVER(k1_pll_clk) = { + .name = "k1_pll_clk", + .id = UCLASS_CLK, + .of_match = k1_pll_clk_match, + .probe = k1_pll_clk_probe, + .ops = &k1_pll_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static int k1_mpmu_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_MPMU); +} + +static int k1_apbc_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APBC); +} + +static int k1_apmu_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APMU); +} + +static int k1_apbc2_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APBC2); +} + +static const struct udevice_id k1_mpmu_clk_match[] = { + { .compatible = "spacemit,k1-syscon-mpmu", + .data = (ulong)&k1_ccu_mpmu_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(mpmu); + +U_BOOT_DRIVER(k1_mpmu_clk) = { + .name = "k1_mpmu_clk", + .id = UCLASS_CLK, + .of_match = k1_mpmu_clk_match, + .bind = k1_mpmu_clk_bind, + .probe = k1_mpmu_clk_probe, + .ops = &k1_mpmu_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id k1_apbc_clk_match[] = { + { .compatible = "spacemit,k1-syscon-apbc", + .data = (ulong)&k1_ccu_apbc_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(apbc); + +U_BOOT_DRIVER(k1_apbc_clk) = { + .name = "k1_apbc_clk", + .id = UCLASS_CLK, + .of_match = k1_apbc_clk_match, + .bind = k1_apbc_clk_bind, + .probe = k1_apbc_clk_probe, + .ops = &k1_apbc_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id k1_apmu_clk_match[] = { + { .compatible = "spacemit,k1-syscon-apmu", + .data = (ulong)&k1_ccu_apmu_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(apmu); + +U_BOOT_DRIVER(k1_apmu_clk) = { + .name = "k1_apmu_clk", + .id = UCLASS_CLK, + .of_match = k1_apmu_clk_match, + .bind = k1_apmu_clk_bind, + .probe = k1_apmu_clk_probe, + .ops = &k1_apmu_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id k1_apbc2_clk_match[] = { + { .compatible = "spacemit,k1-syscon-apbc2" }, + { /* sentinel */ }, +}; + +U_BOOT_DRIVER(k1_apbc2_clk) = { + .name = "k1_apbc2_clk", + .id = UCLASS_CLK, + .of_match = k1_apbc2_clk_match, + .bind = k1_apbc2_clk_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_common.h b/drivers/clk/spacemit/clk_common.h new file mode 100644 index 00000000000..ea5ebf57784 --- /dev/null +++ b/drivers/clk/spacemit/clk_common.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_COMMON_H_ +#define _CLK_COMMON_H_ + +#include <linux/clk-provider.h> + +struct ccu_common; + +typedef int (*ccu_init_fn)(struct ccu_common *common); + +struct ccu_common { + struct regmap *regmap; + struct regmap *lock_regmap; + const char *name; + const char * const *parents; + size_t num_parents; + ccu_init_fn init; + + union { + /* For DDN and MIX */ + struct { + u32 reg_ctrl; + u32 reg_fc; + u32 mask_fc; + }; + + /* For PLL */ + struct { + u32 reg_swcr1; + u32 reg_swcr3; + }; + }; + + struct clk clk; +}; + +#define CCU_COMMON(_id, _name, _parent, _init, _flags) \ + .name = #_name, \ + .parents = (const char *[]) { _parent }, \ + .num_parents = 1, \ + .init = _init, \ + .clk = { .flags = _flags, .id = _id, } \ + +#define CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, _init, _flags) \ + .name = #_name, \ + .parents = _parents, \ + .num_parents = _num_p, \ + .init = _init, \ + .clk = { .flags = _flags, .id = _id, } \ + +static inline struct ccu_common *clk_to_ccu_common(struct clk *clk) +{ + return container_of(clk, struct ccu_common, clk); +} + +#define ccu_read(c, reg) \ + ({ \ + struct ccu_common * const __ccu = (c); \ + u32 tmp; \ + regmap_read(__ccu->regmap, __ccu->reg_##reg, &tmp); \ + tmp; \ + }) +#define ccu_update(c, reg, mask, val) \ + ({ \ + struct ccu_common * const __ccu = (c); \ + regmap_update_bits(__ccu->regmap, __ccu->reg_##reg, \ + mask, val); \ + }) + +#endif /* _CLK_COMMON_H_ */ diff --git a/drivers/clk/spacemit/clk_ddn.c b/drivers/clk/spacemit/clk_ddn.c new file mode 100644 index 00000000000..7b93f30d5c3 --- /dev/null +++ b/drivers/clk/spacemit/clk_ddn.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Authors: Haylen Chu <[email protected]> + * + * DDN stands for "Divider Denominator Numerator", it's M/N clock with a + * constant x2 factor. This clock hardware follows the equation below, + * + * numerator Fin + * 2 * ------------- = ------- + * denominator Fout + * + * Thus, Fout could be calculated with, + * + * Fin denominator + * Fout = ----- * ------------- + * 2 numerator + */ + +#include <dm/device.h> +#include <regmap.h> +#include <linux/clk-provider.h> +#include <linux/rational.h> + +#include "clk_ddn.h" + +#define UBOOT_DM_SPACEMIT_CLK_DDN "spacemit_clk_ddn" + +static unsigned long ccu_ddn_calc_rate(unsigned long prate, unsigned long num, + unsigned long den, unsigned int pre_div) +{ + return prate * den / pre_div / num; +} + +static unsigned long ccu_ddn_calc_best_rate(struct ccu_ddn *ddn, + unsigned long rate, unsigned long prate, + unsigned long *num, unsigned long *den) +{ + rational_best_approximation(rate, prate / ddn->pre_div, + ddn->den_mask >> ddn->den_shift, + ddn->num_mask >> ddn->num_shift, + den, num); + return ccu_ddn_calc_rate(prate, *num, *den, ddn->pre_div); +} + +static unsigned long ccu_ddn_recalc_rate(struct clk *clk) +{ + struct ccu_ddn *ddn = clk_to_ccu_ddn(clk); + unsigned int val, num, den; + + val = ccu_read(&ddn->common, ctrl); + + num = (val & ddn->num_mask) >> ddn->num_shift; + den = (val & ddn->den_mask) >> ddn->den_shift; + + return ccu_ddn_calc_rate(clk_get_parent_rate(clk), num, den, ddn->pre_div); +} + +static unsigned long ccu_ddn_set_rate(struct clk *clk, unsigned long rate) +{ + struct ccu_ddn *ddn = clk_to_ccu_ddn(clk); + unsigned long num, den; + + ccu_ddn_calc_best_rate(ddn, rate, clk_get_parent_rate(clk), &num, &den); + + ccu_update(&ddn->common, ctrl, + ddn->num_mask | ddn->den_mask, + (num << ddn->num_shift) | (den << ddn->den_shift)); + + return 0; +} + +static const struct clk_ops spacemit_clk_ddn_ops = { + .get_rate = ccu_ddn_recalc_rate, + .set_rate = ccu_ddn_set_rate, +}; + +int spacemit_ddn_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DDN, + common->name, common->parents[0]); +} + +U_BOOT_DRIVER(spacemit_clk_ddn) = { + .name = UBOOT_DM_SPACEMIT_CLK_DDN, + .id = UCLASS_CLK, + .ops = &spacemit_clk_ddn_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_ddn.h b/drivers/clk/spacemit/clk_ddn.h new file mode 100644 index 00000000000..1330ced23b1 --- /dev/null +++ b/drivers/clk/spacemit/clk_ddn.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_DDN_H_ +#define _CLK_DDN_H_ + +#include <linux/clk-provider.h> + +#include "clk_common.h" + +struct ccu_ddn { + struct ccu_common common; + unsigned int num_mask; + unsigned int num_shift; + unsigned int den_mask; + unsigned int den_shift; + unsigned int pre_div; +}; + +#define CCU_DDN_MASK(_num_shift, _num_width) \ + GENMASK((_num_shift) + (_num_width) - 1, _num_shift) + +#define CCU_DDN_DEFINE(_id, _var, _name, _parent, _reg_ctrl, _num_mask, \ + _num_shift, _den_mask, _den_shift, _pre_div, _flags) \ +static struct ccu_ddn _var = { \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, spacemit_ddn_init, _flags) \ + }, \ + .num_mask = _num_mask, \ + .num_shift = _num_shift, \ + .den_mask = _den_mask, \ + .den_shift = _den_shift, \ + .pre_div = _pre_div, \ +} + +static inline struct ccu_ddn *clk_to_ccu_ddn(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_ddn, common); +} + +int spacemit_ddn_init(struct ccu_common *common); + +#endif /* _CLK_DDN_H_ */ diff --git a/drivers/clk/spacemit/clk_mix.c b/drivers/clk/spacemit/clk_mix.c new file mode 100644 index 00000000000..a1158512a92 --- /dev/null +++ b/drivers/clk/spacemit/clk_mix.c @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Authors: Haylen Chu <[email protected]> + * + * MIX clock type is the combination of mux, factor or divider, and gate + */ + +#include <dm/device.h> +#include <dm/uclass.h> +#include <div64.h> +#include <regmap.h> +#include <linux/clk-provider.h> +#include <linux/kernel.h> + +#include "clk_mix.h" + +#define UBOOT_DM_SPACEMIT_CLK_GATE "spacemit_clk_gate" +#define UBOOT_DM_SPACEMIT_CLK_FACTOR "spacemit_clk_factor" +#define UBOOT_DM_SPACEMIT_CLK_MUX "spacemit_clk_mux" +#define UBOOT_DM_SPACEMIT_CLK_DIV "spacemit_clk_div" +#define UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE "spacemit_clk_factor_gate" +#define UBOOT_DM_SPACEMIT_CLK_MUX_GATE "spacemit_clk_mux_gate" +#define UBOOT_DM_SPACEMIT_CLK_DIV_GATE "spacemit_clk_div_gate" +#define UBOOT_DM_SPACEMIT_CLK_MUX_DIV "spacemit_clk_mux_div" +#define UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE "spacemit_clk_mux_div_gate" + +#define MIX_FC_TIMEOUT_US 10000 +#define MIX_FC_DELAY_US 5 + +int ccu_gate_disable(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + + ccu_update(&mix->common, ctrl, mix->gate.mask, 0); + + return 0; +} + +int ccu_gate_enable(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_gate_config *gate = &mix->gate; + + ccu_update(&mix->common, ctrl, gate->mask, gate->mask); + + return 0; +} + +static unsigned long ccu_factor_recalc_rate(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + + return clk_get_parent_rate(clk) * mix->factor.mul / mix->factor.div; +} + +static unsigned long ccu_div_recalc_rate(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_div_config *div = &mix->div; + unsigned long val; + + val = ccu_read(&mix->common, ctrl) >> div->shift; + val &= (1 << div->width) - 1; + + return divider_recalc_rate(clk, clk_get_parent_rate(clk), val, NULL, 0, div->width); +} + +/* + * Some clocks require a "FC" (frequency change) bit to be set after changing + * their rates or reparenting. This bit will be automatically cleared by + * hardware in MIX_FC_TIMEOUT_US, which indicates the operation is completed. + */ +static int ccu_mix_trigger_fc(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + unsigned int val; + + if (common->reg_fc) + return 0; + + ccu_update(common, fc, common->mask_fc, common->mask_fc); + + return regmap_read_poll_timeout(common->regmap, common->reg_fc, + val, !(val & common->mask_fc), + MIX_FC_DELAY_US, + MIX_FC_TIMEOUT_US); +} + +static unsigned long +ccu_mix_calc_best_rate(struct clk *clk, unsigned long rate, + struct clk **best_parent, + unsigned long *best_parent_rate, + u32 *div_val) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + struct ccu_mix *mix = clk_to_ccu_mix(clk); + unsigned int parent_num = common->num_parents; + struct ccu_div_config *div = &mix->div; + u32 div_max = 1 << div->width; + unsigned long best_rate = 0; + + for (int i = 0; i < parent_num; i++) { + struct udevice *parent_dev; + unsigned long parent_rate; + struct clk *parent; + + if (uclass_get_device_by_name(UCLASS_CLK, common->parents[i], + &parent_dev)) + continue; + parent = dev_get_clk_ptr(parent_dev); + if (!parent) + continue; + + parent_rate = clk_get_rate(parent); + + for (int j = 1; j <= div_max; j++) { + unsigned long tmp = DIV_ROUND_CLOSEST_ULL(parent_rate, j); + + if (abs(tmp - rate) < abs(best_rate - rate)) { + best_rate = tmp; + + if (div_val) + *div_val = j - 1; + + if (best_parent) { + *best_parent = parent; + *best_parent_rate = parent_rate; + } + } + } + } + + return best_rate; +} + +static unsigned long ccu_mix_set_rate(struct clk *clk, unsigned long rate) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_common *common = &mix->common; + struct ccu_div_config *div = &mix->div; + u32 current_div, target_div, mask; + + ccu_mix_calc_best_rate(clk, rate, NULL, NULL, &target_div); + + current_div = ccu_read(common, ctrl) >> div->shift; + current_div &= (1 << div->width) - 1; + + if (current_div == target_div) + return 0; + + mask = GENMASK(div->width + div->shift - 1, div->shift); + + ccu_update(common, ctrl, mask, target_div << div->shift); + + return ccu_mix_trigger_fc(clk); +} + +static u8 ccu_mux_get_parent(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_mux_config *mux = &mix->mux; + u8 parent; + + parent = ccu_read(&mix->common, ctrl) >> mux->shift; + parent &= (1 << mux->width) - 1; + + return parent; +} + +static int ccu_mux_set_parent(struct clk *clk, struct clk *parent) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_mux_config *mux = &mix->mux; + u32 mask; + int i = 0; + + mask = GENMASK(mux->width + mux->shift - 1, mux->shift); + + for (i = 0; i < common->num_parents; i++) { + if (!strcmp(parent->dev->name, common->parents[i])) + break; + } + + if (i == common->num_parents) + return -EINVAL; + + ccu_update(&mix->common, ctrl, mask, i << mux->shift); + + return ccu_mix_trigger_fc(clk); +} + +int spacemit_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_GATE, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .get_rate = clk_generic_get_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_factor_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_FACTOR, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_factor_ops = { + .get_rate = ccu_factor_recalc_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_factor) = { + .name = UBOOT_DM_SPACEMIT_CLK_FACTOR, + .id = UCLASS_CLK, + .ops = &spacemit_clk_factor_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_ops = { + .set_parent = ccu_mux_set_parent, + .get_rate = clk_generic_get_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_div_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DIV, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_div_ops = { + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_div) = { + .name = UBOOT_DM_SPACEMIT_CLK_DIV, + .id = UCLASS_CLK, + .ops = &spacemit_clk_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_factor_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_factor_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .get_rate = ccu_factor_recalc_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_factor_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_factor_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_GATE, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .set_parent = ccu_mux_set_parent, + .get_rate = clk_generic_get_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_div_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DIV_GATE, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_div_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_div_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_DIV_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_div_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_div_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_DIV, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_div_ops = { + .set_parent = ccu_mux_set_parent, + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux_div) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX_DIV, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_div_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_div_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .set_parent = ccu_mux_set_parent, + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux_div_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_div_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_mix.h b/drivers/clk/spacemit/clk_mix.h new file mode 100644 index 00000000000..26a12cedd0d --- /dev/null +++ b/drivers/clk/spacemit/clk_mix.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_MIX_H_ +#define _CLK_MIX_H_ + +#include <linux/clk-provider.h> + +#include "clk_common.h" + +/** + * struct ccu_gate_config - Gate configuration + * + * @mask: Mask to enable the gate. Some clocks may have more than one bit + * set in this field. + */ +struct ccu_gate_config { + u32 mask; +}; + +struct ccu_factor_config { + u32 div; + u32 mul; +}; + +struct ccu_mux_config { + u8 shift; + u8 width; +}; + +struct ccu_div_config { + u8 shift; + u8 width; +}; + +struct ccu_mix { + struct ccu_factor_config factor; + struct ccu_gate_config gate; + struct ccu_div_config div; + struct ccu_mux_config mux; + struct ccu_common common; +}; + +#define CCU_GATE_INIT(_mask) { .mask = _mask } +#define CCU_FACTOR_INIT(_div, _mul) { .div = _div, .mul = _mul } +#define CCU_MUX_INIT(_shift, _width) { .shift = _shift, .width = _width } +#define CCU_DIV_INIT(_shift, _width) { .shift = _shift, .width = _width } + +#define CCU_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl, \ + _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, spacemit_gate_init, \ + _flags) \ + } \ +} + +#define CCU_FACTOR_DEFINE(_id, _var, _name, _parent, _div, _mul) \ +static struct ccu_mix _var = { \ + .factor = CCU_FACTOR_INIT(_div, _mul), \ + .common = { \ + CCU_COMMON(_id, _name, _parent, spacemit_factor_init, \ + 0) \ + } \ +} + +#define CCU_MUX_DEFINE(_id, _var, _name, _parents, _num_p, _reg_ctrl, \ + _shift, _width, _flags) \ +static struct ccu_mix _var = { \ + .mux = CCU_MUX_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_init, _flags) \ + } \ +} + +#define CCU_DIV_DEFINE(_id, _var, _name, _parent, _reg_ctrl, _shift, \ + _width, _flags) \ +static struct ccu_mix _var = { \ + .div = CCU_DIV_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, spacemit_div_init, \ + _flags) \ + } \ +} + +#define CCU_FACTOR_GATE_FLAGS_DEFINE(_id, _var, _name, _parent, \ + _reg_ctrl, _mask_gate, _div, _mul, \ + _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .factor = CCU_FACTOR_INIT(_div, _mul), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, \ + spacemit_factor_gate_init, _flags) \ + } \ +} + +#define CCU_FACTOR_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl, \ + _mask_gate, _div, _mul) \ + CCU_FACTOR_GATE_FLAGS_DEFINE(_id, _var, _name, _parent, \ + _reg_ctrl, _mask_gate, _div, _mul, \ + 0) + +#define CCU_MUX_GATE_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _shift, _width, _mask_gate, \ + _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .mux = CCU_MUX_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_gate_init, _flags) \ + } \ +} + +#define CCU_DIV_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl, \ + _shift, _width, _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .div = CCU_DIV_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, \ + spacemit_div_gate_init, _flags) \ + } \ +} + +#define CCU_MUX_DIV_GATE_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _mshift, _mwidth, _muxshift, \ + _muxwidth, _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .div = CCU_DIV_INIT(_mshift, _mwidth), \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_div_gate_init, _flags) \ + }, \ +} + +#define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_id, _var, _name, _parents, \ + _num_p, _reg_ctrl, _reg_fc, \ + _mshift, _mwidth, _mask_fc, \ + _muxshift, _muxwidth, \ + _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .div = CCU_DIV_INIT(_mshift, _mwidth), \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + .reg_fc = _reg_fc, \ + .mask_fc = _mask_fc, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_div_gate_init, _flags) \ + }, \ +} + +#define CCU_MUX_DIV_FC_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _reg_fc, _mshift, _mwidth, \ + _mask_fc, _muxshift, _muxwidth, _flags) \ +static struct ccu_mix _var = { \ + .div = CCU_DIV_INIT(_mshift, _mwidth), \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + .reg_fc = _reg_fc, \ + .mask_fc = _mask_fc, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_div_init, _flags) \ + }, \ +} + +#define CCU_MUX_FC_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _reg_fc, _mask_fc, _muxshift, \ + _muxwidth, _flags) \ +static struct ccu_mix _var = { \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + .reg_fc = _reg_fc, \ + .mask_fc = _mask_fc, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_init, \ + _flags) \ + }, \ +} + +static inline struct ccu_mix *clk_to_ccu_mix(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_mix, common); +} + +int ccu_gate_enable(struct clk *clk); +int ccu_gate_disable(struct clk *clk); + +int spacemit_gate_init(struct ccu_common *common); +int spacemit_factor_init(struct ccu_common *common); +int spacemit_mux_init(struct ccu_common *common); +int spacemit_div_init(struct ccu_common *common); +int spacemit_factor_gate_init(struct ccu_common *common); +int spacemit_div_gate_init(struct ccu_common *common); +int spacemit_mux_gate_init(struct ccu_common *common); +int spacemit_mux_div_init(struct ccu_common *common); +int spacemit_mux_div_gate_init(struct ccu_common *common); + +#endif /* _CLK_MIX_H_ */ diff --git a/drivers/clk/spacemit/clk_pll.c b/drivers/clk/spacemit/clk_pll.c new file mode 100644 index 00000000000..56da70af58a --- /dev/null +++ b/drivers/clk/spacemit/clk_pll.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Authors: Haylen Chu <[email protected]> + */ + +#include <dm/device.h> +#include <regmap.h> +#include <linux/bug.h> +#include <linux/clk-provider.h> + +#include "clk_pll.h" + +#define UBOOT_DM_SPACEMIT_CLK_PLL "spacemit_clk_pll" + +#define PLL_TIMEOUT_US 3000 +#define PLL_DELAY_US 5 + +#define PLL_SWCR3_EN ((u32)BIT(31)) +#define PLL_SWCR3_MASK GENMASK(30, 0) + +static const struct ccu_pll_rate_tbl *ccu_pll_lookup_best_rate(struct ccu_pll *pll, + unsigned long rate) +{ + struct ccu_pll_config *config = &pll->config; + const struct ccu_pll_rate_tbl *best_entry; + unsigned long best_delta = ULONG_MAX; + int i; + + for (i = 0; i < config->tbl_num; i++) { + const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i]; + unsigned long delta = abs(entry->rate - rate); + + if (delta < best_delta) { + best_delta = delta; + best_entry = entry; + } + } + + return best_entry; +} + +static const struct ccu_pll_rate_tbl *ccu_pll_lookup_matched_entry(struct ccu_pll *pll) +{ + struct ccu_pll_config *config = &pll->config; + u32 swcr1, swcr3; + int i; + + swcr1 = ccu_read(&pll->common, swcr1); + swcr3 = ccu_read(&pll->common, swcr3); + swcr3 &= PLL_SWCR3_MASK; + + for (i = 0; i < config->tbl_num; i++) { + const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i]; + + if (swcr1 == entry->swcr1 && swcr3 == entry->swcr3) + return entry; + } + + return NULL; +} + +static void ccu_pll_update_param(struct ccu_pll *pll, const struct ccu_pll_rate_tbl *entry) +{ + struct ccu_common *common = &pll->common; + + regmap_write(common->regmap, common->reg_swcr1, entry->swcr1); + ccu_update(common, swcr3, PLL_SWCR3_MASK, entry->swcr3); +} + +static int ccu_pll_enable(struct clk *clk) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + struct ccu_common *common = &pll->common; + unsigned int tmp; + + ccu_update(common, swcr3, PLL_SWCR3_EN, PLL_SWCR3_EN); + + /* check lock status */ + return regmap_read_poll_timeout(common->lock_regmap, + pll->config.reg_lock, + tmp, + tmp & pll->config.mask_lock, + PLL_DELAY_US, PLL_TIMEOUT_US); +} + +static int ccu_pll_disable(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + ccu_update(common, swcr3, PLL_SWCR3_EN, 0); + + return 0; +} + +/* + * PLLs must be gated before changing rate, which is ensured by + * flag CLK_SET_RATE_GATE. + */ +static unsigned long ccu_pll_set_rate(struct clk *clk, unsigned long rate) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + const struct ccu_pll_rate_tbl *entry; + + entry = ccu_pll_lookup_best_rate(pll, rate); + ccu_pll_update_param(pll, entry); + + return 0; +} + +static unsigned long ccu_pll_recalc_rate(struct clk *clk) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + const struct ccu_pll_rate_tbl *entry; + + entry = ccu_pll_lookup_matched_entry(pll); + + WARN_ON_ONCE(!entry); + + return entry ? entry->rate : 0; +} + +static const struct clk_ops spacemit_clk_pll_ops = { + .enable = ccu_pll_enable, + .disable = ccu_pll_disable, + .set_rate = ccu_pll_set_rate, + .get_rate = ccu_pll_recalc_rate, +}; + +int spacemit_pll_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + struct ccu_pll *pll = clk_to_ccu_pll(clk); + int ret; + + ret = clk_register(clk, UBOOT_DM_SPACEMIT_CLK_PLL, + common->name, common->parents[0]); + if (ret) + return ret; + + if (ccu_pll_lookup_matched_entry(pll)) + return 0; + + ccu_pll_disable(clk); + ccu_pll_update_param(pll, &pll->config.rate_tbl[0]); + + return 0; +} + +U_BOOT_DRIVER(spacemit_clk_pll) = { + .name = UBOOT_DM_SPACEMIT_CLK_PLL, + .id = UCLASS_CLK, + .ops = &spacemit_clk_pll_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_pll.h b/drivers/clk/spacemit/clk_pll.h new file mode 100644 index 00000000000..3987cc1141b --- /dev/null +++ b/drivers/clk/spacemit/clk_pll.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_PLL_H_ +#define _CLK_PLL_H_ + +#include <linux/clk-provider.h> + +#include "clk_common.h" + +/** + * struct ccu_pll_rate_tbl - Structure mapping between PLL rate and register + * configuration. + * + * @rate: PLL rate + * @swcr1: Register value of PLLX_SW1_CTRL (PLLx_SWCR1). + * @swcr3: Register value of the PLLx_SW3_CTRL's lowest 31 bits of + * PLLx_SW3_CTRL (PLLx_SWCR3). This highest bit is for enabling + * the PLL and not contained in this field. + */ +struct ccu_pll_rate_tbl { + unsigned long rate; + u32 swcr1; + u32 swcr3; +}; + +#define CCU_PLL_RATE(_rate, _swcr1, _swcr3) \ + { \ + .rate = _rate, \ + .swcr1 = _swcr1, \ + .swcr3 = _swcr3, \ + } + +struct ccu_pll_config { + const struct ccu_pll_rate_tbl *rate_tbl; + u32 tbl_num; + u32 reg_lock; + u32 mask_lock; +}; + +struct ccu_pll { + struct ccu_common common; + struct ccu_pll_config config; +}; + +#define CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock) \ + { \ + .rate_tbl = (_table), \ + .tbl_num = sizeof(_table) / sizeof((_table)[0]), \ + .reg_lock = (_reg_lock), \ + .mask_lock = (_mask_lock), \ + } + +#define CCU_PLL_DEFINE(_id, _var, _name, _parent, _table, _reg_swcr1, \ + _reg_swcr3, _reg_lock, _mask_lock, _flags) \ +static struct ccu_pll _var = { \ + .config = CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock), \ + .common = { \ + .reg_swcr1 = _reg_swcr1, \ + .reg_swcr3 = _reg_swcr3, \ + CCU_COMMON(_id, _name, _parent, spacemit_pll_init, _flags) \ + } \ +} + +static inline struct ccu_pll *clk_to_ccu_pll(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_pll, common); +} + +int spacemit_pll_init(struct ccu_common *common); + +#endif /* _CLK_PLL_H_ */ diff --git a/drivers/clk/sunxi/clk_a523.c b/drivers/clk/sunxi/clk_a523.c index 1de95fbaf2f..494ee195599 100644 --- a/drivers/clk/sunxi/clk_a523.c +++ b/drivers/clk/sunxi/clk_a523.c @@ -16,6 +16,7 @@ static struct ccu_clk_gate a523_gates[] = { [CLK_PLL_PERIPH0_200M] = GATE_DUMMY, [CLK_APB1] = GATE_DUMMY, + [CLK_MBUS_EMAC1] = GATE(0x804, BIT(12)), [CLK_BUS_MMC0] = GATE(0x84c, BIT(0)), [CLK_BUS_MMC1] = GATE(0x84c, BIT(1)), [CLK_BUS_MMC2] = GATE(0x84c, BIT(2)), |
