summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile5
-rw-r--r--drivers/clk/Kconfig12
-rw-r--r--drivers/clk/Makefile2
-rw-r--r--drivers/clk/clk-renesas-pcie.c327
-rw-r--r--drivers/clk/mediatek/clk-mt7622.c239
-rw-r--r--drivers/clk/mediatek/clk-mt7623.c127
-rw-r--r--drivers/clk/mediatek/clk-mt7629.c195
-rw-r--r--drivers/clk/mediatek/clk-mt7981.c126
-rw-r--r--drivers/clk/mediatek/clk-mt7986.c69
-rw-r--r--drivers/clk/mediatek/clk-mt7987.c70
-rw-r--r--drivers/clk/mediatek/clk-mt7988.c144
-rw-r--r--drivers/clk/mediatek/clk-mt8183.c63
-rw-r--r--drivers/clk/mediatek/clk-mt8188.c551
-rw-r--r--drivers/clk/mediatek/clk-mt8189.c112
-rw-r--r--drivers/clk/mediatek/clk-mt8195.c52
-rw-r--r--drivers/clk/mediatek/clk-mt8365.c51
-rw-r--r--drivers/clk/mediatek/clk-mt8512.c101
-rw-r--r--drivers/clk/mediatek/clk-mt8516.c65
-rw-r--r--drivers/clk/mediatek/clk-mt8518.c65
-rw-r--r--drivers/clk/mediatek/clk-mtk.c306
-rw-r--r--drivers/clk/mediatek/clk-mtk.h31
-rw-r--r--drivers/clk/renesas/r8a78000-cpg.c4
-rw-r--r--drivers/clk/spacemit/Kconfig23
-rw-r--r--drivers/clk/spacemit/Makefile7
-rw-r--r--drivers/clk/spacemit/clk-k1.c1878
-rw-r--r--drivers/clk/spacemit/clk_common.h79
-rw-r--r--drivers/clk/spacemit/clk_ddn.c93
-rw-r--r--drivers/clk/spacemit/clk_ddn.h53
-rw-r--r--drivers/clk/spacemit/clk_mix.c403
-rw-r--r--drivers/clk/spacemit/clk_mix.h224
-rw-r--r--drivers/clk/spacemit/clk_pll.c157
-rw-r--r--drivers/clk/spacemit/clk_pll.h81
-rw-r--r--drivers/clk/sunxi/clk_a523.c1
-rw-r--r--drivers/crypto/aspeed/aspeed_hace.c2
-rw-r--r--drivers/crypto/aspeed/cptra_sha.c2
-rw-r--r--drivers/crypto/hash/hash-uclass.c35
-rw-r--r--drivers/firmware/firmware-zynqmp.c104
-rw-r--r--drivers/firmware/scmi/Kconfig3
-rw-r--r--drivers/firmware/scmi/scmi_agent-uclass.c10
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/spacemit_gpio.c253
-rw-r--r--drivers/i2c/Kconfig7
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/i2c/k1_i2c.c523
-rw-r--r--drivers/i2c/k1_i2c.h69
-rw-r--r--drivers/i3c/master.c1
-rw-r--r--drivers/i3c/master/dw-i3c-master.c7
-rw-r--r--drivers/mailbox/mpfs-mbox.c27
-rw-r--r--drivers/misc/mpfs_syscontroller.c36
-rw-r--r--drivers/mmc/mmc.c45
-rw-r--r--drivers/mmc/mmc_private.h4
-rw-r--r--drivers/mmc/mmc_write.c25
-rw-r--r--drivers/mmc/rpmb.c2
-rw-r--r--drivers/mmc/sdhci.c3
-rw-r--r--drivers/mmc/sunxi_mmc.c6
-rw-r--r--drivers/mtd/Kconfig2
-rw-r--r--drivers/mtd/cfi_flash.c9
-rw-r--r--drivers/mtd/nand/raw/rockchip_nfc.c14
-rw-r--r--drivers/mtd/renesas_rpc_hf.c26
-rw-r--r--drivers/mtd/spi/Makefile5
-rw-r--r--drivers/mtd/spi/sf_probe.c8
-rw-r--r--drivers/mtd/ubi/part.c2
-rw-r--r--drivers/net/Kconfig9
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/dm9000x.c6
-rw-r--r--drivers/net/dwc_eth_qos.c6
-rw-r--r--drivers/net/dwc_eth_qos.h1
-rw-r--r--drivers/net/dwc_eth_qos_sunxi.c254
-rw-r--r--drivers/net/dwc_eth_xgmac.c1
-rw-r--r--drivers/net/ftmac100.c6
-rw-r--r--drivers/net/ks8851_mll.c6
-rw-r--r--drivers/net/phy/dp83867.c18
-rw-r--r--drivers/net/phy/phy.c29
-rw-r--r--drivers/net/rtl8169.c103
-rw-r--r--drivers/net/smc911x.c6
-rw-r--r--drivers/nvme/nvme.c73
-rw-r--r--drivers/nvme/nvme.h3
-rw-r--r--drivers/pci/Kconfig1
-rw-r--r--drivers/pci/pci-rcar-gen4.c118
-rw-r--r--drivers/pci/pcie_layerscape_fixup.c5
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-37xx.c2
-rw-r--r--drivers/pinctrl/pinctrl-single.c77
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a77951.c28
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a7796.c22
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a77965.c28
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rk3568.c186
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rv1126.c134
-rw-r--r--drivers/pinctrl/spacemit/Kconfig9
-rw-r--r--drivers/pinctrl/spacemit/Makefile2
-rw-r--r--drivers/pinctrl/spacemit/pinctrl-k1.c550
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c3
-rw-r--r--drivers/power/domain/Kconfig89
-rw-r--r--drivers/power/domain/Makefile15
-rw-r--r--drivers/power/domain/mt2701-power-domain.c89
-rw-r--r--drivers/power/domain/mt7622-power-domain.c56
-rw-r--r--drivers/power/domain/mt8188-power-domain.c665
-rw-r--r--drivers/power/domain/mtk-power-domain.c576
-rw-r--r--drivers/power/domain/mtk-power-domain.h131
-rw-r--r--drivers/power/domain/renesas-r8a78000-power-domain.c4
-rw-r--r--drivers/power/pmic/Kconfig23
-rw-r--r--drivers/power/pmic/Makefile2
-rw-r--r--drivers/power/pmic/pf9453.c170
-rw-r--r--drivers/power/pmic/pmic_spacemit_p1.c94
-rw-r--r--drivers/power/pmic/tps65219.c1
-rw-r--r--drivers/power/regulator/Kconfig22
-rw-r--r--drivers/power/regulator/Makefile2
-rw-r--r--drivers/power/regulator/pf9453.c256
-rw-r--r--drivers/power/regulator/spacemit_p1_regulator.c464
-rw-r--r--drivers/ram/Kconfig1
-rw-r--r--drivers/ram/k3-ddrss/k3-ddrss.c3
-rw-r--r--drivers/remoteproc/renesas_rsip.c202
-rw-r--r--drivers/reset/Kconfig7
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/reset-spacemit-k1.c548
-rw-r--r--drivers/reset/spacemit/Makefile5
-rw-r--r--drivers/reset/spacemit/reset-spacemit-k1.c289
-rw-r--r--drivers/rng/Kconfig7
-rw-r--r--drivers/rng/Makefile1
-rw-r--r--drivers/rng/jh7110_rng.c4
-rw-r--r--drivers/rng/mpfs_rng.c101
-rw-r--r--drivers/rtc/Kconfig7
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/pcf8563.c4
-rw-r--r--drivers/rtc/snvs-rtc.c118
-rw-r--r--drivers/serial/Kconfig15
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial-uclass.c10
-rw-r--r--drivers/serial/serial_coreboot.c3
-rw-r--r--drivers/serial/serial_esp32.c367
-rw-r--r--drivers/serial/serial_mcf.c4
-rw-r--r--drivers/serial/serial_msm_geni.c5
-rw-r--r--drivers/serial/serial_sifive.c11
-rw-r--r--drivers/spi/cf_spi.c2
-rw-r--r--drivers/spi/designware_spi.c12
-rw-r--r--drivers/spi/fsl_qspi.c9
-rw-r--r--drivers/spi/renesas_rpc_spi.c19
-rw-r--r--drivers/spi/spi-sunxi.c4
-rw-r--r--drivers/spi/zynqmp_gqspi.c43
-rw-r--r--drivers/sysinfo/Kconfig1
-rw-r--r--drivers/ufs/Kconfig2
-rw-r--r--drivers/ufs/ufs-amd-versal2.c133
-rw-r--r--drivers/ufs/ufs-renesas-rcar-gen5.c22
-rw-r--r--drivers/ufs/ufs-uclass.c1
-rw-r--r--drivers/usb/gadget/ci_udc.c30
-rw-r--r--drivers/usb/gadget/ci_udc.h4
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg.c26
-rw-r--r--drivers/usb/gadget/f_mass_storage.c8
-rw-r--r--drivers/usb/host/xhci-dwc3.c7
-rw-r--r--drivers/usb/mtu3/Kconfig39
-rw-r--r--drivers/usb/mtu3/Makefile10
-rw-r--r--drivers/usb/mtu3/mtu3.h14
-rw-r--r--drivers/usb/mtu3/mtu3_core.c46
-rw-r--r--drivers/usb/mtu3/mtu3_dr.h4
-rw-r--r--drivers/usb/mtu3/mtu3_gadget.c5
-rw-r--r--drivers/usb/mtu3/mtu3_host.c11
-rw-r--r--drivers/usb/mtu3/mtu3_hw_regs.h11
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c227
-rw-r--r--drivers/watchdog/Kconfig6
-rw-r--r--drivers/watchdog/ast2600_wdt.c1
162 files changed, 11040 insertions, 2677 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 43d0ba33281..269c3db12e8 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_$(PHASE_)PHY) += phy/
obj-$(CONFIG_$(PHASE_)PINCTRL) += pinctrl/
obj-$(CONFIG_$(PHASE_)POWER) += power/
obj-$(CONFIG_$(PHASE_)RAM) += ram/
+obj-$(CONFIG_$(PHASE_)DM_RNG) += rng/
obj-$(CONFIG_$(PHASE_)RTC) += rtc/
obj-$(CONFIG_$(PHASE_)SERIAL) += serial/
obj-$(CONFIG_$(PHASE_)SPI) += spi/
@@ -66,7 +67,8 @@ obj-$(CONFIG_DRAM_SUN20I_D1) += ram/
obj-$(CONFIG_SPL_DM_RESET) += reset/
obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
-obj-$(CONFIG_SPL_USB_GADGET) += usb/common/
+obj-$(CONFIG_SPL_DM_USB) += usb/common/
+obj-$(CONFIG_SPL_USB_MTU3) += usb/mtu3/
obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/udc/
obj-$(CONFIG_SPL_WATCHDOG) += watchdog/
obj-$(CONFIG_SPL_USB_HOST) += usb/host/
@@ -131,7 +133,6 @@ obj-$(CONFIG_W1_EEPROM) += w1-eeprom/
obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
obj-$(CONFIG_FUZZ) += fuzz/
obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock/
-obj-$(CONFIG_$(PHASE_)DM_RNG) += rng/
endif
obj-y += soc/
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)),
diff --git a/drivers/crypto/aspeed/aspeed_hace.c b/drivers/crypto/aspeed/aspeed_hace.c
index 22b5008a296..2469f53472f 100644
--- a/drivers/crypto/aspeed/aspeed_hace.c
+++ b/drivers/crypto/aspeed/aspeed_hace.c
@@ -160,7 +160,7 @@ static int aspeed_hace_init(struct udevice *dev, enum HASH_ALGO algo, void **ctx
free_n_out:
free(hace_ctx);
- return -EINVAL;
+ return -EOPNOTSUPP;
}
static int aspeed_hace_update(struct udevice *dev, void *ctx, const void *ibuf, uint32_t ilen)
diff --git a/drivers/crypto/aspeed/cptra_sha.c b/drivers/crypto/aspeed/cptra_sha.c
index f57778e160d..0dc00f306f1 100644
--- a/drivers/crypto/aspeed/cptra_sha.c
+++ b/drivers/crypto/aspeed/cptra_sha.c
@@ -68,7 +68,7 @@ static int cptra_sha_init(struct udevice *dev, enum HASH_ALGO algo, void **ctxp)
cs_ctx->dgst_len = 64;
break;
default:
- rc = -EINVAL;
+ rc = -EOPNOTSUPP;
goto free_n_out;
};
diff --git a/drivers/crypto/hash/hash-uclass.c b/drivers/crypto/hash/hash-uclass.c
index 5d9f1e0d59b..ffca19af2de 100644
--- a/drivers/crypto/hash/hash-uclass.c
+++ b/drivers/crypto/hash/hash-uclass.c
@@ -84,6 +84,41 @@ int hash_digest_wd(struct udevice *dev, enum HASH_ALGO algo,
return ops->hash_digest_wd(dev, algo, ibuf, ilen, obuf, chunk_sz);
}
+static bool hash_op_unsupported(int ret)
+{
+ return ret == -ENOSYS || ret == -EOPNOTSUPP;
+}
+
+int hash_digest_wd_lookup(enum HASH_ALGO algo, const void *ibuf,
+ const u32 ilen, void *obuf, u32 chunk_sz)
+{
+ struct udevice *dev;
+ int first_probe_err = 0;
+ bool found = false;
+ int ret;
+
+ for (ret = uclass_first_device_check(UCLASS_HASH, &dev); dev;
+ ret = uclass_next_device_check(&dev)) {
+ found = true;
+ if (ret) {
+ if (!first_probe_err)
+ first_probe_err = ret;
+ continue;
+ }
+
+ ret = hash_digest_wd(dev, algo, ibuf, ilen, obuf, chunk_sz);
+ if (!ret)
+ return 0;
+ if (!hash_op_unsupported(ret))
+ return ret;
+ }
+
+ if (first_probe_err)
+ return first_probe_err;
+
+ return found ? -EOPNOTSUPP : -ENODEV;
+}
+
int hash_init(struct udevice *dev, enum HASH_ALGO algo, void **ctxp)
{
struct hash_ops *ops = (struct hash_ops *)device_get_ops(dev);
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index 6052a31b5b4..fae66ccb3d8 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -19,10 +19,10 @@
#include <asm/ptrace.h>
#include <asm/system.h>
#include <linux/bitfield.h>
+#include <linux/delay.h>
#if defined(CONFIG_ZYNQMP_IPI)
#include <mailbox.h>
-#include <asm/arch/sys_proto.h>
#define PMUFW_PAYLOAD_ARG_CNT 8
@@ -176,28 +176,106 @@ unsigned int zynqmp_firmware_version(void)
};
#if defined(CONFIG_ARCH_VERSAL2)
-int zynqmp_pm_ufs_get_txrx_cfgrdy(u32 *value)
+/*
+ * Poll the M-PHY TX/RX config-ready status until it settles or @timeout_us
+ * elapses. Legacy EEMI firmware only offers the per-read status primitive, so
+ * the poll loop lives here rather than in the UFS driver; the timeout budget is
+ * owned by the caller.
+ */
+int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us)
{
- *value = readl(PMXC_SLCR_BASE_ADDRESS + PMXC_TX_RX_CFG_RDY);
- return 0;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ while (timeout_us--) {
+ ret = xilinx_pm_request(PM_IOCTL, PM_REGNODE_PMC_IOU_SLCR,
+ IOCTL_READ_REG, TXRX_CFGRDY_OFFSET, 0, 0,
+ 0, ret_payload);
+ if (ret)
+ return ret;
+
+ if (!(ret_payload[1] & TX_RX_CFG_RDY_MASK))
+ return 0;
+
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
}
-int zynqmp_pm_ufs_sram_csr_read(u32 *value)
+int zynqmp_pm_wait_sram_init_done(u32 timeout_us)
{
- *value = readl(PMXC_SLCR_BASE_ADDRESS + PMXC_SRAM_CSR);
- return 0;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ while (timeout_us--) {
+ ret = xilinx_pm_request(PM_IOCTL, PM_REGNODE_PMC_IOU_SLCR,
+ IOCTL_READ_REG, SRAM_CSR_OFFSET, 0, 0,
+ 0, ret_payload);
+ if (ret)
+ return ret;
+
+ if (ret_payload[1] & SRAM_CSR_INIT_DONE_MASK)
+ return 0;
+
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
}
-int zynqmp_pm_ufs_sram_csr_write(u32 *value)
+int zynqmp_pm_set_sram_bypass(void)
{
- writel(*value, PMXC_SLCR_BASE_ADDRESS + PMXC_SRAM_CSR);
- return 0;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ u32 sram_csr;
+ int ret;
+
+ ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_MASK_WRITE_REG);
+ if (ret) {
+ printf("%s: IOCTL_MASK_WRITE_REG is not supported : %d\n"
+ , __func__, ret);
+ return 0;
+ }
+
+ ret = xilinx_pm_request(PM_IOCTL, PM_REGNODE_PMC_IOU_SLCR,
+ IOCTL_READ_REG, SRAM_CSR_OFFSET, 0, 0,
+ 0, ret_payload);
+ if (ret)
+ return ret;
+
+ sram_csr = ret_payload[1];
+ sram_csr &= ~SRAM_CSR_EXT_LD_DONE_MASK;
+ sram_csr |= SRAM_CSR_BYPASS_MASK;
+
+ return xilinx_pm_request(PM_IOCTL, PM_REGNODE_PMC_IOU_SLCR,
+ IOCTL_MASK_WRITE_REG, SRAM_CSR_OFFSET,
+ GENMASK(2, 1), sram_csr, 0, NULL);
}
-int zynqmp_pm_ufs_cal_reg(u32 *value)
+int zynqmp_pm_get_ufs_calibration_values(u32 *value)
{
- *value = readl(PMXC_EFUSE_CACHE_BASE_ADDRESS + PMXC_UFS_CAL_1_OFFSET);
- return 0;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ if (!value)
+ return -EINVAL;
+
+ ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_REG);
+ if (ret) {
+ printf("%s: IOCTL_READ_REG is not supported : %d\n"
+ , __func__, ret);
+ return 0;
+ }
+
+ ret = xilinx_pm_request(PM_IOCTL, PM_REGNODE_EFUSE_CACHE,
+ IOCTL_READ_REG, UFS_CAL_1_OFFSET, 0, 0,
+ 0, ret_payload);
+ if (ret)
+ return ret;
+
+ *value = ret_payload[1];
+
+ return ret;
}
#endif /* CONFIG_ARCH_VERSAL2 */
diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig
index cd912ebe409..64bc9aef5af 100644
--- a/drivers/firmware/scmi/Kconfig
+++ b/drivers/firmware/scmi/Kconfig
@@ -46,6 +46,9 @@ config SCMI_AGENT_OPTEE
config SCMI_ID_VENDOR_80
bool
+config SCMI_ID_VENDOR_81
+ bool
+
config SCMI_ID_VENDOR_82
bool
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index cd458a7f458..9159e59385b 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -116,6 +116,11 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
proto = priv->vendor_dev_80;
break;
#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_81)
+ case SCMI_PROTOCOL_ID_VENDOR_81:
+ proto = priv->vendor_dev_81;
+ break;
+#endif
#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_82)
case SCMI_PROTOCOL_ID_VENDOR_82:
proto = priv->vendor_dev_82;
@@ -189,6 +194,11 @@ static int scmi_add_protocol(struct udevice *dev,
priv->vendor_dev_80 = proto;
break;
#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_81)
+ case SCMI_PROTOCOL_ID_VENDOR_81:
+ priv->vendor_dev_81 = proto;
+ break;
+#endif
#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_82)
case SCMI_PROTOCOL_ID_VENDOR_82:
priv->vendor_dev_82 = proto;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 75b35fbc5be..a11f3043670 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -449,6 +449,14 @@ config SANDBOX_GPIO_COUNT
of 'anonymous' GPIOs that do not belong to any device or bank.
Select a suitable value depending on your needs.
+config SPACEMIT_GPIO
+ bool "Spacemit K1 GPIO driver"
+ depends on DM_GPIO && TARGET_SPACEMIT_K1
+ help
+ Support the GPIO device in Spacemit SoCs. The GPIOs are arranged
+ into a number of banks (different for each SoC type) each with 32
+ GPIOs.
+
config SUNXI_GPIO
bool "Allwinner GPIO driver"
depends on ARCH_SUNXI
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 863557e45ce..020e23c7252 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o
obj-$(CONFIG_MSM_GPIO) += msm_gpio.o
obj-$(CONFIG_$(PHASE_)PCF8575_GPIO) += pcf8575_gpio.o
obj-$(CONFIG_$(PHASE_)QCOM_PMIC_GPIO) += qcom_pmic_gpio.o qcom_spmi_gpio.o
+obj-$(CONFIG_$(PHASE_)SPACEMIT_GPIO) += spacemit_gpio.o
obj-$(CONFIG_MT7620_GPIO) += mt7620_gpio.o
obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o
obj-$(CONFIG_MSCC_SGPIO) += mscc_sgpio.o
diff --git a/drivers/gpio/spacemit_gpio.c b/drivers/gpio/spacemit_gpio.c
new file mode 100644
index 00000000000..de71880df15
--- /dev/null
+++ b/drivers/gpio/spacemit_gpio.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025-2026 RISCstar Ltd.
+ */
+
+#include <asm/gpio.h>
+#include <clk.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/pinctrl.h>
+#include <dm/read.h>
+#include <dm/uclass.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <log.h>
+
+#define GPIO_BANK_SIZE 32
+#define GPIO_TO_BANK(pin) ((pin) / GPIO_BANK_SIZE)
+#define GPIO_TO_BIT(pin) ((pin) % GPIO_BANK_SIZE)
+
+static inline int gpio_to_reg_offset(unsigned int pin)
+{
+ unsigned int bank = GPIO_TO_BANK(pin);
+
+ if (bank == 0)
+ return 0;
+ else if (bank == 1)
+ return 4;
+ else if (bank == 2)
+ return 8;
+ else if (bank == 3)
+ return 0x100;
+ log_warning("Use default GPIO bank for an invalid GPIO[%d].\n", pin);
+ return 0;
+}
+
+#define REG_PLR(pin) (0x00 + gpio_to_reg_offset(pin))
+#define REG_PDR(pin) (0x0c + gpio_to_reg_offset(pin))
+#define REG_PSR(pin) (0x18 + gpio_to_reg_offset(pin))
+#define REG_PCR(pin) (0x24 + gpio_to_reg_offset(pin))
+#define REG_SDR(pin) (0x54 + gpio_to_reg_offset(pin))
+#define REG_CDR(pin) (0x60 + gpio_to_reg_offset(pin))
+
+struct spacemit_gpio_data {
+ u16 gpio_base;
+ u16 gpio_count;
+ u8 num_banks;
+};
+
+struct spacemit_gpio_priv {
+ void __iomem *regs;
+};
+
+static int spacemit_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+ struct ofnode_phandle_args *args)
+{
+ struct spacemit_gpio_data *data;
+ u32 bank, offset, flags;
+
+ data = (struct spacemit_gpio_data *)dev_get_driver_data(dev);
+ if (args->args_count < 3) {
+ dev_err(dev, "Invalid args count: %d, expected 3\n",
+ args->args_count);
+ return -EINVAL;
+ }
+ bank = args->args[0];
+ offset = args->args[1];
+ flags = args->args[2];
+
+ if (bank >= data->num_banks) {
+ dev_err(dev, "Invalid gpio bank: %u (max %u)\n",
+ bank, data->num_banks - 1);
+ return -EINVAL;
+ }
+ if (offset >= GPIO_BANK_SIZE) {
+ dev_err(dev, "Invalid offset: %u (max 31)\n", offset);
+ return -EINVAL;
+ }
+ desc->offset = bank * GPIO_BANK_SIZE + offset;
+ desc->flags = gpio_flags_xlate(flags);
+ return 0;
+}
+
+static int spacemit_gpio_get_value(struct udevice *dev, unsigned int offset)
+{
+ struct spacemit_gpio_priv *priv = dev_get_priv(dev);
+ void __iomem *addr;
+ u32 value, mask;
+
+ addr = priv->regs + REG_PLR(offset);
+ value = readl(addr);
+ mask = 1 << GPIO_TO_BIT(offset);
+ return !!(value & mask);
+}
+
+static int spacemit_gpio_get_function(struct udevice *dev, unsigned int offset)
+{
+ struct spacemit_gpio_priv *priv = dev_get_priv(dev);
+ void __iomem *addr;
+ u32 value, mask;
+
+ addr = priv->regs + REG_PDR(offset);
+ value = readl(addr);
+ mask = 1 << GPIO_TO_BIT(offset);
+ if (value & mask)
+ return GPIOF_OUTPUT;
+ return GPIOF_INPUT;
+}
+
+static int spacemit_gpio_get_flags(struct udevice *dev, unsigned int offset,
+ ulong *flagsp)
+{
+ ulong flags = 0;
+ u32 dir;
+
+ dir = spacemit_gpio_get_function(dev, offset);
+ if (dir) {
+ flags |= GPIOD_IS_OUT;
+ if (spacemit_gpio_get_value(dev, offset))
+ flags |= GPIOD_IS_OUT_ACTIVE;
+ } else {
+ flags |= GPIOD_IS_IN;
+ }
+ *flagsp = flags;
+ return 0;
+}
+
+static int spacemit_gpio_set_flags(struct udevice *dev, unsigned int offset,
+ ulong flags)
+{
+ struct spacemit_gpio_priv *priv = dev_get_priv(dev);
+ void __iomem *addr;
+ int value;
+
+ value = (flags & GPIOD_IS_OUT_ACTIVE) ? 1 : 0;
+ if (flags & GPIOD_IS_IN) {
+ addr = priv->regs + REG_CDR(offset);
+ writel(1 << GPIO_TO_BIT(offset), addr);
+ }
+ if (flags & GPIOD_IS_OUT) {
+ if (value) {
+ addr = priv->regs + REG_PSR(offset);
+ writel(1 << GPIO_TO_BIT(offset), addr);
+ } else {
+ addr = priv->regs + REG_PCR(offset);
+ writel(1 << GPIO_TO_BIT(offset), addr);
+ }
+ addr = priv->regs + REG_SDR(offset);
+ writel(1 << GPIO_TO_BIT(offset), addr);
+ }
+ return 0;
+}
+
+static int spacemit_gpio_request(struct udevice *dev, unsigned int offset,
+ const char *label)
+{
+ const struct pinctrl_ops *ops;
+ struct udevice *pctldev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_PINCTRL, &pctldev);
+ if (ret)
+ return ret;
+
+ ops = pinctrl_get_ops(pctldev);
+ if (!ops->gpio_request_enable)
+ return -ENOSYS;
+
+ return ops->gpio_request_enable(pctldev, offset);
+}
+
+static int spacemit_gpio_rfree(struct udevice *dev, unsigned int offset)
+{
+ const struct pinctrl_ops *ops;
+ struct udevice *pctldev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_PINCTRL, &pctldev);
+ if (ret)
+ return ret;
+
+ ops = pinctrl_get_ops(pctldev);
+ if (!ops->gpio_disable_free)
+ return -ENOSYS;
+
+ return ops->gpio_disable_free(pctldev, offset);
+}
+
+static const struct dm_gpio_ops spacemit_gpio_ops = {
+ .request = spacemit_gpio_request,
+ .rfree = spacemit_gpio_rfree,
+ .xlate = spacemit_gpio_xlate,
+ .get_value = spacemit_gpio_get_value,
+ .get_function = spacemit_gpio_get_function,
+ .get_flags = spacemit_gpio_get_flags,
+ .set_flags = spacemit_gpio_set_flags,
+};
+
+static int spacemit_gpio_probe(struct udevice *dev)
+{
+ struct spacemit_gpio_priv *priv;
+ struct spacemit_gpio_data *data;
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct clk_bulk clks;
+ int ret;
+
+ data = (struct spacemit_gpio_data *)dev_get_driver_data(dev);
+ priv = dev_get_priv(dev);
+ priv->regs = dev_read_addr_ptr(dev);
+ if (!priv->regs) {
+ dev_err(dev, "Fail to get base address\n");
+ return -EINVAL;
+ }
+ uc_priv->bank_name = "GPIO";
+ uc_priv->gpio_count = data->gpio_count;
+ uc_priv->gpio_base = data->gpio_base;
+
+ ret = clk_get_bulk(dev, &clks);
+ if (ret) {
+ dev_err(dev, "Fail to get bulk clks\n");
+ return ret;
+ }
+ ret = clk_enable_bulk(&clks);
+ if (ret) {
+ dev_err(dev, "Fail to enable bulk clks\n");
+ goto out;
+ }
+ return 0;
+out:
+ clk_release_bulk(&clks);
+ return ret;
+}
+
+static const struct spacemit_gpio_data k1_gpio_data = {
+ .num_banks = 4,
+ .gpio_count = 128,
+ .gpio_base = 0,
+};
+
+static const struct udevice_id spacemit_gpio_ids[] = {
+ { .compatible = "spacemit,k1-gpio", .data = (uintptr_t)&k1_gpio_data, },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(k1_gpio) = {
+ .name = "spacemit_k1_gpio",
+ .id = UCLASS_GPIO,
+ .of_match = spacemit_gpio_ids,
+ .ops = &spacemit_gpio_ops,
+ .priv_auto = sizeof(struct spacemit_gpio_priv),
+ .probe = spacemit_gpio_probe,
+};
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 5f6586c78ba..0e8b2408376 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -797,6 +797,13 @@ config SYS_I2C_IHS
help
Support for gdsys IHS I2C driver on FPGA bus.
+config SYS_I2C_SPACEMIT_K1
+ bool "Spacemit K1 I2C driver"
+ depends on DM_I2C
+ help
+ Support for Spacemit I2C controller. It's based on
+ Driver Model.
+
source "drivers/i2c/muxes/Kconfig"
endif
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 2da649e97d3..0e3a0f9fb5f 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_SYS_I2C_RZ_RIIC) += rz_riic.o
obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o
obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
+obj-$(CONFIG_SYS_I2C_SPACEMIT_K1) += k1_i2c.o
obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o
obj-$(CONFIG_SYS_I2C_SUN6I_P2WI) += sun6i_p2wi.o
obj-$(CONFIG_SYS_I2C_SUN8I_RSB) += sun8i_rsb.o
diff --git a/drivers/i2c/k1_i2c.c b/drivers/i2c/k1_i2c.c
new file mode 100644
index 00000000000..a08ff15803d
--- /dev/null
+++ b/drivers/i2c/k1_i2c.c
@@ -0,0 +1,523 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023-2026 Spacemit, Inc
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <i2c.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <reset.h>
+#include "k1_i2c.h"
+
+#define ICR_OFFSET 0x00
+#define ISR_OFFSET 0x04
+#define ISAR_OFFSET 0x08
+#define IDBR_OFFSET 0x0c
+#define ILCR_OFFSET 0x10
+#define IWCR_OFFSET 0x14
+#define IRCR_OFFSET 0x18
+#define IBMR_OFFSET 0x1c
+#define WFIFO_OFFSET 0x20
+#define WFIFO_WPTR_OFFSET 0x24
+#define WFIFO_RPTR_OFFSET 0x28
+#define RFIFO_OFFSET 0x2c
+#define RFIFO_WPTR_OFFSET 0x30
+#define RFIFO_RPTR_OFFSET 0x34
+
+/* All transfers are described by this data structure */
+struct k1_i2c_msg {
+ u8 condition;
+ u8 acknack;
+ u8 direction;
+ u8 data;
+};
+
+struct k1_i2c {
+ u32 icr;
+ u32 isr;
+ u32 isar;
+ u32 idbr;
+ u32 ilcr;
+ u32 iwcr;
+ u32 irst_cyc;
+ u32 ibmr;
+};
+
+struct k1_i2c_priv {
+ int id;
+ void __iomem *base;
+ struct clk clk;
+ u32 clk_rate;
+};
+
+/*
+ * i2c_reset: - reset the host controller
+ *
+ */
+static void i2c_reset(void __iomem *base)
+{
+ u32 icr_mode;
+ u32 val;
+
+ /* Save bus mode (standard or fast speed) for later use */
+ icr_mode = readl(base + ICR_OFFSET) & ICR_MODE_MASK;
+ /* disable unit */
+ val = readl(base + ICR_OFFSET);
+ writel(val & ~ICR_IUE, base + ICR_OFFSET);
+ udelay(10);
+ /* reset the unit */
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_UR;
+ writel(val, base + ICR_OFFSET);
+ udelay(100);
+ /* disable unit */
+ val = readl(base + ICR_OFFSET);
+ writel(val & ~ICR_IUE, base + ICR_OFFSET);
+
+ /* set slave address */
+ writel(0x00, base + ISR_OFFSET);
+ /* set control reg values */
+ writel(I2C_ICR_INIT | icr_mode, base + ICR_OFFSET);
+ writel(I2C_ISR_INIT, base + ISR_OFFSET); /* set clear interrupt bits */
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_IUE;
+ writel(val, base + ICR_OFFSET); /* enable unit */
+ udelay(100);
+}
+
+static inline bool is_isr_set_or_clr(unsigned long isr, unsigned long set_mask,
+ unsigned long clr_mask)
+{
+ return ((isr & set_mask) == set_mask) && ((isr & clr_mask) == 0);
+}
+
+/*
+ * i2c_isr_set_cleared: - wait until certain bits of the I2C status register
+ * are set and cleared
+ *
+ * @return: 0 on success or -ETIMEDOUT.
+ */
+static int i2c_isr_set_cleared(void __iomem *base, unsigned long set_mask,
+ unsigned long clr_mask)
+{
+ int cnt = 1000, delay = 10, isr, ret;
+
+ ret = read_poll_timeout(readl, isr,
+ is_isr_set_or_clr(isr, set_mask, clr_mask),
+ delay, delay * cnt, base + ISR_OFFSET);
+ return ret;
+}
+
+/*
+ * i2c_transfer: - Transfer one byte over the i2c bus
+ *
+ * This function can transfer a byte over the i2c bus in both directions.
+ * It is used by the public API functions.
+ *
+ * @return: 0: transfer successful or error code
+ */
+static int i2c_transfer(void __iomem *base, struct k1_i2c_msg *msg)
+{
+ int ret;
+ u32 val;
+
+ if (!msg)
+ goto transfer_error_msg_empty;
+
+ switch (msg->direction) {
+ case I2C_WRITE:
+ /* check if bus is not busy */
+ if (i2c_isr_set_cleared(base, 0, ISR_IBB))
+ goto transfer_error_bus_busy;
+
+ /* start transmission */
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_START;
+ writel(val, base + ICR_OFFSET);
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_STOP;
+ writel(val, base + ICR_OFFSET);
+ writel(msg->data, base + IDBR_OFFSET);
+ if (msg->condition == I2C_COND_START) {
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_START;
+ writel(val, base + ICR_OFFSET);
+ }
+ if (msg->condition == I2C_COND_STOP) {
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_STOP;
+ writel(val, base + ICR_OFFSET);
+ }
+ if (msg->acknack == I2C_ACKNAK_SENDNAK) {
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_ACKNAK;
+ writel(val, base + ICR_OFFSET);
+ }
+ if (msg->acknack == I2C_ACKNAK_SENDACK) {
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_ACKNAK;
+ writel(val, base + ICR_OFFSET);
+ }
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_ALDIE;
+ writel(val, base + ICR_OFFSET);
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_TB;
+ writel(val, base + ICR_OFFSET);
+
+ /* transmit register empty? */
+ if (i2c_isr_set_cleared(base, ISR_ITE, 0))
+ goto transfer_error_transmit_timeout;
+
+ /* clear 'transmit empty' state */
+ val = readl(base + ISR_OFFSET);
+ val |= ISR_ITE;
+ writel(val, base + ISR_OFFSET);
+
+ /* wait for ACK from slave */
+ if (msg->acknack == I2C_ACKNAK_WAITACK)
+ if (i2c_isr_set_cleared(base, 0, ISR_ACKNAK))
+ goto transfer_error_ack_missing;
+ break;
+
+ case I2C_READ:
+ /* check if bus is not busy */
+ if (i2c_isr_set_cleared(base, 0, ISR_IBB))
+ goto transfer_error_bus_busy;
+
+ /* start receive */
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_START;
+ writel(val, base + ICR_OFFSET);
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_STOP;
+ writel(val, base + ICR_OFFSET);
+ if (msg->condition == I2C_COND_START) {
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_START;
+ writel(val, base + ICR_OFFSET);
+ }
+ if (msg->condition == I2C_COND_STOP) {
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_STOP;
+ writel(val, base + ICR_OFFSET);
+ }
+ if (msg->acknack == I2C_ACKNAK_SENDNAK) {
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_ACKNAK;
+ writel(val, base + ICR_OFFSET);
+ }
+ if (msg->acknack == I2C_ACKNAK_SENDACK) {
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_ACKNAK;
+ writel(val, base + ICR_OFFSET);
+ }
+ val = readl(base + ICR_OFFSET);
+ val &= ~ICR_ALDIE;
+ writel(val, base + ICR_OFFSET);
+ val = readl(base + ICR_OFFSET);
+ val |= ICR_TB;
+ writel(val, base + ICR_OFFSET);
+
+ /* receive register full? */
+ if (i2c_isr_set_cleared(base, ISR_IRF, 0))
+ goto transfer_error_receive_timeout;
+
+ msg->data = readl(base + IDBR_OFFSET);
+
+ /* clear 'receive empty' state */
+ val = readl(base + ISR_OFFSET);
+ val |= ISR_IRF;
+ writel(val, base + ISR_OFFSET);
+ break;
+ default:
+ goto transfer_error_illegal_param;
+ }
+
+ return 0;
+
+transfer_error_msg_empty:
+ debug("%s: error: 'msg' is empty\n", __func__);
+ ret = -EINVAL;
+ goto i2c_transfer_finish;
+
+transfer_error_transmit_timeout:
+ debug("%s: error: transmit timeout\n", __func__);
+ ret = -ETIMEDOUT;
+ goto i2c_transfer_finish;
+
+transfer_error_ack_missing:
+ debug("%s: error: ACK missing\n", __func__);
+ ret = -EREMOTEIO;
+ goto i2c_transfer_finish;
+
+transfer_error_receive_timeout:
+ debug("%s: error: receive timeout\n", __func__);
+ ret = -ETIMEDOUT;
+ goto i2c_transfer_finish;
+
+transfer_error_illegal_param:
+ debug("%s: error: illegal parameters\n", __func__);
+ ret = -EINVAL;
+ goto i2c_transfer_finish;
+
+transfer_error_bus_busy:
+ debug("%s: error: bus is busy\n", __func__);
+ ret = -EIO;
+ goto i2c_transfer_finish;
+
+i2c_transfer_finish:
+ debug("%s: ISR: 0x%04x\n", __func__, readl(base + ISR_OFFSET));
+ i2c_reset(base);
+ return ret;
+}
+
+static int __i2c_read(void __iomem *base, uchar chip, u8 *addr, int alen,
+ uchar *buffer, int len)
+{
+ struct k1_i2c_msg msg;
+ int ret;
+
+ debug("%s(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n",
+ __func__, chip, *addr, alen, len);
+
+ if (len == 0) {
+ pr_err("reading zero byte is invalid\n");
+ return -EINVAL;
+ }
+
+ i2c_reset(base);
+
+ /* dummy chip address write */
+ debug("%s: dummy chip address write\n", __func__);
+ msg.condition = I2C_COND_START;
+ msg.acknack = I2C_ACKNAK_WAITACK;
+ msg.direction = I2C_WRITE;
+ msg.data = (chip << 1);
+ msg.data &= 0xFE;
+ ret = i2c_transfer(base, &msg);
+ if (ret)
+ return ret;
+
+ /*
+ * send memory address bytes;
+ * alen defines how much bytes we have to send.
+ */
+ while (--alen >= 0) {
+ debug("%s: send address byte %02x (alen=%d)\n",
+ __func__, *addr, alen);
+ msg.condition = I2C_COND_NORMAL;
+ msg.acknack = I2C_ACKNAK_WAITACK;
+ msg.direction = I2C_WRITE;
+ msg.data = addr[alen];
+ ret = i2c_transfer(base, &msg);
+ if (ret)
+ return ret;
+ }
+
+ /* start read sequence */
+ debug("%s: start read sequence\n", __func__);
+ msg.condition = I2C_COND_START;
+ msg.acknack = I2C_ACKNAK_WAITACK;
+ msg.direction = I2C_WRITE;
+ msg.data = (chip << 1);
+ msg.data |= 0x01;
+ ret = i2c_transfer(base, &msg);
+ if (ret)
+ return ret;
+
+ /* read bytes; send NACK at last byte */
+ while (len--) {
+ if (len == 0) {
+ msg.condition = I2C_COND_STOP;
+ msg.acknack = I2C_ACKNAK_SENDNAK;
+ } else {
+ msg.condition = I2C_COND_NORMAL;
+ msg.acknack = I2C_ACKNAK_SENDACK;
+ }
+
+ msg.direction = I2C_READ;
+ msg.data = 0x00;
+ ret = i2c_transfer(base, &msg);
+ if (ret)
+ return ret;
+
+ *buffer = msg.data;
+ debug("%s: reading byte (%p)=0x%02x\n",
+ __func__, buffer, *buffer);
+ buffer++;
+ }
+
+ i2c_reset(base);
+
+ return 0;
+}
+
+static int __i2c_write(struct k1_i2c *base, uchar chip, u8 *addr, int alen,
+ uchar *buffer, int len)
+{
+ struct k1_i2c_msg msg;
+ int ret;
+
+ debug("%s(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n",
+ __func__, chip, *addr, alen, len);
+
+ i2c_reset(base);
+
+ /* chip address write */
+ debug("%s: chip address write\n", __func__);
+ msg.condition = I2C_COND_START;
+ msg.acknack = I2C_ACKNAK_WAITACK;
+ msg.direction = I2C_WRITE;
+ msg.data = (chip << 1);
+ msg.data &= 0xFE;
+ ret = i2c_transfer(base, &msg);
+ if (ret)
+ return ret;
+
+ /*
+ * send memory address bytes;
+ * alen defines how much bytes we have to send.
+ */
+ while (--alen >= 0) {
+ debug("%s: send address byte %02x (alen=%d)\n",
+ __func__, *addr, alen);
+ msg.condition = I2C_COND_NORMAL;
+ msg.acknack = I2C_ACKNAK_WAITACK;
+ msg.direction = I2C_WRITE;
+ msg.data = addr[alen];
+ ret = i2c_transfer(base, &msg);
+ if (ret)
+ return ret;
+ }
+
+ /* write bytes; send NACK at last byte */
+ while (len--) {
+ debug("%s: writing byte (%p)=0x%02x\n",
+ __func__, buffer, *buffer);
+
+ if (len == 0)
+ msg.condition = I2C_COND_STOP;
+ else
+ msg.condition = I2C_COND_NORMAL;
+
+ msg.acknack = I2C_ACKNAK_WAITACK;
+ msg.direction = I2C_WRITE;
+ msg.data = *(buffer++);
+
+ ret = i2c_transfer(base, &msg);
+ if (ret)
+ return ret;
+ }
+
+ i2c_reset(base);
+
+ return 0;
+}
+
+static int k1_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+{
+ struct k1_i2c_priv *i2c = dev_get_priv(bus);
+ struct i2c_msg *dmsg, *omsg, dummy;
+
+ memset(&dummy, 0, sizeof(struct i2c_msg));
+
+ /*
+ * We expect either two messages (one with an offset and one with the
+ * actual data) or one message (just data or offset/data combined)
+ */
+ if (nmsgs > 2 || nmsgs == 0) {
+ debug("%s: Only one or two messages are supported.", __func__);
+ return -EINVAL;
+ }
+
+ omsg = nmsgs == 1 ? &dummy : msg;
+ dmsg = nmsgs == 1 ? msg : msg + 1;
+
+ if (dmsg->flags & I2C_M_RD)
+ return __i2c_read(i2c->base, dmsg->addr, omsg->buf,
+ omsg->len, dmsg->buf, dmsg->len);
+ else
+ return __i2c_write(i2c->base, dmsg->addr, omsg->buf,
+ omsg->len, dmsg->buf, dmsg->len);
+}
+
+static int k1_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+ struct k1_i2c_priv *priv = dev_get_priv(bus);
+ void __iomem *base = priv->base;
+ u32 val;
+
+ if (speed > I2C_SPEED_STANDARD_RATE)
+ val = ICR_FM;
+ else
+ val = ICR_SM;
+ clrsetbits_le32(base + ICR_OFFSET, ICR_MODE_MASK, val);
+
+ return 0;
+}
+
+static int k1_i2c_probe(struct udevice *bus)
+{
+ struct k1_i2c_priv *priv = dev_get_priv(bus);
+ struct reset_ctl reset;
+ int ret;
+
+ priv->id = dev_seq(bus);
+
+ /*
+ * The upstream K1 dts intentionally omits the 'resets' property
+ * on i2c nodes — the apbc clock-enable path performs the
+ * controller reset internally as part of clock gating. Treat the
+ * reset lookup as optional so we work on the kernel-mainline DT.
+ */
+ ret = reset_get_by_index(bus, 0, &reset);
+ if (!ret) {
+ reset_assert(&reset);
+ udelay(10);
+ reset_deassert(&reset);
+ udelay(10);
+ } else if (ret != -ENOENT && ret != -ENODATA) {
+ dev_err(bus, "%s: reset lookup failed (%d)\n", __func__, ret);
+ return ret;
+ }
+
+ ret = clk_get_by_index(bus, 0, &priv->clk);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(&priv->clk);
+ if (ret && ret != -ENOSYS && ret != -EOPNOTSUPP) {
+ debug("%s: failed to enable clock\n", __func__);
+ return ret;
+ }
+ priv->clk_rate = clk_get_rate(&priv->clk);
+
+ priv->base = (void *)devfdt_get_addr_ptr(bus);
+ k1_i2c_set_bus_speed(bus, priv->clk_rate);
+ return 0;
+}
+
+static const struct dm_i2c_ops k1_i2c_ops = {
+ .xfer = k1_i2c_xfer,
+ .set_bus_speed = k1_i2c_set_bus_speed,
+};
+
+static const struct udevice_id k1_i2c_ids[] = {
+ { .compatible = "spacemit,k1-i2c" },
+ { }
+};
+
+U_BOOT_DRIVER(i2c_spacemit) = {
+ .name = "i2c_spacemit",
+ .id = UCLASS_I2C,
+ .of_match = k1_i2c_ids,
+ .probe = k1_i2c_probe,
+ .priv_auto = sizeof(struct k1_i2c_priv),
+ .ops = &k1_i2c_ops,
+};
diff --git a/drivers/i2c/k1_i2c.h b/drivers/i2c/k1_i2c.h
new file mode 100644
index 00000000000..856947aa43b
--- /dev/null
+++ b/drivers/i2c/k1_i2c.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2023-2026 Spacemit Ltd.
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#ifndef __SPACEMIT_I2C_H
+#define __SPACEMIT_I2C_H
+
+/* Shall the current transfer have a start/stop condition? */
+#define I2C_COND_NORMAL 0
+#define I2C_COND_START 1
+#define I2C_COND_STOP 2
+
+/* Shall the current transfer be ack/nacked or being waited for it? */
+#define I2C_ACKNAK_WAITACK 1
+#define I2C_ACKNAK_SENDACK 2
+#define I2C_ACKNAK_SENDNAK 4
+
+/* Specify who shall transfer the data (master or slave) */
+#define I2C_READ 0
+#define I2C_WRITE 1
+
+#if (CONFIG_SYS_I2C_SPEED == 400000)
+#define I2C_ICR_INIT (ICR_FM | ICR_BEIE | ICR_IRFIE | ICR_ITEIE | \
+ ICR_GCD | ICR_SCLE)
+#else
+#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | \
+ ICR_SCLE)
+#endif
+
+/* ----- Control register bits ---------------------------------------- */
+
+#define ICR_START 0x1 /* start bit */
+#define ICR_STOP 0x2 /* stop bit */
+#define ICR_ACKNAK 0x4 /* send ACK(0) or NAK(1) */
+#define ICR_TB 0x8 /* transfer byte bit */
+#define ICR_MA BIT(12) /* master abort */
+#define ICR_SCLE BIT(13) /* master clock enable, mona SCLEA */
+#define ICR_IUE BIT(14) /* unit enable */
+#define ICR_GCD BIT(21) /* general call disable */
+#define ICR_ITEIE BIT(19) /* enable tx interrupts */
+#define ICR_IRFIE BIT(20) /* enable rx interrupts, mona: DRFIE */
+#define ICR_BEIE BIT(22) /* enable bus error ints */
+#define ICR_SSDIE BIT(24) /* slave STOP detected int enable */
+#define ICR_ALDIE BIT(18) /* enable arbitration interrupt */
+#define ICR_SADIE BIT(23) /* slave address detected int enable */
+#define ICR_UR BIT(10) /* unit reset */
+#define ICR_SM (0x0) /* Standard Mode */
+#define ICR_FM BIT(8) /* Fast Mode */
+#define ICR_MODE_MASK (0x300) /* Mode mask */
+
+/* ----- Status register bits ----------------------------------------- */
+
+#define ISR_RWM BIT(13) /* read/write mode */
+#define ISR_ACKNAK BIT(14) /* ack/nak status */
+#define ISR_UB BIT(15) /* unit busy */
+#define ISR_IBB BIT(16) /* bus busy */
+#define ISR_SSD BIT(24) /* slave stop detected */
+#define ISR_ALD BIT(18) /* arbitration loss detected */
+#define ISR_ITE BIT(19) /* tx buffer empty */
+#define ISR_IRF BIT(20) /* rx buffer full */
+#define ISR_GCAD BIT(21) /* general call address detected */
+#define ISR_SAD BIT(23) /* slave address detected */
+#define ISR_BED BIT(22) /* bus error no ACK/NAK */
+
+#define I2C_ISR_INIT 0x1FDE000
+
+#endif
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 019167a2dc5..1cf1ffd99cc 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1443,7 +1443,6 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
if (IS_ERR(newdev))
return PTR_ERR(newdev);
- master->this = newdev;
ret = i3c_master_attach_i3c_dev(master, newdev);
if (ret)
goto err_free_dev;
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 0c4af7e528a..25933adf010 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -671,8 +671,8 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
for (pos = 0; pos < master->maxdevs; pos++) {
if (newdevs & BIT(pos)) {
- i3c_master_add_i3c_dev_locked(m, master->addrs[pos]);
- master->i3cdev[pos] = m->this;
+ if (i3c_master_add_i3c_dev_locked(m, master->addrs[pos]))
+ continue;
master->num_i3cdevs++;
}
}
@@ -806,6 +806,7 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr;
master->free_pos &= ~BIT(pos);
i3c_dev_set_master_data(dev, data);
+ master->i3cdev[pos] = dev;
writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]),
master->regs +
@@ -972,7 +973,7 @@ static int dw_i3c_probe(struct udevice *dev)
}
ret = reset_get_bulk(dev, &master->resets);
- if (ret) {
+ if (ret && ret != -ENOTSUPP && ret != -ENOENT) {
dev_err(dev, "Can't get reset: %d\n", ret);
return ret;
}
diff --git a/drivers/mailbox/mpfs-mbox.c b/drivers/mailbox/mpfs-mbox.c
index b1ce377525e..8b7a2719330 100644
--- a/drivers/mailbox/mpfs-mbox.c
+++ b/drivers/mailbox/mpfs-mbox.c
@@ -18,6 +18,7 @@
#include <linux/compat.h>
#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/iopoll.h>
#include <log.h>
#include <mailbox-uclass.h>
#include <mpfs-mailbox.h>
@@ -60,11 +61,15 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data)
u32 mailbox_val, cmd_shifted, value;
u8 *byte_buf;
u8 idx, byte_idx, byte_offset;
+ int ret;
u32 *word_buf = (u32 *)msg->cmd_data;
- if (mpfs_mbox_busy(chan))
- return -EBUSY;
+ ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_SR_OFFSET,
+ value, !(value & SERVICE_SR_BUSY_MASK),
+ 1, 20);
+ if (ret)
+ return ret;
for (idx = 0; idx < (msg->cmd_data_size / BYTES_4); idx++)
writel(word_buf[idx], mbox->mbox_base + msg->mbox_offset + idx * BYTES_4);
@@ -86,13 +91,19 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data)
regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, cmd_shifted);
- do {
- regmap_read(mbox->control_scb, SERVICES_CR_OFFSET, &value);
- } while (SERVICE_CR_REQ_MASK == (value & SERVICE_CR_REQ_MASK));
+ ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_CR_OFFSET,
+ value, !(value & SERVICE_CR_REQ_MASK),
+ 1, /* poll every 1 µs */
+ 20); /* timeout 20 ms */
+ if (ret)
+ return ret;
- do {
- regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &value);
- } while (SERVICE_SR_BUSY_MASK == (value & SERVICE_SR_BUSY_MASK));
+ ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_SR_OFFSET,
+ value, !(value & SERVICE_SR_BUSY_MASK),
+ 1,
+ 20);
+ if (ret)
+ return ret;
msg->response->resp_status = (value >> SERVICE_SR_STATUS_SHIFT);
if (msg->response->resp_status)
diff --git a/drivers/misc/mpfs_syscontroller.c b/drivers/misc/mpfs_syscontroller.c
index f608d5518b0..b9aea7e1181 100644
--- a/drivers/misc/mpfs_syscontroller.c
+++ b/drivers/misc/mpfs_syscontroller.c
@@ -11,6 +11,7 @@
#include <asm/system.h>
#include <dm.h>
#include <dm/device_compat.h>
+#include <dm/lists.h>
#include <env.h>
#include <errno.h>
#include <linux/compat.h>
@@ -86,6 +87,30 @@ int mpfs_syscontroller_run_service(struct mpfs_syscontroller_priv *sys_controlle
EXPORT_SYMBOL_GPL(mpfs_syscontroller_run_service);
/**
+ * mpfs_syscontroller_recv_response() - Receive the MPFS system service response
+ * @sys_controller: MPFS system controller instance
+ * @msg: System service message
+ * @timeout_ms: Timeout in milliseconds
+ *
+ * Receive the mailbox response for a previously issued MPFS system
+ * controller service request and populate the response buffer.
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+int mpfs_syscontroller_recv_response(struct mpfs_syscontroller_priv *sys_controller, struct
+ mpfs_mss_msg * msg, unsigned long timeout_ms)
+{
+ int ret;
+
+ ret = mbox_recv(&sys_controller->chan, msg, timeout_ms);
+ if (ret)
+ dev_err(sys_controller->chan.dev, "Service failed: %d, abort. Failure: %u\n", ret,
+ msg->response->resp_status);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mpfs_syscontroller_recv_response);
+
+/**
* mpfs_syscontroller_read_sernum() - Use system service to read the device serial number
* @sys_serv_priv: system service private data
* @device_serial_number: device serial number
@@ -116,11 +141,9 @@ int mpfs_syscontroller_read_sernum(struct mpfs_sys_serv *sys_serv_priv, u8 *devi
}
/* Receive the response */
- ret = mbox_recv(&sys_serv_priv->sys_controller->chan, &msg, timeoutsecs);
- if (ret) {
- dev_err(sys_serv_priv->sys_controller->chan.dev, "Service failed: %d, abort. Failure: %u\n", ret, msg.response->resp_status);
+ ret = mpfs_syscontroller_recv_response(sys_serv_priv->sys_controller, &msg, timeoutsecs);
+ if (ret)
return ret;
- }
debug("%s: Read successful %s\n",
__func__, sys_serv_priv->sys_controller->chan.dev->name);
@@ -312,6 +335,7 @@ EXPORT_SYMBOL(mpfs_syscontroller_process_dtbo);
static int mpfs_syscontroller_probe(struct udevice *dev)
{
struct mpfs_syscontroller_priv *sys_controller = dev_get_priv(dev);
+ struct udevice *rng_dev;
int ret;
ret = mbox_get_by_index(dev, 0, &sys_controller->chan);
@@ -321,6 +345,10 @@ static int mpfs_syscontroller_probe(struct udevice *dev)
return ret;
}
+ ret = device_bind_driver(dev, "mpfs_rng", "mpfs-rng", &rng_dev);
+ if (ret)
+ dev_err(dev, "Failed to bind mpfs_rng: %d\n", ret);
+
init_completion(&sys_controller->c);
dev_info(dev, "Registered MPFS system controller\n");
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2e565560656..670e92ee12b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -325,7 +325,7 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
if ((status & MMC_STATUS_RDY_FOR_DATA) &&
(status & MMC_STATUS_CURR_STATE) !=
MMC_STATE_PRG)
- break;
+ return 0;
if (status & MMC_STATUS_MASK) {
#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
@@ -340,14 +340,10 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
udelay(1000);
}
- if (timeout_ms <= 0) {
#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
- log_err("Timeout waiting card ready\n");
+ log_err("Timeout waiting card ready\n");
#endif
- return -ETIMEDOUT;
- }
-
- return 0;
+ return -ETIMEDOUT;
}
int mmc_set_blocklen(struct mmc *mmc, int len)
@@ -461,6 +457,14 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
struct mmc_cmd cmd;
struct mmc_data data;
+ if (blkcnt > 1 && (mmc->host_caps & MMC_CAP_CMD23)) {
+ cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
+ cmd.cmdarg = blkcnt & 0x0000ffff;
+ cmd.resp_type = MMC_RSP_R1;
+ if (mmc_send_cmd(mmc, &cmd, NULL))
+ return 0;
+ }
+
if (blkcnt > 1)
cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
else
@@ -481,7 +485,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
if (mmc_send_cmd(mmc, &cmd, &data))
return 0;
- if (blkcnt > 1) {
+ if (blkcnt > 1 && !(mmc->host_caps & MMC_CAP_CMD23)) {
if (mmc_send_stop_transmission(mmc, false)) {
#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
log_err("mmc fail to send stop cmd\n");
@@ -494,7 +498,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
}
#if !CONFIG_IS_ENABLED(DM_MMC)
-static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
+int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
{
if (mmc->cfg->ops->get_b_max)
return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt);
@@ -1037,6 +1041,10 @@ static int mmc_get_capabilities(struct mmc *mmc)
mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
+ /* CMD23(SET_BLOCK_COUNT) requires eMMC spec v3.1 or above */
+ if (mmc->version < MMC_VERSION_3)
+ mmc->host_caps &= ~MMC_CAP_CMD23;
+
if (mmc_host_is_spi(mmc))
return 0;
@@ -1436,6 +1444,8 @@ static int sd_get_capabilities(struct mmc *mmc)
if (mmc->scr[0] & SD_DATA_4BIT)
mmc->card_caps |= MMC_MODE_4BIT;
+ if (!(mmc->scr[0] & SD_SCR_CMD23_SUPPORT))
+ mmc->host_caps &= ~MMC_CAP_CMD23;
/* Version 1.0 doesn't support switching */
if (mmc->version == SD_VERSION_1_0)
@@ -3177,10 +3187,19 @@ int mmc_deinit(struct mmc *mmc)
return 0;
if (IS_SD(mmc)) {
- caps_filtered = mmc->card_caps &
- ~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
- MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
- MMC_CAP(UHS_SDR104));
+ u32 uhs_mask = UHS_CAPS;
+
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+ /*
+ * Per SD spec, once a card enters 1.8V signaling it
+ * cannot revert to 3.3V without a power cycle.
+ * If the card is operating at 1.8V, keep UHS_SDR12
+ * as the minimum fallback mode.
+ */
+ if (mmc_sd_card_using_v18(mmc))
+ uhs_mask &= ~MMC_CAP(UHS_SDR12);
+#endif
+ caps_filtered = mmc->card_caps & ~uhs_mask;
return sd_select_mode_and_width(mmc, caps_filtered);
} else {
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
index fc45f017e5d..24e68ceb5e6 100644
--- a/drivers/mmc/mmc_private.h
+++ b/drivers/mmc/mmc_private.h
@@ -17,6 +17,10 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout);
int mmc_set_blocklen(struct mmc *mmc, int len);
+#if !CONFIG_IS_ENABLED(DM_MMC)
+int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt);
+#endif
+
#if CONFIG_IS_ENABLED(BLK)
ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
void *dst);
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 928c05872ca..e739720b77c 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -165,7 +165,15 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
if (blkcnt == 0)
return 0;
- else if (blkcnt == 1)
+ if (blkcnt > 1 && mmc->host_caps & MMC_CAP_CMD23) {
+ cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
+ cmd.cmdarg = blkcnt & 0x0000ffff;
+ cmd.resp_type = MMC_RSP_R1;
+ if (mmc_send_cmd(mmc, &cmd, NULL))
+ return 0;
+ }
+
+ if (blkcnt == 1)
cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
else
cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
@@ -191,10 +199,13 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
*/
}
- /* SPI multiblock writes terminate using a special
- * token, not a STOP_TRANSMISSION request.
+ /*
+ * SPI multiblock writes terminate using a special token, not CMD12.
+ * When CMD23 was issued the card auto-terminates, so CMD12 is also
+ * skipped in that case.
*/
- if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
+ if (!mmc_host_is_spi(mmc) && blkcnt > 1 &&
+ !(mmc->host_caps & MMC_CAP_CMD23)) {
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
@@ -228,6 +239,7 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
int dev_num = block_dev->devnum;
lbaint_t cur, blocks_todo = blkcnt;
int err;
+ uint b_max;
struct mmc *mmc = find_mmc_device(dev_num);
if (!mmc)
@@ -240,9 +252,10 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
if (mmc_set_blocklen(mmc, mmc->write_bl_len))
return 0;
+ b_max = mmc_get_b_max(mmc, (void *)src, blkcnt);
+
do {
- cur = (blocks_todo > mmc->cfg->b_max) ?
- mmc->cfg->b_max : blocks_todo;
+ cur = (blocks_todo > b_max) ? b_max : blocks_todo;
if (mmc_write_blocks(mmc, start, cur, src) != cur)
return 0;
blocks_todo -= cur;
diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
index 8bfdffd56f5..26d2262ef45 100644
--- a/drivers/mmc/rpmb.c
+++ b/drivers/mmc/rpmb.c
@@ -452,7 +452,7 @@ static int rpmb_route_frames(struct mmc *mmc, struct s_rpmb *req,
return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
case RPMB_REQ_READ_DATA:
- if (req_cnt != 1 || !req_cnt)
+ if (req_cnt != 1 || !rsp_cnt)
return -EINVAL;
return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 71a6d8ea2f5..962a99cd05a 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -733,7 +733,8 @@ static int sdhci_init(struct mmc *mmc)
*/
host->force_align_buffer = true;
#else
- if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) {
+ if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
+ !host->align_buffer) {
host->align_buffer = memalign(8, 512 * 1024);
if (!host->align_buffer) {
log_err("Aligned buffer alloc failed\n");
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index e28c81afffe..84f4e4c2198 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -576,8 +576,8 @@ struct mmc *sunxi_mmc_init(int sdc_no)
cfg->host_caps = MMC_MODE_4BIT;
if ((IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN8I) ||
- IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_MACH_SUN55I_A523)) &&
- (sdc_no == 2))
+ IS_ENABLED(CONFIG_MACH_SUN9I) || IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+ IS_ENABLED(CONFIG_MACH_SUN55I_A523)) && (sdc_no == 2))
cfg->host_caps = MMC_MODE_8BIT;
cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
@@ -663,7 +663,7 @@ static const struct dm_mmc_ops sunxi_mmc_ops = {
static unsigned get_mclk_offset(void)
{
- if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
+ if (IS_ENABLED(CONFIG_MACH_SUN9I))
return 0x410;
if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 38d6dd142dd..f6bd9f6f2e9 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -196,7 +196,7 @@ config ALTERA_QSPI
config RENESAS_RPC_HF
bool "Renesas R-Car Gen3 RPC HyperFlash driver"
- depends on RCAR_GEN3 && DM_MTD
+ depends on RCAR_64 && DM_MTD
help
This enables access to HyperFlash memory through the Renesas
R-Car Gen3 RPC controller.
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index e50502824ac..cf52abf1554 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -2407,13 +2407,6 @@ unsigned long flash_init(void)
unsigned long size = 0;
int i;
-#ifdef CONFIG_SYS_FLASH_PROTECTION
- /* read environment from EEPROM */
- char s[64];
-
- env_get_f("unlock", s, sizeof(s));
-#endif
-
#ifdef CONFIG_CFI_FLASH /* for driver model */
cfi_flash_init_dm();
#endif
@@ -2438,7 +2431,7 @@ unsigned long flash_init(void)
#endif /* CONFIG_SYS_FLASH_QUIET_TEST */
}
#ifdef CONFIG_SYS_FLASH_PROTECTION
- else if (strcmp(s, "yes") == 0) {
+ else if (env_get_yesno("unlock")) {
/*
* Only the U-Boot image and it's environment
* is protected, all other sectors are
diff --git a/drivers/mtd/nand/raw/rockchip_nfc.c b/drivers/mtd/nand/raw/rockchip_nfc.c
index ea8e67d1a23..d23a651f369 100644
--- a/drivers/mtd/nand/raw/rockchip_nfc.c
+++ b/drivers/mtd/nand/raw/rockchip_nfc.c
@@ -440,7 +440,8 @@ static int rk_nfc_write_page_raw(struct mtd_info *mtd,
int i, pages_per_blk;
pages_per_blk = mtd->erasesize / mtd->writesize;
- if ((page < (pages_per_blk * rknand->boot_blks)) &&
+ if ((chip->options & NAND_IS_BOOT_MEDIUM) &&
+ (page < (pages_per_blk * rknand->boot_blks)) &&
rknand->boot_ecc != ecc->strength) {
/*
* There's currently no method to notify the MTD framework that
@@ -560,7 +561,8 @@ static int rk_nfc_write_page_hwecc(struct mtd_info *mtd,
*
* Configure the ECC algorithm supported by the boot ROM.
*/
- if (page < (pages_per_blk * rknand->boot_blks)) {
+ if ((page < (pages_per_blk * rknand->boot_blks)) &&
+ (chip->options & NAND_IS_BOOT_MEDIUM)) {
boot_rom_mode = 1;
if (rknand->boot_ecc != ecc->strength)
rk_nfc_hw_ecc_setup(chip, rknand->boot_ecc);
@@ -624,8 +626,8 @@ static int rk_nfc_read_page_raw(struct mtd_info *mtd,
int i, pages_per_blk;
pages_per_blk = mtd->erasesize / mtd->writesize;
- if ((page < (pages_per_blk * rknand->boot_blks)) &&
- nfc->selected_bank == 0 &&
+ if ((chip->options & NAND_IS_BOOT_MEDIUM) &&
+ (page < (pages_per_blk * rknand->boot_blks)) &&
rknand->boot_ecc != ecc->strength) {
/*
* There's currently no method to notify the MTD framework that
@@ -700,8 +702,8 @@ static int rk_nfc_read_page_hwecc(struct mtd_info *mtd,
* are used by the boot ROM.
* Configure the ECC algorithm supported by the boot ROM.
*/
- if (page < (pages_per_blk * rknand->boot_blks) &&
- nfc->selected_bank == 0) {
+ if ((page < (pages_per_blk * rknand->boot_blks)) &&
+ (chip->options & NAND_IS_BOOT_MEDIUM)) {
boot_rom_mode = 1;
if (rknand->boot_ecc != ecc->strength)
rk_nfc_hw_ecc_setup(chip, rknand->boot_ecc);
diff --git a/drivers/mtd/renesas_rpc_hf.c b/drivers/mtd/renesas_rpc_hf.c
index 9390c9e9ab3..c94a25fe6a1 100644
--- a/drivers/mtd/renesas_rpc_hf.c
+++ b/drivers/mtd/renesas_rpc_hf.c
@@ -344,21 +344,21 @@ static int rpc_hf_bind(struct udevice *parent)
static int rpc_hf_probe(struct udevice *dev)
{
- void *blob = (void *)gd->fdt_blob;
- const fdt32_t *cell;
- int node = dev_of_offset(dev);
- int parent, addrc, sizec, len, ret;
- struct clk clk;
phys_addr_t flash_base;
+ struct clk clk;
+ int ret;
- parent = fdt_parent_offset(blob, node);
- fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
- cell = fdt_getprop(blob, node, "reg", &len);
- if (!cell)
- return -ENOENT;
+ rpc_base = dev_read_addr_name(dev, "regs");
+ if (rpc_base == FDT_ADDR_T_NONE) {
+ dev_err(dev, "Failed to get RPC control registers\n");
+ return -EINVAL;
+ }
- if (addrc != 2 || sizec != 2)
+ flash_base = dev_read_addr_name(dev, "dirmap");
+ if (flash_base == FDT_ADDR_T_NONE) {
+ dev_err(dev, "Failed to get RPC direct map registers\n");
return -EINVAL;
+ }
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0) {
@@ -372,9 +372,6 @@ static int rpc_hf_probe(struct udevice *dev)
return ret;
}
- rpc_base = fdt_translate_address(blob, node, cell);
- flash_base = fdt_translate_address(blob, node, cell + addrc + sizec);
-
flash_info[0].dev = dev;
flash_info[0].base = flash_base;
cfi_flash_num_flash_banks = 1;
@@ -387,6 +384,7 @@ static const struct udevice_id rpc_hf_ids[] = {
{ .compatible = "renesas,r7s72100-rpc-if" },
{ .compatible = "renesas,rcar-gen3-rpc-if" },
{ .compatible = "renesas,rcar-gen4-rpc-if" },
+ { .compatible = "renesas,rcar-gen5-rpc-if" },
{}
};
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 44e67cd913a..9a96be11e6d 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -8,14 +8,13 @@ spi-nor-y := sf_probe.o spi-nor-ids.o
ifdef CONFIG_XPL_BUILD
obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o
+endif
+
ifeq ($(CONFIG_$(PHASE_)SPI_FLASH_TINY),y)
spi-nor-y += spi-nor-tiny.o
else
spi-nor-y += spi-nor-core.o
endif
-else
-spi-nor-y += spi-nor-core.o
-endif
obj-$(CONFIG_SPI_FLASH) += spi-nor.o
obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 7100b64bf22..dee03662d45 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -229,9 +229,11 @@ static int spi_flash_std_remove(struct udevice *dev)
spi_mem_dirmap_destroy(flash->dirmap.rdesc);
}
- ret = spi_nor_remove(flash);
- if (ret)
- return ret;
+ if (CONFIG_IS_ENABLED(SPI_FLASH_SOFT_RESET)) {
+ ret = spi_nor_remove(flash);
+ if (ret)
+ return ret;
+ }
if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
spi_flash_mtd_unregister(flash);
diff --git a/drivers/mtd/ubi/part.c b/drivers/mtd/ubi/part.c
index 6c017eb7299..aff0b109b70 100644
--- a/drivers/mtd/ubi/part.c
+++ b/drivers/mtd/ubi/part.c
@@ -49,7 +49,7 @@ static int __maybe_unused part_get_info_ubi(struct blk_desc *dev_desc, int part_
if (!vol)
return -ENOENT;
- snprintf(info->name, PART_NAME_LEN, vol->name);
+ snprintf(info->name, PART_NAME_LEN, "%s", vol->name);
info->start = 0;
info->size = (unsigned long)vol->used_bytes / dev_desc->blksz;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4399c6c7a99..faa08e9ebba 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -284,6 +284,15 @@ config DWC_ETH_QOS_STM32
The Synopsys Designware Ethernet QOS IP block with the specific
configuration used in STM32MP soc.
+config DWC_ETH_QOS_SUNXI
+ bool "Synopsys DWC Ethernet QOS device support for Allwinner SoCs"
+ depends on DWC_ETH_QOS && ARCH_SUNXI
+ select REGMAP
+ select SUNXI_SYSCON
+ help
+ The Synopsys Designware Ethernet QOS IP block with specific
+ configuration used in Allwinner SoCs.
+
config DWC_ETH_QOS_TEGRA186
bool "Synopsys DWC Ethernet QOS device support for TEGRA186"
depends on DWC_ETH_QOS
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 761f7f0f451..4c1f4094ab2 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
obj-$(CONFIG_DWC_ETH_QOS_STM32) += dwc_eth_qos_stm32.o
+obj-$(CONFIG_DWC_ETH_QOS_SUNXI) += dwc_eth_qos_sunxi.o
obj-$(CONFIG_DWC_ETH_XGMAC) += dwc_eth_xgmac.o
obj-$(CONFIG_DWC_ETH_XGMAC_SOCFPGA) += dwc_eth_xgmac_socfpga.o
obj-$(CONFIG_E1000) += e1000.o
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c
index 9e17f0b9c28..53225979b66 100644
--- a/drivers/net/dm9000x.c
+++ b/drivers/net/dm9000x.c
@@ -638,11 +638,6 @@ static int dm9000_read_rom_hwaddr(struct udevice *dev)
return !is_valid_ethaddr(pdata->enetaddr);
}
-static int dm9000_bind(struct udevice *dev)
-{
- return device_set_name(dev, dev->name);
-}
-
static int dm9000_of_to_plat(struct udevice *dev)
{
struct dm9000_priv *db = dev_get_priv(dev);
@@ -673,7 +668,6 @@ U_BOOT_DRIVER(dm9000) = {
.name = "eth_dm9000",
.id = UCLASS_ETH,
.of_match = dm9000_ids,
- .bind = dm9000_bind,
.of_to_plat = dm9000_of_to_plat,
.ops = &dm9000_ops,
.priv_auto = sizeof(struct dm9000_priv),
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index b7e6299c307..e7cf68d011c 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1665,6 +1665,12 @@ static const struct udevice_id eqos_ids[] = {
.data = (ulong)&eqos_mtk_config
},
#endif
+#if IS_ENABLED(CONFIG_DWC_ETH_QOS_SUNXI)
+ {
+ .compatible = "allwinner,sun55i-a523-gmac200",
+ .data = (ulong)&eqos_sunxi_config
+ },
+#endif
{ }
};
diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
index 978b848b46e..ccb3c3a1453 100644
--- a/drivers/net/dwc_eth_qos.h
+++ b/drivers/net/dwc_eth_qos.h
@@ -318,3 +318,4 @@ extern struct eqos_config eqos_stm32mp25_config;
extern struct eqos_config eqos_jh7110_config;
extern struct eqos_config eqos_adi_config;
extern struct eqos_config eqos_mtk_config;
+extern struct eqos_config eqos_sunxi_config;
diff --git a/drivers/net/dwc_eth_qos_sunxi.c b/drivers/net/dwc_eth_qos_sunxi.c
new file mode 100644
index 00000000000..91d871dd271
--- /dev/null
+++ b/drivers/net/dwc_eth_qos_sunxi.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Corentin Labbe <[email protected]>
+ * Copyright (C) 2025 Chen-Yu Tsai <[email protected]>
+ * Copyright (C) 2026 Junhui Liu <[email protected]>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <net.h>
+#include <phy.h>
+#include <power/regulator.h>
+#include <regmap.h>
+#include <reset.h>
+#include <malloc.h>
+#include <syscon.h>
+
+#include "dwc_eth_qos.h"
+
+#define SYSCON_REG 0x34
+
+#define SYSCON_PHY_SELECT BIT(15) /* 1: internal, 0: external */
+/* RMII specific bits */
+#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */
+/* Generic system control EMAC_CLK bits */
+#define SYSCON_ETXDC_MASK GENMASK(12, 10)
+#define SYSCON_ERXDC_MASK GENMASK(9, 5)
+/* EMAC PHY Interface Type */
+#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */
+#define SYSCON_ETCS_MASK GENMASK(1, 0)
+#define SYSCON_ETCS_MII 0x0
+#define SYSCON_ETCS_EXT_GMII 0x1
+#define SYSCON_ETCS_INT_GMII 0x2
+
+struct sunxi_platform_data {
+ struct clk_bulk clks;
+ struct reset_ctl_bulk resets;
+};
+
+static int sunxi_gmac_set_syscon(struct udevice *dev,
+ phy_interface_t interface_type)
+{
+ struct regmap *regmap;
+ u32 val, reg = 0;
+ int ret;
+
+ regmap = syscon_regmap_lookup_by_phandle(dev, "syscon");
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Unable to map syscon\n");
+ return PTR_ERR(regmap);
+ }
+
+ if (!dev_read_u32(dev, "tx-internal-delay-ps", &val)) {
+ if (val % 100) {
+ dev_err(dev, "tx-delay must be a multiple of 100\n");
+ return -EINVAL;
+ }
+ val /= 100;
+ dev_dbg(dev, "set tx-delay to %x\n", val);
+
+ if (!FIELD_FIT(SYSCON_ETXDC_MASK, val)) {
+ dev_err(dev, "TX clock delay exceeds maximum\n");
+ return -EINVAL;
+ }
+
+ reg |= FIELD_PREP(SYSCON_ETXDC_MASK, val);
+ }
+
+ if (!dev_read_u32(dev, "rx-internal-delay-ps", &val)) {
+ if (val % 100) {
+ dev_err(dev, "rx-delay must be a multiple of 100\n");
+ return -EINVAL;
+ }
+ val /= 100;
+ dev_dbg(dev, "set rx-delay to %x\n", val);
+ if (!FIELD_FIT(SYSCON_ERXDC_MASK, val)) {
+ dev_err(dev, "Invalid RX clock delay: %d\n", val);
+ return -EINVAL;
+ }
+
+ reg |= FIELD_PREP(SYSCON_ERXDC_MASK, val);
+ }
+
+ switch (interface_type) {
+ case PHY_INTERFACE_MODE_MII:
+ /* default */
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ reg |= SYSCON_RMII_EN;
+ break;
+ default:
+ dev_err(dev, "Unsupported interface mode: %s\n",
+ phy_interface_strings[interface_type]);
+ return -EINVAL;
+ }
+
+ ret = regmap_write(regmap, SYSCON_REG, reg);
+ if (ret < 0) {
+ dev_err(dev, "Failed to write to syscon\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int eqos_start_clks_sunxi(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct sunxi_platform_data *data = pdata->priv_pdata;
+
+ return clk_enable_bulk(&data->clks);
+}
+
+static int eqos_stop_clks_sunxi(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct sunxi_platform_data *data = pdata->priv_pdata;
+
+ return clk_disable_bulk(&data->clks);
+}
+
+static int eqos_start_resets_sunxi(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct sunxi_platform_data *data = pdata->priv_pdata;
+ int ret;
+
+ ret = reset_deassert_bulk(&data->resets);
+ if (ret)
+ return ret;
+
+ return sunxi_gmac_set_syscon(dev, pdata->phy_interface);
+}
+
+static int eqos_stop_resets_sunxi(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct sunxi_platform_data *data = pdata->priv_pdata;
+
+ return reset_assert_bulk(&data->resets);
+}
+
+static int eqos_probe_resources_sunxi(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct sunxi_platform_data *data;
+ struct udevice *phy_supply = NULL;
+ int ret;
+
+ ret = eqos_get_base_addr_dt(dev);
+ if (ret) {
+ dev_err(dev, "Failed to get base address: %d\n", ret);
+ return ret;
+ }
+
+ data = calloc(1, sizeof(struct sunxi_platform_data));
+ if (!data)
+ return -ENOMEM;
+
+ pdata->priv_pdata = data;
+
+ pdata->phy_interface = eqos->config->interface(dev);
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
+ dev_err(dev, "Failed to get PHY interface mode\n");
+ return -EINVAL;
+ }
+
+ ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
+ if (ret) {
+ dev_err(dev, "Failed to get stmmaceth clock: %d\n", ret);
+ return ret;
+ }
+
+ ret = reset_get_bulk(dev, &data->resets);
+ if (ret) {
+ dev_err(dev, "Failed to get resets: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_get_bulk(dev, &data->clks);
+ if (ret) {
+ dev_err(dev, "Failed to get clocks: %d\n", ret);
+ return ret;
+ }
+
+ if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ ret = device_get_supply_regulator(dev, "phy-supply", &phy_supply);
+ if (ret && ret != -ENOENT) {
+ dev_err(dev, "Failed to get PHY supply: %d\n", ret);
+ return ret;
+ }
+
+ if (phy_supply) {
+ ret = regulator_set_enable_if_allowed(phy_supply, true);
+ if (ret) {
+ dev_err(dev, "Failed to enable phy supply: %d\n", ret);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int eqos_remove_resources_sunxi(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct sunxi_platform_data *data = pdata->priv_pdata;
+
+ reset_assert_bulk(&data->resets);
+ clk_disable_bulk(&data->clks);
+
+ return 0;
+}
+
+static struct eqos_ops eqos_sunxi_ops = {
+ .eqos_inval_desc = eqos_inval_desc_generic,
+ .eqos_flush_desc = eqos_flush_desc_generic,
+ .eqos_inval_buffer = eqos_inval_buffer_generic,
+ .eqos_flush_buffer = eqos_flush_buffer_generic,
+ .eqos_probe_resources = eqos_probe_resources_sunxi,
+ .eqos_remove_resources = eqos_remove_resources_sunxi,
+ .eqos_stop_resets = eqos_stop_resets_sunxi,
+ .eqos_start_resets = eqos_start_resets_sunxi,
+ .eqos_stop_clks = eqos_stop_clks_sunxi,
+ .eqos_start_clks = eqos_start_clks_sunxi,
+ .eqos_calibrate_pads = eqos_null_ops,
+ .eqos_disable_calibration = eqos_null_ops,
+ .eqos_set_tx_clk_speed = eqos_null_ops,
+ .eqos_get_enetaddr = eqos_null_ops,
+};
+
+struct eqos_config __maybe_unused eqos_sunxi_config = {
+ .reg_access_always_ok = false,
+ .mdio_wait = 10,
+ .swr_wait = 50,
+ .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+ .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_150_250,
+ .axi_bus_width = EQOS_AXI_WIDTH_64,
+ .interface = dev_read_phy_mode,
+ .ops = &eqos_sunxi_ops
+};
diff --git a/drivers/net/dwc_eth_xgmac.c b/drivers/net/dwc_eth_xgmac.c
index 311b57011c3..4e664a88f68 100644
--- a/drivers/net/dwc_eth_xgmac.c
+++ b/drivers/net/dwc_eth_xgmac.c
@@ -507,6 +507,7 @@ static int xgmac_start(struct udevice *dev)
xgmac->config->interface(dev));
if (!xgmac->phy) {
pr_err("%s phy_connect() failed\n", dev->name);
+ ret = -ENODEV;
goto err_stop_resets;
}
diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c
index fa0b3dbb6d1..d9826178e82 100644
--- a/drivers/net/ftmac100.c
+++ b/drivers/net/ftmac100.c
@@ -429,11 +429,6 @@ static int ftmac100_remove(struct udevice *dev)
return 0;
}
-static int ftmac100_bind(struct udevice *dev)
-{
- return device_set_name(dev, dev->name);
-}
-
static const struct eth_ops ftmac100_ops = {
.start = ftmac100_start,
.send = ftmac100_send,
@@ -451,7 +446,6 @@ U_BOOT_DRIVER(ftmac100) = {
.name = "ftmac100",
.id = UCLASS_ETH,
.of_match = ftmac100_ids,
- .bind = ftmac100_bind,
.of_to_plat = ftmac100_of_to_plat,
.probe = ftmac100_probe,
.remove = ftmac100_remove,
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index 2c956154d09..c2f87d4222b 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -571,11 +571,6 @@ static int ks8851_read_rom_hwaddr(struct udevice *dev)
return !is_valid_ethaddr(pdata->enetaddr);
}
-static int ks8851_bind(struct udevice *dev)
-{
- return device_set_name(dev, dev->name);
-}
-
static int ks8851_probe(struct udevice *dev)
{
struct ks_net *ks = dev_get_priv(dev);
@@ -615,7 +610,6 @@ U_BOOT_DRIVER(ks8851) = {
.name = "eth_ks8851",
.id = UCLASS_ETH,
.of_match = ks8851_ids,
- .bind = ks8851_bind,
.of_to_plat = ks8851_of_to_plat,
.probe = ks8851_probe,
.ops = &ks8851_ops,
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index ebed61de133..34c871857e1 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -126,6 +126,22 @@ struct dp83867_private {
bool sgmii_ref_clk_en;
};
+static int dp83867_phy_extread(struct phy_device *phydev,
+ int addr, int devad, int reg)
+{
+ if (devad != DP83867_DEVADDR)
+ return -EINVAL;
+ return phy_read_mmd(phydev, devad, addr);
+};
+
+static int dp83867_phy_extwrite(struct phy_device *phydev, int addr,
+ int devad, int reg, u16 val)
+{
+ if (devad != DP83867_DEVADDR)
+ return -EINVAL;
+ return phy_write_mmd(phydev, devad, addr, (u32)val);
+};
+
static int dp83867_config_port_mirroring(struct phy_device *phydev)
{
struct dp83867_private *dp83867 =
@@ -410,4 +426,6 @@ U_BOOT_PHY_DRIVER(dp83867) = {
.config = &dp83867_config,
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
+ .readext = dp83867_phy_extread,
+ .writeext = dp83867_phy_extwrite,
};
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d7e0c4fe02d..f2e9b2a9820 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -20,6 +20,7 @@
#include <asm-generic/gpio.h>
#include <dm/device_compat.h>
#include <dm/of_extra.h>
+#include <dm/uclass-internal.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -921,6 +922,27 @@ static struct phy_device *phy_connect_fixed(struct mii_dev *bus,
}
#endif
+#ifdef CONFIG_DM_ETH_PHY
+static struct phy_device *phy_connect_dm_bound(struct mii_dev *bus,
+ struct udevice *dev,
+ uint mask)
+{
+ struct udevice *dm_phy_dev;
+ struct phy_device *phydev;
+
+ if (!uclass_find_device_by_phandle(UCLASS_ETH_PHY, dev,
+ "phy-handle", &dm_phy_dev)) {
+ phydev = phy_find_by_mask(bus, mask);
+ if (phydev)
+ phydev->node = dev_ofnode(dm_phy_dev);
+
+ return phydev;
+ }
+
+ return NULL;
+}
+#endif
+
struct phy_device *phy_connect(struct mii_dev *bus, int addr,
struct udevice *dev,
phy_interface_t interface)
@@ -928,8 +950,13 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
struct phy_device *phydev = NULL;
uint mask = (addr >= 0) ? (1 << addr) : 0xffffffff;
+#ifdef CONFIG_DM_ETH_PHY
+ phydev = phy_connect_dm_bound(bus, dev, mask);
+#endif
+
#ifdef CONFIG_PHY_FIXED
- phydev = phy_connect_fixed(bus, dev);
+ if (!phydev)
+ phydev = phy_connect_fixed(bus, dev);
#endif
#ifdef CONFIG_PHY_NCSI
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index e203faed26b..0208ff2d435 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -49,6 +49,7 @@
#include <asm/cache.h>
#include <asm/io.h>
#include <pci.h>
+#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/printk.h>
@@ -152,8 +153,24 @@ enum RTL8125_registers {
IntrMask_8125 = 0x38,
IntrStatus_8125 = 0x3C,
TxPoll_8125 = 0x90,
+ RX_DESC_MODE = 0xd8,
+ MACOCP = 0xb0,
+ RADMFIFO_PROTECT = 0x0402,
+ TX_DESC_MODE = 0xeb58,
};
+/* MAC OCP indirect access via the MACOCP register */
+#define RTL8125_OCP_WRITE 0x80000000
+#define RTL8125_OCP_ADDR_SHIFT 16
+#define RX_DESC_CRC_DROP BIT(0)
+#define RX_DESC_TYPE BIT(1)
+
+/* TX_DESC_MODE (MAC OCP 0xeb58): TX descriptor format select, bits [1:0] */
+#define TX_DESC_FMT_MASK GENMASK(1, 0)
+#define TX_DESC_FMT_STD BIT(0)
+#define TX_DESC_FMT_V3 BIT(1)
+#define RX_PAUSE_SLOT_ON BIT(11)
+
enum RTL8169_register_content {
/*InterruptStatusBits */
SYSErr = 0x8000,
@@ -271,6 +288,8 @@ static struct {
{"RTL-8168h/8111h", 0x54, 0xff7e1880,},
{"RTL-8125B", 0x64, 0xff7e1880,},
{"RTL-8125d", 0x6a, 0xff7e5880,},
+ {"RTL-8126A", 0x66, 0xff7e5880,},
+ {"RTL-8127A", 0x6e, 0xff7e5880,},
};
enum _DescStatusBit {
@@ -355,6 +374,8 @@ static const unsigned int rtl8169_rx_config =
static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8126) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8127) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168) },
@@ -398,6 +419,33 @@ int mdio_read(int RegAddr)
return value;
}
+/* RTL8125/8126/8127 share the same register layout and quirks */
+static bool rtl_is_8125(struct pci_child_plat *pplat)
+{
+ return pplat->device == 0x8125 || pplat->device == 0x8126 ||
+ pplat->device == 0x8127;
+}
+
+static void rtl_mac_ocp_write(u16 reg_addr, u16 value)
+{
+ u32 data32;
+
+ data32 = (u32)(reg_addr / 2) << RTL8125_OCP_ADDR_SHIFT;
+ data32 += value;
+ data32 |= RTL8125_OCP_WRITE;
+ RTL_W32(MACOCP, data32);
+}
+
+static u16 rtl_mac_ocp_read(u16 reg_addr)
+{
+ u32 data32;
+
+ data32 = (u32)(reg_addr / 2) << RTL8125_OCP_ADDR_SHIFT;
+ RTL_W32(MACOCP, data32);
+
+ return (u16)RTL_R32(MACOCP);
+}
+
static int rtl8169_init_board(unsigned long dev_iobase, const char *name)
{
int i;
@@ -571,12 +619,15 @@ static int rtl_recv_common(struct udevice *dev, unsigned long dev_iobase,
return length;
} else {
- u32 IntrStatus = IntrStatus_8169;
+ u32 sts;
- if (pplat->device == 0x8125)
- IntrStatus = IntrStatus_8125;
- ushort sts = RTL_R8(IntrStatus);
- RTL_W8(IntrStatus, sts & ~(TxErr | RxErr | SYSErr));
+ if (rtl_is_8125(pplat)) {
+ sts = RTL_R32(IntrStatus_8125);
+ RTL_W32(IntrStatus_8125, sts & ~(TxErr | RxErr | SYSErr));
+ } else {
+ sts = RTL_R16(IntrStatus_8169);
+ RTL_W16(IntrStatus_8169, sts & ~(TxErr | RxErr | SYSErr));
+ }
udelay(100); /* wait */
}
tpc->cur_rx = cur_rx;
@@ -636,8 +687,8 @@ static int rtl_send_common(struct udevice *dev, unsigned long dev_iobase,
((len > ETH_ZLEN) ? len : ETH_ZLEN));
}
rtl_flush_tx_desc(&tpc->TxDescArray[entry]);
- if (pplat->device == 0x8125)
- RTL_W8(TxPoll_8125, 0x1); /* set polling bit */
+ if (rtl_is_8125(pplat))
+ RTL_W32(TxPoll_8125, 0x1); /* set polling bit */
else
RTL_W8(TxPoll_8169, 0x40); /* set polling bit */
@@ -697,6 +748,8 @@ static void rtl8169_set_rx_mode(void)
static void rtl8169_hw_start(struct udevice *dev)
{
+ u8 version = rtl_chip_info[tpc->chipset].version;
+ u16 tx_desc_mode;
u32 i;
#ifdef DEBUG_RTL8169
@@ -719,6 +772,36 @@ static void rtl8169_hw_start(struct udevice *dev)
RTL_W8(Cfg9346, Cfg9346_Unlock);
+ /*
+ * RTL8125D/8126A/8127A require explicit descriptor-type and CRC-drop setup.
+ * RTL8125B (0x64) is intentionally excluded to avoid regressing working hardware.
+ */
+ switch (version) {
+ case 0x6a:
+ case 0x66:
+ case 0x6e:
+ /* Reg 0xD8: Disable CRC drop and force legacy 16-byte RX desc */
+ RTL_W8(RX_DESC_MODE, RTL_R8(RX_DESC_MODE) & ~(RX_DESC_CRC_DROP | RX_DESC_TYPE));
+
+ /* RxConfig 0x44: enable RX pause slot (RTL8125B and later) */
+ RTL_W32(RxConfig, RTL_R32(RxConfig) | RX_PAUSE_SLOT_ON);
+
+ /* MAC OCP 0xEB58: TX descriptor format setup */
+ tx_desc_mode = rtl_mac_ocp_read(TX_DESC_MODE) & ~TX_DESC_FMT_MASK;
+
+ if (version == 0x6e) {
+ /* RTL8127A specific: Tx desc V3 and RADM FIFO protection */
+ rtl_mac_ocp_write(TX_DESC_MODE, tx_desc_mode | TX_DESC_FMT_V3);
+ RTL_W16(RADMFIFO_PROTECT, 0x2001);
+ } else {
+ /* RTL8125D / RTL8126A specific: standard Tx desc */
+ rtl_mac_ocp_write(TX_DESC_MODE, tx_desc_mode | TX_DESC_FMT_STD);
+ }
+ break;
+ default:
+ break;
+ }
+
/* RTL-8169sb/8110sb or previous version */
if (tpc->chipset <= 5)
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
@@ -860,8 +943,8 @@ static void rtl_halt_common(struct udevice *dev)
RTL_W8(ChipCmd, 0x00);
/* Disable interrupts by clearing the interrupt mask. */
- if (pplat->device == 0x8125)
- RTL_W16(IntrMask_8125, 0x0000);
+ if (rtl_is_8125(pplat))
+ RTL_W32(IntrMask_8125, 0x00000000);
else
RTL_W16(IntrMask_8169, 0x0000);
@@ -1052,6 +1135,8 @@ static int rtl8169_eth_probe(struct udevice *dev)
switch (pplat->device) {
case 0x8125:
+ case 0x8126:
+ case 0x8127:
case 0x8161:
case 0x8168:
region = 2;
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index f39ba40944f..2835eb45856 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -431,11 +431,6 @@ static int smc911x_read_rom_hwaddr(struct udevice *dev)
return 0;
}
-static int smc911x_bind(struct udevice *dev)
-{
- return device_set_name(dev, dev->name);
-}
-
static int smc911x_probe(struct udevice *dev)
{
struct smc911x_priv *priv = dev_get_priv(dev);
@@ -487,7 +482,6 @@ U_BOOT_DRIVER(smc911x) = {
.name = "eth_smc911x",
.id = UCLASS_ETH,
.of_match = smc911x_ids,
- .bind = smc911x_bind,
.of_to_plat = smc911x_of_to_plat,
.probe = smc911x_probe,
.ops = &smc911x_ops,
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 147a104149e..c815a967137 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -8,10 +8,10 @@
#include <bootdev.h>
#include <cpu_func.h>
#include <dm.h>
-#include <errno.h>
#include <log.h>
#include <malloc.h>
#include <memalign.h>
+#include <phys2bus.h>
#include <time.h>
#include <dm/device-internal.h>
#include <linux/compat.h>
@@ -101,6 +101,8 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
printf("Error: malloc prp_pool fail\n");
return -ENOMEM;
}
+ dev->prp_pool_dma = dev_phys_to_bus(dev->udev,
+ (uintptr_t)dev->prp_pool);
dev->prp_entry_num = num_pages * (prps_per_page - 1) + 1;
}
@@ -108,8 +110,10 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
i = 0;
while (nprps) {
if ((i == (prps_per_page - 1)) && nprps > 1) {
- *(prp_pool + i) = cpu_to_le64((ulong)prp_pool +
- page_size);
+ dma_addr_t prp_pool_dma =
+ dev_phys_to_bus(dev->udev, (uintptr_t)prp_pool);
+ *(prp_pool + i) = cpu_to_le64(prp_pool_dma +
+ page_size);
i = 0;
prp_pool = (u64 *)((uintptr_t)prp_pool + page_size);
}
@@ -117,7 +121,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
dma_addr += page_size;
nprps--;
}
- *prp2 = (ulong)dev->prp_pool;
+ *prp2 = dev->prp_pool_dma;
flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool +
num_pages * page_size);
@@ -258,11 +262,15 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev,
nvmeq->cqes = (void *)memalign(4096, NVME_CQ_ALLOCATION);
if (!nvmeq->cqes)
goto free_nvmeq;
+ nvmeq->cq_dma_addr = dev_phys_to_bus(dev->udev,
+ (uintptr_t)nvmeq->cqes);
memset((void *)nvmeq->cqes, 0, NVME_CQ_SIZE(depth));
nvmeq->sq_cmds = (void *)memalign(4096, NVME_SQ_SIZE(depth));
if (!nvmeq->sq_cmds)
goto free_queue;
+ nvmeq->sq_dma_addr = dev_phys_to_bus(dev->udev,
+ (uintptr_t)nvmeq->sq_cmds);
memset((void *)nvmeq->sq_cmds, 0, NVME_SQ_SIZE(depth));
nvmeq->dev = dev;
@@ -410,8 +418,8 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
writel(aqa, &dev->bar->aqa);
- nvme_writeq((ulong)nvmeq->sq_cmds, &dev->bar->asq);
- nvme_writeq((ulong)nvmeq->cqes, &dev->bar->acq);
+ nvme_writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
+ nvme_writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
result = nvme_enable_ctrl(dev);
if (result)
@@ -437,7 +445,7 @@ static int nvme_alloc_cq(struct nvme_dev *dev, u16 qid,
memset(&c, 0, sizeof(c));
c.create_cq.opcode = nvme_admin_create_cq;
- c.create_cq.prp1 = cpu_to_le64((ulong)nvmeq->cqes);
+ c.create_cq.prp1 = cpu_to_le64(nvmeq->cq_dma_addr);
c.create_cq.cqid = cpu_to_le16(qid);
c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
c.create_cq.cq_flags = cpu_to_le16(flags);
@@ -454,7 +462,7 @@ static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid,
memset(&c, 0, sizeof(c));
c.create_sq.opcode = nvme_admin_create_sq;
- c.create_sq.prp1 = cpu_to_le64((ulong)nvmeq->sq_cmds);
+ c.create_sq.prp1 = cpu_to_le64(nvmeq->sq_dma_addr);
c.create_sq.sqid = cpu_to_le16(qid);
c.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
c.create_sq.sq_flags = cpu_to_le16(flags);
@@ -464,13 +472,13 @@ static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid,
}
int nvme_identify(struct nvme_dev *dev, unsigned nsid,
- unsigned cns, dma_addr_t dma_addr)
+ unsigned cns, dma_addr_t cpu_addr)
{
struct nvme_command c;
u32 page_size = dev->page_size;
+ dma_addr_t dma_addr = dev_phys_to_bus(dev->udev, cpu_addr);
int offset = dma_addr & (page_size - 1);
int length = sizeof(struct nvme_id_ctrl);
- dma_addr_t orig_dma_addr = dma_addr;
int ret;
memset(&c, 0, sizeof(c));
@@ -488,49 +496,22 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid,
c.identify.cns = cpu_to_le32(cns);
- nvme_invalidate_cache_aligned((uintptr_t)orig_dma_addr,
+ nvme_invalidate_cache_aligned((uintptr_t)cpu_addr,
sizeof(struct nvme_id_ctrl));
ret = nvme_submit_admin_cmd(dev, &c, NULL);
if (!ret)
- nvme_invalidate_cache_aligned((uintptr_t)orig_dma_addr,
+ nvme_invalidate_cache_aligned((uintptr_t)cpu_addr,
sizeof(struct nvme_id_ctrl));
return ret;
}
-int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
- dma_addr_t dma_addr, u32 *result)
-{
- struct nvme_command c;
- int ret;
-
- memset(&c, 0, sizeof(c));
- c.features.opcode = nvme_admin_get_features;
- c.features.nsid = cpu_to_le32(nsid);
- c.features.prp1 = cpu_to_le64(dma_addr);
- c.features.fid = cpu_to_le32(fid);
-
- ret = nvme_submit_admin_cmd(dev, &c, result);
-
- /*
- * TODO: Add some cache invalidation when a DMA buffer is involved
- * in the request, here and before the command gets submitted. The
- * buffer size varies by feature, also some features use a different
- * field in the command packet to hold the buffer address.
- * Section 5.21.1 (Set Features command) in the NVMe specification
- * details the buffer requirements for each feature.
- *
- * At the moment there is no user of this function.
- */
-
- return ret;
-}
-
int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
- dma_addr_t dma_addr, u32 *result)
+ dma_addr_t cpu_addr, u32 *result)
{
struct nvme_command c;
+ dma_addr_t dma_addr = dev_phys_to_bus(dev->udev, cpu_addr);
memset(&c, 0, sizeof(c));
c.features.opcode = nvme_admin_set_features;
@@ -769,7 +750,7 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,
u64 prp2;
u64 total_len = blkcnt << desc->log2blksz;
u64 temp_len = total_len;
- uintptr_t temp_buffer = (uintptr_t)buffer;
+ uintptr_t dma_addr = dev_phys_to_bus(udev, (uintptr_t)buffer);
u64 slba = blknr;
u16 lbas = 1 << (dev->max_transfer_shift - ns->lba_shift);
@@ -797,19 +778,19 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,
}
if (nvme_setup_prps(dev, &prp2,
- lbas << ns->lba_shift, temp_buffer))
+ lbas << ns->lba_shift, dma_addr))
return -EIO;
c.rw.slba = cpu_to_le64(slba);
slba += lbas;
c.rw.length = cpu_to_le16(lbas - 1);
- c.rw.prp1 = cpu_to_le64(temp_buffer);
+ c.rw.prp1 = cpu_to_le64(dma_addr);
c.rw.prp2 = cpu_to_le64(prp2);
status = nvme_submit_sync_cmd(dev->queues[NVME_IO_Q],
&c, NULL, IO_TIMEOUT);
if (status)
break;
temp_len -= (u32)lbas << ns->lba_shift;
- temp_buffer += lbas << ns->lba_shift;
+ dma_addr += lbas << ns->lba_shift;
}
if (read)
@@ -884,6 +865,8 @@ int nvme_init(struct udevice *udev)
printf("Error: %s: Out of memory!\n", udev->name);
goto free_queue;
}
+
+ ndev->prp_pool_dma = dev_phys_to_bus(udev, (uintptr_t)ndev->prp_pool);
ndev->prp_entry_num = MAX_PRP_POOL >> 3;
ret = nvme_setup_io_queues(ndev);
diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h
index bc1d612dde4..7c6ed4d9b55 100644
--- a/drivers/nvme/nvme.h
+++ b/drivers/nvme/nvme.h
@@ -619,6 +619,7 @@ struct nvme_dev {
u32 page_size;
u8 vwc;
u64 *prp_pool;
+ uintptr_t prp_pool_dma;
u32 prp_entry_num;
u32 nn;
};
@@ -637,7 +638,9 @@ enum nvme_queue_id {
struct nvme_queue {
struct nvme_dev *dev;
struct nvme_command *sq_cmds;
+ dma_addr_t sq_dma_addr;
struct nvme_completion *cqes;
+ dma_addr_t cq_dma_addr;
u32 __iomem *q_db;
u16 q_depth;
s16 cq_vector;
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 9ffccc3a80b..2b2ccdf4745 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -396,6 +396,7 @@ config PCI_RCAR_GEN4
depends on RCAR_GEN4
select DM_RESET
select DM_GPIO
+ select FW_LOADER
select PCIE_DW_COMMON
help
Say Y here if you want to enable PCIe controller support on
diff --git a/drivers/pci/pci-rcar-gen4.c b/drivers/pci/pci-rcar-gen4.c
index e165271f58c..b1d43b2e7aa 100644
--- a/drivers/pci/pci-rcar-gen4.c
+++ b/drivers/pci/pci-rcar-gen4.c
@@ -19,6 +19,7 @@
#include <dm.h>
#include <dm/device_compat.h>
#include <env.h>
+#include <fw_loader.h>
#include <log.h>
#include <reset.h>
@@ -75,6 +76,7 @@
#define RCAR_GEN4_PCIE_FIRMWARE_NAME "rcar_gen4_pcie.bin"
#define RCAR_GEN4_PCIE_FIRMWARE_BASE_ADDR 0xc000
+#define RCAR_GEN4_PCIE_FIRMWARE_SIZE 0x8000
#define PCIE_T_PVPERL_MS 100
@@ -97,17 +99,26 @@
struct rcar_gen4_pcie {
/* Must be first member of the struct */
struct pcie_dw dw;
- struct reset_ctl pwr_rst;
+ struct reset_ctl *pwr_rst;
struct clk *core_clk;
struct clk *ref_clk;
- struct gpio_desc pe_rst;
+ struct gpio_desc *pe_rst;
void *app_base;
void *dbi2_base;
void *phy_base;
u32 max_link_speed;
u32 num_lanes;
u16 *firmware;
- u32 firmware_size;
+ size_t firmware_size;
+};
+
+/**
+ * struct rcar_gen4_pcie_plat - Renesas R-Car Gen4 DW PCIe controller platform data
+ *
+ * @probed: Controller was started
+ */
+struct rcar_gen4_pcie_plat {
+ bool probed;
};
/* Common */
@@ -302,7 +313,7 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
if (ret)
return ret;
- ret = reset_assert(&rcar->pwr_rst);
+ ret = reset_assert(rcar->pwr_rst);
if (ret)
goto err_unprepare;
@@ -312,11 +323,11 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
DEVICE_TYPE_RC |
((rcar->num_lanes < 4) ? BIFUR_MOD_SET_ON : 0));
- ret = reset_deassert(&rcar->pwr_rst);
+ ret = reset_deassert(rcar->pwr_rst);
if (ret)
goto err_unprepare;
- reset_status(&rcar->pwr_rst);
+ reset_status(rcar->pwr_rst);
mdelay(1);
rcar_gen4_pcie_additional_common_init(rcar);
@@ -335,7 +346,7 @@ static int rcar_gen4_pcie_host_init(struct udevice *dev)
struct rcar_gen4_pcie *rcar = dev_get_priv(dev);
int ret;
- dm_gpio_set_value(&rcar->pe_rst, 1);
+ dm_gpio_set_value(rcar->pe_rst, 1);
ret = rcar_gen4_pcie_common_init(rcar);
if (ret)
@@ -355,63 +366,38 @@ static int rcar_gen4_pcie_host_init(struct udevice *dev)
mdelay(PCIE_T_PVPERL_MS); /* pe_rst requires 100msec delay */
- dm_gpio_set_value(&rcar->pe_rst, 0);
+ dm_gpio_set_value(rcar->pe_rst, 0);
return 0;
}
static int rcar_gen4_pcie_load_firmware(struct rcar_gen4_pcie *rcar)
{
- ulong addr, size;
int ret;
- /*
- * Run user specified firmware loading script, which loads the
- * firmware from whichever location the user decides it should
- * load the firmware from, by whatever means the user decides.
- */
- ret = run_command_list("run renesas_rcar_gen4_load_firmware", -1, 0);
- if (ret) {
- printf("Firmware loading script 'renesas_rcar_gen4_load_firmware' not defined or failed.\n");
- goto fail;
- }
-
- /* Find out where the firmware got loaded and how long it is. */
- addr = env_get_hex("renesas_rcar_gen4_load_firmware_addr", 0);
- size = env_get_hex("renesas_rcar_gen4_load_firmware_size", 0);
-
- /*
- * Clear the variables set by the firmware loading script, as
- * their content would become stale once this function exits.
- */
- env_set("renesas_rcar_gen4_load_firmware_addr", NULL);
- env_set("renesas_rcar_gen4_load_firmware_size", NULL);
-
- if (!addr || !size) {
- printf("Firmware address (%lx) or size (%lx) are invalid.\n", addr, size);
- goto fail;
- }
-
- /* Create local copy of the loaded firmware. */
- rcar->firmware = (u16 *)memdup((void *)addr, size);
+ rcar->firmware = calloc(1, RCAR_GEN4_PCIE_FIRMWARE_SIZE);
if (!rcar->firmware)
return -ENOMEM;
- rcar->firmware_size = size;
+ ret = request_firmware_into_buf_via_script(rcar->firmware,
+ RCAR_GEN4_PCIE_FIRMWARE_SIZE,
+ "renesas_rcar_gen4_load_firmware",
+ &rcar->firmware_size);
+ if (ret) {
+ free(rcar->firmware);
- return 0;
+ printf("Define 'renesas_rcar_gen4_load_firmware' script which loads the R-Car\n"
+ "Gen4 PCIe controller firmware from storage into memory and sets these\n"
+ "two environment variables:\n"
+ " renesas_rcar_gen4_load_firmware_addr ... address of firmware in memory\n"
+ " renesas_rcar_gen4_load_firmware_size ... length of firmware in bytes\n"
+ "\n"
+ "Example:\n"
+ " => env set renesas_rcar_gen4_load_firmware 'env set renesas_rcar_gen4_load_firmware_addr 0x54000000 && load mmc 0:1 ${renesas_rcar_gen4_load_firmware_addr} lib/firmware/rcar_gen4_pcie.bin && env set renesas_rcar_gen4_load_firmware_size ${filesize}'\n"
+ );
+ }
-fail:
- printf("Define 'renesas_rcar_gen4_load_firmware' script which loads the R-Car\n"
- "Gen4 PCIe controller firmware from storage into memory and sets these\n"
- "two environment variables:\n"
- " renesas_rcar_gen4_load_firmware_addr ... address of firmware in memory\n"
- " renesas_rcar_gen4_load_firmware_size ... length of firmware in bytes\n"
- "\n"
- "Example:\n"
- " => env set renesas_rcar_gen4_load_firmware 'env set renesas_rcar_gen4_load_firmware_addr 0x54000000 && load mmc 0:1 ${renesas_rcar_gen4_load_firmware_addr} lib/firmware/rcar_gen4_pcie.bin && env set renesas_rcar_gen4_load_firmware_size ${filesize}'\n"
- );
- return -EINVAL;
+ return ret;
}
/**
@@ -427,10 +413,14 @@ fail:
static int rcar_gen4_pcie_probe(struct udevice *dev)
{
struct rcar_gen4_pcie *rcar = dev_get_priv(dev);
+ struct rcar_gen4_pcie_plat *plat = dev_get_plat(dev);
struct udevice *ctlr = pci_get_controller(dev);
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
int ret;
+ if (plat->probed)
+ return -ENODEV;
+
ret = rcar_gen4_pcie_load_firmware(rcar);
if (ret)
return ret;
@@ -438,9 +428,9 @@ static int rcar_gen4_pcie_probe(struct udevice *dev)
rcar->dw.first_busno = dev_seq(dev);
rcar->dw.dev = dev;
- ret = reset_get_by_name(dev, "pwr", &rcar->pwr_rst);
- if (ret)
- return ret;
+ rcar->pwr_rst = devm_reset_control_get(dev, "pwr");
+ if (IS_ERR(rcar->pwr_rst))
+ return PTR_ERR(rcar->pwr_rst);
rcar->core_clk = devm_clk_get(dev, "core");
if (IS_ERR(rcar->core_clk))
@@ -451,13 +441,13 @@ static int rcar_gen4_pcie_probe(struct udevice *dev)
return PTR_ERR(rcar->ref_clk);
ret = clk_prepare_enable(rcar->ref_clk);
- if (ret)
+ if (ret && ret != -ENOSYS)
return ret;
- ret = gpio_request_by_name(dev, "reset-gpios", 0, &rcar->pe_rst,
- GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
- if (ret)
- return ret;
+ rcar->pe_rst = devm_gpiod_get(dev, "reset",
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+ if (IS_ERR(rcar->pe_rst))
+ return PTR_ERR(rcar->pe_rst);
ret = rcar_gen4_pcie_host_init(dev);
if (ret)
@@ -470,6 +460,7 @@ static int rcar_gen4_pcie_probe(struct udevice *dev)
dw_pcie_link_set_max_link_width(&rcar->dw, rcar->num_lanes);
ret = rcar_gen4_pcie_start_link(rcar);
+ plat->probed = true;
if (ret)
return ret;
@@ -478,8 +469,8 @@ static int rcar_gen4_pcie_probe(struct udevice *dev)
if (!rcar_gen4_pcie_link_up(rcar)) {
printf("PCIE-%d: Link down\n", dev_seq(dev));
rcar_gen4_pcie_ltssm_control(rcar, false);
- dm_gpio_set_value(&rcar->pe_rst, 1);
- reset_assert(&rcar->pwr_rst);
+ dm_gpio_set_value(rcar->pe_rst, 1);
+ reset_assert(rcar->pwr_rst);
clk_disable_unprepare(rcar->ref_clk);
return -ENODEV;
}
@@ -510,8 +501,8 @@ static int rcar_gen4_pcie_remove(struct udevice *dev)
struct rcar_gen4_pcie *rcar = dev_get_priv(dev);
rcar_gen4_pcie_ltssm_control(rcar, false);
- dm_gpio_set_value(&rcar->pe_rst, 1);
- reset_assert(&rcar->pwr_rst);
+ dm_gpio_set_value(rcar->pe_rst, 1);
+ reset_assert(rcar->pwr_rst);
clk_disable_unprepare(rcar->ref_clk);
return 0;
@@ -592,5 +583,6 @@ U_BOOT_DRIVER(rcar_gen4_pcie) = {
.probe = rcar_gen4_pcie_probe,
.remove = rcar_gen4_pcie_remove,
.priv_auto = sizeof(struct rcar_gen4_pcie),
+ .plat_auto = sizeof(struct rcar_gen4_pcie_plat),
.flags = DM_FLAG_ACTIVE_DMA,
};
diff --git a/drivers/pci/pcie_layerscape_fixup.c b/drivers/pci/pcie_layerscape_fixup.c
index 97c38c0bfa7..5299aee63db 100644
--- a/drivers/pci/pcie_layerscape_fixup.c
+++ b/drivers/pci/pcie_layerscape_fixup.c
@@ -319,6 +319,11 @@ static struct extra_iommu_entry *get_extra_iommu_ents(void *blob,
/* Hot-plug entry */
entries[i].action = EXTRA_IOMMU_ENTRY_HOTPLUG;
p += 2;
+ /* Skip the comma separator so it check the
+ * next "pci@" group.
+ */
+ if (*p == ',')
+ p++;
} else if (!strncmp(p, "vfs", 3) ||
!strncmp(p, "noari_vfs", 9)) {
/* VFs or VFs with ARI disabled entry */
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 69ee9155a01..fd30aaeeaa8 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -440,6 +440,7 @@ source "drivers/pinctrl/nxp/Kconfig"
source "drivers/pinctrl/qcom/Kconfig"
source "drivers/pinctrl/renesas/Kconfig"
source "drivers/pinctrl/rockchip/Kconfig"
+source "drivers/pinctrl/spacemit/Kconfig"
source "drivers/pinctrl/sunxi/Kconfig"
source "drivers/pinctrl/tegra/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 6c6e8b59122..91149796bb5 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_$(PHASE_)PINCTRL_ROCKCHIP) += rockchip/
obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o
obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
+obj-$(CONFIG_$(PHASE_)PINCTRL_SPACEMIT_K1) += spacemit/
obj-$(CONFIG_PINCTRL_STARFIVE) += starfive/
obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 884ed258d17..ea726b96f61 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -720,6 +720,8 @@ static int armada_37xx_pinctrl_probe(struct udevice *dev)
return -ENODEV;
}
+ info->dev = dev;
+
/*
* we allocate functions for number of pins and hope there are
* fewer unique functions than pins available
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 42980e097e0..0029a7e1a27 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -509,29 +509,74 @@ static int single_add_gpio_func(struct udevice *dev)
struct single_priv *priv = dev_get_priv(dev);
const char *propname = "pinctrl-single,gpio-range";
const char *cellname = "#pinctrl-single,gpio-range-cells";
+ ofnode node = dev_ofnode(dev);
struct single_gpiofunc_range *range;
struct ofnode_phandle_args gpiospec;
- int ret, i;
+ int size, total_cells, cells_per_entry, entries, ret, i;
- for (i = 0; ; i++) {
- ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), propname,
- cellname, 0, i, &gpiospec);
- /* Do not treat it as error. Only treat it as end condition. */
- if (ret) {
- ret = 0;
+ /*
+ * The original loop called ofnode_parse_phandle_with_args() once per
+ * entry. On a flat DT each call resolves the phandle, which scans the
+ * whole tree, so the repeated parse is quadratic in the number of
+ * entries and proportional to the tree size. This is very slow
+ * pre-relocation with caches off.
+ *
+ * The phandle target is not used here (only the argument cells are
+ * stored), so resolve it only for the first entry to learn the
+ * per-entry cell count, then read the argument cells directly. This
+ * follows the existing pinctrl-single,gpio-range usage observed in
+ * current DTs, where entries use the same provider and therefore a
+ * uniform per-entry cell count.
+ */
+ ret = ofnode_parse_phandle_with_args(node, propname, cellname, 0, 0,
+ &gpiospec);
+ if (ret)
+ return 0;
+ if (gpiospec.args_count != 3)
+ return 0;
+
+ cells_per_entry = 1 + gpiospec.args_count;
+ size = ofnode_read_size(node, propname);
+ if (size < (int)sizeof(u32))
+ return 0;
+ total_cells = size / sizeof(u32);
+ entries = total_cells / cells_per_entry;
+ if (!entries)
+ return 0;
+
+ range = devm_kcalloc(dev, entries, sizeof(*range), GFP_KERNEL);
+ if (!range)
+ return -ENOMEM;
+
+ for (i = 0; i < entries; i++) {
+ int base = i * cells_per_entry;
+ u32 phandle;
+
+ ret = ofnode_read_u32_index(node, propname, base, &phandle);
+ if (ret)
break;
- }
- range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
- if (!range) {
- ret = -ENOMEM;
+
+ /* A zero phandle terminates the list, as in the original loop. */
+ if (!phandle)
break;
- }
- range->offset = gpiospec.args[0];
- range->npins = gpiospec.args[1];
- range->gpiofunc = gpiospec.args[2];
+
+ ret = ofnode_read_u32_index(node, propname, base + 1, &range->offset);
+ if (ret)
+ break;
+
+ ret = ofnode_read_u32_index(node, propname, base + 2, &range->npins);
+ if (ret)
+ break;
+
+ ret = ofnode_read_u32_index(node, propname, base + 3, &range->gpiofunc);
+ if (ret)
+ break;
+
list_add_tail(&range->node, &priv->gpiofuncs);
+ range++;
}
- return ret;
+
+ return 0;
}
static int single_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/renesas/pfc-r8a77951.c b/drivers/pinctrl/renesas/pfc-r8a77951.c
index 99b90e6df0d..0c4e91b6df5 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77951.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77951.c
@@ -1827,7 +1827,6 @@ static const unsigned int canfd1_data_pins[] = {
static const unsigned int canfd1_data_mux[] = {
CANFD1_TX_MARK, CANFD1_RX_MARK,
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77951
/* - DRIF0 --------------------------------------------------------------- */
@@ -2046,7 +2045,6 @@ static const unsigned int drif3_data1_b_mux[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77951 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
/* - DU --------------------------------------------------------------------- */
static const unsigned int du_rgb666_pins[] = {
/* R[7:2], G[7:2], B[7:2] */
@@ -2459,7 +2457,6 @@ static const unsigned int intc_ex_irq5_pins[] = {
static const unsigned int intc_ex_irq5_mux[] = {
IRQ5_MARK,
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77951
/* - MLB+ ------------------------------------------------------------------- */
@@ -2471,7 +2468,6 @@ static const unsigned int mlb_3pin_mux[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77951 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
/* - MSIOF0 ----------------------------------------------------------------- */
static const unsigned int msiof0_clk_pins[] = {
/* SCK */
@@ -3307,6 +3303,7 @@ static const unsigned int qspi1_data_mux[] = {
QSPI1_IO2_MARK, QSPI1_IO3_MARK,
};
+#ifdef CONFIG_PINCTRL_PFC_FULL
/* - SATA --------------------------------------------------------------------*/
static const unsigned int sata0_devslp_a_pins[] = {
/* DEVSLP */
@@ -3322,6 +3319,7 @@ static const unsigned int sata0_devslp_b_pins[] = {
static const unsigned int sata0_devslp_b_mux[] = {
SATA_DEVSLP_B_MARK,
};
+#endif
/* - SCIF0 ------------------------------------------------------------------ */
static const unsigned int scif0_data_pins[] = {
@@ -3874,7 +3872,6 @@ static const unsigned int ssi9_ctrl_b_pins[] = {
static const unsigned int ssi9_ctrl_b_mux[] = {
SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
};
-#endif
/* - TMU -------------------------------------------------------------------- */
static const unsigned int tmu_tclk1_a_pins[] = {
@@ -3935,6 +3932,7 @@ static const unsigned int tpu_to3_pins[] = {
static const unsigned int tpu_to3_mux[] = {
TPU0TO3_MARK,
};
+#endif
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
@@ -4378,8 +4376,10 @@ static const struct {
SH_PFC_PIN_GROUP(qspi1_ctrl),
BUS_DATA_PIN_GROUP(qspi1_data, 2),
BUS_DATA_PIN_GROUP(qspi1_data, 4),
+#ifdef CONFIG_PINCTRL_PFC_FULL
SH_PFC_PIN_GROUP(sata0_devslp_a),
SH_PFC_PIN_GROUP(sata0_devslp_b),
+#endif
SH_PFC_PIN_GROUP(scif0_data),
SH_PFC_PIN_GROUP(scif0_clk),
SH_PFC_PIN_GROUP(scif0_ctrl),
@@ -4461,7 +4461,6 @@ static const struct {
SH_PFC_PIN_GROUP(ssi9_data_b),
SH_PFC_PIN_GROUP(ssi9_ctrl_a),
SH_PFC_PIN_GROUP(ssi9_ctrl_b),
-#endif
SH_PFC_PIN_GROUP(tmu_tclk1_a),
SH_PFC_PIN_GROUP(tmu_tclk1_b),
SH_PFC_PIN_GROUP(tmu_tclk2_a),
@@ -4470,6 +4469,7 @@ static const struct {
SH_PFC_PIN_GROUP(tpu_to1),
SH_PFC_PIN_GROUP(tpu_to2),
SH_PFC_PIN_GROUP(tpu_to3),
+#endif
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
SH_PFC_PIN_GROUP(usb2),
@@ -4506,7 +4506,7 @@ static const struct {
SH_PFC_PIN_GROUP(vin5_clk),
#endif
},
-#ifdef CONFIG_PINCTRL_PFC_R8A77951
+#if defined(CONFIG_PINCTRL_PFC_FULL) && defined(CONFIG_PINCTRL_PFC_R8A77951)
.automotive = {
SH_PFC_PIN_GROUP(drif0_ctrl_a),
SH_PFC_PIN_GROUP(drif0_data0_a),
@@ -4601,7 +4601,6 @@ static const char * const canfd0_groups[] = {
static const char * const canfd1_groups[] = {
"canfd1_data",
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77951
static const char * const drif0_groups[] = {
@@ -4647,7 +4646,6 @@ static const char * const drif3_groups[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77951 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const du_groups[] = {
"du_rgb666",
"du_rgb888",
@@ -4740,7 +4738,6 @@ static const char * const intc_ex_groups[] = {
"intc_ex_irq4",
"intc_ex_irq5",
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77951
static const char * const mlb_3pin_groups[] = {
@@ -4748,7 +4745,6 @@ static const char * const mlb_3pin_groups[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77951 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const msiof0_groups[] = {
"msiof0_clk",
"msiof0_sync",
@@ -4907,10 +4903,12 @@ static const char * const qspi1_groups[] = {
"qspi1_data4",
};
+#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const sata0_groups[] = {
"sata0_devslp_a",
"sata0_devslp_b",
};
+#endif
static const char * const scif0_groups[] = {
"scif0_data",
@@ -5028,7 +5026,6 @@ static const char * const ssi_groups[] = {
"ssi9_ctrl_a",
"ssi9_ctrl_b",
};
-#endif
static const char * const tmu_groups[] = {
"tmu_tclk1_a",
@@ -5043,6 +5040,7 @@ static const char * const tpu_groups[] = {
"tpu_to2",
"tpu_to3",
};
+#endif
static const char * const usb0_groups[] = {
"usb0",
@@ -5146,7 +5144,9 @@ static const struct {
#endif
SH_PFC_FUNCTION(qspi0),
SH_PFC_FUNCTION(qspi1),
+#ifdef CONFIG_PINCTRL_PFC_FULL
SH_PFC_FUNCTION(sata0),
+#endif
SH_PFC_FUNCTION(scif0),
SH_PFC_FUNCTION(scif1),
SH_PFC_FUNCTION(scif2),
@@ -5160,9 +5160,9 @@ static const struct {
SH_PFC_FUNCTION(sdhi3),
#ifdef CONFIG_PINCTRL_PFC_FULL
SH_PFC_FUNCTION(ssi),
-#endif
SH_PFC_FUNCTION(tmu),
SH_PFC_FUNCTION(tpu),
+#endif
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb2),
@@ -5173,7 +5173,7 @@ static const struct {
SH_PFC_FUNCTION(vin5),
#endif
},
-#ifdef CONFIG_PINCTRL_PFC_R8A77951
+#if defined(CONFIG_PINCTRL_PFC_FULL) && defined(CONFIG_PINCTRL_PFC_R8A77951)
.automotive = {
SH_PFC_FUNCTION(drif0),
SH_PFC_FUNCTION(drif1),
diff --git a/drivers/pinctrl/renesas/pfc-r8a7796.c b/drivers/pinctrl/renesas/pfc-r8a7796.c
index a587dfb89d4..ac1dbae9954 100644
--- a/drivers/pinctrl/renesas/pfc-r8a7796.c
+++ b/drivers/pinctrl/renesas/pfc-r8a7796.c
@@ -1833,7 +1833,6 @@ static const unsigned int canfd1_data_pins[] = {
static const unsigned int canfd1_data_mux[] = {
CANFD1_TX_MARK, CANFD1_RX_MARK,
};
-#endif
#if defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961)
/* - DRIF0 --------------------------------------------------------------- */
@@ -2052,7 +2051,6 @@ static const unsigned int drif3_data1_b_mux[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77960 || CONFIG_PINCTRL_PFC_R8A77961 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
/* - DU --------------------------------------------------------------------- */
static const unsigned int du_rgb666_pins[] = {
/* R[7:2], G[7:2], B[7:2] */
@@ -2465,7 +2463,6 @@ static const unsigned int intc_ex_irq5_pins[] = {
static const unsigned int intc_ex_irq5_mux[] = {
IRQ5_MARK,
};
-#endif
#if defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961)
/* - MLB+ ------------------------------------------------------------------- */
@@ -2477,7 +2474,6 @@ static const unsigned int mlb_3pin_mux[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77960 || CONFIG_PINCTRL_PFC_R8A77961 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
/* - MSIOF0 ----------------------------------------------------------------- */
static const unsigned int msiof0_clk_pins[] = {
/* SCK */
@@ -3866,7 +3862,6 @@ static const unsigned int ssi9_ctrl_b_pins[] = {
static const unsigned int ssi9_ctrl_b_mux[] = {
SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
};
-#endif
/* - TMU -------------------------------------------------------------------- */
static const unsigned int tmu_tclk1_a_pins[] = {
@@ -3927,6 +3922,7 @@ static const unsigned int tpu_to3_pins[] = {
static const unsigned int tpu_to3_mux[] = {
TPU0TO3_MARK,
};
+#endif
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
@@ -4435,7 +4431,6 @@ static const struct {
SH_PFC_PIN_GROUP(ssi9_data_b),
SH_PFC_PIN_GROUP(ssi9_ctrl_a),
SH_PFC_PIN_GROUP(ssi9_ctrl_b),
-#endif
SH_PFC_PIN_GROUP(tmu_tclk1_a),
SH_PFC_PIN_GROUP(tmu_tclk1_b),
SH_PFC_PIN_GROUP(tmu_tclk2_a),
@@ -4444,6 +4439,7 @@ static const struct {
SH_PFC_PIN_GROUP(tpu_to1),
SH_PFC_PIN_GROUP(tpu_to2),
SH_PFC_PIN_GROUP(tpu_to3),
+#endif
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
SH_PFC_PIN_GROUP(usb30),
@@ -4478,7 +4474,8 @@ static const struct {
SH_PFC_PIN_GROUP(vin5_clk),
#endif
},
-#if defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961)
+#if defined(CONFIG_PINCTRL_PFC_FULL) && \
+ (defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961))
.automotive = {
SH_PFC_PIN_GROUP(drif0_ctrl_a),
SH_PFC_PIN_GROUP(drif0_data0_a),
@@ -4573,7 +4570,6 @@ static const char * const canfd0_groups[] = {
static const char * const canfd1_groups[] = {
"canfd1_data",
};
-#endif
#if defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961)
static const char * const drif0_groups[] = {
@@ -4619,7 +4615,6 @@ static const char * const drif3_groups[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77960 || CONFIG_PINCTRL_PFC_R8A77961 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const du_groups[] = {
"du_rgb666",
"du_rgb888",
@@ -4712,7 +4707,6 @@ static const char * const intc_ex_groups[] = {
"intc_ex_irq4",
"intc_ex_irq5",
};
-#endif
#if defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961)
static const char * const mlb_3pin_groups[] = {
@@ -4720,7 +4714,6 @@ static const char * const mlb_3pin_groups[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77960 || CONFIG_PINCTRL_PFC_R8A77961 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const msiof0_groups[] = {
"msiof0_clk",
"msiof0_sync",
@@ -4995,7 +4988,6 @@ static const char * const ssi_groups[] = {
"ssi9_ctrl_a",
"ssi9_ctrl_b",
};
-#endif
static const char * const tmu_groups[] = {
"tmu_tclk1_a",
@@ -5010,6 +5002,7 @@ static const char * const tpu_groups[] = {
"tpu_to2",
"tpu_to3",
};
+#endif
static const char * const usb0_groups[] = {
"usb0",
@@ -5118,9 +5111,9 @@ static const struct {
SH_PFC_FUNCTION(sdhi3),
#ifdef CONFIG_PINCTRL_PFC_FULL
SH_PFC_FUNCTION(ssi),
-#endif
SH_PFC_FUNCTION(tmu),
SH_PFC_FUNCTION(tpu),
+#endif
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb30),
@@ -5129,7 +5122,8 @@ static const struct {
SH_PFC_FUNCTION(vin5),
#endif
},
-#if defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961)
+#if defined(CONFIG_PINCTRL_PFC_FULL) && \
+ (defined(CONFIG_PINCTRL_PFC_R8A77960) || defined(CONFIG_PINCTRL_PFC_R8A77961))
.automotive = {
SH_PFC_FUNCTION(drif0),
SH_PFC_FUNCTION(drif1),
diff --git a/drivers/pinctrl/renesas/pfc-r8a77965.c b/drivers/pinctrl/renesas/pfc-r8a77965.c
index 9049d762a59..d1c1f562fca 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77965.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77965.c
@@ -1848,7 +1848,6 @@ static const unsigned int canfd1_data_pins[] = {
static const unsigned int canfd1_data_mux[] = {
CANFD1_TX_MARK, CANFD1_RX_MARK,
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77965
/* - DRIF0 --------------------------------------------------------------- */
@@ -2126,7 +2125,6 @@ static const unsigned int drif3_data1_b_mux[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77965 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
/* - DU --------------------------------------------------------------------- */
static const unsigned int du_rgb666_pins[] = {
/* R[7:2], G[7:2], B[7:2] */
@@ -2616,7 +2614,6 @@ static const unsigned int intc_ex_irq5_pins[] = {
static const unsigned int intc_ex_irq5_mux[] = {
IRQ5_MARK,
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77965
/* - MLB+ ------------------------------------------------------------------- */
@@ -2628,7 +2625,6 @@ static const unsigned int mlb_3pin_mux[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77965 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
/* - MSIOF0 ----------------------------------------------------------------- */
static const unsigned int msiof0_clk_pins[] = {
/* SCK */
@@ -3464,6 +3460,7 @@ static const unsigned int qspi1_data_mux[] = {
QSPI1_IO2_MARK, QSPI1_IO3_MARK,
};
+#ifdef CONFIG_PINCTRL_PFC_FULL
/* - SATA --------------------------------------------------------------------*/
static const unsigned int sata0_devslp_a_pins[] = {
/* DEVSLP */
@@ -3482,6 +3479,7 @@ static const unsigned int sata0_devslp_b_pins[] = {
static const unsigned int sata0_devslp_b_mux[] = {
SATA_DEVSLP_B_MARK,
};
+#endif
/* - SCIF0 ------------------------------------------------------------------ */
static const unsigned int scif0_data_pins[] = {
@@ -4071,7 +4069,6 @@ static const unsigned int ssi9_ctrl_b_pins[] = {
static const unsigned int ssi9_ctrl_b_mux[] = {
SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
};
-#endif
/* - TMU -------------------------------------------------------------------- */
static const unsigned int tmu_tclk1_a_pins[] = {
@@ -4139,6 +4136,7 @@ static const unsigned int tpu_to3_pins[] = {
static const unsigned int tpu_to3_mux[] = {
TPU0TO3_MARK,
};
+#endif
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
@@ -4588,8 +4586,10 @@ static const struct {
SH_PFC_PIN_GROUP(qspi1_ctrl),
BUS_DATA_PIN_GROUP(qspi1_data, 2),
BUS_DATA_PIN_GROUP(qspi1_data, 4),
+#ifdef CONFIG_PINCTRL_PFC_FULL
SH_PFC_PIN_GROUP(sata0_devslp_a),
SH_PFC_PIN_GROUP(sata0_devslp_b),
+#endif
SH_PFC_PIN_GROUP(scif0_data),
SH_PFC_PIN_GROUP(scif0_clk),
SH_PFC_PIN_GROUP(scif0_ctrl),
@@ -4671,7 +4671,6 @@ static const struct {
SH_PFC_PIN_GROUP(ssi9_data_b),
SH_PFC_PIN_GROUP(ssi9_ctrl_a),
SH_PFC_PIN_GROUP(ssi9_ctrl_b),
-#endif
SH_PFC_PIN_GROUP(tmu_tclk1_a),
SH_PFC_PIN_GROUP(tmu_tclk1_b),
SH_PFC_PIN_GROUP(tmu_tclk2_a),
@@ -4680,6 +4679,7 @@ static const struct {
SH_PFC_PIN_GROUP(tpu_to1),
SH_PFC_PIN_GROUP(tpu_to2),
SH_PFC_PIN_GROUP(tpu_to3),
+#endif
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
SH_PFC_PIN_GROUP(usb30),
@@ -4714,7 +4714,7 @@ static const struct {
SH_PFC_PIN_GROUP(vin5_clk),
#endif
},
-#ifdef CONFIG_PINCTRL_PFC_R8A77965
+#if defined(CONFIG_PINCTRL_PFC_FULL) && defined(CONFIG_PINCTRL_PFC_R8A77965)
.automotive = {
SH_PFC_PIN_GROUP(drif0_ctrl_a),
SH_PFC_PIN_GROUP(drif0_data0_a),
@@ -4809,7 +4809,6 @@ static const char * const canfd0_groups[] = {
static const char * const canfd1_groups[] = {
"canfd1_data",
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77965
static const char * const drif0_groups[] = {
@@ -4855,7 +4854,6 @@ static const char * const drif3_groups[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77965 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const du_groups[] = {
"du_rgb666",
"du_rgb888",
@@ -4948,7 +4946,6 @@ static const char * const intc_ex_groups[] = {
"intc_ex_irq4",
"intc_ex_irq5",
};
-#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77965
static const char * const mlb_3pin_groups[] = {
@@ -4956,7 +4953,6 @@ static const char * const mlb_3pin_groups[] = {
};
#endif /* CONFIG_PINCTRL_PFC_R8A77965 */
-#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const msiof0_groups[] = {
"msiof0_clk",
"msiof0_sync",
@@ -5115,10 +5111,12 @@ static const char * const qspi1_groups[] = {
"qspi1_data4",
};
+#ifdef CONFIG_PINCTRL_PFC_FULL
static const char * const sata0_groups[] = {
"sata0_devslp_a",
"sata0_devslp_b",
};
+#endif
static const char * const scif0_groups[] = {
"scif0_data",
@@ -5235,7 +5233,6 @@ static const char * const ssi_groups[] = {
"ssi9_ctrl_a",
"ssi9_ctrl_b",
};
-#endif
static const char * const tmu_groups[] = {
"tmu_tclk1_a",
@@ -5250,6 +5247,7 @@ static const char * const tpu_groups[] = {
"tpu_to2",
"tpu_to3",
};
+#endif
static const char * const usb0_groups[] = {
"usb0",
@@ -5345,7 +5343,9 @@ static const struct {
#endif
SH_PFC_FUNCTION(qspi0),
SH_PFC_FUNCTION(qspi1),
+#ifdef CONFIG_PINCTRL_PFC_FULL
SH_PFC_FUNCTION(sata0),
+#endif
SH_PFC_FUNCTION(scif0),
SH_PFC_FUNCTION(scif1),
SH_PFC_FUNCTION(scif2),
@@ -5359,9 +5359,9 @@ static const struct {
SH_PFC_FUNCTION(sdhi3),
#ifdef CONFIG_PINCTRL_PFC_FULL
SH_PFC_FUNCTION(ssi),
-#endif
SH_PFC_FUNCTION(tmu),
SH_PFC_FUNCTION(tpu),
+#endif
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb30),
@@ -5370,7 +5370,7 @@ static const struct {
SH_PFC_FUNCTION(vin5),
#endif
},
-#ifdef CONFIG_PINCTRL_PFC_R8A77965
+#if defined(CONFIG_PINCTRL_PFC_FULL) && defined(CONFIG_PINCTRL_PFC_R8A77965)
.automotive = {
SH_PFC_FUNCTION(drif0),
SH_PFC_FUNCTION(drif1),
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
index c8a91b8bb6e..514481530fa 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3568.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
@@ -12,99 +12,99 @@
#include "pinctrl-rockchip.h"
static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
- MR_PMUGRF(RK_GPIO0, RK_PB7, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(1, 0, 0)), /* PWM0 IO mux selection M0 */
- MR_PMUGRF(RK_GPIO0, RK_PC7, RK_FUNC_2, 0x0110, RK_GENMASK_VAL(1, 0, 1)), /* PWM0 IO mux selection M1 */
- MR_PMUGRF(RK_GPIO0, RK_PC0, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(3, 2, 0)), /* PWM1 IO mux selection M0 */
- MR_PMUGRF(RK_GPIO0, RK_PB5, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(3, 2, 1)), /* PWM1 IO mux selection M1 */
- MR_PMUGRF(RK_GPIO0, RK_PC1, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(5, 4, 0)), /* PWM2 IO mux selection M0 */
- MR_PMUGRF(RK_GPIO0, RK_PB6, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(5, 4, 1)), /* PWM2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)), /* CAN0 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)), /* CAN0 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)), /* CAN1 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)), /* CAN1 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)), /* CAN2 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)), /* CAN2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)), /* EDPDP_HPDIN IO mux selection M0 */
- MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)), /* EDPDP_HPDIN IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)), /* GMAC1 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)), /* GMAC1 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)), /* HDMITX IO mux selection M0 */
- MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)), /* HDMITX IO mux selection M1 */
- MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)), /* I2C2 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)), /* I2C2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)), /* I2C3 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)), /* I2C3 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)), /* I2C4 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)), /* I2C4 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)), /* I2C5 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)), /* I2C5 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_5, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO1, RK_PD6, RK_FUNC_4, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PB5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC0, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PC0, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC6, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)), /* SDMMC2 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)), /* SDMMC2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)), /* SPI0 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)), /* SPI0 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)), /* SPI1 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)), /* SPI1 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)), /* SPI2 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)), /* SPI2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)), /* SPI3 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)), /* SPI3 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)), /* UART1 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)), /* UART2 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)), /* UART2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)), /* UART3 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)), /* UART3 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)), /* UART4 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)), /* UART4 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)), /* UART5 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)), /* UART5 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)), /* UART6 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)), /* UART6 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)), /* UART7 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)), /* UART7 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
- MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)), /* UART8 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)), /* UART8 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)), /* UART9 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)), /* UART9 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)), /* UART9 IO mux selection M2 */
- MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)), /* I2S1 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)), /* I2S1 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)), /* I2S1 IO mux selection M2 */
- MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)), /* I2S2 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)), /* I2S2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)), /* I2S3 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)), /* I2S3 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
- MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PA0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 2)), /* PDM IO mux selection M2 */
- MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)), /* PCIE20 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)), /* PCIE20 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)), /* PCIE20 IO mux selection M2 */
- MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux selection M2 */
- MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux selection M2 */
+ MR_PMUGRF(0, RK_PB7, 1, 0x0110, RK_GENMASK_VAL(1, 0, 0)), /* PWM0 IO mux selection M0 */
+ MR_PMUGRF(0, RK_PC7, 2, 0x0110, RK_GENMASK_VAL(1, 0, 1)), /* PWM0 IO mux selection M1 */
+ MR_PMUGRF(0, RK_PC0, 1, 0x0110, RK_GENMASK_VAL(3, 2, 0)), /* PWM1 IO mux selection M0 */
+ MR_PMUGRF(0, RK_PB5, 4, 0x0110, RK_GENMASK_VAL(3, 2, 1)), /* PWM1 IO mux selection M1 */
+ MR_PMUGRF(0, RK_PC1, 1, 0x0110, RK_GENMASK_VAL(5, 4, 0)), /* PWM2 IO mux selection M0 */
+ MR_PMUGRF(0, RK_PB6, 4, 0x0110, RK_GENMASK_VAL(5, 4, 1)), /* PWM2 IO mux selection M1 */
+ MR_TOPGRF(0, RK_PB3, 2, 0x0300, RK_GENMASK_VAL(0, 0, 0)), /* CAN0 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PA1, 4, 0x0300, RK_GENMASK_VAL(0, 0, 1)), /* CAN0 IO mux selection M1 */
+ MR_TOPGRF(1, RK_PA1, 3, 0x0300, RK_GENMASK_VAL(2, 2, 0)), /* CAN1 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC3, 3, 0x0300, RK_GENMASK_VAL(2, 2, 1)), /* CAN1 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PB5, 3, 0x0300, RK_GENMASK_VAL(4, 4, 0)), /* CAN2 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PB2, 4, 0x0300, RK_GENMASK_VAL(4, 4, 1)), /* CAN2 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PC4, 1, 0x0300, RK_GENMASK_VAL(6, 6, 0)), /* EDPDP_HPDIN IO mux selection M0 */
+ MR_TOPGRF(0, RK_PC2, 2, 0x0300, RK_GENMASK_VAL(6, 6, 1)), /* EDPDP_HPDIN IO mux selection M1 */
+ MR_TOPGRF(3, RK_PB1, 3, 0x0300, RK_GENMASK_VAL(8, 8, 0)), /* GMAC1 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PA7, 3, 0x0300, RK_GENMASK_VAL(8, 8, 1)), /* GMAC1 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PD1, 1, 0x0300, RK_GENMASK_VAL(10, 10, 0)), /* HDMITX IO mux selection M0 */
+ MR_TOPGRF(0, RK_PC7, 1, 0x0300, RK_GENMASK_VAL(10, 10, 1)), /* HDMITX IO mux selection M1 */
+ MR_TOPGRF(0, RK_PB6, 1, 0x0300, RK_GENMASK_VAL(14, 14, 0)), /* I2C2 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PB4, 1, 0x0300, RK_GENMASK_VAL(14, 14, 1)), /* I2C2 IO mux selection M1 */
+ MR_TOPGRF(1, RK_PA0, 1, 0x0304, RK_GENMASK_VAL(0, 0, 0)), /* I2C3 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PB6, 4, 0x0304, RK_GENMASK_VAL(0, 0, 1)), /* I2C3 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PB2, 1, 0x0304, RK_GENMASK_VAL(2, 2, 0)), /* I2C4 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PB1, 2, 0x0304, RK_GENMASK_VAL(2, 2, 1)), /* I2C4 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PB4, 4, 0x0304, RK_GENMASK_VAL(4, 4, 0)), /* I2C5 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PD0, 2, 0x0304, RK_GENMASK_VAL(4, 4, 1)), /* I2C5 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PB1, 5, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
+ MR_TOPGRF(1, RK_PD5, 4, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PB2, 5, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
+ MR_TOPGRF(1, RK_PD6, 4, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PB5, 5, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PA1, 2, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PB6, 5, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC0, 3, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PB7, 2, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC5, 1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PC0, 2, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC6, 1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PC4, 1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC2, 1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PC5, 1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC3, 1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PD2, 3, 0x0308, RK_GENMASK_VAL(14, 14, 0)), /* SDMMC2 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PA5, 5, 0x0308, RK_GENMASK_VAL(14, 14, 1)), /* SDMMC2 IO mux selection M1 */
+ MR_TOPGRF(0, RK_PB5, 2, 0x030c, RK_GENMASK_VAL(0, 0, 0)), /* SPI0 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PD3, 3, 0x030c, RK_GENMASK_VAL(0, 0, 1)), /* SPI0 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PB5, 3, 0x030c, RK_GENMASK_VAL(2, 2, 0)), /* SPI1 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PC3, 3, 0x030c, RK_GENMASK_VAL(2, 2, 1)), /* SPI1 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PC1, 4, 0x030c, RK_GENMASK_VAL(4, 4, 0)), /* SPI2 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PA0, 3, 0x030c, RK_GENMASK_VAL(4, 4, 1)), /* SPI2 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PB3, 4, 0x030c, RK_GENMASK_VAL(6, 6, 0)), /* SPI3 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC2, 2, 0x030c, RK_GENMASK_VAL(6, 6, 1)), /* SPI3 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PB4, 2, 0x030c, RK_GENMASK_VAL(8, 8, 0)), /* UART1 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PD6, 4, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
+ MR_TOPGRF(0, RK_PD1, 1, 0x030c, RK_GENMASK_VAL(10, 10, 0)), /* UART2 IO mux selection M0 */
+ MR_TOPGRF(1, RK_PD5, 2, 0x030c, RK_GENMASK_VAL(10, 10, 1)), /* UART2 IO mux selection M1 */
+ MR_TOPGRF(1, RK_PA1, 2, 0x030c, RK_GENMASK_VAL(12, 12, 0)), /* UART3 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PB7, 4, 0x030c, RK_GENMASK_VAL(12, 12, 1)), /* UART3 IO mux selection M1 */
+ MR_TOPGRF(1, RK_PA6, 2, 0x030c, RK_GENMASK_VAL(14, 14, 0)), /* UART4 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PB2, 4, 0x030c, RK_GENMASK_VAL(14, 14, 1)), /* UART4 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PA2, 3, 0x0310, RK_GENMASK_VAL(0, 0, 0)), /* UART5 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PC2, 4, 0x0310, RK_GENMASK_VAL(0, 0, 1)), /* UART5 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PA4, 3, 0x0310, RK_GENMASK_VAL(2, 2, 0)), /* UART6 IO mux selection M0 */
+ MR_TOPGRF(1, RK_PD5, 3, 0x0310, RK_GENMASK_VAL(2, 2, 1)), /* UART6 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PA6, 3, 0x0310, RK_GENMASK_VAL(5, 4, 0)), /* UART7 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PC4, 4, 0x0310, RK_GENMASK_VAL(5, 4, 1)), /* UART7 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PA2, 4, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
+ MR_TOPGRF(2, RK_PC5, 3, 0x0310, RK_GENMASK_VAL(6, 6, 0)), /* UART8 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PD7, 4, 0x0310, RK_GENMASK_VAL(6, 6, 1)), /* UART8 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PB0, 3, 0x0310, RK_GENMASK_VAL(9, 8, 0)), /* UART9 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC5, 4, 0x0310, RK_GENMASK_VAL(9, 8, 1)), /* UART9 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PA4, 4, 0x0310, RK_GENMASK_VAL(9, 8, 2)), /* UART9 IO mux selection M2 */
+ MR_TOPGRF(1, RK_PA2, 1, 0x0310, RK_GENMASK_VAL(11, 10, 0)), /* I2S1 IO mux selection M0 */
+ MR_TOPGRF(3, RK_PC6, 4, 0x0310, RK_GENMASK_VAL(11, 10, 1)), /* I2S1 IO mux selection M1 */
+ MR_TOPGRF(2, RK_PD0, 5, 0x0310, RK_GENMASK_VAL(11, 10, 2)), /* I2S1 IO mux selection M2 */
+ MR_TOPGRF(2, RK_PC1, 1, 0x0310, RK_GENMASK_VAL(12, 12, 0)), /* I2S2 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PB6, 5, 0x0310, RK_GENMASK_VAL(12, 12, 1)), /* I2S2 IO mux selection M1 */
+ MR_TOPGRF(3, RK_PA2, 4, 0x0310, RK_GENMASK_VAL(14, 14, 0)), /* I2S3 IO mux selection M0 */
+ MR_TOPGRF(4, RK_PC2, 5, 0x0310, RK_GENMASK_VAL(14, 14, 1)), /* I2S3 IO mux selection M1 */
+ MR_TOPGRF(1, RK_PA4, 3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
+ MR_TOPGRF(1, RK_PA6, 3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
+ MR_TOPGRF(3, RK_PD6, 5, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
+ MR_TOPGRF(4, RK_PA0, 4, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
+ MR_TOPGRF(3, RK_PC4, 5, 0x0314, RK_GENMASK_VAL(1, 0, 2)), /* PDM IO mux selection M2 */
+ MR_TOPGRF(0, RK_PA5, 3, 0x0314, RK_GENMASK_VAL(3, 2, 0)), /* PCIE20 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PD0, 4, 0x0314, RK_GENMASK_VAL(3, 2, 1)), /* PCIE20 IO mux selection M1 */
+ MR_TOPGRF(1, RK_PB0, 4, 0x0314, RK_GENMASK_VAL(3, 2, 2)), /* PCIE20 IO mux selection M2 */
+ MR_TOPGRF(0, RK_PA4, 3, 0x0314, RK_GENMASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PD2, 4, 0x0314, RK_GENMASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux selection M1 */
+ MR_TOPGRF(1, RK_PA5, 4, 0x0314, RK_GENMASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux selection M2 */
+ MR_TOPGRF(0, RK_PA6, 2, 0x0314, RK_GENMASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux selection M0 */
+ MR_TOPGRF(2, RK_PD4, 4, 0x0314, RK_GENMASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux selection M1 */
+ MR_TOPGRF(4, RK_PC2, 4, 0x0314, RK_GENMASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux selection M2 */
};
static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
diff --git a/drivers/pinctrl/rockchip/pinctrl-rv1126.c b/drivers/pinctrl/rockchip/pinctrl-rv1126.c
index 3878a5420dc..88966ef34a6 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rv1126.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rv1126.c
@@ -45,101 +45,101 @@ static struct rockchip_mux_recalced_data rv1126_mux_recalced_data[] = {
};
static struct rockchip_mux_route_data rv1126_mux_route_data[] = {
- MR_TOPGRF(RK_GPIO3, RK_PD2, 1, 0x10260, RK_GENMASK_VAL(0, 0, 0)), /* I2S0_MCLK_M0 */
- MR_TOPGRF(RK_GPIO3, RK_PB0, 3, 0x10260, RK_GENMASK_VAL(0, 0, 1)), /* I2S0_MCLK_M1 */
+ MR_TOPGRF(3, RK_PD2, 1, 0x10260, RK_GENMASK_VAL(0, 0, 0)), /* I2S0_MCLK_M0 */
+ MR_TOPGRF(3, RK_PB0, 3, 0x10260, RK_GENMASK_VAL(0, 0, 1)), /* I2S0_MCLK_M1 */
- MR_TOPGRF(RK_GPIO0, RK_PD4, 4, 0x10260, RK_GENMASK_VAL(3, 2, 0)), /* I2S1_MCLK_M0 */
- MR_TOPGRF(RK_GPIO1, RK_PD5, 2, 0x10260, RK_GENMASK_VAL(3, 2, 1)), /* I2S1_MCLK_M1 */
- MR_TOPGRF(RK_GPIO2, RK_PC7, 6, 0x10260, RK_GENMASK_VAL(3, 2, 2)), /* I2S1_MCLK_M2 */
+ MR_TOPGRF(0, RK_PD4, 4, 0x10260, RK_GENMASK_VAL(3, 2, 0)), /* I2S1_MCLK_M0 */
+ MR_TOPGRF(1, RK_PD5, 2, 0x10260, RK_GENMASK_VAL(3, 2, 1)), /* I2S1_MCLK_M1 */
+ MR_TOPGRF(2, RK_PC7, 6, 0x10260, RK_GENMASK_VAL(3, 2, 2)), /* I2S1_MCLK_M2 */
- MR_TOPGRF(RK_GPIO1, RK_PD0, 1, 0x10260, RK_GENMASK_VAL(4, 4, 0)), /* I2S2_MCLK_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PB3, 2, 0x10260, RK_GENMASK_VAL(4, 4, 1)), /* I2S2_MCLK_M1 */
+ MR_TOPGRF(1, RK_PD0, 1, 0x10260, RK_GENMASK_VAL(4, 4, 0)), /* I2S2_MCLK_M0 */
+ MR_TOPGRF(2, RK_PB3, 2, 0x10260, RK_GENMASK_VAL(4, 4, 1)), /* I2S2_MCLK_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD4, 2, 0x10260, RK_GENMASK_VAL(12, 12, 0)), /* PDM_CLK0_M0 */
- MR_TOPGRF(RK_GPIO3, RK_PC0, 3, 0x10260, RK_GENMASK_VAL(12, 12, 1)), /* PDM_CLK0_M1 */
+ MR_TOPGRF(3, RK_PD4, 2, 0x10260, RK_GENMASK_VAL(12, 12, 0)), /* PDM_CLK0_M0 */
+ MR_TOPGRF(3, RK_PC0, 3, 0x10260, RK_GENMASK_VAL(12, 12, 1)), /* PDM_CLK0_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PC6, 1, 0x10264, RK_GENMASK_VAL(0, 0, 0)), /* CIF_CLKOUT_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD1, 3, 0x10264, RK_GENMASK_VAL(0, 0, 1)), /* CIF_CLKOUT_M1 */
+ MR_TOPGRF(3, RK_PC6, 1, 0x10264, RK_GENMASK_VAL(0, 0, 0)), /* CIF_CLKOUT_M0 */
+ MR_TOPGRF(2, RK_PD1, 3, 0x10264, RK_GENMASK_VAL(0, 0, 1)), /* CIF_CLKOUT_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA4, 5, 0x10264, RK_GENMASK_VAL(5, 4, 0)), /* I2C3_SCL_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD4, 7, 0x10264, RK_GENMASK_VAL(5, 4, 1)), /* I2C3_SCL_M1 */
- MR_TOPGRF(RK_GPIO1, RK_PD6, 3, 0x10264, RK_GENMASK_VAL(5, 4, 2)), /* I2C3_SCL_M2 */
+ MR_TOPGRF(3, RK_PA4, 5, 0x10264, RK_GENMASK_VAL(5, 4, 0)), /* I2C3_SCL_M0 */
+ MR_TOPGRF(2, RK_PD4, 7, 0x10264, RK_GENMASK_VAL(5, 4, 1)), /* I2C3_SCL_M1 */
+ MR_TOPGRF(1, RK_PD6, 3, 0x10264, RK_GENMASK_VAL(5, 4, 2)), /* I2C3_SCL_M2 */
- MR_TOPGRF(RK_GPIO3, RK_PA0, 7, 0x10264, RK_GENMASK_VAL(6, 6, 0)), /* I2C4_SCL_M0 */
- MR_TOPGRF(RK_GPIO4, RK_PA0, 4, 0x10264, RK_GENMASK_VAL(6, 6, 1)), /* I2C4_SCL_M1 */
+ MR_TOPGRF(3, RK_PA0, 7, 0x10264, RK_GENMASK_VAL(6, 6, 0)), /* I2C4_SCL_M0 */
+ MR_TOPGRF(4, RK_PA0, 4, 0x10264, RK_GENMASK_VAL(6, 6, 1)), /* I2C4_SCL_M1 */
- MR_TOPGRF(RK_GPIO2, RK_PA5, 7, 0x10264, RK_GENMASK_VAL(9, 8, 0)), /* I2C5_SCL_M0 */
- MR_TOPGRF(RK_GPIO3, RK_PB0, 5, 0x10264, RK_GENMASK_VAL(9, 8, 1)), /* I2C5_SCL_M1 */
- MR_TOPGRF(RK_GPIO1, RK_PD0, 4, 0x10264, RK_GENMASK_VAL(9, 8, 2)), /* I2C5_SCL_M2 */
+ MR_TOPGRF(2, RK_PA5, 7, 0x10264, RK_GENMASK_VAL(9, 8, 0)), /* I2C5_SCL_M0 */
+ MR_TOPGRF(3, RK_PB0, 5, 0x10264, RK_GENMASK_VAL(9, 8, 1)), /* I2C5_SCL_M1 */
+ MR_TOPGRF(1, RK_PD0, 4, 0x10264, RK_GENMASK_VAL(9, 8, 2)), /* I2C5_SCL_M2 */
- MR_TOPGRF(RK_GPIO3, RK_PC0, 5, 0x10264, RK_GENMASK_VAL(11, 10, 0)), /* SPI1_CLK_M0 */
- MR_TOPGRF(RK_GPIO1, RK_PC6, 3, 0x10264, RK_GENMASK_VAL(11, 10, 1)), /* SPI1_CLK_M1 */
- MR_TOPGRF(RK_GPIO2, RK_PD5, 6, 0x10264, RK_GENMASK_VAL(11, 10, 2)), /* SPI1_CLK_M2 */
+ MR_TOPGRF(3, RK_PC0, 5, 0x10264, RK_GENMASK_VAL(11, 10, 0)), /* SPI1_CLK_M0 */
+ MR_TOPGRF(1, RK_PC6, 3, 0x10264, RK_GENMASK_VAL(11, 10, 1)), /* SPI1_CLK_M1 */
+ MR_TOPGRF(2, RK_PD5, 6, 0x10264, RK_GENMASK_VAL(11, 10, 2)), /* SPI1_CLK_M2 */
- MR_TOPGRF(RK_GPIO3, RK_PC0, 2, 0x10264, RK_GENMASK_VAL(12, 12, 0)), /* RGMII_CLK_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PB7, 2, 0x10264, RK_GENMASK_VAL(12, 12, 1)), /* RGMII_CLK_M1 */
+ MR_TOPGRF(3, RK_PC0, 2, 0x10264, RK_GENMASK_VAL(12, 12, 0)), /* RGMII_CLK_M0 */
+ MR_TOPGRF(2, RK_PB7, 2, 0x10264, RK_GENMASK_VAL(12, 12, 1)), /* RGMII_CLK_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA1, 3, 0x10264, RK_GENMASK_VAL(13, 13, 0)), /* CAN_TXD_M0 */
- MR_TOPGRF(RK_GPIO3, RK_PA7, 5, 0x10264, RK_GENMASK_VAL(13, 13, 1)), /* CAN_TXD_M1 */
+ MR_TOPGRF(3, RK_PA1, 3, 0x10264, RK_GENMASK_VAL(13, 13, 0)), /* CAN_TXD_M0 */
+ MR_TOPGRF(3, RK_PA7, 5, 0x10264, RK_GENMASK_VAL(13, 13, 1)), /* CAN_TXD_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA4, 6, 0x10268, RK_GENMASK_VAL(0, 0, 0)), /* PWM8_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD7, 5, 0x10268, RK_GENMASK_VAL(0, 0, 1)), /* PWM8_M1 */
+ MR_TOPGRF(3, RK_PA4, 6, 0x10268, RK_GENMASK_VAL(0, 0, 0)), /* PWM8_M0 */
+ MR_TOPGRF(2, RK_PD7, 5, 0x10268, RK_GENMASK_VAL(0, 0, 1)), /* PWM8_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA5, 6, 0x10268, RK_GENMASK_VAL(2, 2, 0)), /* PWM9_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD6, 5, 0x10268, RK_GENMASK_VAL(2, 2, 1)), /* PWM9_M1 */
+ MR_TOPGRF(3, RK_PA5, 6, 0x10268, RK_GENMASK_VAL(2, 2, 0)), /* PWM9_M0 */
+ MR_TOPGRF(2, RK_PD6, 5, 0x10268, RK_GENMASK_VAL(2, 2, 1)), /* PWM9_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA6, 6, 0x10268, RK_GENMASK_VAL(4, 4, 0)), /* PWM10_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PD5, 5, 0x10268, RK_GENMASK_VAL(4, 4, 1)), /* PWM10_M1 */
+ MR_TOPGRF(3, RK_PA6, 6, 0x10268, RK_GENMASK_VAL(4, 4, 0)), /* PWM10_M0 */
+ MR_TOPGRF(2, RK_PD5, 5, 0x10268, RK_GENMASK_VAL(4, 4, 1)), /* PWM10_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA7, 6, 0x10268, RK_GENMASK_VAL(6, 6, 0)), /* PWM11_IR_M0 */
- MR_TOPGRF(RK_GPIO3, RK_PA1, 5, 0x10268, RK_GENMASK_VAL(6, 6, 1)), /* PWM11_IR_M1 */
+ MR_TOPGRF(3, RK_PA7, 6, 0x10268, RK_GENMASK_VAL(6, 6, 0)), /* PWM11_IR_M0 */
+ MR_TOPGRF(3, RK_PA1, 5, 0x10268, RK_GENMASK_VAL(6, 6, 1)), /* PWM11_IR_M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA5, 3, 0x10268, RK_GENMASK_VAL(8, 8, 0)), /* UART2_TX_M0 */
- MR_TOPGRF(RK_GPIO3, RK_PA2, 1, 0x10268, RK_GENMASK_VAL(8, 8, 1)), /* UART2_TX_M1 */
+ MR_TOPGRF(1, RK_PA5, 3, 0x10268, RK_GENMASK_VAL(8, 8, 0)), /* UART2_TX_M0 */
+ MR_TOPGRF(3, RK_PA2, 1, 0x10268, RK_GENMASK_VAL(8, 8, 1)), /* UART2_TX_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PC6, 3, 0x10268, RK_GENMASK_VAL(11, 10, 0)), /* UART3_TX_M0 */
- MR_TOPGRF(RK_GPIO1, RK_PA7, 2, 0x10268, RK_GENMASK_VAL(11, 10, 1)), /* UART3_TX_M1 */
- MR_TOPGRF(RK_GPIO3, RK_PA0, 4, 0x10268, RK_GENMASK_VAL(11, 10, 2)), /* UART3_TX_M2 */
+ MR_TOPGRF(3, RK_PC6, 3, 0x10268, RK_GENMASK_VAL(11, 10, 0)), /* UART3_TX_M0 */
+ MR_TOPGRF(1, RK_PA7, 2, 0x10268, RK_GENMASK_VAL(11, 10, 1)), /* UART3_TX_M1 */
+ MR_TOPGRF(3, RK_PA0, 4, 0x10268, RK_GENMASK_VAL(11, 10, 2)), /* UART3_TX_M2 */
- MR_TOPGRF(RK_GPIO3, RK_PA4, 4, 0x10268, RK_GENMASK_VAL(13, 12, 0)), /* UART4_TX_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PA6, 4, 0x10268, RK_GENMASK_VAL(13, 12, 1)), /* UART4_TX_M1 */
- MR_TOPGRF(RK_GPIO1, RK_PD5, 3, 0x10268, RK_GENMASK_VAL(13, 12, 2)), /* UART4_TX_M2 */
+ MR_TOPGRF(3, RK_PA4, 4, 0x10268, RK_GENMASK_VAL(13, 12, 0)), /* UART4_TX_M0 */
+ MR_TOPGRF(2, RK_PA6, 4, 0x10268, RK_GENMASK_VAL(13, 12, 1)), /* UART4_TX_M1 */
+ MR_TOPGRF(1, RK_PD5, 3, 0x10268, RK_GENMASK_VAL(13, 12, 2)), /* UART4_TX_M2 */
- MR_TOPGRF(RK_GPIO3, RK_PA6, 4, 0x10268, RK_GENMASK_VAL(15, 14, 0)), /* UART5_TX_M0 */
- MR_TOPGRF(RK_GPIO2, RK_PB0, 4, 0x10268, RK_GENMASK_VAL(15, 14, 1)), /* UART5_TX_M1 */
- MR_TOPGRF(RK_GPIO2, RK_PA0, 3, 0x10268, RK_GENMASK_VAL(15, 14, 2)), /* UART5_TX_M2 */
+ MR_TOPGRF(3, RK_PA6, 4, 0x10268, RK_GENMASK_VAL(15, 14, 0)), /* UART5_TX_M0 */
+ MR_TOPGRF(2, RK_PB0, 4, 0x10268, RK_GENMASK_VAL(15, 14, 1)), /* UART5_TX_M1 */
+ MR_TOPGRF(2, RK_PA0, 3, 0x10268, RK_GENMASK_VAL(15, 14, 2)), /* UART5_TX_M2 */
- MR_PMUGRF(RK_GPIO0, RK_PB6, 3, 0x0114, RK_GENMASK_VAL(0, 0, 0)), /* PWM0_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PB3, 5, 0x0114, RK_GENMASK_VAL(0, 0, 1)), /* PWM0_M1 */
+ MR_PMUGRF(0, RK_PB6, 3, 0x0114, RK_GENMASK_VAL(0, 0, 0)), /* PWM0_M0 */
+ MR_PMUGRF(2, RK_PB3, 5, 0x0114, RK_GENMASK_VAL(0, 0, 1)), /* PWM0_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PB7, 3, 0x0114, RK_GENMASK_VAL(2, 2, 0)), /* PWM1_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PB2, 5, 0x0114, RK_GENMASK_VAL(2, 2, 1)), /* PWM1_M1 */
+ MR_PMUGRF(0, RK_PB7, 3, 0x0114, RK_GENMASK_VAL(2, 2, 0)), /* PWM1_M0 */
+ MR_PMUGRF(2, RK_PB2, 5, 0x0114, RK_GENMASK_VAL(2, 2, 1)), /* PWM1_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PC0, 3, 0x0114, RK_GENMASK_VAL(4, 4, 0)), /* PWM2_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PB1, 5, 0x0114, RK_GENMASK_VAL(4, 4, 1)), /* PWM2_M1 */
+ MR_PMUGRF(0, RK_PC0, 3, 0x0114, RK_GENMASK_VAL(4, 4, 0)), /* PWM2_M0 */
+ MR_PMUGRF(2, RK_PB1, 5, 0x0114, RK_GENMASK_VAL(4, 4, 1)), /* PWM2_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PC1, 3, 0x0114, RK_GENMASK_VAL(6, 6, 0)), /* PWM3_IR_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PB0, 5, 0x0114, RK_GENMASK_VAL(6, 6, 1)), /* PWM3_IR_M1 */
+ MR_PMUGRF(0, RK_PC1, 3, 0x0114, RK_GENMASK_VAL(6, 6, 0)), /* PWM3_IR_M0 */
+ MR_PMUGRF(2, RK_PB0, 5, 0x0114, RK_GENMASK_VAL(6, 6, 1)), /* PWM3_IR_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PC2, 3, 0x0114, RK_GENMASK_VAL(8, 8, 0)), /* PWM4_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PA7, 5, 0x0114, RK_GENMASK_VAL(8, 8, 1)), /* PWM4_M1 */
+ MR_PMUGRF(0, RK_PC2, 3, 0x0114, RK_GENMASK_VAL(8, 8, 0)), /* PWM4_M0 */
+ MR_PMUGRF(2, RK_PA7, 5, 0x0114, RK_GENMASK_VAL(8, 8, 1)), /* PWM4_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PC3, 3, 0x0114, RK_GENMASK_VAL(10, 10, 0)), /* PWM5_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PA6, 5, 0x0114, RK_GENMASK_VAL(10, 10, 1)), /* PWM5_M1 */
+ MR_PMUGRF(0, RK_PC3, 3, 0x0114, RK_GENMASK_VAL(10, 10, 0)), /* PWM5_M0 */
+ MR_PMUGRF(2, RK_PA6, 5, 0x0114, RK_GENMASK_VAL(10, 10, 1)), /* PWM5_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PB2, 3, 0x0114, RK_GENMASK_VAL(12, 12, 0)), /* PWM6_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PD4, 5, 0x0114, RK_GENMASK_VAL(12, 12, 1)), /* PWM6_M1 */
+ MR_PMUGRF(0, RK_PB2, 3, 0x0114, RK_GENMASK_VAL(12, 12, 0)), /* PWM6_M0 */
+ MR_PMUGRF(2, RK_PD4, 5, 0x0114, RK_GENMASK_VAL(12, 12, 1)), /* PWM6_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PB1, 3, 0x0114, RK_GENMASK_VAL(14, 14, 0)), /* PWM7_IR_M0 */
- MR_PMUGRF(RK_GPIO3, RK_PA0, 5, 0x0114, RK_GENMASK_VAL(14, 14, 1)), /* PWM7_IR_M1 */
+ MR_PMUGRF(0, RK_PB1, 3, 0x0114, RK_GENMASK_VAL(14, 14, 0)), /* PWM7_IR_M0 */
+ MR_PMUGRF(3, RK_PA0, 5, 0x0114, RK_GENMASK_VAL(14, 14, 1)), /* PWM7_IR_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PB0, 1, 0x0118, RK_GENMASK_VAL(1, 0, 0)), /* SPI0_CLK_M0 */
- MR_PMUGRF(RK_GPIO2, RK_PA1, 1, 0x0118, RK_GENMASK_VAL(1, 0, 1)), /* SPI0_CLK_M1 */
- MR_PMUGRF(RK_GPIO2, RK_PB2, 6, 0x0118, RK_GENMASK_VAL(1, 0, 2)), /* SPI0_CLK_M2 */
+ MR_PMUGRF(0, RK_PB0, 1, 0x0118, RK_GENMASK_VAL(1, 0, 0)), /* SPI0_CLK_M0 */
+ MR_PMUGRF(2, RK_PA1, 1, 0x0118, RK_GENMASK_VAL(1, 0, 1)), /* SPI0_CLK_M1 */
+ MR_PMUGRF(2, RK_PB2, 6, 0x0118, RK_GENMASK_VAL(1, 0, 2)), /* SPI0_CLK_M2 */
- MR_PMUGRF(RK_GPIO0, RK_PB6, 2, 0x0118, RK_GENMASK_VAL(2, 2, 0)), /* UART1_TX_M0 */
- MR_PMUGRF(RK_GPIO1, RK_PD0, 5, 0x0118, RK_GENMASK_VAL(2, 2, 1)), /* UART1_TX_M1 */
- MR_PMUGRF(RK_GPIO0, RK_PC3, 1, 0x0118, RK_GENMASK_VAL(4, 4, 1)), /* I2C2 */
+ MR_PMUGRF(0, RK_PB6, 2, 0x0118, RK_GENMASK_VAL(2, 2, 0)), /* UART1_TX_M0 */
+ MR_PMUGRF(1, RK_PD0, 5, 0x0118, RK_GENMASK_VAL(2, 2, 1)), /* UART1_TX_M1 */
+ MR_PMUGRF(0, RK_PC3, 1, 0x0118, RK_GENMASK_VAL(4, 4, 1)), /* I2C2 */
};
static int rv1126_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
diff --git a/drivers/pinctrl/spacemit/Kconfig b/drivers/pinctrl/spacemit/Kconfig
new file mode 100644
index 00000000000..6aab89e160c
--- /dev/null
+++ b/drivers/pinctrl/spacemit/Kconfig
@@ -0,0 +1,9 @@
+config PINCTRL_SPACEMIT_K1
+ bool "Spacemit K1 SoC pinctrl driver"
+ depends on PINCTRL_GENERIC && DM
+ help
+ Supports pin multiplexing control on Spacemit K1 SoCs.
+
+ The driver is controlled by a device tree node which contains both
+ the GPIO definitions and pin control functions for each available
+ multiplex function.
diff --git a/drivers/pinctrl/spacemit/Makefile b/drivers/pinctrl/spacemit/Makefile
new file mode 100644
index 00000000000..0dc43c72cb1
--- /dev/null
+++ b/drivers/pinctrl/spacemit/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y += pinctrl-k1.o
diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.c b/drivers/pinctrl/spacemit/pinctrl-k1.c
new file mode 100644
index 00000000000..a6a22eacac7
--- /dev/null
+++ b/drivers/pinctrl/spacemit/pinctrl-k1.c
@@ -0,0 +1,550 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Yixun Lan <[email protected]>
+ * Copyright (c) 2025-2026 RISCstar Ltd.
+ */
+
+#include <clk.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/pinctrl.h>
+#include <dm/read.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+/*
+ * +---------+----------+-----------+--------+--------+----------+--------+
+ * | pull | drive | schmitter | slew | edge | strong | mux |
+ * | up/down | strength | trigger | rate | detect | pull | mode |
+ * +---------+----------+-----------+--------+--------+----------+--------+
+ * 3 bits 3 bits 2 bits 1 bit 3 bits 1 bit 3 bits
+ */
+
+#define PAD_MUX GENMASK(2, 0)
+#define PAD_STRONG_PULL BIT(3)
+#define PAD_EDGE_RISE BIT(4)
+#define PAD_EDGE_FALL BIT(5)
+#define PAD_EDGE_CLEAR BIT(6)
+#define PAD_SLEW_RATE GENMASK(12, 11)
+#define PAD_SLEW_RATE_EN BIT(7)
+#define PAD_SCHMITT GENMASK(9, 8)
+#define PAD_DRIVE GENMASK(12, 10)
+#define PAD_PULLDOWN BIT(13)
+#define PAD_PULLUP BIT(14)
+#define PAD_PULL_EN BIT(15)
+
+#define PIN_POWER_STATE_1V8 1800
+#define PIN_POWER_STATE_3V3 3300
+
+enum spacemit_pin_io_type {
+ IO_TYPE_NONE = 0,
+ IO_TYPE_1V8,
+ IO_TYPE_3V3,
+ IO_TYPE_EXTERNAL,
+};
+
+struct spacemit_pin_io {
+ unsigned int pin : 12; // 0~4095
+ unsigned int io_type : 4; // 0~15
+ unsigned int ds : 8; // 0~255
+ unsigned int reserved : 8;
+};
+
+struct spacemit_pinctrl_data {
+ struct spacemit_pin_io *io_pins;
+ int nr_io_pins;
+
+ void __iomem * (*pin_to_reg)(struct udevice *dev, unsigned int pin);
+ int (*get_gpio_mux)(struct udevice *dev, unsigned int pin);
+ int (*get_pins)(struct udevice *dev);
+ int (*get_functions)(struct udevice *dev);
+ int (*get_io_type)(struct udevice *dev, unsigned int pin);
+};
+
+struct spacemit_pinctrl_priv {
+ void __iomem *regs;
+ struct spacemit_pin_io *io_pins;
+ int nr_io_pins;
+};
+
+struct spacemit_pin_mux_config {
+ const struct spacemit_pin *pin;
+ u32 config;
+};
+
+struct spacemit_pin_drv_strength {
+ unsigned int val : 8;
+ unsigned int ma : 16;
+ unsigned int reserved : 8;
+};
+
+static char pin_name[PINNAME_SIZE];
+
+/* External: IO voltage via external source, can be 1.8V or 3.3V */
+static struct spacemit_pin_io k1_io_pins[] = {
+ { 47, IO_TYPE_EXTERNAL, 0, },
+ { 48, IO_TYPE_EXTERNAL, 0, },
+ { 49, IO_TYPE_EXTERNAL, 0, },
+ { 50, IO_TYPE_EXTERNAL, 0, },
+ { 51, IO_TYPE_EXTERNAL, 0, },
+ { 52, IO_TYPE_EXTERNAL, 0, },
+ { 75, IO_TYPE_EXTERNAL, 0, },
+ { 76, IO_TYPE_EXTERNAL, 0, },
+ { 77, IO_TYPE_EXTERNAL, 0, },
+ { 78, IO_TYPE_EXTERNAL, 0, },
+ { 79, IO_TYPE_EXTERNAL, 0, },
+ { 80, IO_TYPE_EXTERNAL, 0, },
+ { 98, IO_TYPE_EXTERNAL, 0, },
+ { 99, IO_TYPE_EXTERNAL, 0, },
+ { 100, IO_TYPE_EXTERNAL, 0, },
+ { 101, IO_TYPE_EXTERNAL, 0, },
+ { 102, IO_TYPE_EXTERNAL, 0, },
+ { 103, IO_TYPE_EXTERNAL, 0, },
+ { 104, IO_TYPE_EXTERNAL, 0, },
+ { 105, IO_TYPE_EXTERNAL, 0, },
+ { 106, IO_TYPE_EXTERNAL, 0, },
+ { 107, IO_TYPE_EXTERNAL, 0, },
+ { 108, IO_TYPE_EXTERNAL, 0, },
+ { 109, IO_TYPE_EXTERNAL, 0, },
+};
+
+static inline int k1_get_pins(struct udevice *dev)
+{
+ return 128;
+}
+
+static inline int k1_get_functions(struct udevice *dev)
+{
+ return 7;
+}
+
+// The pin number equals to the gpio number.
+static void __iomem *k1_pin_to_reg(struct udevice *dev, unsigned int pin)
+{
+ struct spacemit_pinctrl_priv *priv = dev_get_priv(dev);
+ unsigned int offset = 1;
+
+ if (pin < 86) {
+ offset += pin;
+ } else if (pin < 93) {
+ offset += pin + 36;
+ } else if (pin < 98) {
+ offset += pin + 23;
+ } else if (pin == 98) { // QSPI_DAT3
+ offset += 92;
+ } else if (pin == 99) { // QSPI_DAT2
+ offset += 91;
+ } else if (pin == 100) { // QSPI_DAT1
+ offset += 90;
+ } else if (pin == 101) { // QSPI_DAT0
+ offset += 89;
+ } else if (pin == 102) { // QSPI_CLK
+ offset += 94;
+ } else if (pin == 103) { // QSPI_CS1
+ offset += 93;
+ } else if (pin < 111) {
+ offset += pin + 5;
+ } else if (pin < 128) {
+ offset += pin + 19;
+ } else {
+ dev_err(dev, "Invalid pin (%u)\n", pin);
+ return NULL;
+ }
+ return priv->regs + (offset << 2);
+}
+
+static int k1_get_gpio_mux(struct udevice *dev, unsigned int selector)
+{
+ u32 mux = 0;
+
+ if (selector < 70) {
+ mux = 0;
+ } else if (selector < 74) {
+ mux = 1;
+ } else if (selector < 93) {
+ mux = 0;
+ } else if (selector < 104) {
+ mux = 1;
+ } else if (selector < 110) {
+ mux = 4;
+ } else if (selector < 128) {
+ mux = 0;
+ } else {
+ dev_err(dev, "Invalid pin (%u)\n", selector);
+ return -EINVAL;
+ }
+ return mux;
+}
+
+static int k1_get_io_type(struct udevice *dev, unsigned int selector)
+{
+ if (selector < 47)
+ return IO_TYPE_1V8;
+ else if (selector < 53)
+ return IO_TYPE_EXTERNAL;
+ else if (selector < 75)
+ return IO_TYPE_1V8;
+ else if (selector < 81)
+ return IO_TYPE_EXTERNAL;
+ else if (selector < 98)
+ return IO_TYPE_1V8;
+ else if (selector < 110)
+ return IO_TYPE_EXTERNAL;
+ else if (selector < 128)
+ return IO_TYPE_1V8;
+ return -EINVAL;
+}
+
+/* use IO high level output current as the table */
+static struct spacemit_pin_drv_strength spacemit_ds_1v8_tbl[4] = {
+ { 0, 11 },
+ { 2, 21 },
+ { 4, 32 },
+ { 6, 42 },
+};
+
+static struct spacemit_pin_drv_strength spacemit_ds_3v3_tbl[8] = {
+ { 0, 7 },
+ { 2, 10 },
+ { 4, 13 },
+ { 6, 16 },
+ { 1, 19 },
+ { 3, 23 },
+ { 5, 26 },
+ { 7, 29 },
+};
+
+static inline u8 spacemit_get_ds_value(struct spacemit_pin_drv_strength *tbl,
+ u32 num, u32 ma)
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ if (ma <= tbl[i].ma)
+ return tbl[i].val;
+
+ return tbl[num - 1].val;
+}
+
+static inline u32 spacemit_get_ds_ma(struct spacemit_pin_drv_strength *tbl,
+ u32 num, u32 val)
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ if (val == tbl[i].val)
+ return tbl[i].ma;
+
+ return 0;
+}
+
+static inline u8 spacemit_get_drive_strength(enum spacemit_pin_io_type type,
+ u32 ma)
+{
+ switch (type) {
+ case IO_TYPE_1V8:
+ return spacemit_get_ds_value(spacemit_ds_1v8_tbl,
+ ARRAY_SIZE(spacemit_ds_1v8_tbl),
+ ma);
+ case IO_TYPE_3V3:
+ return spacemit_get_ds_value(spacemit_ds_3v3_tbl,
+ ARRAY_SIZE(spacemit_ds_3v3_tbl),
+ ma);
+ default:
+ return 0;
+ }
+}
+
+static inline u32 spacemit_get_drive_strength_ma(enum spacemit_pin_io_type type,
+ u32 value)
+{
+ switch (type) {
+ case IO_TYPE_1V8:
+ return spacemit_get_ds_ma(spacemit_ds_1v8_tbl,
+ ARRAY_SIZE(spacemit_ds_1v8_tbl),
+ value & 0x6);
+ case IO_TYPE_3V3:
+ return spacemit_get_ds_ma(spacemit_ds_3v3_tbl,
+ ARRAY_SIZE(spacemit_ds_3v3_tbl),
+ value);
+ default:
+ return 0;
+ }
+}
+
+static inline u16 spacemit_dt_get_pin(u32 value)
+{
+ return value >> 16;
+}
+
+static inline u16 spacemit_dt_get_pin_mux(u32 value)
+{
+ return value & GENMASK(15, 0);
+}
+
+static int spacemit_get_pins_count(struct udevice *dev)
+{
+ struct spacemit_pinctrl_data *data;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ if (!data || !data->get_pins)
+ return -EINVAL;
+ return data->get_pins(dev);
+}
+
+static const char *spacemit_get_pin_name(struct udevice *dev,
+ unsigned int selector)
+{
+ struct spacemit_pinctrl_data *data;
+ unsigned int npins;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ if (!data || !data->get_pins)
+ return NULL;
+ npins = data->get_pins(dev);
+
+ if (selector >= npins)
+ snprintf(pin_name, PINNAME_SIZE, "Error");
+ else
+ snprintf(pin_name, PINNAME_SIZE, "PIN%u", selector);
+
+ return pin_name;
+}
+
+static int spacemit_get_functions_count(struct udevice *dev)
+{
+ struct spacemit_pinctrl_data *data;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ if (!data || !data->get_functions)
+ return -EINVAL;
+ return data->get_functions(dev);
+}
+
+static int spacemit_get_pin_muxing(struct udevice *dev, unsigned int pin,
+ char *buf, int size)
+{
+ struct spacemit_pinctrl_data *data;
+ void __iomem *addr;
+ u32 mux, val;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ if (!data || !data->pin_to_reg)
+ return -EINVAL;
+
+ addr = data->pin_to_reg(dev, pin);
+ if (!addr)
+ return -EINVAL;
+
+ val = readl(addr);
+ mux = val & PAD_MUX;
+ snprintf(buf, size, "[%p] 0x%08x MUX%d", addr, val, mux);
+ return 0;
+}
+
+static int spacemit_pinctrl_request_gpio(struct udevice *dev,
+ unsigned int selector)
+{
+ struct spacemit_pinctrl_data *data;
+ void __iomem *addr;
+ int mux;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ if (!data || !data->pin_to_reg || !data->get_gpio_mux)
+ return -EINVAL;
+ addr = data->pin_to_reg(dev, selector);
+ mux = data->get_gpio_mux(dev, selector);
+ if (mux < 0) {
+ dev_err(dev, "Invalid pin (%d)\n", selector);
+ return -EINVAL;
+ }
+ clrsetbits_le32(addr, PAD_MUX, mux & PAD_MUX);
+ return 0;
+}
+
+static int spacemit_pinctrl_free_gpio(struct udevice *dev,
+ unsigned int selector)
+{
+ return 0;
+}
+
+static int spacemit_pinmux_set(struct udevice *dev, unsigned int pin,
+ unsigned int mux)
+{
+ struct spacemit_pinctrl_data *data;
+ void __iomem *addr;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ if (!data || !data->pin_to_reg)
+ return -EINVAL;
+ addr = data->pin_to_reg(dev, pin);
+ clrsetbits_le32(addr, PAD_MUX, mux & PAD_MUX);
+ return 0;
+}
+
+static int spacemit_pinmux_property_set(struct udevice *dev, u32 pinmux_group)
+{
+ u32 pin, mux;
+
+ pin = spacemit_dt_get_pin(pinmux_group);
+ mux = spacemit_dt_get_pin_mux(pinmux_group);
+ return spacemit_pinmux_set(dev, pin, mux);
+}
+
+static const struct pinconf_param spacemit_pinconf_params[] = {
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, U32_MAX },
+ { "power-source", PIN_CONFIG_POWER_SOURCE, U32_MAX },
+};
+
+static int spacemit_pinconf_set(struct udevice *dev, unsigned int pin_selector,
+ unsigned int param, unsigned int argument)
+{
+ struct spacemit_pinctrl_data *data;
+ struct spacemit_pinctrl_priv *priv = dev_get_priv(dev);
+ void __iomem *addr;
+ u32 mask = 0;
+ unsigned int io_type;
+ u8 ds;
+ bool found;
+ int i;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ if (!data || !data->pin_to_reg)
+ return -EINVAL;
+ addr = data->pin_to_reg(dev, pin_selector);
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ clrbits_le32(addr, PAD_PULLUP | PAD_PULLDOWN | PAD_PULL_EN);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ mask = PAD_PULLDOWN | PAD_PULLUP | PAD_PULL_EN;
+ clrsetbits_le32(addr, mask, PAD_PULLDOWN | PAD_PULL_EN);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ mask = PAD_PULLDOWN | PAD_PULLUP | PAD_PULL_EN;
+ clrsetbits_le32(addr, mask, PAD_PULLUP | PAD_PULL_EN);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ io_type = IO_TYPE_1V8;
+ for (i = 0; i < priv->nr_io_pins; i++) {
+ if (priv->io_pins[i].pin != pin_selector)
+ continue;
+ io_type = priv->io_pins[i].io_type;
+ break;
+ }
+ if (io_type != IO_TYPE_3V3 && io_type != IO_TYPE_1V8) {
+ dev_err(dev, "Invalid IO type (%d)\n", io_type);
+ return -EINVAL;
+ }
+ ds = spacemit_get_drive_strength(io_type, argument);
+ clrsetbits_le32(addr, PAD_DRIVE, ds);
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ for (i = 0, found = false; i < priv->nr_io_pins; i++) {
+ if (priv->io_pins[i].pin != pin_selector)
+ continue;
+ if (argument == PIN_POWER_STATE_3V3) {
+ priv->io_pins[i].io_type = IO_TYPE_3V3;
+ found = true;
+ } else if (argument == PIN_POWER_STATE_1V8) {
+ priv->io_pins[i].io_type = IO_TYPE_1V8;
+ found = true;
+ }
+ break;
+ }
+ if (!found && argument != PIN_POWER_STATE_1V8) {
+ dev_err(dev, "Invalid power source (%d)\n", argument);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static int spacemit_pinctrl_probe(struct udevice *dev)
+{
+ struct spacemit_pinctrl_data *data;
+ struct spacemit_pinctrl_priv *priv;
+ struct clk_bulk clks;
+ size_t size;
+ int ret;
+
+ data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
+ priv = dev_get_priv(dev);
+ priv->regs = dev_read_addr_ptr(dev);
+ if (!priv->regs) {
+ dev_err(dev, "Fail to get base address\n");
+ return -EINVAL;
+ }
+ priv->nr_io_pins = data->nr_io_pins;
+ size = priv->nr_io_pins * sizeof(struct spacemit_pin_io);
+ priv->io_pins = (struct spacemit_pin_io *)memdup(data->io_pins, size);
+ if (!priv->io_pins) {
+ dev_err(dev, "Fail to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ ret = clk_get_bulk(dev, &clks);
+ if (ret) {
+ dev_err(dev, "Fail to get bulk clks\n");
+ goto out_get_clk;
+ }
+ ret = clk_enable_bulk(&clks);
+ if (ret) {
+ dev_err(dev, "Fail to enable bulk clks\n");
+ goto out_clks;
+ }
+ return 0;
+out_clks:
+ clk_release_bulk(&clks);
+out_get_clk:
+ free(priv->io_pins);
+ return ret;
+}
+
+static const struct spacemit_pinctrl_data k1_pinctrl_data = {
+ .io_pins = k1_io_pins,
+ .nr_io_pins = ARRAY_SIZE(k1_io_pins),
+ .pin_to_reg = k1_pin_to_reg,
+ .get_gpio_mux = k1_get_gpio_mux,
+ .get_pins = k1_get_pins,
+ .get_functions = k1_get_functions,
+ .get_io_type = k1_get_io_type,
+};
+
+static const struct udevice_id spacemit_pinctrl_ids[] = {
+ {
+ .compatible = "spacemit,k1-pinctrl",
+ .data = (uintptr_t)&k1_pinctrl_data,
+ }, { /* sentinel */ }
+};
+
+static const struct pinctrl_ops spacemit_pinctrl_ops = {
+ .get_pins_count = spacemit_get_pins_count,
+ .get_pin_name = spacemit_get_pin_name,
+ .get_functions_count = spacemit_get_functions_count,
+ .get_pin_muxing = spacemit_get_pin_muxing,
+ .set_state = pinctrl_generic_set_state,
+ .gpio_request_enable = spacemit_pinctrl_request_gpio,
+ .gpio_disable_free = spacemit_pinctrl_free_gpio,
+ .pinmux_set = spacemit_pinmux_set,
+ .pinmux_property_set = spacemit_pinmux_property_set,
+ .pinconf_num_params = ARRAY_SIZE(spacemit_pinconf_params),
+ .pinconf_params = spacemit_pinconf_params,
+ .pinconf_set = spacemit_pinconf_set,
+};
+
+U_BOOT_DRIVER(spacemit_pinctrl) = {
+ .name = "spacemit_pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = spacemit_pinctrl_ids,
+ .ops = &spacemit_pinctrl_ops,
+ .priv_auto = sizeof(struct spacemit_pinctrl_priv),
+ .probe = spacemit_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index a8632aeaf8f..ab4e88c9918 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -761,7 +761,8 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_pinctrl_desc =
};
static const struct sunxi_pinctrl_function sun55i_a523_pinctrl_functions[] = {
- { "gmac0", 5 }, /* PI0-PI16 */
+ { "gmac0", 5 }, /* PH0-PH7, PH9-PH10, PH14-PH18 */
+ { "gmac1", 5 }, /* PJ0-PJ9, PJ11-PJ15 */
{ "gpio_in", 0 },
{ "gpio_out", 1 },
{ "mmc0", 2 }, /* PF0-PF5 */
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index bb9c52155d2..12b0e2c9914 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -9,6 +9,14 @@ config POWER_DOMAIN
domains). This may be used to save power. This API provides the
means to control such power management hardware.
+config AGILEX5_PMGR_POWER_DOMAIN
+ bool "Enable the Agilex5 PMGR power domain driver"
+ depends on SPL_POWER_DOMAIN && ARCH_SOCFPGA_SOC64
+ help
+ Enable support for power gating peripherals' SRAM specified in
+ the handoff data values obtained from the bitstream to reduce
+ power consumption.
+
config APPLE_PMGR_POWER_DOMAIN
bool "Enable the Apple PMGR power domain driver"
depends on POWER_DOMAIN
@@ -18,14 +26,6 @@ config APPLE_PMGR_POWER_DOMAIN
This driver is needed to power on parts of the SoC that have
not been powered on by previous boot stages.
-config AGILEX5_PMGR_POWER_DOMAIN
- bool "Enable the Agilex5 PMGR power domain driver"
- depends on SPL_POWER_DOMAIN && ARCH_SOCFPGA_SOC64
- help
- Enable support for power gating peripherals' SRAM specified in
- the handoff data values obtained from the bitstream to reduce
- power consumption.
-
config BCM6328_POWER_DOMAIN
bool "Enable the BCM6328 power domain driver"
depends on POWER_DOMAIN && ARCH_BMIPS
@@ -62,12 +62,12 @@ config IMX8MP_MEDIAMIX_BLKCTRL
help
Enable support for manipulating NXP i.MX8MP on-SoC MEDIAMIX block controller.
-config MTK_POWER_DOMAIN
- bool "Enable the MediaTek power domain driver"
- depends on POWER_DOMAIN && ARCH_MEDIATEK
+config MESON_EE_POWER_DOMAIN
+ bool "Enable Amlogic Everything-Else power domain driver"
+ depends on POWER_DOMAIN && ARCH_MESON
help
- Enable support for manipulating MediaTek power domains via MMIO
- mapped registers.
+ Enable support for manipulating Amlogic Meson Everything-Else power
+ domains.
config MESON_GX_VPU_POWER_DOMAIN
bool "Enable Amlogic Meson GX VPU power domain driver"
@@ -76,13 +76,6 @@ config MESON_GX_VPU_POWER_DOMAIN
Enable support for manipulating Amlogic Meson GX Video Processing
Unit power domain.
-config MESON_EE_POWER_DOMAIN
- bool "Enable Amlogic Everything-Else power domain driver"
- depends on POWER_DOMAIN && ARCH_MESON
- help
- Enable support for manipulating Amlogic Meson Everything-Else power
- domains.
-
config MESON_SECURE_POWER_DOMAIN
bool "Enable Amlogic Secure power domain driver"
depends on POWER_DOMAIN && ARCH_MESON && MESON_A1
@@ -90,6 +83,40 @@ config MESON_SECURE_POWER_DOMAIN
Enable support for manipulating Amlogic Meson Secure power domains.
Support for Amlogic A1 series.
+config MT2701_POWER_DOMAIN
+ bool "Enable the MediaTek power domain driver for MT2701 compatible SoC"
+ depends on POWER_DOMAIN && ARCH_MEDIATEK
+ select MTK_POWER_DOMAIN
+ help
+ Enable support for manipulating MediaTek power domains via MMIO
+ mapped registers for MT2701 compatible SoC. The driver powers
+ the SoC power domains on and off and handles the associated bus
+ protection bits. It is also used on MT7623.
+
+config MT7622_POWER_DOMAIN
+ bool "Enable the MediaTek power domain driver for MT7622 compatible SoC"
+ depends on POWER_DOMAIN && ARCH_MEDIATEK
+ select MTK_POWER_DOMAIN
+ help
+ Enable support for manipulating MediaTek power domains via MMIO
+ mapped registers for MT7622 compatible SoC. The driver powers
+ the SoC power domains on and off and handles the associated bus
+ protection bits. It is also used on MT7629.
+
+config MT8188_POWER_DOMAIN
+ bool "Enable the MediaTek power domain driver for MT8188 compatible SoC"
+ depends on POWER_DOMAIN && ARCH_MEDIATEK
+ select MTK_POWER_DOMAIN
+ help
+ Enable support for manipulating MediaTek power domains via MMIO
+ mapped registers for MT8188 compatible SoC. The driver powers
+ the SoC power domains on and off and handles the associated bus
+ protection steps, per-domain clocks and parent domains.
+
+config MTK_POWER_DOMAIN
+ bool
+ depends on POWER_DOMAIN && ARCH_MEDIATEK
+
config QCOM_RPMH_POWER_DOMAIN
bool "Enable the QCOM RPMH Power domain driver"
depends on POWER_DOMAIN && ARCH_SNAPDRAGON
@@ -128,12 +155,13 @@ config TEGRA186_POWER_DOMAIN
Enable support for manipulating Tegra's on-SoC power domains via IPC
requests to the BPMP (Boot and Power Management Processor).
-config TI_SCI_POWER_DOMAIN
- bool "Enable the TI SCI-based power domain driver"
- depends on POWER_DOMAIN && TI_SCI_PROTOCOL
+config TI_OMAP_PRM_POWER_DOMAIN
+ bool "Enable the TI OMAP PRM power domain driver"
+ depends on POWER_DOMAIN && ARCH_OMAP2PLUS
help
- Generic power domain implementation for TI devices implementing the
- TI SCI protocol.
+ Enable support for TI OMAP Power and Reset Manager (PRM) power domains.
+ The driver is currently a stub to be able to probe devices that
+ require this type of power domain device.
config TI_POWER_DOMAIN
bool "Enable the TI K3 Power domain driver"
@@ -141,13 +169,12 @@ config TI_POWER_DOMAIN
help
Generic power domain implementation for TI K3 devices.
-config TI_OMAP_PRM_POWER_DOMAIN
- bool "Enable the TI OMAP PRM power domain driver"
- depends on POWER_DOMAIN && ARCH_OMAP2PLUS
+config TI_SCI_POWER_DOMAIN
+ bool "Enable the TI SCI-based power domain driver"
+ depends on POWER_DOMAIN && TI_SCI_PROTOCOL
help
- Enable support for TI OMAP Power and Reset Manager (PRM) power domains.
- The driver is currently a stub to be able to probe devices that
- require this type of power domain device.
+ Generic power domain implementation for TI devices implementing the
+ TI SCI protocol.
config ZYNQMP_POWER_DOMAIN
bool "Enable the Xilinx ZynqMP Power domain driver"
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index 110153d5cf8..e6fe71c374a 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -4,24 +4,27 @@
#
obj-$(CONFIG_$(PHASE_)POWER_DOMAIN) += power-domain-uclass.o
-obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
obj-$(CONFIG_AGILEX5_PMGR_POWER_DOMAIN) += altr-pmgr-agilex5.o
+obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
obj-$(CONFIG_IMX8MP_MEDIAMIX_BLKCTRL) += imx8mp-mediamix.o
-obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
-obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o
+obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
obj-$(CONFIG_MESON_SECURE_POWER_DOMAIN) += meson-secure-pwrc.o
+obj-$(CONFIG_MT2701_POWER_DOMAIN) += mt2701-power-domain.o
+obj-$(CONFIG_MT7622_POWER_DOMAIN) += mt7622-power-domain.o
+obj-$(CONFIG_MT8188_POWER_DOMAIN) += mt8188-power-domain.o
+obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
+obj-$(CONFIG_QCOM_RPMH_POWER_DOMAIN) += qcom-rpmhpd.o
obj-$(CONFIG_RENESAS_R8A78000_POWER_DOMAIN) += renesas-r8a78000-power-domain.o
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
obj-$(CONFIG_SCMI_POWER_DOMAIN) += scmi-power-domain.o
obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
-obj-$(CONFIG_TI_SCI_POWER_DOMAIN) += ti-sci-power-domain.o
-obj-$(CONFIG_TI_POWER_DOMAIN) += ti-power-domain.o
obj-$(CONFIG_TI_OMAP_PRM_POWER_DOMAIN) += ti-omap-prm.o
+obj-$(CONFIG_TI_POWER_DOMAIN) += ti-power-domain.o
+obj-$(CONFIG_TI_SCI_POWER_DOMAIN) += ti-sci-power-domain.o
obj-$(CONFIG_ZYNQMP_POWER_DOMAIN) += zynqmp-power-domain.o
-obj-$(CONFIG_QCOM_RPMH_POWER_DOMAIN) += qcom-rpmhpd.o
diff --git a/drivers/power/domain/mt2701-power-domain.c b/drivers/power/domain/mt2701-power-domain.c
new file mode 100644
index 00000000000..5bef4aa97ea
--- /dev/null
+++ b/drivers/power/domain/mt2701-power-domain.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Copyright (C) 2026 BayLibre, SAS
+ * Author: Ryder Lee <[email protected]>
+ * Julien Stephan <[email protected]>
+ */
+
+#include <dm.h>
+#include <dt-bindings/power/mt2701-power.h>
+#include <linux/bitops.h>
+
+#include "mtk-power-domain.h"
+
+static const struct mtk_scp_domain_data mt2701_scp_domain[] = {
+ [MT2701_POWER_DOMAIN_CONN] = {
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = SPM_CONN_PWR_CON,
+ .bus_prot_mask = BIT(8) | BIT(2),
+ },
+ [MT2701_POWER_DOMAIN_DISP] = {
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .bus_prot_mask = BIT(2),
+ },
+ [MT2701_POWER_DOMAIN_MFG] = {
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT2701_POWER_DOMAIN_VDEC] = {
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT2701_POWER_DOMAIN_ISP] = {
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ },
+ [MT2701_POWER_DOMAIN_BDP] = {
+ .sta_mask = PWR_STATUS_BDP,
+ .ctl_offs = SPM_BDP_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ },
+ [MT2701_POWER_DOMAIN_ETH] = {
+ .sta_mask = PWR_STATUS_ETH,
+ .ctl_offs = SPM_ETH_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT2701_POWER_DOMAIN_HIF] = {
+ .sta_mask = PWR_STATUS_HIF,
+ .ctl_offs = SPM_HIF_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT2701_POWER_DOMAIN_IFR_MSC] = {
+ .sta_mask = PWR_STATUS_IFR_MSC,
+ .ctl_offs = SPM_IFR_MSC_PWR_CON,
+ },
+};
+
+MTK_SCP_SOC_DATA(mt2701, mt2701_scp_domain);
+
+static const struct udevice_id mt2701_power_domain_ids[] = {
+ {
+ .compatible = "mediatek,mt2701-scpsys",
+ .data = (ulong)&mt2701_scp_soc_data,
+ },
+ {
+ .compatible = "mediatek,mt7623-scpsys",
+ .data = (ulong)&mt2701_scp_soc_data,
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mt2701_power_domain) = {
+ .name = "mt2701_power_domain",
+ .id = UCLASS_POWER_DOMAIN,
+ .ops = &mtk_power_domain_ops,
+ .probe = mtk_scpsys_probe,
+ .of_match = mt2701_power_domain_ids,
+ .priv_auto = sizeof(struct mtk_scpsys),
+};
diff --git a/drivers/power/domain/mt7622-power-domain.c b/drivers/power/domain/mt7622-power-domain.c
new file mode 100644
index 00000000000..13f2154e145
--- /dev/null
+++ b/drivers/power/domain/mt7622-power-domain.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Copyright (C) 2026 BayLibre, SAS
+ * Author: Ryder Lee <[email protected]>
+ * Julien Stephan <[email protected]>
+ */
+
+#include <dm.h>
+#include <dt-bindings/power/mt7622-power.h>
+#include <linux/bitops.h>
+
+#include "mtk-power-domain.h"
+
+static const struct mtk_scp_domain_data mt7622_scp_domain[] = {
+ [MT7622_POWER_DOMAIN_ETHSYS] = {
+ .sta_mask = PWR_STATUS_ETHSYS,
+ .ctl_offs = SPM_ETHSYS_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .bus_prot_mask = (BIT(3) | BIT(17)),
+ },
+ [MT7622_POWER_DOMAIN_HIF0] = {
+ .sta_mask = PWR_STATUS_HIF0,
+ .ctl_offs = SPM_HIF0_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .bus_prot_mask = GENMASK(25, 24),
+ },
+ [MT7622_POWER_DOMAIN_HIF1] = {
+ .sta_mask = PWR_STATUS_HIF1,
+ .ctl_offs = SPM_HIF1_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .bus_prot_mask = GENMASK(28, 26),
+ },
+};
+
+MTK_SCP_SOC_DATA(mt7622, mt7622_scp_domain);
+
+static const struct udevice_id mt7622_power_domain_ids[] = {
+ {
+ .compatible = "mediatek,mt7622-scpsys",
+ .data = (ulong)&mt7622_scp_soc_data,
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mt7622_power_domain) = {
+ .name = "mt7622_power_domain",
+ .id = UCLASS_POWER_DOMAIN,
+ .ops = &mtk_power_domain_ops,
+ .probe = mtk_scpsys_probe,
+ .of_match = mt7622_power_domain_ids,
+ .priv_auto = sizeof(struct mtk_scpsys),
+};
diff --git a/drivers/power/domain/mt8188-power-domain.c b/drivers/power/domain/mt8188-power-domain.c
new file mode 100644
index 00000000000..265d222f17a
--- /dev/null
+++ b/drivers/power/domain/mt8188-power-domain.c
@@ -0,0 +1,665 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 MediaTek Inc.
+ * Copyright (C) 2026 BayLibre, SAS.
+ * Authors: Chris-QJ Chen <[email protected]>
+ * Julien Stephan <[email protected]>
+ */
+
+#include <dm.h>
+#include <dt-bindings/power/mediatek,mt8188-power.h>
+#include <linux/bitops.h>
+
+#include "mtk-power-domain.h"
+
+/* Infra bus protection register offsets */
+#define MT8188_TOP_AXI_PROT_EN_SET 0x2A0
+#define MT8188_TOP_AXI_PROT_EN_CLR 0x2A4
+#define MT8188_TOP_AXI_PROT_EN_STA 0x228
+#define MT8188_TOP_AXI_PROT_EN_1_SET 0x2A8
+#define MT8188_TOP_AXI_PROT_EN_1_CLR 0x2AC
+#define MT8188_TOP_AXI_PROT_EN_1_STA 0x258
+#define MT8188_TOP_AXI_PROT_EN_2_SET 0x714
+#define MT8188_TOP_AXI_PROT_EN_2_CLR 0x718
+#define MT8188_TOP_AXI_PROT_EN_2_STA 0x724
+#define MT8188_TOP_AXI_PROT_EN_MM_SET 0x2D4
+#define MT8188_TOP_AXI_PROT_EN_MM_CLR 0x2D8
+#define MT8188_TOP_AXI_PROT_EN_MM_STA 0x2EC
+#define MT8188_TOP_AXI_PROT_EN_MM_2_SET 0xDCC
+#define MT8188_TOP_AXI_PROT_EN_MM_2_CLR 0xDD0
+#define MT8188_TOP_AXI_PROT_EN_MM_2_STA 0xDD8
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET 0xB84
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR 0xB88
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA 0xB90
+#define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET 0xBCC
+#define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR 0xBD0
+#define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA 0xBD8
+
+/* MFG1 bus protection bits */
+#define MT8188_TOP_AXI_PROT_EN_MFG1_STEP1 BIT(11)
+#define MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2 BIT(7)
+#define MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3 BIT(19)
+#define MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4 BIT(5)
+#define MT8188_TOP_AXI_PROT_EN_MFG1_STEP5 GENMASK(22, 21)
+#define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6 BIT(17)
+
+/* PCIe bus protection bits */
+#define MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1 BIT(2)
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2 (BIT(8) | BIT(18) | BIT(30))
+
+/* Ethernet / HDMI / DP / eDP bus protection bits */
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1 BIT(24)
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1 BIT(20)
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1 BIT(23)
+#define MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1 BIT(22)
+
+/* ADSP bus protection bits */
+#define MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1 GENMASK(31, 29)
+#define MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2 (GENMASK(4, 3) | BIT(28))
+#define MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1 (GENMASK(16, 14) | BIT(23) | BIT(27))
+#define MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2 (GENMASK(19, 17) | GENMASK(26, 25))
+#define MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1 GENMASK(11, 8)
+#define MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2 GENMASK(22, 21)
+
+/* Audio bus protection bits */
+#define MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1 BIT(20)
+#define MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2 BIT(12)
+#define MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1 BIT(24)
+#define MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2 BIT(13)
+
+/* Video / display bus protection bits */
+#define MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1 BIT(10)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2 GENMASK(9, 8)
+#define MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3 BIT(23)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4 (BIT(1) | BIT(4) | BIT(11))
+#define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5 BIT(20)
+#define MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1 (GENMASK(18, 17) | GENMASK(21, 20))
+#define MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2 BIT(6)
+#define MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3 BIT(21)
+#define MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1 GENMASK(31, 30)
+#define MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2 BIT(22)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3 BIT(10)
+#define MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1 GENMASK(6, 5)
+#define MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2 BIT(23)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3 BIT(18)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1 BIT(23)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2 BIT(21)
+#define MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1 BIT(13)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2 BIT(13)
+#define MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1 BIT(14)
+#define MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2 BIT(29)
+#define MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1 (BIT(9) | BIT(11))
+#define MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2 BIT(26)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3 BIT(2)
+#define MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1 (BIT(1) | BIT(3))
+#define MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2 BIT(25)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3 BIT(16)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1 GENMASK(27, 26)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2 GENMASK(25, 24)
+#define MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1 (BIT(2) | BIT(4))
+#define MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2 BIT(0)
+#define MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3 BIT(22)
+#define MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4 BIT(24)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5 BIT(17)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1 GENMASK(31, 30)
+#define MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2 BIT(2)
+#define MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3 GENMASK(29, 28)
+#define MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4 BIT(1)
+
+static const struct mtk_scp_domain_data mt8188_scp_domain[] = {
+ [MT8188_POWER_DOMAIN_MFG0] = {
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x300,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8188_POWER_DOMAIN_MFG1] = {
+ .sta_mask = BIT(2),
+ .ctl_offs = 0x304,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3,
+ MT8188_TOP_AXI_PROT_EN_1_SET,
+ MT8188_TOP_AXI_PROT_EN_1_CLR,
+ MT8188_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP5,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_MFG2] = {
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x308,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8188_POWER_DOMAIN_MFG3] = {
+ .sta_mask = BIT(4),
+ .ctl_offs = 0x30C,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8188_POWER_DOMAIN_MFG4] = {
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x310,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8188_POWER_DOMAIN_PEXTP_MAC_P0] = {
+ .sta_mask = BIT(10),
+ .ctl_offs = 0x324,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_PEXTP_PHY_TOP] = {
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x328,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ },
+ [MT8188_POWER_DOMAIN_CSIRX_TOP] = {
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x3C4,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ },
+ [MT8188_POWER_DOMAIN_ETHER] = {
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x338,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_HDMI_TX] = {
+ .sta_mask = BIT(18),
+ .ctl_offs = 0x37C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_ADSP_AO] = {
+ .sta_mask = BIT(10),
+ .ctl_offs = 0x35C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_ADSP_INFRA] = {
+ .sta_mask = BIT(9),
+ .ctl_offs = 0x358,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_ADSP] = {
+ .sta_mask = BIT(8),
+ .ctl_offs = 0x354,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_AUDIO] = {
+ .sta_mask = BIT(6),
+ .ctl_offs = 0x34C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_AUDIO_ASRC] = {
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x350,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VPPSYS0] = {
+ .sta_mask = BIT(11),
+ .ctl_offs = 0x360,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VDOSYS0] = {
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x368,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VDOSYS1] = {
+ .sta_mask = BIT(14),
+ .ctl_offs = 0x36C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_DP_TX] = {
+ .sta_mask = BIT(16),
+ .ctl_offs = 0x374,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_EDP_TX] = {
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x378,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VPPSYS1] = {
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x364,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_WPE] = {
+ .sta_mask = BIT(15),
+ .ctl_offs = 0x370,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VDEC0] = {
+ .sta_mask = BIT(19),
+ .ctl_offs = 0x380,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VDEC1] = {
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x384,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VENC] = {
+ .sta_mask = BIT(22),
+ .ctl_offs = 0x38C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_IMG_VCORE] = {
+ .sta_mask = BIT(28),
+ .ctl_offs = 0x3A4,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_IMG_MAIN] = {
+ .sta_mask = BIT(29),
+ .ctl_offs = 0x3A8,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_DIP] = {
+ .sta_mask = BIT(30),
+ .ctl_offs = 0x3AC,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8188_POWER_DOMAIN_IPE] = {
+ .sta_mask = BIT(31),
+ .ctl_offs = 0x3B0,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8188_POWER_DOMAIN_CAM_VCORE] = {
+ .sta_mask = BIT(27),
+ .ctl_offs = 0x3A0,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3,
+ MT8188_TOP_AXI_PROT_EN_1_SET,
+ MT8188_TOP_AXI_PROT_EN_1_CLR,
+ MT8188_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_CAM_MAIN] = {
+ .sta_mask = BIT(24),
+ .ctl_offs = 0x394,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_infracfg = {
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_CAM_SUBA] = {
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x398,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8188_POWER_DOMAIN_CAM_SUBB] = {
+ .sta_mask = BIT(26),
+ .ctl_offs = 0x39C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+};
+
+MTK_SCP_SOC_DATA(mt8188, mt8188_scp_domain);
+
+static const struct udevice_id mt8188_power_domain_ids[] = {
+ {
+ .compatible = "mediatek,mt8188-power-controller",
+ .data = (ulong)&mt8188_scp_soc_data,
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mt8188_power_domain) = {
+ .name = "mt8188_power_domain",
+ .id = UCLASS_POWER_DOMAIN,
+ .ops = &mtk_power_domain_ops,
+ .probe = mtk_power_controller_probe,
+ .of_match = mt8188_power_domain_ids,
+ .priv_auto = sizeof(struct mtk_scpsys),
+};
diff --git a/drivers/power/domain/mtk-power-domain.c b/drivers/power/domain/mtk-power-domain.c
index 24dd540897d..9eef58d2d57 100644
--- a/drivers/power/domain/mtk-power-domain.c
+++ b/drivers/power/domain/mtk-power-domain.c
@@ -6,161 +6,15 @@
#include <clk.h>
#include <dm.h>
-#include <malloc.h>
-#include <power-domain-uclass.h>
#include <regmap.h>
#include <syscon.h>
#include <asm/io.h>
-#include <asm/processor.h>
-#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/iopoll.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
-#include <dt-bindings/power/mt7623-power.h>
-#include <dt-bindings/power/mt7629-power.h>
-
-#define SPM_EN (0xb16 << 16 | 0x1)
-#define SPM_VDE_PWR_CON 0x0210
-#define SPM_MFG_PWR_CON 0x0214
-#define SPM_ISP_PWR_CON 0x0238
-#define SPM_DIS_PWR_CON 0x023c
-#define SPM_CONN_PWR_CON 0x0280
-#define SPM_BDP_PWR_CON 0x029c
-#define SPM_ETH_PWR_CON 0x02a0
-#define SPM_HIF_PWR_CON 0x02a4
-#define SPM_IFR_MSC_PWR_CON 0x02a8
-#define SPM_ETHSYS_PWR_CON 0x2e0
-#define SPM_HIF0_PWR_CON 0x2e4
-#define SPM_HIF1_PWR_CON 0x2e8
-#define SPM_PWR_STATUS 0x60c
-#define SPM_PWR_STATUS_2ND 0x610
-
-#define PWR_RST_B_BIT BIT(0)
-#define PWR_ISO_BIT BIT(1)
-#define PWR_ON_BIT BIT(2)
-#define PWR_ON_2ND_BIT BIT(3)
-#define PWR_CLK_DIS_BIT BIT(4)
-
-#define PWR_STATUS_CONN BIT(1)
-#define PWR_STATUS_DISP BIT(3)
-#define PWR_STATUS_MFG BIT(4)
-#define PWR_STATUS_ISP BIT(5)
-#define PWR_STATUS_VDEC BIT(7)
-#define PWR_STATUS_BDP BIT(14)
-#define PWR_STATUS_ETH BIT(15)
-#define PWR_STATUS_HIF BIT(16)
-#define PWR_STATUS_IFR_MSC BIT(17)
-#define PWR_STATUS_ETHSYS BIT(24)
-#define PWR_STATUS_HIF0 BIT(25)
-#define PWR_STATUS_HIF1 BIT(26)
-
-/* Infrasys configuration */
-#define INFRA_TOPDCM_CTRL 0x10
-#define INFRA_TOPAXI_PROT_EN 0x220
-#define INFRA_TOPAXI_PROT_STA1 0x228
-
-#define DCM_TOP_EN BIT(0)
-
-enum scp_domain_type {
- SCPSYS_MT7622,
- SCPSYS_MT7623,
- SCPSYS_MT7629,
-};
-
-struct scp_domain;
-
-struct scp_domain_data {
- struct scp_domain *scpd;
- u32 sta_mask;
- int ctl_offs;
- u32 sram_pdn_bits;
- u32 sram_pdn_ack_bits;
- u32 bus_prot_mask;
-};
-
-struct scp_domain {
- void __iomem *base;
- void __iomem *infracfg;
- enum scp_domain_type type;
- struct scp_domain_data *data;
-};
-
-static struct scp_domain_data scp_domain_mt7623[] = {
- [MT7623_POWER_DOMAIN_CONN] = {
- .sta_mask = PWR_STATUS_CONN,
- .ctl_offs = SPM_CONN_PWR_CON,
- .bus_prot_mask = BIT(8) | BIT(2),
- },
- [MT7623_POWER_DOMAIN_DISP] = {
- .sta_mask = PWR_STATUS_DISP,
- .ctl_offs = SPM_DIS_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .bus_prot_mask = BIT(2),
- },
- [MT7623_POWER_DOMAIN_MFG] = {
- .sta_mask = PWR_STATUS_MFG,
- .ctl_offs = SPM_MFG_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(12, 12),
- },
- [MT7623_POWER_DOMAIN_VDEC] = {
- .sta_mask = PWR_STATUS_VDEC,
- .ctl_offs = SPM_VDE_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(12, 12),
- },
- [MT7623_POWER_DOMAIN_ISP] = {
- .sta_mask = PWR_STATUS_ISP,
- .ctl_offs = SPM_ISP_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(13, 12),
- },
- [MT7623_POWER_DOMAIN_BDP] = {
- .sta_mask = PWR_STATUS_BDP,
- .ctl_offs = SPM_BDP_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- },
- [MT7623_POWER_DOMAIN_ETH] = {
- .sta_mask = PWR_STATUS_ETH,
- .ctl_offs = SPM_ETH_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(15, 12),
- },
- [MT7623_POWER_DOMAIN_HIF] = {
- .sta_mask = PWR_STATUS_HIF,
- .ctl_offs = SPM_HIF_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(15, 12),
- },
- [MT7623_POWER_DOMAIN_IFR_MSC] = {
- .sta_mask = PWR_STATUS_IFR_MSC,
- .ctl_offs = SPM_IFR_MSC_PWR_CON,
- },
-};
-
-static struct scp_domain_data scp_domain_mt7629[] = {
- [MT7629_POWER_DOMAIN_ETHSYS] = {
- .sta_mask = PWR_STATUS_ETHSYS,
- .ctl_offs = SPM_ETHSYS_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(15, 12),
- .bus_prot_mask = (BIT(3) | BIT(17)),
- },
- [MT7629_POWER_DOMAIN_HIF0] = {
- .sta_mask = PWR_STATUS_HIF0,
- .ctl_offs = SPM_HIF0_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(15, 12),
- .bus_prot_mask = GENMASK(25, 24),
- },
- [MT7629_POWER_DOMAIN_HIF1] = {
- .sta_mask = PWR_STATUS_HIF1,
- .ctl_offs = SPM_HIF1_PWR_CON,
- .sram_pdn_bits = GENMASK(11, 8),
- .sram_pdn_ack_bits = GENMASK(15, 12),
- .bus_prot_mask = GENMASK(28, 26),
- },
-};
+#include "mtk-power-domain.h"
/**
* This function enables the bus protection bits for disabled power
@@ -189,13 +43,79 @@ static int mtk_infracfg_clear_bus_protection(void __iomem *infracfg,
!(val & mask), 100);
}
-static int scpsys_domain_is_on(struct scp_domain_data *data)
+static int _scpsys_bus_protect_enable(const struct mtk_scpsys_bus_prot_data *bpd,
+ void __iomem *reg)
+{
+ u32 val = 0, mask = bpd->bus_prot_mask;
+
+ if (!mask)
+ return 0;
+
+ if (bpd->bus_prot_reg_update)
+ clrsetbits_le32(reg + bpd->bus_prot_set, mask, mask);
+ else
+ writel(mask, reg + bpd->bus_prot_set);
+
+ return readl_poll_timeout(reg + bpd->bus_prot_sta, val, (val & mask) == mask, 1000);
+}
+
+static int _scpsys_bus_protect_disable(const struct mtk_scpsys_bus_prot_data *bpd,
+ void __iomem *reg)
+{
+ u32 val = 0, mask = bpd->bus_prot_mask;
+
+ if (!mask)
+ return 0;
+
+ if (bpd->bus_prot_reg_update)
+ clrbits_le32(reg + bpd->bus_prot_clr, mask);
+ else
+ writel(mask, reg + bpd->bus_prot_clr);
+
+ if (bpd->ignore_clr_ack)
+ return 0;
+
+ return readl_poll_timeout(reg + bpd->bus_prot_sta, val, !(val & mask), 1000);
+}
+
+static int scpsys_bus_protect_enable(const struct mtk_scpsys_bus_prot_data *bpd,
+ int bpd_size, void __iomem *reg)
{
- struct scp_domain *scpd = data->scpd;
- u32 sta = readl(scpd->base + SPM_PWR_STATUS) &
- data->sta_mask;
- u32 sta2 = readl(scpd->base + SPM_PWR_STATUS_2ND) &
- data->sta_mask;
+ int ret, i;
+
+ for (i = 0; i < bpd_size; i++) {
+ ret = _scpsys_bus_protect_enable(&bpd[i], reg);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int scpsys_bus_protect_disable(const struct mtk_scpsys_bus_prot_data *bpd,
+ int bpd_size, void __iomem *reg)
+{
+ int i, ret;
+
+ for (i = bpd_size - 1; i >= 0; i--) {
+ ret = _scpsys_bus_protect_disable(&bpd[i], reg);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_scpsys_domain_is_on(struct power_domain *power_domain)
+{
+ struct mtk_scpsys *scpsys = dev_get_priv(power_domain->dev);
+ const struct mtk_scp_domain_data *data = scpsys->domains[power_domain->id].data;
+ u32 spm_pwr_status = data->pwr_sta_offs ?: SPM_PWR_STATUS;
+ u32 spm_pwr_status_2nd = data->pwr_sta2nd_offs ?: SPM_PWR_STATUS_2ND;
+ u32 sta, sta2;
+
+ sta = readl(scpsys->base + spm_pwr_status) & data->sta_mask;
+ sta2 = readl(scpsys->base + spm_pwr_status_2nd) & data->sta_mask;
/*
* A domain is on when both status bits are set. If only one is set
@@ -209,16 +129,40 @@ static int scpsys_domain_is_on(struct scp_domain_data *data)
return -EINVAL;
}
-static int scpsys_power_on(struct power_domain *power_domain)
+static int mtk_scpsys_power_on(struct power_domain *power_domain)
{
- struct scp_domain *scpd = dev_get_priv(power_domain->dev);
- struct scp_domain_data *data = &scpd->data[power_domain->id];
- void __iomem *ctl_addr = scpd->base + data->ctl_offs;
- u32 pdn_ack = data->sram_pdn_ack_bits;
+ struct mtk_scpsys *scpsys = dev_get_priv(power_domain->dev);
+ struct mtk_scp_domain *domain;
+ const struct mtk_scp_domain_data *data;
+ void __iomem *ctl_addr;
+ void __iomem *infracfg;
+ u32 pdn_ack;
u32 val;
int ret, tmp;
- writel(SPM_EN, scpd->base);
+ if (power_domain->id >= scpsys->soc_data->num_domains)
+ return -EINVAL;
+
+ domain = &scpsys->domains[power_domain->id];
+ data = domain->data;
+ if (!data)
+ return -EINVAL;
+
+ ctl_addr = scpsys->base + data->ctl_offs;
+ infracfg = domain->infracfg ? domain->infracfg : scpsys->infracfg;
+ pdn_ack = data->sram_pdn_ack_bits;
+
+ if (domain->has_pd) {
+ ret = power_domain_on(&domain->parent_pd);
+ if (ret)
+ return ret;
+ }
+
+ ret = clk_enable_bulk(&domain->clks);
+ if (ret)
+ return ret;
+
+ writel(SPM_EN, scpsys->base);
val = readl(ctl_addr);
val |= PWR_ON_BIT;
@@ -227,7 +171,7 @@ static int scpsys_power_on(struct power_domain *power_domain)
val |= PWR_ON_2ND_BIT;
writel(val, ctl_addr);
- ret = readx_poll_timeout(scpsys_domain_is_on, data, tmp, tmp > 0,
+ ret = readx_poll_timeout(mtk_scpsys_domain_is_on, power_domain, tmp, tmp > 0,
100);
if (ret < 0)
return ret;
@@ -241,6 +185,10 @@ static int scpsys_power_on(struct power_domain *power_domain)
val |= PWR_RST_B_BIT;
writel(val, ctl_addr);
+ ret = clk_enable_bulk(&domain->subsys_clks);
+ if (ret)
+ return ret;
+
val &= ~data->sram_pdn_bits;
writel(val, ctl_addr);
@@ -249,31 +197,52 @@ static int scpsys_power_on(struct power_domain *power_domain)
return ret;
if (data->bus_prot_mask) {
- ret = mtk_infracfg_clear_bus_protection(scpd->infracfg,
+ ret = mtk_infracfg_clear_bus_protection(infracfg,
data->bus_prot_mask);
if (ret)
return ret;
}
+ ret = scpsys_bus_protect_disable(data->bp_infracfg, SPM_MAX_BUS_PROT_DATA, infracfg);
+ if (ret < 0)
+ return ret;
return 0;
}
-static int scpsys_power_off(struct power_domain *power_domain)
+static int mtk_scpsys_power_off(struct power_domain *power_domain)
{
- struct scp_domain *scpd = dev_get_priv(power_domain->dev);
- struct scp_domain_data *data = &scpd->data[power_domain->id];
- void __iomem *ctl_addr = scpd->base + data->ctl_offs;
- u32 pdn_ack = data->sram_pdn_ack_bits;
+ struct mtk_scpsys *scpsys = dev_get_priv(power_domain->dev);
+ struct mtk_scp_domain *domain;
+ const struct mtk_scp_domain_data *data;
+ void __iomem *ctl_addr;
+ void __iomem *infracfg;
+ u32 pdn_ack;
u32 val;
int ret, tmp;
+ if (power_domain->id >= scpsys->soc_data->num_domains)
+ return -EINVAL;
+
+ domain = &scpsys->domains[power_domain->id];
+ data = domain->data;
+ if (!data)
+ return -EINVAL;
+
+ ctl_addr = scpsys->base + data->ctl_offs;
+ infracfg = domain->infracfg ?: scpsys->infracfg;
+ pdn_ack = data->sram_pdn_ack_bits;
+
if (data->bus_prot_mask) {
- ret = mtk_infracfg_set_bus_protection(scpd->infracfg,
+ ret = mtk_infracfg_set_bus_protection(infracfg,
data->bus_prot_mask);
if (ret)
return ret;
}
+ ret = scpsys_bus_protect_enable(data->bp_infracfg, SPM_MAX_BUS_PROT_DATA, infracfg);
+ if (ret < 0)
+ return ret;
+
val = readl(ctl_addr);
val |= data->sram_pdn_bits;
writel(val, ctl_addr);
@@ -283,6 +252,10 @@ static int scpsys_power_off(struct power_domain *power_domain)
if (ret < 0)
return ret;
+ ret = clk_disable_bulk(&domain->subsys_clks);
+ if (ret)
+ return ret;
+
val |= PWR_ISO_BIT;
writel(val, ctl_addr);
@@ -298,60 +271,38 @@ static int scpsys_power_off(struct power_domain *power_domain)
val &= ~PWR_ON_2ND_BIT;
writel(val, ctl_addr);
- ret = readx_poll_timeout(scpsys_domain_is_on, data, tmp, !tmp, 100);
+ ret = readx_poll_timeout(mtk_scpsys_domain_is_on, power_domain, tmp, !tmp, 100);
if (ret < 0)
return ret;
- return 0;
-}
-
-static int scpsys_power_request(struct power_domain *power_domain)
-{
- struct scp_domain *scpd = dev_get_priv(power_domain->dev);
- struct scp_domain_data *data;
-
- data = &scpd->data[power_domain->id];
- data->scpd = scpd;
-
- return 0;
-}
-
-static int mtk_power_domain_hook(struct udevice *dev)
-{
- struct scp_domain *scpd = dev_get_priv(dev);
-
- scpd->type = (enum scp_domain_type)dev_get_driver_data(dev);
-
- switch (scpd->type) {
- case SCPSYS_MT7623:
- scpd->data = scp_domain_mt7623;
- break;
- case SCPSYS_MT7622:
- case SCPSYS_MT7629:
- scpd->data = scp_domain_mt7629;
- break;
- default:
- return -EINVAL;
- }
+ ret = clk_disable_bulk(&domain->clks);
+ if (ret)
+ return ret;
return 0;
}
-static int mtk_power_domain_probe(struct udevice *dev)
+int mtk_scpsys_probe(struct udevice *dev)
{
struct ofnode_phandle_args args;
- struct scp_domain *scpd = dev_get_priv(dev);
+ struct mtk_scpsys *scpsys = dev_get_priv(dev);
struct regmap *regmap;
struct clk_bulk bulk;
- int err;
+ int err, i;
- scpd->base = dev_read_addr_ptr(dev);
- if (!scpd->base)
+ scpsys->base = dev_read_addr_ptr(dev);
+ if (!scpsys->base)
return -ENOENT;
- err = mtk_power_domain_hook(dev);
- if (err)
- return err;
+ scpsys->soc_data = (const struct mtk_scp_soc_data *)dev_get_driver_data(dev);
+
+ scpsys->domains = devm_kcalloc(dev, scpsys->soc_data->num_domains,
+ sizeof(*scpsys->domains), GFP_KERNEL);
+ if (!scpsys->domains)
+ return -ENOMEM;
+
+ for (i = 0; i < scpsys->soc_data->num_domains; i++)
+ scpsys->domains[i].data = &scpsys->soc_data->data[i];
/* get corresponding syscon phandle */
err = dev_read_phandle_with_args(dev, "infracfg", NULL, 0, 0, &args);
@@ -362,12 +313,12 @@ static int mtk_power_domain_probe(struct udevice *dev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- scpd->infracfg = regmap_get_range(regmap, 0);
- if (!scpd->infracfg)
+ scpsys->infracfg = regmap_get_range(regmap, 0);
+ if (!scpsys->infracfg)
return -ENOENT;
/* enable Infra DCM */
- setbits_le32(scpd->infracfg + INFRA_TOPDCM_CTRL, DCM_TOP_EN);
+ setbits_le32(scpsys->infracfg + INFRA_TOPDCM_CTRL, DCM_TOP_EN);
err = clk_get_bulk(dev, &bulk);
if (err)
@@ -376,33 +327,180 @@ static int mtk_power_domain_probe(struct udevice *dev)
return clk_enable_bulk(&bulk);
}
-static const struct udevice_id mtk_power_domain_ids[] = {
- {
- .compatible = "mediatek,mt7622-scpsys",
- .data = SCPSYS_MT7622,
- },
- {
- .compatible = "mediatek,mt7623-scpsys",
- .data = SCPSYS_MT7623,
- },
- {
- .compatible = "mediatek,mt7629-scpsys",
- .data = SCPSYS_MT7629,
- },
- { /* sentinel */ }
-};
+static int mtk_scpsys_add_one_domain(struct udevice *dev, ofnode node, int parent_id)
+{
+ struct mtk_scpsys *scpsys = dev_get_priv(dev);
+ struct ofnode_phandle_args args;
+ struct mtk_scp_domain *domain;
+ struct regmap *regmap;
+ const char *clk_name;
+ int i, ret, num_clks;
+ u32 id;
-static const struct power_domain_ops mtk_power_domain_ops = {
- .off = scpsys_power_off,
- .on = scpsys_power_on,
- .request = scpsys_power_request,
-};
+ ret = ofnode_read_u32(node, "reg", &id);
+ if (ret) {
+ dev_err(dev, "%s: failed to retrieve domain id from reg: %d\n",
+ ofnode_get_name(node), ret);
+ return ret;
+ }
+
+ if (id >= scpsys->soc_data->num_domains) {
+ dev_err(dev, "%s: invalid domain id %d\n", ofnode_get_name(node), id);
+ return -EINVAL;
+ }
+
+ domain = &scpsys->domains[id];
+ domain->data = &scpsys->soc_data->data[id];
+
+ if (parent_id >= 0) {
+ domain->has_pd = true;
+ domain->parent_pd.dev = dev;
+ domain->parent_pd.id = parent_id;
+ }
+
+ if (ofnode_read_bool(node, "mediatek,infracfg")) {
+ ret = ofnode_parse_phandle_with_args(node, "mediatek,infracfg", NULL, 0, 0, &args);
+ if (ret)
+ return ret;
+
+ regmap = syscon_node_to_regmap(args.node);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ domain->infracfg = regmap_get_range(regmap, 0);
+
+ /* enable Infra DCM */
+ if (domain->infracfg)
+ setbits_le32(domain->infracfg + INFRA_TOPDCM_CTRL,
+ DCM_TOP_EN);
+ }
+
+ num_clks = ofnode_read_string_count(node, "clock-names");
+ for (i = 0; i < num_clks; i++) {
+ ret = ofnode_read_string_index(node, "clock-names", i, &clk_name);
+ if (ret) {
+ dev_err(dev, "%s: failed to retrieve clock-names at index %i: %d\n",
+ ofnode_get_name(node), i, ret);
+ return ret;
+ }
+
+ if (strchr(clk_name, '-'))
+ domain->subsys_clks.count++;
+ else
+ domain->clks.count++;
+ }
+
+ if (domain->clks.count) {
+ domain->clks.clks = devm_kcalloc(dev, domain->clks.count,
+ sizeof(struct clk), GFP_KERNEL);
+ if (!domain->clks.clks)
+ return -ENOMEM;
+ }
+
+ if (domain->subsys_clks.count) {
+ domain->subsys_clks.clks = devm_kcalloc(dev,
+ domain->subsys_clks.count,
+ sizeof(struct clk), GFP_KERNEL);
+ if (!domain->subsys_clks.clks)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < domain->clks.count; i++) {
+ ret = clk_get_by_index_nodev(node, i, &domain->clks.clks[i]);
+ if (ret < 0) {
+ dev_err(dev, "%s: failed to get clk at index %d: %d\n",
+ ofnode_get_name(node), i, ret);
+ goto err_put_clocks;
+ }
+ }
+
+ for (i = 0; i < domain->subsys_clks.count; i++) {
+ ret = clk_get_by_index_nodev(node, i + domain->clks.count,
+ &domain->subsys_clks.clks[i]);
+ if (ret < 0) {
+ dev_err(dev, "%s: failed to get subsys clk at index %d: %d\n",
+ ofnode_get_name(node), i + domain->clks.count, ret);
+ goto err_put_subsys_clocks;
+ }
+ }
+
+ return 0;
+
+err_put_subsys_clocks:
+ clk_release_all(domain->subsys_clks.clks, domain->subsys_clks.count);
+ domain->subsys_clks.count = 0;
+err_put_clocks:
+ clk_release_all(domain->clks.clks, domain->clks.count);
+ domain->clks.count = 0;
+ domain->data = NULL;
+ return ret;
+}
+
+static int mtk_scpsys_add_subdomain(struct udevice *dev, ofnode node)
+{
+ ofnode subnode;
+ int ret;
+ u32 id;
+
+ ret = ofnode_read_u32(node, "reg", &id);
+ if (ret) {
+ dev_err(dev, "%s: failed to get domain id\n", ofnode_get_name(node));
+ return ret;
+ }
+
+ ofnode_for_each_subnode(subnode, node) {
+ ret = mtk_scpsys_add_one_domain(dev, subnode, id);
+ if (ret) {
+ dev_err(dev, "failed to add child domain: %s\n",
+ ofnode_get_name(subnode));
+ continue;
+ }
+
+ ret = mtk_scpsys_add_subdomain(dev, subnode);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int mtk_power_controller_probe(struct udevice *dev)
+{
+ struct mtk_scpsys *scpsys = dev_get_priv(dev);
+ ofnode subnode;
+ int ret;
+
+ scpsys->base = dev_read_addr_ptr(dev_get_parent(dev));
+ if (!scpsys->base)
+ return -ENOENT;
+
+ scpsys->soc_data = (const struct mtk_scp_soc_data *)dev_get_driver_data(dev);
+
+ scpsys->domains = devm_kcalloc(dev, scpsys->soc_data->num_domains,
+ sizeof(*scpsys->domains), GFP_KERNEL);
+ if (!scpsys->domains)
+ return -ENOMEM;
+
+ dev_for_each_subnode(subnode, dev) {
+ ret = mtk_scpsys_add_one_domain(dev, subnode, -1);
+ if (ret) {
+ dev_err(dev, "failed to add child domain: %s\n",
+ ofnode_get_name(subnode));
+ continue;
+ }
+
+ ret = mtk_scpsys_add_subdomain(dev, subnode);
+ if (ret) {
+ dev_err(dev, "failed to add sub domain: %s\n",
+ ofnode_get_name(subnode));
+ return ret;
+ }
+ }
+
+ return 0;
+}
-U_BOOT_DRIVER(mtk_power_domain) = {
- .name = "mtk_power_domain",
- .id = UCLASS_POWER_DOMAIN,
- .ops = &mtk_power_domain_ops,
- .probe = mtk_power_domain_probe,
- .of_match = mtk_power_domain_ids,
- .priv_auto = sizeof(struct scp_domain),
+const struct power_domain_ops mtk_power_domain_ops = {
+ .off = mtk_scpsys_power_off,
+ .on = mtk_scpsys_power_on,
};
diff --git a/drivers/power/domain/mtk-power-domain.h b/drivers/power/domain/mtk-power-domain.h
new file mode 100644
index 00000000000..5bf0ca850ec
--- /dev/null
+++ b/drivers/power/domain/mtk-power-domain.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Copyright (C) 2026 BayLibre, SAS
+ * Author: Ryder Lee <[email protected]>
+ * Julien Stephan <[email protected]>
+ */
+
+#ifndef __MTK_POWER_DOMAIN_H
+#define __MTK_POWER_DOMAIN_H
+
+#include <clk.h>
+#include <power-domain-uclass.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct udevice;
+
+#define SPM_EN (0xb16 << 16 | 0x1)
+#define SPM_VDE_PWR_CON 0x0210
+#define SPM_MFG_PWR_CON 0x0214
+#define SPM_ISP_PWR_CON 0x0238
+#define SPM_DIS_PWR_CON 0x023c
+#define SPM_CONN_PWR_CON 0x0280
+#define SPM_BDP_PWR_CON 0x029c
+#define SPM_ETH_PWR_CON 0x02a0
+#define SPM_HIF_PWR_CON 0x02a4
+#define SPM_IFR_MSC_PWR_CON 0x02a8
+#define SPM_ETHSYS_PWR_CON 0x2e0
+#define SPM_HIF0_PWR_CON 0x2e4
+#define SPM_HIF1_PWR_CON 0x2e8
+#define SPM_PWR_STATUS 0x60c
+#define SPM_PWR_STATUS_2ND 0x610
+
+#define PWR_RST_B_BIT BIT(0)
+#define PWR_ISO_BIT BIT(1)
+#define PWR_ON_BIT BIT(2)
+#define PWR_ON_2ND_BIT BIT(3)
+#define PWR_CLK_DIS_BIT BIT(4)
+
+#define PWR_STATUS_CONN BIT(1)
+#define PWR_STATUS_DISP BIT(3)
+#define PWR_STATUS_MFG BIT(4)
+#define PWR_STATUS_ISP BIT(5)
+#define PWR_STATUS_VDEC BIT(7)
+#define PWR_STATUS_BDP BIT(14)
+#define PWR_STATUS_ETH BIT(15)
+#define PWR_STATUS_HIF BIT(16)
+#define PWR_STATUS_IFR_MSC BIT(17)
+#define PWR_STATUS_ETHSYS BIT(24)
+#define PWR_STATUS_HIF0 BIT(25)
+#define PWR_STATUS_HIF1 BIT(26)
+
+/* Infrasys configuration */
+#define INFRA_TOPDCM_CTRL 0x10
+#define INFRA_TOPAXI_PROT_EN 0x220
+#define INFRA_TOPAXI_PROT_STA1 0x228
+
+#define DCM_TOP_EN BIT(0)
+
+#define SPM_MAX_BUS_PROT_DATA 6
+
+struct mtk_scp_domain;
+
+struct mtk_scpsys_bus_prot_data {
+ u32 bus_prot_mask;
+ u32 bus_prot_set;
+ u32 bus_prot_clr;
+ u32 bus_prot_sta;
+ bool bus_prot_reg_update;
+ bool ignore_clr_ack;
+};
+
+struct mtk_scp_domain_data {
+ u32 sta_mask;
+ int ctl_offs;
+ u32 sram_pdn_bits;
+ u32 sram_pdn_ack_bits;
+ u32 bus_prot_mask;
+ const struct mtk_scpsys_bus_prot_data bp_infracfg[SPM_MAX_BUS_PROT_DATA];
+ int pwr_sta_offs;
+ int pwr_sta2nd_offs;
+};
+
+struct mtk_scp_soc_data {
+ const struct mtk_scp_domain_data *data;
+ int num_domains;
+};
+
+#define MTK_SCP_SOC_DATA(_name, _domains) \
+static const struct mtk_scp_soc_data _name##_scp_soc_data = { \
+ .data = _domains, \
+ .num_domains = ARRAY_SIZE(_domains), \
+}
+
+struct mtk_scp_domain {
+ const struct mtk_scp_domain_data *data;
+ void __iomem *infracfg;
+ struct clk_bulk clks;
+ struct clk_bulk subsys_clks;
+ bool has_pd;
+ struct power_domain parent_pd;
+};
+
+struct mtk_scpsys {
+ void __iomem *base;
+ void __iomem *infracfg;
+ const struct mtk_scp_soc_data *soc_data;
+ struct mtk_scp_domain *domains;
+};
+
+#define _BUS_PROT(_mask, _set, _clr, _sta, _update, _ignore) { \
+ .bus_prot_mask = (_mask), \
+ .bus_prot_set = (_set), \
+ .bus_prot_clr = (_clr), \
+ .bus_prot_sta = (_sta), \
+ .bus_prot_reg_update = (_update), \
+ .ignore_clr_ack = (_ignore), \
+}
+
+#define BUS_PROT_WR(_mask, _set, _clr, _sta) \
+ _BUS_PROT(_mask, _set, _clr, _sta, false, false)
+
+int mtk_scpsys_probe(struct udevice *dev);
+int mtk_power_controller_probe(struct udevice *dev);
+
+extern const struct power_domain_ops mtk_power_domain_ops;
+
+#endif /* __MTK_POWER_DOMAIN_H */
diff --git a/drivers/power/domain/renesas-r8a78000-power-domain.c b/drivers/power/domain/renesas-r8a78000-power-domain.c
index 57b3b56b2d9..62b56fd8ae0 100644
--- a/drivers/power/domain/renesas-r8a78000-power-domain.c
+++ b/drivers/power/domain/renesas-r8a78000-power-domain.c
@@ -166,6 +166,7 @@ struct rst_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 rst_map_in gen5_rst_map_dt_sdk_4_28[] = {
{ SCP_RESET_DOMAIN_ID_UFS0, 202 },
@@ -220,7 +221,8 @@ static int gen5_reset_of_xlate(struct reset_ctl *reset_ctl,
map = gen5_rst_map_dt_sdk_4_28;
map_size = ARRAY_SIZE(gen5_rst_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_rst_map_dt_sdk_4_31;
map_size = ARRAY_SIZE(gen5_rst_map_dt_sdk_4_31);
} else {
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 4bd9b4e1940..95687d0bdfd 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -171,6 +171,21 @@ config SPL_DM_PMIC_PCA9450
This config enables implementation of driver-model pmic uclass features
for PMIC PCA9450 in SPL. The driver implements read/write operations.
+config DM_PMIC_PF9453
+ bool "Enable Driver Model for PMIC PF9453"
+ depends on DM_I2C
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC PF9453. The driver implements read/write operations.
+
+config SPL_DM_PMIC_PF9453
+ bool "Enable Driver Model for PMIC PF9453 in SPL"
+ depends on SPL_DM_PMIC
+ depends on SPL_DM_I2C
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC PF9453 in SPL. The driver implements read/write operations.
+
config DM_PMIC_PFUZE100
bool "Enable Driver Model for PMIC PFUZE100"
help
@@ -434,6 +449,14 @@ config PMIC_RAA215300
allows register access and will bind the sysreset driver
(CONFIG_SYSRESET_RAA215300) if it is enabled.
+config PMIC_SPACEMIT_P1
+ bool "Enable driver for Spacemit P1 power management chip"
+ depends on DM_PMIC
+ help
+ The P1 PMIC integrates multiple functions including
+ voltage regulators, a watchdog timer, GPIO interfaces, and a
+ real-time clock.
+
config DM_PMIC_MTK_PWRAP
bool "Enable driver for MediaTek PMIC Wrapper Support"
help
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 2cda5a892fd..da9b810de90 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_$(PHASE_)DM_PMIC_BD71837) += bd71837.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_MP5416) += mp5416.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_PFUZE100) += pfuze100.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_PCA9450) += pca9450.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_PF9453) += pf9453.o
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
obj-$(CONFIG_PMIC_AB8500) += ab8500.o
@@ -32,6 +33,7 @@ obj-$(CONFIG_$(PHASE_)DM_PMIC_TPS80031) += tps80031.o
obj-$(CONFIG_$(PHASE_)PMIC_PALMAS) += palmas.o
obj-$(CONFIG_$(PHASE_)PMIC_LP873X) += lp873x.o
obj-$(CONFIG_$(PHASE_)PMIC_LP87565) += lp87565.o
+obj-$(CONFIG_PMIC_SPACEMIT_P1) += pmic_spacemit_p1.o
obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
obj-$(CONFIG_PMIC_TPS65217) += pmic_tps65217.o
obj-$(CONFIG_PMIC_TPS65219) += tps65219.o
diff --git a/drivers/power/pmic/pf9453.c b/drivers/power/pmic/pf9453.c
new file mode 100644
index 00000000000..71d766bce5b
--- /dev/null
+++ b/drivers/power/pmic/pf9453.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <asm/global_data.h>
+#include <asm-generic/gpio.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <i2c.h>
+#include <linux/err.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/pf9453.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+ /* buck */
+ { .prefix = "b", .driver = PF9453_REGULATOR_DRIVER},
+ { .prefix = "B", .driver = PF9453_REGULATOR_DRIVER},
+ /* ldo */
+ { .prefix = "l", .driver = PF9453_REGULATOR_DRIVER},
+ { .prefix = "L", .driver = PF9453_REGULATOR_DRIVER},
+ { },
+};
+
+struct pf9453_priv {
+ struct gpio_desc *sd_vsel_gpio;
+};
+
+static int pf9453_reg_count(struct udevice *dev)
+{
+ return PF9453_REG_NUM;
+}
+
+static bool is_reg_protect(uint reg)
+{
+ switch (reg) {
+ case PF9453_BUCK1OUT:
+ case PF9453_BUCK2OUT:
+ case PF9453_BUCK3OUT:
+ case PF9453_BUCK4OUT:
+ case PF9453_LDO1OUT_L:
+ case PF9453_LDO1OUT_H:
+ case PF9453_LDO2OUT:
+ case PF9453_LDOSNVS_CFG1:
+ case PF9453_BUCK2OUT_MAX_LIMIT:
+ case PF9453_BUCK2OUT_MIN_LIMIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int pf9453_write(struct udevice *dev, uint reg, const uint8_t *buff, int len)
+{
+ bool is_pro;
+ u32 val = PF9453_UNLOCK_KEY;
+
+ is_pro = is_reg_protect(reg);
+ if (is_pro) {
+ if (dm_i2c_write(dev, PF9453_REG_LOCK, (uint8_t *)&val, 1)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ val = PF9453_LOCK_KEY;
+ if (dm_i2c_write(dev, PF9453_REG_LOCK, (uint8_t *)&val, 1)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+ } else {
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int pf9453_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pf9453_bind(struct udevice *dev)
+{
+ int children;
+ ofnode regulators_node;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node,
+ pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static int pf9453_probe(struct udevice *dev)
+{
+ struct pf9453_priv *priv = dev_get_priv(dev);
+ unsigned int reset_ctrl;
+ int ret = 0;
+
+ if (CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(DM_REGULATOR_PF9453)) {
+ priv->sd_vsel_gpio = devm_gpiod_get_optional(dev, "sd-vsel",
+ GPIOD_IS_OUT |
+ GPIOD_IS_OUT_ACTIVE);
+ if (IS_ERR(priv->sd_vsel_gpio)) {
+ ret = PTR_ERR(priv->sd_vsel_gpio);
+ dev_err(dev, "Failed to request SD_VSEL GPIO: %d\n", ret);
+ if (ret)
+ return ret;
+ }
+ }
+
+ if (ofnode_read_bool(dev_ofnode(dev), "nxp,wdog_b-warm-reset"))
+ reset_ctrl = PF9453_PMIC_RESET_WDOG_B_CFG_WARM;
+ else
+ reset_ctrl = PF9453_PMIC_RESET_WDOG_B_CFG_COLD;
+
+ return pmic_clrsetbits(dev, PF9453_RESET_CTRL,
+ PF9453_PMIC_RESET_WDOG_B_CFG_MASK, reset_ctrl);
+}
+
+static struct dm_pmic_ops pf9453_ops = {
+ .reg_count = pf9453_reg_count,
+ .read = pf9453_read,
+ .write = pf9453_write,
+};
+
+static const struct udevice_id pf9453_ids[] = {
+ { .compatible = "nxp,pf9453", .data = NXP_CHIP_TYPE_PF9453, },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_pf9453) = {
+ .name = "pf9453 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = pf9453_ids,
+ .bind = pf9453_bind,
+ .probe = pf9453_probe,
+ .ops = &pf9453_ops,
+ .priv_auto = sizeof(struct pf9453_priv),
+};
diff --git a/drivers/power/pmic/pmic_spacemit_p1.c b/drivers/power/pmic/pmic_spacemit_p1.c
new file mode 100644
index 00000000000..46c5926874c
--- /dev/null
+++ b/drivers/power/pmic/pmic_spacemit_p1.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/spacemit_p1.h>
+
+static int pmic_p1_reg_count(struct udevice *dev)
+{
+ return P1_MAX_REGS;
+}
+
+static int pmic_p1_write(struct udevice *dev, uint reg, const u8 *buffer,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buffer, len);
+ if (ret)
+ pr_err("%s write error on register %02x\n", dev->name, reg);
+
+ return ret;
+}
+
+static int pmic_p1_read(struct udevice *dev, uint reg, u8 *buffer,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buffer, len);
+ if (ret)
+ pr_err("%s read error on register %02x\n", dev->name, reg);
+
+ return ret;
+}
+
+static const struct pmic_child_info p1_children_info[] = {
+ { .prefix = "buck", .driver = P1_BUCK_DRIVER },
+ { .prefix = "aldo", .driver = P1_ALDO_DRIVER },
+ { .prefix = "dldo", .driver = P1_DLDO_DRIVER },
+ { },
+};
+
+static int pmic_p1_bind(struct udevice *dev)
+{
+ const struct pmic_child_info *p1_children_info =
+ (struct pmic_child_info *)dev_get_driver_data(dev);
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s regulators subnode not found\n", dev->name);
+ return -EINVAL;
+ }
+
+ children = pmic_bind_children(dev, regulators_node,
+ p1_children_info);
+ if (!children)
+ debug("%s has no children (regulators)\n", dev->name);
+
+ return 0;
+}
+
+static int pmic_p1_probe(struct udevice *dev)
+{
+ return 0;
+}
+
+static struct dm_pmic_ops pmic_p1_ops = {
+ .reg_count = pmic_p1_reg_count,
+ .read = pmic_p1_read,
+ .write = pmic_p1_write,
+};
+
+static const struct udevice_id pmic_p1_match[] = {
+ {
+ .compatible = "spacemit,p1",
+ .data = (ulong)&p1_children_info,
+ }, {
+ /* sentinel */
+ }
+};
+
+U_BOOT_DRIVER(pmic_p1) = {
+ .name = "pmic_p1",
+ .id = UCLASS_PMIC,
+ .of_match = pmic_p1_match,
+ .bind = pmic_p1_bind,
+ .probe = pmic_p1_probe,
+ .ops = &pmic_p1_ops,
+};
diff --git a/drivers/power/pmic/tps65219.c b/drivers/power/pmic/tps65219.c
index 0716af027a3..1fecde84795 100644
--- a/drivers/power/pmic/tps65219.c
+++ b/drivers/power/pmic/tps65219.c
@@ -55,6 +55,7 @@ static int tps65219_bind(struct udevice *dev)
if (!ofnode_valid(regulators_node)) {
debug("%s: %s regulators subnode not found!\n", __func__,
dev->name);
+ return -ENXIO;
}
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 9f80bb953e8..00a25acfdf9 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -103,6 +103,21 @@ config SPL_DM_REGULATOR_PCA9450
This config enables implementation of driver-model regulator uclass
features for regulators on ROHM PCA9450 in SPL.
+config DM_REGULATOR_PF9453
+ bool "Enable Driver Model for NXP PF9453 regulators"
+ depends on DM_REGULATOR && DM_PMIC_PF9453
+ help
+ This config enables implementation of driver-model regulator uclass
+ features for regulators on NXP PF9453 PMICs. PF9453 contains 6 bucks
+ and 5 LDOS. The driver implements get/set api for value and enable.
+
+config SPL_DM_REGULATOR_PF9453
+ bool "Enable Driver Model for NXP PF9453 regulators in SPL"
+ depends on DM_REGULATOR_PF9453 && SPL
+ help
+ This config enables implementation of driver-model regulator uclass
+ features for regulators on ROHM PF9453 in SPL.
+
config DM_REGULATOR_DA9063
bool "Enable Driver Model for REGULATOR DA9063"
depends on DM_REGULATOR && DM_PMIC_DA9063
@@ -600,3 +615,10 @@ config SANDBOX_PMBUS
(DM_REGULATOR_PMBUS_GENERIC) and the pmbus CLI command can be
exercised by the dm unit tests with no real hardware. Only
useful for testing; say N on real boards.
+
+config DM_REGULATOR_SPACEMIT_P1
+ bool "Enable driver for Spacemit P1 PMIC regulators"
+ depends on DM_REGULATOR && PMIC_SPACEMIT_P1
+ help
+ Enable implementation of driver-model regulator uclass features
+ for regulator P1. The driver supports BUCKs, LDOs and SWITCHes.
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index b8599ea7fd9..a40c9d340d9 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_DM_REGULATOR_NPCM8XX) += npcm8xx_regulator.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PFUZE100) += pfuze100.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_BD71837) += bd71837.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PCA9450) += pca9450.o
+obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PF9453) += pf9453.o
obj-$(CONFIG_$(PHASE_)REGULATOR_PWM) += pwm_regulator.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_COMMON) += regulator_common.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_$(PHASE_)REGULATOR_RK8XX) += rk8xx.o
obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
+obj-$(CONFIG_DM_REGULATOR_SPACEMIT_P1) += spacemit_p1_regulator.o
obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PALMAS) += palmas_regulator.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PBIAS) += pbias_regulator.o
diff --git a/drivers/power/regulator/pf9453.c b/drivers/power/regulator/pf9453.c
new file mode 100644
index 00000000000..6ecde09bafa
--- /dev/null
+++ b/drivers/power/regulator/pf9453.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * NXP PF9453 regulator driver
+ * Copyright 2024 NXP
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <linux/bitops.h>
+#include <power/pf9453.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+/**
+ * struct pf9453_vrange - describe linear range of voltages
+ *
+ * @min_volt: smallest voltage in range
+ * @step: how much voltage changes at each selector step
+ * @min_sel: smallest selector in the range
+ * @max_sel: maximum selector in the range
+ */
+struct pf9453_vrange {
+ unsigned int min_volt;
+ unsigned int step;
+ u8 min_sel;
+ u8 max_sel;
+};
+
+/**
+ * struct pf9453_plat - describe regulator control registers
+ *
+ * @name: name of the regulator. Used for matching the dt-entry
+ * @enable_reg: register address used to enable/disable regulator
+ * @enablemask: register mask used to enable/disable regulator
+ * @volt_reg: register address used to configure regulator voltage
+ * @volt_mask: register mask used to configure regulator voltage
+ * @ranges: pointer to ranges of regulator voltages and matching register
+ * values
+ * @numranges: number of voltage ranges pointed by ranges
+ */
+struct pf9453_plat {
+ const char *name;
+ u8 enable_reg;
+ u8 enablemask;
+ u8 volt_reg;
+ u8 volt_mask;
+ struct pf9453_vrange *ranges;
+ unsigned int numranges;
+};
+
+#define PCA_RANGE(_min, _vstep, _sel_low, _sel_hi) \
+{ \
+ .min_volt = (_min), .step = (_vstep), \
+ .min_sel = (_sel_low), .max_sel = (_sel_hi), \
+}
+
+#define PCA_DATA(_name, enreg, enmask, vreg, vmask, _range, _numranges) \
+{ \
+ .name = (_name), .enable_reg = (enreg), .enablemask = (enmask), \
+ .volt_reg = (vreg), .volt_mask = (vmask), .ranges = (_range), \
+ .numranges = _numranges \
+}
+
+static struct pf9453_vrange pf9453_buck134_vranges[] = {
+ PCA_RANGE(600000, 25000, 0, 0x7f),
+};
+
+static struct pf9453_vrange pf9453_buck2_vranges[] = {
+ PCA_RANGE(600000, 12500, 0, 0x7f),
+};
+
+static struct pf9453_vrange pf9453_ldo1_vranges[] = {
+ PCA_RANGE(800000, 25000, 0x0, 0x64),
+};
+
+static struct pf9453_vrange pf9453_ldo2_vranges[] = {
+ PCA_RANGE(500000, 25000, 0x0, 0x3a),
+};
+
+static struct pf9453_vrange pf9453_ldosnvs_vranges[] = {
+ PCA_RANGE(800000, 25000, 0x0, 0x58),
+};
+
+static struct pf9453_plat pf9453_reg_data[] = {
+ PCA_DATA("BUCK1", PF9453_BUCK1CTRL, PF9453_EN_MODE_MASK,
+ PF9453_BUCK1OUT, PF9453_BUCK_RUN_MASK,
+ pf9453_buck134_vranges, ARRAY_SIZE(pf9453_buck134_vranges)),
+ PCA_DATA("BUCK2", PF9453_BUCK2CTRL, PF9453_EN_MODE_MASK,
+ PF9453_BUCK2OUT, PF9453_BUCK_RUN_MASK,
+ pf9453_buck2_vranges, ARRAY_SIZE(pf9453_buck2_vranges)),
+ PCA_DATA("BUCK3", PF9453_BUCK3CTRL, PF9453_EN_MODE_MASK,
+ PF9453_BUCK3OUT, PF9453_BUCK_RUN_MASK,
+ pf9453_buck134_vranges, ARRAY_SIZE(pf9453_buck134_vranges)),
+ PCA_DATA("BUCK4", PF9453_BUCK4CTRL, PF9453_EN_MODE_MASK,
+ PF9453_BUCK4OUT, PF9453_BUCK_RUN_MASK,
+ pf9453_buck134_vranges, ARRAY_SIZE(pf9453_buck134_vranges)),
+ /* LDOs */
+ PCA_DATA("LDO1", PF9453_LDO1CFG, PF9453_EN_MODE_MASK,
+ PF9453_LDO1OUT_H, PF9453_LDO1_MASK,
+ pf9453_ldo1_vranges, ARRAY_SIZE(pf9453_ldo1_vranges)),
+ PCA_DATA("LDO2", PF9453_LDO2CFG, PF9453_EN_MODE_MASK,
+ PF9453_LDO2OUT, PF9453_LDO2_MASK,
+ pf9453_ldo2_vranges, ARRAY_SIZE(pf9453_ldo2_vranges)),
+ PCA_DATA("LDO-SNVS", PF9453_LDOSNVS_CFG2, PF9453_EN_MODE_MASK,
+ PF9453_LDOSNVS_CFG1, PF9453_LDOSNVS_MASK,
+ pf9453_ldosnvs_vranges, ARRAY_SIZE(pf9453_ldosnvs_vranges)),
+};
+
+static int vrange_find_value(struct pf9453_vrange *r, unsigned int sel,
+ unsigned int *val)
+{
+ if (!val || sel < r->min_sel || sel > r->max_sel)
+ return -EINVAL;
+
+ *val = r->min_volt + r->step * (sel - r->min_sel);
+ return 0;
+}
+
+static int vrange_find_selector(struct pf9453_vrange *r, int val,
+ unsigned int *sel)
+{
+ int ret = -EINVAL;
+ int num_vals = r->max_sel - r->min_sel + 1;
+
+ if (val >= r->min_volt &&
+ val <= r->min_volt + r->step * (num_vals - 1)) {
+ if (r->step) {
+ *sel = r->min_sel + ((val - r->min_volt) / r->step);
+ ret = 0;
+ } else {
+ *sel = r->min_sel;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int pf9453_get_enable(struct udevice *dev)
+{
+ struct pf9453_plat *plat = dev_get_plat(dev);
+ int val;
+
+ val = pmic_reg_read(dev->parent, plat->enable_reg);
+ if (val < 0)
+ return val;
+
+ return (val & plat->enablemask);
+}
+
+static int pf9453_set_enable(struct udevice *dev, bool enable)
+{
+ int val = 0;
+ struct pf9453_plat *plat = dev_get_plat(dev);
+
+ if (enable)
+ val = plat->enablemask;
+
+ return pmic_clrsetbits(dev->parent, plat->enable_reg, plat->enablemask,
+ val);
+}
+
+static int pf9453_get_value(struct udevice *dev)
+{
+ struct pf9453_plat *plat = dev_get_plat(dev);
+ unsigned int reg, tmp;
+ int i, ret;
+
+ ret = pmic_reg_read(dev->parent, plat->volt_reg);
+ if (ret < 0)
+ return ret;
+
+ reg = ret;
+ reg &= plat->volt_mask;
+
+ for (i = 0; i < plat->numranges; i++) {
+ struct pf9453_vrange *r = &plat->ranges[i];
+
+ if (!vrange_find_value(r, reg, &tmp))
+ return tmp;
+ }
+
+ pr_err("Unknown voltage value read from pmic\n");
+
+ return -EINVAL;
+}
+
+static int pf9453_set_value(struct udevice *dev, int uvolt)
+{
+ struct pf9453_plat *plat = dev_get_plat(dev);
+ unsigned int sel;
+ int i, found = 0;
+
+ for (i = 0; i < plat->numranges; i++) {
+ struct pf9453_vrange *r = &plat->ranges[i];
+
+ found = !vrange_find_selector(r, uvolt, &sel);
+ if (found) {
+ unsigned int tmp;
+
+ /*
+ * We require exactly the requested value to be
+ * supported - this can be changed later if needed
+ */
+ found = !vrange_find_value(r, sel, &tmp);
+ if (found && tmp == uvolt)
+ break;
+ found = 0;
+ }
+ }
+
+ if (!found)
+ return -EINVAL;
+
+ return pmic_clrsetbits(dev->parent, plat->volt_reg,
+ plat->volt_mask, sel);
+}
+
+static int pf9453_regulator_probe(struct udevice *dev)
+{
+ struct pf9453_plat *plat = dev_get_plat(dev);
+ int i, type;
+
+ type = dev_get_driver_data(dev_get_parent(dev));
+
+ if (type != NXP_CHIP_TYPE_PF9453) {
+ debug("Unknown PMIC type\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pf9453_reg_data); i++) {
+ if (strcmp(dev->name, pf9453_reg_data[i].name))
+ continue;
+ *plat = pf9453_reg_data[i];
+ return 0;
+ }
+
+ pr_err("Unknown regulator '%s'\n", dev->name);
+
+ return -ENOENT;
+}
+
+static const struct dm_regulator_ops pf9453_regulator_ops = {
+ .get_value = pf9453_get_value,
+ .set_value = pf9453_set_value,
+ .get_enable = pf9453_get_enable,
+ .set_enable = pf9453_set_enable,
+};
+
+U_BOOT_DRIVER(pf9453_regulator) = {
+ .name = PF9453_REGULATOR_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &pf9453_regulator_ops,
+ .probe = pf9453_regulator_probe,
+ .plat_auto = sizeof(struct pf9453_plat),
+};
diff --git a/drivers/power/regulator/spacemit_p1_regulator.c b/drivers/power/regulator/spacemit_p1_regulator.c
new file mode 100644
index 00000000000..7b5eb710edf
--- /dev/null
+++ b/drivers/power/regulator/spacemit_p1_regulator.c
@@ -0,0 +1,464 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#include <dm.h>
+#include <dm/lists.h>
+#include <errno.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/spacemit_p1.h>
+
+struct p1_reg_info {
+ uint min_uv;
+ uint step_uv;
+ u8 vsel_reg;
+ u8 vsel_sleep_reg;
+ u8 config_reg;
+ u8 vsel_mask;
+ u8 min_sel;
+ u8 max_sel;
+};
+
+static const struct p1_reg_info p1_bucks[] = {
+ /* BUCK 1 */
+ { 500000, 5000, P1_BUCK_VSEL(1), P1_BUCK_SVSEL(1), P1_BUCK_CTRL(1),
+ BUCK_VSEL_MASK, 0x00, 0xaa },
+ { 1375000, 25000, P1_BUCK_VSEL(1), P1_BUCK_SVSEL(1), P1_BUCK_CTRL(1),
+ BUCK_VSEL_MASK, 0xab, 0xfe },
+ /* BUCK 2 */
+ { 500000, 5000, P1_BUCK_VSEL(2), P1_BUCK_SVSEL(2), P1_BUCK_CTRL(2),
+ BUCK_VSEL_MASK, 0x00, 0xaa },
+ { 1375000, 25000, P1_BUCK_VSEL(2), P1_BUCK_SVSEL(2), P1_BUCK_CTRL(2),
+ BUCK_VSEL_MASK, 0xab, 0xfe },
+ /* BUCK 3 */
+ { 500000, 5000, P1_BUCK_VSEL(3), P1_BUCK_SVSEL(3), P1_BUCK_CTRL(3),
+ BUCK_VSEL_MASK, 0x00, 0xaa },
+ { 1375000, 25000, P1_BUCK_VSEL(3), P1_BUCK_SVSEL(3), P1_BUCK_CTRL(3),
+ BUCK_VSEL_MASK, 0xab, 0xfe },
+ /* BUCK 4 */
+ { 500000, 5000, P1_BUCK_VSEL(4), P1_BUCK_SVSEL(4), P1_BUCK_CTRL(4),
+ BUCK_VSEL_MASK, 0x00, 0xaa },
+ { 1375000, 25000, P1_BUCK_VSEL(4), P1_BUCK_SVSEL(4), P1_BUCK_CTRL(4),
+ BUCK_VSEL_MASK, 0xab, 0xfe },
+ /* BUCK 5 */
+ { 500000, 5000, P1_BUCK_VSEL(5), P1_BUCK_SVSEL(5), P1_BUCK_CTRL(5),
+ BUCK_VSEL_MASK, 0x00, 0xaa },
+ { 1375000, 25000, P1_BUCK_VSEL(5), P1_BUCK_SVSEL(5), P1_BUCK_CTRL(5),
+ BUCK_VSEL_MASK, 0xab, 0xfe },
+ /* BUCK 6 */
+ { 500000, 5000, P1_BUCK_VSEL(6), P1_BUCK_SVSEL(6), P1_BUCK_CTRL(6),
+ BUCK_VSEL_MASK, 0x00, 0xaa },
+ { 1375000, 25000, P1_BUCK_VSEL(6), P1_BUCK_SVSEL(6), P1_BUCK_CTRL(6),
+ BUCK_VSEL_MASK, 0xab, 0xfe },
+};
+
+static const struct p1_reg_info p1_aldos[] = {
+ /* ALDO 1 */
+ { 500000, 25000, P1_ALDO_VOLT(1), P1_ALDO_SVOLT(1), P1_ALDO_CTRL(1),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* ALDO 2 */
+ { 500000, 25000, P1_ALDO_VOLT(2), P1_ALDO_SVOLT(2), P1_ALDO_CTRL(2),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* ALDO 3 */
+ { 500000, 25000, P1_ALDO_VOLT(3), P1_ALDO_SVOLT(3), P1_ALDO_CTRL(3),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* ALDO 4 */
+ { 500000, 25000, P1_ALDO_VOLT(4), P1_ALDO_SVOLT(4), P1_ALDO_CTRL(4),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+};
+
+static const struct p1_reg_info p1_dldos[] = {
+ /* DLDO 1 */
+ { 500000, 25000, P1_DLDO_VOLT(1), P1_DLDO_SVOLT(1), P1_DLDO_CTRL(1),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* DLDO 2 */
+ { 500000, 25000, P1_DLDO_VOLT(2), P1_DLDO_SVOLT(2), P1_DLDO_CTRL(2),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* DLDO 3 */
+ { 500000, 25000, P1_DLDO_VOLT(3), P1_DLDO_SVOLT(3), P1_DLDO_CTRL(3),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* DLDO 4 */
+ { 500000, 25000, P1_DLDO_VOLT(4), P1_DLDO_SVOLT(4), P1_DLDO_CTRL(4),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* DLDO 5 */
+ { 500000, 25000, P1_DLDO_VOLT(5), P1_DLDO_SVOLT(5), P1_DLDO_CTRL(5),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* DLDO 6 */
+ { 500000, 25000, P1_DLDO_VOLT(6), P1_DLDO_SVOLT(6), P1_DLDO_CTRL(6),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+ /* DLDO 7 */
+ { 500000, 25000, P1_DLDO_VOLT(7), P1_DLDO_SVOLT(7), P1_DLDO_CTRL(7),
+ ALDO_VSEL_MASK, 0x0b, 0x7f },
+};
+
+static const struct p1_reg_info *get_buck_reg(struct udevice *pmic,
+ int idx, int uvolt)
+{
+ if (idx < 0)
+ return NULL;
+ if (uvolt < 1375000)
+ return &p1_bucks[(idx - 1) * 2 + 0];
+ return &p1_bucks[(idx - 1) * 2 + 1];
+}
+
+static const struct p1_reg_info *get_aldo_reg(struct udevice *pmic,
+ int idx, int uvolt)
+{
+ if (idx < 1 || idx > ARRAY_SIZE(p1_aldos))
+ return NULL;
+ return &p1_aldos[idx - 1];
+}
+
+static const struct p1_reg_info *get_dldo_reg(struct udevice *pmic,
+ int idx, int uvolt)
+{
+ if (idx < 1 || idx > ARRAY_SIZE(p1_dldos))
+ return NULL;
+ return &p1_dldos[idx - 1];
+}
+
+static int buck_get_value(struct udevice *dev)
+{
+ const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ if (!ops || !ops->read)
+ return -ENOSYS;
+
+ info = get_buck_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+ ret = pmic_reg_read(dev->parent, info->vsel_reg);
+ if (ret < 0)
+ return ret;
+ val = ret & info->vsel_mask;
+ while (val > info->max_sel)
+ info++;
+
+ return info->min_uv + (val - info->min_sel) * info->step_uv;
+}
+
+static int buck_set_value(struct udevice *dev, int uvolt)
+{
+ const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ if (!ops || !ops->write)
+ return -ENOSYS;
+
+ info = get_buck_reg(dev->parent, dev->driver_data, uvolt);
+ if (!info)
+ return -ENOENT;
+ val = (uvolt - info->min_uv);
+ val = val / info->step_uv;
+ val += info->min_sel;
+ ret = pmic_reg_write(dev->parent, info->vsel_reg, val);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int buck_get_enable(struct udevice *dev)
+{
+ const struct p1_reg_info *info;
+ int ret;
+
+ info = get_buck_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->config_reg);
+ if (ret < 0)
+ return ret;
+ return ret & BUCK_EN_MASK;
+}
+
+static int buck_set_enable(struct udevice *dev, bool enable)
+{
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ info = get_buck_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->config_reg);
+ if (ret < 0)
+ return ret;
+ val = (unsigned int)ret;
+ val &= BUCK_EN_MASK;
+
+ if (enable == val)
+ return 0;
+
+ val = enable;
+ ret = pmic_clrsetbits(dev->parent, info->config_reg, BUCK_EN_MASK, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct dm_regulator_ops p1_buck_ops = {
+ .get_value = buck_get_value,
+ .set_value = buck_set_value,
+ .get_enable = buck_get_enable,
+ .set_enable = buck_set_enable,
+};
+
+static int p1_buck_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata;
+
+ uc_pdata = dev_get_uclass_plat(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_BUCK;
+ uc_pdata->mode_count = 0;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(p1_buck) = {
+ .name = P1_BUCK_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &p1_buck_ops,
+ .probe = p1_buck_probe,
+};
+
+static int aldo_get_value(struct udevice *dev)
+{
+ const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ if (!ops || !ops->read)
+ return -ENOSYS;
+
+ info = get_aldo_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->vsel_reg);
+ if (ret < 0)
+ return ret;
+
+ val = ret & info->vsel_mask;
+ while (val > info->max_sel)
+ info++;
+
+ return info->min_uv + (val - info->min_sel) * info->step_uv;
+}
+
+static int aldo_set_value(struct udevice *dev, int uvolt)
+{
+ const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ if (!ops || !ops->write)
+ return -ENOSYS;
+
+ info = get_aldo_reg(dev->parent, dev->driver_data, uvolt);
+ if (!info)
+ return -ENOENT;
+ val = (uvolt - info->min_uv);
+ val = val / info->step_uv;
+ val += info->min_sel;
+ ret = pmic_reg_write(dev->parent, info->vsel_reg, val);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int aldo_get_enable(struct udevice *dev)
+{
+ const struct p1_reg_info *info;
+ int ret;
+
+ info = get_aldo_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->config_reg);
+ if (ret < 0)
+ return ret;
+ return ret & ALDO_EN_MASK;
+}
+
+static int aldo_set_enable(struct udevice *dev, bool enable)
+{
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ info = get_aldo_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->config_reg);
+ if (ret < 0)
+ return ret;
+ val = (unsigned int)ret;
+ val &= ALDO_EN_MASK;
+
+ if (enable == val)
+ return 0;
+
+ val = enable;
+ ret = pmic_clrsetbits(dev->parent, info->config_reg, ALDO_EN_MASK, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct dm_regulator_ops p1_aldo_ops = {
+ .get_value = aldo_get_value,
+ .set_value = aldo_set_value,
+ .get_enable = aldo_get_enable,
+ .set_enable = aldo_set_enable,
+};
+
+static int p1_aldo_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata;
+
+ uc_pdata = dev_get_uclass_plat(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_LDO;
+ uc_pdata->mode_count = 0;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(p1_aldo) = {
+ .name = P1_ALDO_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &p1_aldo_ops,
+ .probe = p1_aldo_probe,
+};
+
+static int dldo_get_value(struct udevice *dev)
+{
+ const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ if (!ops || !ops->read)
+ return -ENOSYS;
+
+ info = get_dldo_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->vsel_reg);
+ if (ret < 0)
+ return ret;
+
+ val = ret & info->vsel_mask;
+ while (val > info->max_sel)
+ info++;
+
+ return info->min_uv + (val - info->min_sel) * info->step_uv;
+}
+
+static int dldo_set_value(struct udevice *dev, int uvolt)
+{
+ const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ if (!ops || !ops->write)
+ return -ENOSYS;
+
+ info = get_dldo_reg(dev->parent, dev->driver_data, uvolt);
+ if (!info)
+ return -ENOENT;
+ val = (uvolt - info->min_uv);
+ val = val / info->step_uv;
+ val += info->min_sel;
+ ret = pmic_reg_write(dev->parent, info->vsel_reg, val);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int dldo_get_enable(struct udevice *dev)
+{
+ const struct p1_reg_info *info;
+ int ret;
+
+ info = get_dldo_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->config_reg);
+ if (ret < 0)
+ return ret;
+ return ret & DLDO_EN_MASK;
+}
+
+static int dldo_set_enable(struct udevice *dev, bool enable)
+{
+ const struct p1_reg_info *info;
+ uint val;
+ int ret;
+
+ info = get_dldo_reg(dev->parent, dev->driver_data, 0);
+ if (!info)
+ return -ENOENT;
+
+ ret = pmic_reg_read(dev->parent, info->config_reg);
+ if (ret < 0)
+ return ret;
+ val = (unsigned int)ret;
+ val &= DLDO_EN_MASK;
+
+ if (enable == val)
+ return 0;
+
+ val = enable;
+ ret = pmic_clrsetbits(dev->parent, info->config_reg, DLDO_EN_MASK, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct dm_regulator_ops p1_dldo_ops = {
+ .get_value = dldo_get_value,
+ .set_value = dldo_set_value,
+ .get_enable = dldo_get_enable,
+ .set_enable = dldo_set_enable,
+};
+
+static int p1_dldo_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata;
+
+ uc_pdata = dev_get_uclass_plat(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_LDO;
+ uc_pdata->mode_count = 0;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(p1_dldo) = {
+ .name = P1_DLDO_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &p1_dldo_ops,
+ .probe = p1_dldo_probe,
+};
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index cfbfa1252d0..acd6d9cfd6a 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -121,6 +121,7 @@ config IMXRT_SDRAM
config K3_INLINE_ECC
bool "Enable TI Inline ECC support"
depends on K3_DDRSS
+ select FDT_64BIT
help
Enable Inline ECC support on K3 platforms. 1/9th of the SDRAM space
is used for ECC storage and the rest 8/9th is available for system
diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index 5144470b931..c406998b20a 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -931,11 +931,10 @@ static int k3_ddrss_probe(struct udevice *dev)
struct k3_ddrss_ecc_region *r = range;
for (int i = 0; (i < K3_DDRSS_MAX_ECC_REG) && (r->range != 0); i++, r++) {
- end = r->start + r->range;
ddr_ram_size = ddrss->ddr_ram_size;
ecc_res = ddrss->ecc_reserved_space;
- if (end > (ddr_ram_size - ecc_res))
+ if (r->range > (ddr_ram_size - ecc_res))
ddrss->ecc_regions[i].range = ddr_ram_size - ecc_res;
else
ddrss->ecc_regions[i].range = r->range;
diff --git a/drivers/remoteproc/renesas_rsip.c b/drivers/remoteproc/renesas_rsip.c
index 76ccaf93b1a..c71424a2c16 100644
--- a/drivers/remoteproc/renesas_rsip.c
+++ b/drivers/remoteproc/renesas_rsip.c
@@ -13,6 +13,7 @@
#include <linux/sizes.h>
#include <malloc.h>
#include <remoteproc.h>
+#include <reset.h>
/* R-Car X5H contains 1 SCP core, 6 lockstep Cortex-R52 and 32 Cortex-A720AE cores. */
#define RCAR5_SCP_CORES 1
@@ -20,6 +21,9 @@
#define RCAR5_CA720_CORES 32
#define SCP_BASE 0xc1340000
+#define SCP_CFGVECTABLE (SCP_BASE + 0x0)
+#define SCP_CFGNSSTCALIB (SCP_BASE + 0x10)
+#define SCP_CFGNSSTCALIB_13_3MHZ 0x010040f0
#define SCP_CPUWAIT (SCP_BASE + 0x30)
#define SCP_CPUWAIT_WAIT BIT(0)
#define SCP_STCM 0xc1000000
@@ -96,26 +100,59 @@ static void scp_send_interrupt(void)
* This must be removed when proper upstream SCP port exists
*/
#define SCMI_PD_POWER_STATE_SET_BOOTADDR 0x4411
+#define SCMI_PD_POWER_STATE_SET_STATE_ON 0
+#define SCMI_PD_POWER_STATE_SET_STATE_OFF BIT(30)
+#define SCMI_PD_POWER_STATE_GET 0x4405
/**
- * scp_cpu_core_start() - Boot CPU core by invoking SCP via SCMI
+ * scp_cpu_core_id_to_domain() - Convert core ID to SCMI domain ID
+ * @core: CPU core
+ * @domain: SCMI domain
+ */
+static int scp_cpu_core_id_to_domain(const u32 core, u32 *domain)
+{
+ if (core >= RCAR5_SCP_CORES && core < RCAR5_SCP_CORES + RCAR5_CR52_CORES) {
+ /* CR52 */
+ *domain = core - RCAR5_SCP_CORES + SCMI_PD_CORE_RT_CORE00;
+ return 0;
+ }
+
+ if (core >= RCAR5_SCP_CORES + RCAR5_CR52_CORES &&
+ core < RCAR5_SCP_CORES + RCAR5_CR52_CORES + RCAR5_CA720_CORES) {
+ /* CA720 */
+ *domain = core - RCAR5_SCP_CORES - RCAR5_CR52_CORES + SCMI_PD_CORE_AP_CORE00;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * scp_cpu_core_set() - Start or stop CPU core by invoking SCP via SCMI
* @core: CPU core to boot
* @ep: Entry point
+ * @state: Power state, 0: Power on, BIT(30): Power off
*/
-static void scp_cpu_core_start(const u32 core, const u32 ep)
+static int scp_cpu_core_set(const u32 core, const u32 ep, const u32 state)
{
struct scp_scmi_shmem *shmem = (struct scp_scmi_shmem *)SCP_SCMI_SHMEM_AREA09;
struct scp_scmi_pd_power_state_set_a2p scmi_parameter = {
.flags = 1, /* Asynchronous power transition using APMU */
- .domain_id = core,
- .power_state = 0, /* Power on */
+ .domain_id = 0, /* Core ID */
+ .power_state = state, /* 0: Power on, BIT(30): Power off */
.boot_addr = ep,
};
u32 status;
+ int ret;
+
+ ret = scp_cpu_core_id_to_domain(core, &scmi_parameter.domain_id);
+ if (ret)
+ return ret;
/* Wait for SCP to be free, then set it busy */
scp_wait_fw_free();
shmem->status &= ~SCP_SCMI_STATUS_FREE;
+ shmem->flags = 0;
/* Set up the message and copy it to SHMEM */
shmem->message_header = SCMI_PD_POWER_STATE_SET_BOOTADDR;
@@ -128,8 +165,59 @@ static void scp_cpu_core_start(const u32 core, const u32 ep)
/* Read back the result */
status = readl((uintptr_t)shmem->payload);
- if (status)
- printf("SCP POWER_STATE_SET failed, status=0x%x\n", status);
+ if (status) {
+ printf("SCP POWER_STATE_SET domain %d failed, status=0x%x (%d)\n",
+ scmi_parameter.domain_id, status, status);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * scp_cpu_core_get() - Get CPU core state by invoking SCP via SCMI
+ * @core: CPU core to get
+ */
+static int scp_cpu_core_get(const u32 core)
+{
+ struct scp_scmi_shmem *shmem = (struct scp_scmi_shmem *)SCP_SCMI_SHMEM_AREA09;
+ u32 status, pwr;
+ u32 domain_id; /* Core ID */
+ int ret;
+
+ ret = scp_cpu_core_id_to_domain(core, &domain_id);
+ if (ret)
+ return ret;
+
+ /* Wait for SCP to be free, then set it busy */
+ scp_wait_fw_free();
+ shmem->status &= ~SCP_SCMI_STATUS_FREE;
+ shmem->flags = 0;
+
+ /* Set up the message and copy it to SHMEM */
+ shmem->message_header = SCMI_PD_POWER_STATE_GET;
+ memcpy(shmem->payload, &domain_id, sizeof(domain_id));
+ shmem->length = sizeof(shmem->message_header) + sizeof(domain_id);
+
+ /* Send message to SCP and wait for completion */
+ scp_send_interrupt();
+ scp_wait_fw_free();
+
+ /* Read back the result */
+ status = readl((uintptr_t)shmem->payload);
+ if (status) {
+ printf("SCP POWER_STATE_GET domain %d failed, status=0x%x (%d)\n",
+ domain_id, status, status);
+ return -EINVAL;
+ }
+
+ pwr = readl((uintptr_t)(shmem->payload + 4));
+ if (pwr == SCMI_PD_POWER_STATE_SET_STATE_ON)
+ return 0;
+ else if (pwr == SCMI_PD_POWER_STATE_SET_STATE_OFF)
+ return 1;
+ else
+ return -EINVAL;
}
/**
@@ -163,6 +251,42 @@ static int renesas_rsip_rproc_load(struct udevice *dev, ulong addr, ulong size)
}
/**
+ * renesas_rsip_rproc_init() - Initialize the remote processor
+ * @dev: corresponding remote processor device
+ *
+ * Return: 0 if all went ok, else corresponding -ve error
+ */
+static int renesas_rsip_rproc_init(struct udevice *dev)
+{
+ struct renesas_rsip_rproc_privdata *priv = dev_get_priv(dev);
+ struct reset_ctl *rst = dev_get_priv(dev->parent);
+ u32 addr;
+
+ if (priv->core_id != 0) /* No init for non-SCP cores */
+ return 0;
+
+ /*
+ * Put SCP into reset, configure SCP entry point address and systick
+ * timer, release SCP from reset, and zero out SCP STCM regions.
+ */
+ reset_assert(rst);
+
+ writel(SCP_STCM, SCP_CFGVECTABLE);
+ writel(SCP_CFGNSSTCALIB_13_3MHZ, SCP_CFGNSSTCALIB);
+ setbits_le32(SCP_CPUWAIT, SCP_CPUWAIT_WAIT);
+
+ reset_deassert(rst);
+
+ /* Fill zero to SCP STCM regions 0 ... 27 */
+ for (addr = SCP_STCM; addr < 0xc1061b00; addr += 8)
+ writeq(0, addr);
+
+ asm volatile("dsb sy");
+
+ return 0;
+}
+
+/**
* renesas_rsip_rproc_start() - Start the remote processor
* @dev: corresponding remote processor device
*
@@ -171,27 +295,16 @@ static int renesas_rsip_rproc_load(struct udevice *dev, ulong addr, ulong size)
static int renesas_rsip_rproc_start(struct udevice *dev)
{
struct renesas_rsip_rproc_privdata *priv = dev_get_priv(dev);
- int scmi_core;
if (priv->core_id == 0) {
/* SCP */
clrbits_le32(SCP_CPUWAIT, SCP_CPUWAIT_WAIT);
return 0;
- } else if (priv->core_id >= RCAR5_SCP_CORES &&
- priv->core_id < RCAR5_SCP_CORES + RCAR5_CR52_CORES) {
- /* CR52 */
- scmi_core = priv->core_id - RCAR5_SCP_CORES +
- SCMI_PD_CORE_RT_CORE00;
- } else if (priv->core_id >= RCAR5_SCP_CORES + RCAR5_CR52_CORES &&
- priv->core_id < RCAR5_SCP_CORES + RCAR5_CR52_CORES + RCAR5_CA720_CORES) {
- /* CA720 */
- scmi_core = priv->core_id - RCAR5_SCP_CORES - RCAR5_CR52_CORES +
- SCMI_PD_CORE_AP_CORE00;
+ } else {
+ /* CR52 or CA720 */
+ return scp_cpu_core_set(priv->core_id, priv->ep,
+ SCMI_PD_POWER_STATE_SET_STATE_ON);
}
-
- scp_cpu_core_start(scmi_core, priv->ep);
-
- return 0;
}
/**
@@ -204,12 +317,14 @@ static int renesas_rsip_rproc_stop(struct udevice *dev)
{
struct renesas_rsip_rproc_privdata *priv = dev_get_priv(dev);
- if (priv->core_id == 0) { /* SCP */
- setbits_le32(SCP_CPUWAIT, SCP_CPUWAIT_WAIT);
- return 0;
+ if (priv->core_id == 0) {
+ /* SCP */
+ return renesas_rsip_rproc_init(dev);
+ } else {
+ /* CR52 or CA720 */
+ return scp_cpu_core_set(priv->core_id, 0,
+ SCMI_PD_POWER_STATE_SET_STATE_OFF);
}
-
- return 0;
}
/**
@@ -233,19 +348,15 @@ static int renesas_rsip_rproc_reset(struct udevice *dev)
*/
static int renesas_rsip_rproc_is_running(struct udevice *dev)
{
- /* We assume the core is stopped. */
- return 1;
-}
+ struct renesas_rsip_rproc_privdata *priv = dev_get_priv(dev);
-/**
- * renesas_rsip_rproc_init() - Initialize the remote processor
- * @dev: corresponding remote processor device
- *
- * Return: 0 if all went ok, else corresponding -ve error
- */
-static int renesas_rsip_rproc_init(struct udevice *dev)
-{
- return 0;
+ if (priv->core_id == 0) {
+ /* SCP */
+ return readl(SCP_CPUWAIT) & SCP_CPUWAIT_WAIT;
+ } else {
+ /* CR52 or CA720 */
+ return scp_cpu_core_get(priv->core_id);
+ }
}
/**
@@ -297,6 +408,19 @@ U_BOOT_DRIVER(renesas_rsip_core) = {
};
/**
+ * renesas_rsip_rproc_probe() - Common rproc driver probe
+ * @dev: corresponding remote processor parent device
+ *
+ * Return: 0 if all went ok, else corresponding -ve error
+ */
+static int renesas_rsip_rproc_probe(struct udevice *parent)
+{
+ struct reset_ctl *rst = dev_get_priv(parent);
+
+ return reset_get_by_index(parent, 0, rst);
+}
+
+/**
* renesas_rsip_rproc_bind() - Bind rproc driver to each core control
* @dev: corresponding remote processor parent device
*
@@ -355,4 +479,6 @@ U_BOOT_DRIVER(renesas_rsip_rproc) = {
.of_match = renesas_rsip_rproc_ids,
.id = UCLASS_NOP,
.bind = renesas_rsip_rproc_bind,
+ .probe = renesas_rsip_rproc_probe,
+ .priv_auto = sizeof(struct reset_ctl),
};
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c851354c7a5..db764ed5ace 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -279,12 +279,5 @@ config RESET_RZG2L_USBPHY_CTRL
RZ/G2L SoC. This is required for USB 2.0 functionality to work on this
SoC.
-config RESET_SPACEMIT_K1
- bool "Support for SPACEMIT's K1 Reset driver"
- depends on DM_RESET
- help
- Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert
- is supported.
-
source "drivers/reset/stm32/Kconfig"
endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 3fce96509cd..384f4336331 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_RESET_DRA7) += reset-dra7.o
obj-$(CONFIG_RESET_AT91) += reset-at91.o
obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o
obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
-obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o
+obj-$(CONFIG_CLK_SPACEMIT_K1) += spacemit/
obj-$(CONFIG_ARCH_STM32) += stm32/
obj-$(CONFIG_ARCH_STM32MP) += stm32/
diff --git a/drivers/reset/reset-spacemit-k1.c b/drivers/reset/reset-spacemit-k1.c
deleted file mode 100644
index 613e002fc4f..00000000000
--- a/drivers/reset/reset-spacemit-k1.c
+++ /dev/null
@@ -1,548 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2022 Spacemit Inc.
- * Copyright (C) 2025 Huan Zhou <[email protected]>
- */
-
-#include <asm/io.h>
-#include <config.h>
-#include <dm.h>
-#include <dm/device_compat.h>
-#include <dm/device-internal.h>
-#include <dm/lists.h>
-#include <dt-bindings/reset/spacemit-k1-reset.h>
-#include <linux/bitops.h>
-#include <reset-uclass.h>
-
-/* APBC register offset */
-#define APBC_UART1_CLK_RST 0x0
-#define APBC_UART2_CLK_RST 0x4
-#define APBC_GPIO_CLK_RST 0x8
-#define APBC_PWM0_CLK_RST 0xc
-#define APBC_PWM1_CLK_RST 0x10
-#define APBC_PWM2_CLK_RST 0x14
-#define APBC_PWM3_CLK_RST 0x18
-#define APBC_TWSI8_CLK_RST 0x20
-#define APBC_UART3_CLK_RST 0x24
-#define APBC_RTC_CLK_RST 0x28
-#define APBC_TWSI0_CLK_RST 0x2c
-#define APBC_TWSI1_CLK_RST 0x30
-#define APBC_TIMERS1_CLK_RST 0x34
-#define APBC_TWSI2_CLK_RST 0x38
-#define APBC_AIB_CLK_RST 0x3c
-#define APBC_TWSI4_CLK_RST 0x40
-#define APBC_TIMERS2_CLK_RST 0x44
-#define APBC_ONEWIRE_CLK_RST 0x48
-#define APBC_TWSI5_CLK_RST 0x4c
-#define APBC_DRO_CLK_RST 0x58
-#define APBC_IR_CLK_RST 0x5c
-#define APBC_TWSI6_CLK_RST 0x60
-#define APBC_TWSI7_CLK_RST 0x68
-#define APBC_TSEN_CLK_RST 0x6c
-
-#define APBC_UART4_CLK_RST 0x70
-#define APBC_UART5_CLK_RST 0x74
-#define APBC_UART6_CLK_RST 0x78
-#define APBC_SSP3_CLK_RST 0x7c
-
-#define APBC_SSPA0_CLK_RST 0x80
-#define APBC_SSPA1_CLK_RST 0x84
-
-#define APBC_IPC_AP2AUD_CLK_RST 0x90
-#define APBC_UART7_CLK_RST 0x94
-#define APBC_UART8_CLK_RST 0x98
-#define APBC_UART9_CLK_RST 0x9c
-
-#define APBC_CAN0_CLK_RST 0xa0
-#define APBC_PWM4_CLK_RST 0xa8
-#define APBC_PWM5_CLK_RST 0xac
-#define APBC_PWM6_CLK_RST 0xb0
-#define APBC_PWM7_CLK_RST 0xb4
-#define APBC_PWM8_CLK_RST 0xb8
-#define APBC_PWM9_CLK_RST 0xbc
-#define APBC_PWM10_CLK_RST 0xc0
-#define APBC_PWM11_CLK_RST 0xc4
-#define APBC_PWM12_CLK_RST 0xc8
-#define APBC_PWM13_CLK_RST 0xcc
-#define APBC_PWM14_CLK_RST 0xd0
-#define APBC_PWM15_CLK_RST 0xd4
-#define APBC_PWM16_CLK_RST 0xd8
-#define APBC_PWM17_CLK_RST 0xdc
-#define APBC_PWM18_CLK_RST 0xe0
-#define APBC_PWM19_CLK_RST 0xe4
-/* end of APBC register offset */
-
-/* MPMU register offset */
-#define MPMU_WDTPCR 0x200
-/* end of MPMU register offset */
-
-/* APMU register offset */
-#define APMU_JPG_CLK_RES_CTRL 0x20
-#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x24
-#define APMU_ISP_CLK_RES_CTRL 0x38
-#define APMU_LCD_CLK_RES_CTRL1 0x44
-#define APMU_LCD_SPI_CLK_RES_CTRL 0x48
-#define APMU_LCD_CLK_RES_CTRL2 0x4c
-#define APMU_CCIC_CLK_RES_CTRL 0x50
-#define APMU_SDH0_CLK_RES_CTRL 0x54
-#define APMU_SDH1_CLK_RES_CTRL 0x58
-#define APMU_USB_CLK_RES_CTRL 0x5c
-#define APMU_QSPI_CLK_RES_CTRL 0x60
-#define APMU_USB_CLK_RES_CTRL 0x5c
-#define APMU_DMA_CLK_RES_CTRL 0x64
-#define APMU_AES_CLK_RES_CTRL 0x68
-#define APMU_VPU_CLK_RES_CTRL 0xa4
-#define APMU_GPU_CLK_RES_CTRL 0xcc
-#define APMU_SDH2_CLK_RES_CTRL 0xe0
-#define APMU_PMUA_MC_CTRL 0xe8
-#define APMU_PMU_CC2_AP 0x100
-#define APMU_PMUA_EM_CLK_RES_CTRL 0x104
-
-#define APMU_AUDIO_CLK_RES_CTRL 0x14c
-#define APMU_HDMI_CLK_RES_CTRL 0x1B8
-
-#define APMU_PCIE_CLK_RES_CTRL_0 0x3cc
-#define APMU_PCIE_CLK_RES_CTRL_1 0x3d4
-#define APMU_PCIE_CLK_RES_CTRL_2 0x3dc
-
-#define APMU_EMAC0_CLK_RES_CTRL 0x3e4
-#define APMU_EMAC1_CLK_RES_CTRL 0x3ec
-/* end of APMU register offset */
-
-/* APBC2 register offset */
-#define APBC2_UART1_CLK_RST 0x00
-#define APBC2_SSP2_CLK_RST 0x04
-#define APBC2_TWSI3_CLK_RST 0x08
-#define APBC2_RTC_CLK_RST 0x0c
-#define APBC2_TIMERS0_CLK_RST 0x10
-#define APBC2_KPC_CLK_RST 0x14
-#define APBC2_GPIO_CLK_RST 0x1c
-/* end of APBC2 register offset */
-
-enum spacemit_reset_base_type {
- RST_BASE_TYPE_MPMU = 0,
- RST_BASE_TYPE_APMU = 1,
- RST_BASE_TYPE_APBC = 2,
- RST_BASE_TYPE_APBS = 3,
- RST_BASE_TYPE_CIU = 4,
- RST_BASE_TYPE_DCIU = 5,
- RST_BASE_TYPE_DDRC = 6,
- RST_BASE_TYPE_AUDC = 7,
- RST_BASE_TYPE_APBC2 = 8,
-};
-
-struct spacemit_reset_signal {
- u32 offset;
- u32 mask;
- u32 deassert_val;
- u32 assert_val;
- enum spacemit_reset_base_type type;
-};
-
-struct spacemit_reset_base {
- void __iomem *mpmu_base;
- void __iomem *apmu_base;
- void __iomem *apbc_base;
- void __iomem *apbs_base;
- void __iomem *ciu_base;
- void __iomem *dciu_base;
- void __iomem *ddrc_base;
- void __iomem *audio_ctrl_base;
- void __iomem *apbc2_base;
-};
-
-struct spacemit_reset {
- struct spacemit_reset_base io_base;
- const struct spacemit_reset_signal *signals;
-};
-
-enum {
- RESET_TWSI6_SPL = 0,
- RESET_TWSI8_SPL,
- RESET_SDH_AXI_SPL,
- RESET_SDH0_SPL,
- RESET_USB_AXI_SPL,
- RESET_USBP1_AXI_SPL,
- RESET_USB3_0_SPL,
- RESET_QSPI_SPL,
- RESET_QSPI_BUS_SPL,
- RESET_AES_SPL,
- RESET_SDH2_SPL,
- RESET_NUMBER_SPL
-};
-
-static const struct spacemit_reset_signal
- k1_reset_signals[RESET_NUMBER] = {
- [RESET_UART1] = { APBC_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART2] = { APBC_UART2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_GPIO] = { APBC_GPIO_CLK_RST, BIT(2), 0,
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM0] = { APBC_PWM0_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM1] = { APBC_PWM1_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM2] = { APBC_PWM2_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM3] = { APBC_PWM3_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM4] = { APBC_PWM4_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM5] = { APBC_PWM5_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM6] = { APBC_PWM6_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM7] = { APBC_PWM7_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM8] = { APBC_PWM8_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM9] = { APBC_PWM9_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM10] = { APBC_PWM10_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM11] = { APBC_PWM11_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM12] = { APBC_PWM12_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM13] = { APBC_PWM13_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM14] = { APBC_PWM14_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM15] = { APBC_PWM15_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM16] = { APBC_PWM16_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM17] = { APBC_PWM17_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM18] = { APBC_PWM18_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM19] = { APBC_PWM19_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_SSP3] = { APBC_SSP3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART3] = { APBC_UART3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_RTC] = { APBC_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI0] = { APBC_TWSI0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TIMERS1] = { APBC_TIMERS1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_AIB] = { APBC_AIB_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TIMERS2] = { APBC_TIMERS2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_ONEWIRE] = { APBC_ONEWIRE_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_SSPA0] = { APBC_SSPA0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_SSPA1] = { APBC_SSPA1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_DRO] = { APBC_DRO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_IR] = { APBC_IR_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI1] = { APBC_TWSI1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TSEN] = { APBC_TSEN_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI2] = { APBC_TWSI2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI4] = { APBC_TWSI4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI5] = { APBC_TWSI5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI6] = { APBC_TWSI6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI7] = { APBC_TWSI7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI8] = { APBC_TWSI8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_IPC_AP2AUD] = { APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART4] = { APBC_UART4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART5] = { APBC_UART5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART6] = { APBC_UART6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART7] = { APBC_UART7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART8] = { APBC_UART8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART9] = { APBC_UART9_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_CAN0] = { APBC_CAN0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- /* MPMU */
- [RESET_WDT] = { MPMU_WDTPCR, BIT(2), 0, BIT(2), RST_BASE_TYPE_MPMU },
- /* APMU */
- [RESET_JPG] = { APMU_JPG_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_CSI] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC2_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL,
- BIT(2),
- BIT(2),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_CCIC3_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL,
- BIT(29),
- BIT(29),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_ISP] = { APMU_ISP_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_AHB] = { APMU_ISP_CLK_RES_CTRL, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_CI] = { APMU_ISP_CLK_RES_CTRL, BIT(16), BIT(16), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_CPP] = { APMU_ISP_CLK_RES_CTRL, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD] = { APMU_LCD_CLK_RES_CTRL1, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_DSI_ESC] = { APMU_LCD_CLK_RES_CTRL1, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
- [RESET_V2D] = { APMU_LCD_CLK_RES_CTRL1, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
- [RESET_MIPI] = { APMU_LCD_CLK_RES_CTRL1, BIT(15), BIT(15), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI_BUS] = { APMU_LCD_SPI_CLK_RES_CTRL,
- BIT(4),
- BIT(4),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI_HBUS] = { APMU_LCD_SPI_CLK_RES_CTRL,
- BIT(2),
- BIT(2),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_LCD_MCLK] = { APMU_LCD_CLK_RES_CTRL2, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC_4X] = { APMU_CCIC_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC1_PHY] = { APMU_CCIC_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH_AXI] = { APMU_SDH0_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH0] = { APMU_SDH0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH1] = { APMU_SDH1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_USB_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_USBP1_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_USB3_0] = { APMU_USB_CLK_RES_CTRL,
- BIT(9) | BIT(10) | BIT(11),
- BIT(9) | BIT(10) | BIT(11),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_QSPI] = { APMU_QSPI_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_QSPI_BUS] = { APMU_QSPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_DMA] = { APMU_DMA_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_AES] = { APMU_AES_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_VPU] = { APMU_VPU_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_GPU] = { APMU_GPU_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH2] = { APMU_SDH2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_MC] = { APMU_PMUA_MC_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_EM_AXI] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_EM] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_AUDIO_SYS] = { APMU_AUDIO_CLK_RES_CTRL,
- BIT(0) | BIT(2) | BIT(3),
- BIT(0) | BIT(2) | BIT(3),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_HDMI] = { APMU_HDMI_CLK_RES_CTRL, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
- [RESET_PCIE0] = { APMU_PCIE_CLK_RES_CTRL_0,
- BIT(3) | BIT(4) | BIT(5) | BIT(8),
- BIT(3) | BIT(4) | BIT(5),
- BIT(8),
- RST_BASE_TYPE_APMU },
- [RESET_PCIE1] = { APMU_PCIE_CLK_RES_CTRL_1,
- BIT(3) | BIT(4) | BIT(5) | BIT(8),
- BIT(3) | BIT(4) | BIT(5),
- BIT(8),
- RST_BASE_TYPE_APMU },
- [RESET_PCIE2] = { APMU_PCIE_CLK_RES_CTRL_2, 0x138, 0x38, 0x100, RST_BASE_TYPE_APMU },
- [RESET_EMAC0] = { APMU_EMAC0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_EMAC1] = { APMU_EMAC1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SEC_UART1] = { APBC2_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_SSP2] = { APBC2_SSP2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_TWSI3] = { APBC2_TWSI3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_RTC] = { APBC2_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_TIMERS0] = { APBC2_TIMERS0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_KPC] = { APBC2_KPC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_GPIO] = { APBC2_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- };
-
-static u32 spacemit_reset_read(struct spacemit_reset *reset, u32 id)
-{
- void __iomem *base;
-
- switch (reset->signals[id].type) {
- case RST_BASE_TYPE_APMU:
- base = reset->io_base.apmu_base;
- break;
- case RST_BASE_TYPE_APBC:
- base = reset->io_base.apbc_base;
- break;
- default:
- base = reset->io_base.apbc_base;
- break;
- }
-
- return readl(base + reset->signals[id].offset);
-}
-
-static void spacemit_reset_write(struct spacemit_reset *reset, u32 value, u32 id)
-{
- void __iomem *base;
-
- switch (reset->signals[id].type) {
- case RST_BASE_TYPE_APMU:
- base = reset->io_base.apmu_base;
- break;
- case RST_BASE_TYPE_APBC:
- base = reset->io_base.apbc_base;
- break;
- default:
- base = reset->io_base.apbc_base;
- break;
- }
-
- writel(value, base + reset->signals[id].offset);
-}
-
-static void spacemit_reset_set(struct reset_ctl *rst, u32 id, bool assert)
-{
- u32 value;
- struct spacemit_reset *reset = dev_get_priv(rst->dev);
-
- value = spacemit_reset_read(reset, id);
-
- if (assert) {
- value &= ~reset->signals[id].mask;
- value |= reset->signals[id].assert_val;
- } else {
- value &= ~reset->signals[id].mask;
- value |= reset->signals[id].deassert_val;
- }
-
- spacemit_reset_write(reset, value, id);
-}
-
-static int spacemit_reset_update(struct reset_ctl *rst, bool assert)
-{
- if (rst->id < RESET_UART1 || rst->id >= RESET_NUMBER)
- return 0;
-
- /* can not write to twsi8 */
- if (rst->id == RESET_TWSI8)
- return 0;
-
- spacemit_reset_set(rst, rst->id, assert);
- return 0;
-}
-
-static int spacemit_reset_assert(struct reset_ctl *rst)
-{
- return spacemit_reset_update(rst, true);
-}
-
-static int spacemit_reset_deassert(struct reset_ctl *rst)
-{
- return spacemit_reset_update(rst, false);
-}
-
-static int spacemit_k1_reset_probe(struct udevice *dev)
-{
- struct spacemit_reset *reset = dev_get_priv(dev);
-
- reset->io_base.mpmu_base = (void *)dev_remap_addr_index(dev, 0);
- if (!reset->io_base.mpmu_base) {
- pr_err("failed to map mpmu registers\n");
- goto out;
- }
-
- reset->io_base.apmu_base = (void *)dev_remap_addr_index(dev, 1);
- if (!reset->io_base.apmu_base) {
- pr_err("failed to map apmu registers\n");
- goto out;
- }
-
- reset->io_base.apbc_base = (void *)dev_remap_addr_index(dev, 2);
- if (!reset->io_base.apbc_base) {
- pr_err("failed to map apbc registers\n");
- goto out;
- }
-
- reset->io_base.apbs_base = (void *)dev_remap_addr_index(dev, 3);
- if (!reset->io_base.apbs_base) {
- pr_err("failed to map apbs registers\n");
- goto out;
- }
-
- reset->io_base.ciu_base = (void *)dev_remap_addr_index(dev, 4);
- if (!reset->io_base.ciu_base) {
- pr_err("failed to map ciu registers\n");
- goto out;
- }
-
- reset->io_base.dciu_base = (void *)dev_remap_addr_index(dev, 5);
- if (!reset->io_base.dciu_base) {
- pr_err("failed to map dragon ciu registers\n");
- goto out;
- }
-
- reset->io_base.ddrc_base = (void *)dev_remap_addr_index(dev, 6);
- if (!reset->io_base.ddrc_base) {
- pr_err("failed to map ddrc registers\n");
- goto out;
- }
-
- reset->io_base.apbc2_base = (void *)dev_remap_addr_index(dev, 7);
- if (!reset->io_base.apbc2_base) {
- pr_err("failed to map apbc2 registers\n");
- goto out;
- }
-
- reset->signals = k1_reset_signals;
-
-out:
- return 0;
-}
-
-const struct reset_ops k1_reset_ops = {
- .rst_assert = spacemit_reset_assert,
- .rst_deassert = spacemit_reset_deassert,
-};
-
-static const struct udevice_id k1_reset_ids[] = {
- { .compatible = "spacemit,k1-reset", },
- {},
-};
-
-U_BOOT_DRIVER(k1_reset) = {
- .name = "spacemit,k1-reset",
- .id = UCLASS_RESET,
- .ops = &k1_reset_ops,
- .of_match = k1_reset_ids,
- .probe = spacemit_k1_reset_probe,
- .priv_auto = sizeof(struct spacemit_reset),
-};
diff --git a/drivers/reset/spacemit/Makefile b/drivers/reset/spacemit/Makefile
new file mode 100644
index 00000000000..16722c68954
--- /dev/null
+++ b/drivers/reset/spacemit/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# SpacemiT reset drivers
+
+obj-y += reset-spacemit-k1.o
diff --git a/drivers/reset/spacemit/reset-spacemit-k1.c b/drivers/reset/spacemit/reset-spacemit-k1.c
new file mode 100644
index 00000000000..129e1cc96f1
--- /dev/null
+++ b/drivers/reset/spacemit/reset-spacemit-k1.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SpacemiT K1 reset driver (syscon-bound).
+ *
+ * Copyright (C) 2022 Spacemit Inc.
+ * Copyright (C) 2025 Huan Zhou <[email protected]>
+ * Copyright (C) 2026 RISCstar Ltd.
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/spacemit,k1-syscon.h>
+#include <linux/bitops.h>
+#include <malloc.h>
+#include <reset-uclass.h>
+#include <soc/spacemit/k1-reset.h>
+#include <soc/spacemit/k1-syscon.h>
+
+/* ===================================================================
+ * Per-syscon reset signal tables.
+ *
+ * Indexed by the kernel-side per-syscon-local IDs from
+ * <dt-bindings/clock/spacemit,k1-syscon.h>. Each entry is
+ * (offset, assert_mask, deassert_mask): bits in assert_mask are set
+ * when the reset line is asserted; bits in deassert_mask are set when
+ * deasserted; the union (assert_mask | deassert_mask) is the set of
+ * bits the controller will overwrite on each transition.
+ *
+ * Layout mirrors the kernel-side K1 reset driver.
+ * ===================================================================
+ */
+
+struct spacemit_k1_reset_data {
+ u32 offset;
+ u32 assert_mask;
+ u32 deassert_mask;
+};
+
+#define RESET_DATA(o, a, d) { \
+ .offset = (o), .assert_mask = (a), .deassert_mask = (d) \
+}
+
+static const struct spacemit_k1_reset_data k1_mpmu_resets[] = {
+ [RESET_WDT] = RESET_DATA(MPMU_WDTPCR, BIT(2), 0),
+};
+
+static const struct spacemit_k1_reset_data k1_apbc_resets[] = {
+ [RESET_UART0] = RESET_DATA(APBC_UART1_CLK_RST, BIT(2), 0),
+ [RESET_UART2] = RESET_DATA(APBC_UART2_CLK_RST, BIT(2), 0),
+ [RESET_UART3] = RESET_DATA(APBC_UART3_CLK_RST, BIT(2), 0),
+ [RESET_UART4] = RESET_DATA(APBC_UART4_CLK_RST, BIT(2), 0),
+ [RESET_UART5] = RESET_DATA(APBC_UART5_CLK_RST, BIT(2), 0),
+ [RESET_UART6] = RESET_DATA(APBC_UART6_CLK_RST, BIT(2), 0),
+ [RESET_UART7] = RESET_DATA(APBC_UART7_CLK_RST, BIT(2), 0),
+ [RESET_UART8] = RESET_DATA(APBC_UART8_CLK_RST, BIT(2), 0),
+ [RESET_UART9] = RESET_DATA(APBC_UART9_CLK_RST, BIT(2), 0),
+ [RESET_GPIO] = RESET_DATA(APBC_GPIO_CLK_RST, BIT(2), 0),
+ [RESET_PWM0] = RESET_DATA(APBC_PWM0_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM1] = RESET_DATA(APBC_PWM1_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM2] = RESET_DATA(APBC_PWM2_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM3] = RESET_DATA(APBC_PWM3_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM4] = RESET_DATA(APBC_PWM4_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM5] = RESET_DATA(APBC_PWM5_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM6] = RESET_DATA(APBC_PWM6_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM7] = RESET_DATA(APBC_PWM7_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM8] = RESET_DATA(APBC_PWM8_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM9] = RESET_DATA(APBC_PWM9_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM10] = RESET_DATA(APBC_PWM10_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM11] = RESET_DATA(APBC_PWM11_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM12] = RESET_DATA(APBC_PWM12_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM13] = RESET_DATA(APBC_PWM13_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM14] = RESET_DATA(APBC_PWM14_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM15] = RESET_DATA(APBC_PWM15_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM16] = RESET_DATA(APBC_PWM16_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM17] = RESET_DATA(APBC_PWM17_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM18] = RESET_DATA(APBC_PWM18_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM19] = RESET_DATA(APBC_PWM19_CLK_RST, BIT(2), BIT(0)),
+ [RESET_SSP3] = RESET_DATA(APBC_SSP3_CLK_RST, BIT(2), 0),
+ [RESET_RTC] = RESET_DATA(APBC_RTC_CLK_RST, BIT(2), 0),
+ [RESET_TWSI0] = RESET_DATA(APBC_TWSI0_CLK_RST, BIT(2), 0),
+ [RESET_TWSI1] = RESET_DATA(APBC_TWSI1_CLK_RST, BIT(2), 0),
+ [RESET_TWSI2] = RESET_DATA(APBC_TWSI2_CLK_RST, BIT(2), 0),
+ [RESET_TWSI4] = RESET_DATA(APBC_TWSI4_CLK_RST, BIT(2), 0),
+ [RESET_TWSI5] = RESET_DATA(APBC_TWSI5_CLK_RST, BIT(2), 0),
+ [RESET_TWSI6] = RESET_DATA(APBC_TWSI6_CLK_RST, BIT(2), 0),
+ [RESET_TWSI7] = RESET_DATA(APBC_TWSI7_CLK_RST, BIT(2), 0),
+ [RESET_TWSI8] = RESET_DATA(APBC_TWSI8_CLK_RST, BIT(2), 0),
+ [RESET_TIMERS1] = RESET_DATA(APBC_TIMERS1_CLK_RST, BIT(2), 0),
+ [RESET_TIMERS2] = RESET_DATA(APBC_TIMERS2_CLK_RST, BIT(2), 0),
+ [RESET_AIB] = RESET_DATA(APBC_AIB_CLK_RST, BIT(2), 0),
+ [RESET_ONEWIRE] = RESET_DATA(APBC_ONEWIRE_CLK_RST, BIT(2), 0),
+ [RESET_SSPA0] = RESET_DATA(APBC_SSPA0_CLK_RST, BIT(2), 0),
+ [RESET_SSPA1] = RESET_DATA(APBC_SSPA1_CLK_RST, BIT(2), 0),
+ [RESET_DRO] = RESET_DATA(APBC_DRO_CLK_RST, BIT(2), 0),
+ [RESET_IR] = RESET_DATA(APBC_IR_CLK_RST, BIT(2), 0),
+ [RESET_TSEN] = RESET_DATA(APBC_TSEN_CLK_RST, BIT(2), 0),
+ [RESET_IPC_AP2AUD] = RESET_DATA(APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0),
+ [RESET_CAN0] = RESET_DATA(APBC_CAN0_CLK_RST, BIT(2), 0),
+};
+
+static const struct spacemit_k1_reset_data k1_apmu_resets[] = {
+ [RESET_CCIC_4X] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_CCIC1_PHY] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_SDH_AXI] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_SDH0] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_SDH1] = RESET_DATA(APMU_SDH1_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_SDH2] = RESET_DATA(APMU_SDH2_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_USBP1_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_USB_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_USB30_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(9)),
+ [RESET_USB30_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(10)),
+ [RESET_USB30_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(11)),
+ [RESET_QSPI] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_QSPI_BUS] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_DMA] = RESET_DATA(APMU_DMA_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AES] = RESET_DATA(APMU_AES_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_VPU] = RESET_DATA(APMU_VPU_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_GPU] = RESET_DATA(APMU_GPU_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMMC] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMMC_X] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AUDIO_SYS] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AUDIO_MCU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_AUDIO_APMU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(3)),
+ [RESET_HDMI] = RESET_DATA(APMU_HDMI_CLK_RES_CTRL, 0, BIT(9)),
+ [RESET_PCIE0_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(3)),
+ [RESET_PCIE0_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(4)),
+ [RESET_PCIE0_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(5)),
+ [RESET_PCIE0_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, BIT(8), 0),
+ [RESET_PCIE1_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(3)),
+ [RESET_PCIE1_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(4)),
+ [RESET_PCIE1_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(5)),
+ [RESET_PCIE1_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, BIT(8), 0),
+ [RESET_PCIE2_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(3)),
+ [RESET_PCIE2_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(4)),
+ [RESET_PCIE2_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(5)),
+ [RESET_PCIE2_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, BIT(8), 0),
+ [RESET_EMAC0] = RESET_DATA(APMU_EMAC0_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMAC1] = RESET_DATA(APMU_EMAC1_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_JPG] = RESET_DATA(APMU_JPG_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_CCIC2PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_CCIC3PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(29)),
+ [RESET_CSI] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_ISP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_ISP_CPP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(27)),
+ [RESET_ISP_BUS] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(3)),
+ [RESET_ISP_CI] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(16)),
+ [RESET_DPU_MCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL2, 0, BIT(9)),
+ [RESET_DPU_ESC] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(3)),
+ [RESET_DPU_HCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(4)),
+ [RESET_DPU_SPIBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_DPU_SPI_HBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_V2D] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(27)),
+ [RESET_MIPI] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(15)),
+ [RESET_MC] = RESET_DATA(APMU_PMUA_MC_CTRL, 0, BIT(0)),
+};
+
+static const struct spacemit_k1_reset_data k1_apbc2_resets[] = {
+ [RESET_APBC2_UART1] = RESET_DATA(APBC2_UART1_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_SSP2] = RESET_DATA(APBC2_SSP2_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_TWSI3] = RESET_DATA(APBC2_TWSI3_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_RTC] = RESET_DATA(APBC2_RTC_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_TIMERS0] = RESET_DATA(APBC2_TIMERS0_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_KPC] = RESET_DATA(APBC2_KPC_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_GPIO] = RESET_DATA(APBC2_GPIO_CLK_RST, BIT(2), 0),
+};
+
+/* ===================================================================
+ * Driver
+ * ===================================================================
+ */
+
+struct spacemit_k1_reset_priv {
+ void __iomem *base;
+ const struct spacemit_k1_reset_data *table;
+ size_t table_size;
+};
+
+static int spacemit_k1_reset_xfer(struct reset_ctl *rst, bool assert)
+{
+ struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev);
+ const struct spacemit_k1_reset_data *e;
+ u32 v;
+
+ if (rst->id >= priv->table_size)
+ return -EINVAL;
+
+ e = &priv->table[rst->id];
+ if (e->assert_mask == 0 && e->deassert_mask == 0)
+ return -EINVAL; /* not owned by this syscon */
+
+ v = readl(priv->base + e->offset);
+ v &= ~(e->assert_mask | e->deassert_mask);
+ v |= assert ? e->assert_mask : e->deassert_mask;
+ writel(v, priv->base + e->offset);
+
+ return 0;
+}
+
+static int spacemit_k1_reset_assert(struct reset_ctl *rst)
+{
+ return spacemit_k1_reset_xfer(rst, true);
+}
+
+static int spacemit_k1_reset_deassert(struct reset_ctl *rst)
+{
+ return spacemit_k1_reset_xfer(rst, false);
+}
+
+static int spacemit_k1_reset_request(struct reset_ctl *rst)
+{
+ struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev);
+
+ return rst->id < priv->table_size ? 0 : -EINVAL;
+}
+
+static const struct reset_ops spacemit_k1_reset_ops = {
+ .request = spacemit_k1_reset_request,
+ .rst_assert = spacemit_k1_reset_assert,
+ .rst_deassert = spacemit_k1_reset_deassert,
+};
+
+static int spacemit_k1_reset_probe(struct udevice *dev)
+{
+ struct spacemit_k1_reset_priv *priv = dev_get_priv(dev);
+
+ priv->base = (void __iomem *)dev_remap_addr(dev);
+ if (!priv->base)
+ return -ENODEV;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(spacemit_k1_reset) = {
+ .name = "spacemit_k1_reset",
+ .id = UCLASS_RESET,
+ .ops = &spacemit_k1_reset_ops,
+ .probe = spacemit_k1_reset_probe,
+ .priv_auto = sizeof(struct spacemit_k1_reset_priv),
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_k1_reset_bind(struct udevice *parent,
+ enum spacemit_k1_reset_syscon syscon)
+{
+ struct spacemit_k1_reset_priv *priv;
+ struct udevice *rst_dev;
+ const struct spacemit_k1_reset_data *table;
+ size_t table_size;
+ int ret;
+
+ switch (syscon) {
+ case SPACEMIT_K1_RESET_MPMU:
+ table = k1_mpmu_resets;
+ table_size = ARRAY_SIZE(k1_mpmu_resets);
+ break;
+ case SPACEMIT_K1_RESET_APMU:
+ table = k1_apmu_resets;
+ table_size = ARRAY_SIZE(k1_apmu_resets);
+ break;
+ case SPACEMIT_K1_RESET_APBC:
+ table = k1_apbc_resets;
+ table_size = ARRAY_SIZE(k1_apbc_resets);
+ break;
+ case SPACEMIT_K1_RESET_APBC2:
+ table = k1_apbc2_resets;
+ table_size = ARRAY_SIZE(k1_apbc2_resets);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = device_bind_driver_to_node(parent, "spacemit_k1_reset", "reset",
+ dev_ofnode(parent), &rst_dev);
+ if (ret)
+ return ret;
+
+ priv = malloc(sizeof(*priv));
+ if (!priv) {
+ device_unbind(rst_dev);
+ return -ENOMEM;
+ }
+ priv->table = table;
+ priv->table_size = table_size;
+ dev_set_priv(rst_dev, priv);
+
+ return 0;
+}
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
index 19b2b707677..bacb026308b 100644
--- a/drivers/rng/Kconfig
+++ b/drivers/rng/Kconfig
@@ -23,6 +23,13 @@ config RNG_MESON
Enable support for hardware random number generator
of Amlogic Meson SoCs.
+config RNG_MPFS
+ bool "Microchip PolarFire SoC Random Number Generator support"
+ depends on DM_RNG && MPFS_SYSCONTROLLER
+ help
+ Enable support for hardware random number generator
+ of Microchip's PolarFire SoCs.
+
config RNG_SANDBOX
bool "Sandbox random number generator"
depends on SANDBOX
diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile
index 30c58272d41..50622d4705f 100644
--- a/drivers/rng/Makefile
+++ b/drivers/rng/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_$(PHASE_)DM_RNG) += rng-uclass.o
obj-$(CONFIG_RNG_MESON) += meson-rng.o
+obj-$(CONFIG_RNG_MPFS) += mpfs_rng.o
obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o
obj-$(CONFIG_RNG_MSM) += msm_rng.o
obj-$(CONFIG_RNG_NPCM) += npcm_rng.o
diff --git a/drivers/rng/jh7110_rng.c b/drivers/rng/jh7110_rng.c
index eb21afe4e7c..d54898c67f6 100644
--- a/drivers/rng/jh7110_rng.c
+++ b/drivers/rng/jh7110_rng.c
@@ -233,9 +233,9 @@ static int starfive_trng_of_to_plat(struct udevice *dev)
{
struct starfive_trng_plat *pdata = dev_get_plat(dev);
- pdata->base = (void *)dev_read_addr(dev);
+ pdata->base = dev_read_addr_ptr(dev);
if (!pdata->base)
- return -ENODEV;
+ return -EINVAL;
pdata->hclk = devm_clk_get(dev, "hclk");
if (IS_ERR(pdata->hclk))
diff --git a/drivers/rng/mpfs_rng.c b/drivers/rng/mpfs_rng.c
new file mode 100644
index 00000000000..820103a0202
--- /dev/null
+++ b/drivers/rng/mpfs_rng.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Microchip's PolarFire SoC (MPFS) System Controller Driver
+ *
+ * Copyright (C) 2026 Microchip Technology Inc. All rights reserved.
+ *
+ * Author: Jamie Gibbons <[email protected]>
+ *
+ */
+
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/printk.h>
+#include <mailbox.h>
+#include <malloc.h>
+#include <mpfs-mailbox.h>
+#include <rng.h>
+#include <string.h>
+
+#define CMD_OPCODE 0x21
+#define CMD_DATA_SIZE 0U
+#define CMD_DATA NULL
+#define MBOX_OFFSET 0U
+#define RESP_OFFSET 0U
+#define RNG_RESP_BYTES 32U
+
+/**
+ * struct mpfs_rng_priv - Structure representing System Controller data.
+ * @mpfs_syscontroller_priv: System Controller
+ */
+struct mpfs_rng_priv {
+ struct mpfs_syscontroller_priv *sys_controller;
+};
+
+static int mpfs_rng_read(struct udevice *dev, void *data, size_t len)
+{
+ struct mpfs_rng_priv *rng_priv = dev_get_priv(dev);
+ u32 response_msg[RNG_RESP_BYTES / sizeof(u32)];
+ size_t count = 0, copy_size;
+ int ret;
+
+ struct mpfs_mss_response response = {
+ .resp_status = 0U,
+ .resp_msg = (u32 *)response_msg,
+ .resp_size = RNG_RESP_BYTES,
+ };
+ struct mpfs_mss_msg msg = {
+ .cmd_opcode = CMD_OPCODE,
+ .cmd_data_size = CMD_DATA_SIZE,
+ .response = &response,
+ .cmd_data = CMD_DATA,
+ .mbox_offset = MBOX_OFFSET,
+ .resp_offset = RESP_OFFSET,
+ };
+
+ while (count < len) {
+ ret = mpfs_syscontroller_run_service(rng_priv->sys_controller, &msg);
+ if (ret)
+ return ret;
+
+ ret = mpfs_syscontroller_recv_response(rng_priv->sys_controller, &msg, 1000);
+ if (ret)
+ return ret;
+
+ copy_size = (len - count > RNG_RESP_BYTES) ? RNG_RESP_BYTES : (len - count);
+ memcpy((u8 *)data + count, response_msg, copy_size);
+ count += copy_size;
+ }
+
+ return 0;
+}
+
+static int mpfs_rng_probe(struct udevice *dev)
+{
+ struct mpfs_rng_priv *rng_priv = dev_get_priv(dev);
+
+ rng_priv->sys_controller = mpfs_syscontroller_get(dev->parent);
+ if (IS_ERR(rng_priv->sys_controller)) {
+ dev_err(dev, "Failed to get system controller\n");
+ return PTR_ERR(rng_priv->sys_controller);
+ }
+
+ return 0;
+}
+
+static const struct dm_rng_ops mpfs_rng_ops = {
+ .read = mpfs_rng_read,
+};
+
+U_BOOT_DRIVER(mpfs_rng) = {
+ .name = "mpfs_rng",
+ .id = UCLASS_RNG,
+ .probe = mpfs_rng_probe,
+ .priv_auto = sizeof(struct mpfs_rng_priv),
+ .ops = &mpfs_rng_ops,
+};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6fb3019a644..5b44cc99c97 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -296,6 +296,13 @@ config SPL_RTC_SANDBOX
emulator and is used to test the RTC uclasses and associated code,
as well as the I2C subsystem.
+config RTC_SNVS
+ bool "Enable i.MX SNVS RTC driver"
+ depends on DM_RTC
+ help
+ Enable i.MX RTC driver. This driver supports the RTC that is present
+ on various NXP i.MX SoCs.
+
config RTC_STM32
bool "Enable STM32 RTC driver"
depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 782f5a3bc3d..742481ce185 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_RTC_RV8803) += rv8803.o
obj-$(CONFIG_RTC_RX8025) += rx8025.o
obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
obj-$(CONFIG_RTC_S35392A) += s35392a.o
+obj-$(CONFIG_RTC_SNVS) += snvs-rtc.o
obj-$(CONFIG_RTC_STM32) += stm32_rtc.o
obj-$(CONFIG_$(PHASE_)RTC_SANDBOX) += sandbox_rtc.o
obj-$(CONFIG_RTC_ABX80X) += abx80x.o
diff --git a/drivers/rtc/pcf8563.c b/drivers/rtc/pcf8563.c
index 03bef68051b..b20666e8b4a 100644
--- a/drivers/rtc/pcf8563.c
+++ b/drivers/rtc/pcf8563.c
@@ -16,6 +16,7 @@
#include <log.h>
#include <rtc.h>
#include <i2c.h>
+#include <linux/errno.h>
#if !CONFIG_IS_ENABLED(DM_RTC)
static uchar rtc_read (uchar reg);
@@ -144,7 +145,7 @@ static int pcf8563_rtc_get(struct udevice *dev, struct rtc_time *tmp)
if (sec & 0x80) {
puts("### Warning: RTC Low Voltage - date/time not reliable\n");
- rel = -1;
+ rel = -EINVAL;
}
tmp->tm_sec = bcd2bin(sec & 0x7F);
@@ -213,6 +214,7 @@ static const struct rtc_ops pcf8563_rtc_ops = {
static const struct udevice_id pcf8563_rtc_ids[] = {
{ .compatible = "nxp,pcf8563" },
+ { .compatible = "haoyu,hym8563" },
{ }
};
diff --git a/drivers/rtc/snvs-rtc.c b/drivers/rtc/snvs-rtc.c
new file mode 100644
index 00000000000..c1b4fa0f8da
--- /dev/null
+++ b/drivers/rtc/snvs-rtc.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018-2026 INIT GmbH, Alexander Koch <[email protected]>
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <linux/bitops.h>
+#include <linux/iopoll.h>
+#include <malloc.h>
+#include <rtc.h>
+
+#define SNVS_LPSRTCMR 0x1c
+#define SNVS_LPSRTCLR 0x20
+#define SNVS_LPCR 0x04
+#define SNVS_LPCR_SRTC_ENV BIT(0)
+#define CNTR_TO_SECS_SH 15
+
+struct snvs_rtc_priv {
+ fdt_addr_t base;
+};
+
+static int snvs_rtc_enable(struct udevice *dev)
+{
+ struct snvs_rtc_priv *priv = dev_get_priv(dev);
+ u32 val;
+
+ setbits_le32(priv->base + SNVS_LPCR, SNVS_LPCR_SRTC_ENV);
+
+ return readl_poll_timeout(priv->base + SNVS_LPCR, val,
+ (val & SNVS_LPCR_SRTC_ENV), 1000);
+}
+
+static int snvs_rtc_disable(struct udevice *dev)
+{
+ struct snvs_rtc_priv *priv = dev_get_priv(dev);
+ u32 val;
+
+ clrbits_le32(priv->base + SNVS_LPCR, SNVS_LPCR_SRTC_ENV);
+
+ return readl_poll_timeout(priv->base + SNVS_LPCR, val,
+ !(val & SNVS_LPCR_SRTC_ENV), 1000);
+}
+
+static int snvs_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+ struct snvs_rtc_priv *priv = dev_get_priv(dev);
+ u64 read1, read2;
+
+ /* Require two identical consecutive reads as stated in manual */
+ do {
+ read1 = (u64)readl(priv->base + SNVS_LPSRTCMR) << 32ULL;
+ read1 |= readl(priv->base + SNVS_LPSRTCLR);
+
+ read2 = (u64)readl(priv->base + SNVS_LPSRTCMR) << 32ULL;
+ read2 |= readl(priv->base + SNVS_LPSRTCLR);
+ } while (read1 != read2);
+
+ /* Convert 47-bit counter to 32-bit raw second count */
+ rtc_to_tm((time_t)(read1 >> CNTR_TO_SECS_SH), tm);
+
+ return 0;
+}
+
+static int snvs_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+ struct snvs_rtc_priv *priv = dev_get_priv(dev);
+ u32 time = rtc_mktime(tm);
+ int ret;
+
+ ret = snvs_rtc_disable(dev);
+ if (ret)
+ return ret;
+
+ /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
+ writel(time << CNTR_TO_SECS_SH, priv->base + SNVS_LPSRTCLR);
+ writel(time >> (32 - CNTR_TO_SECS_SH), priv->base + SNVS_LPSRTCMR);
+
+ return snvs_rtc_enable(dev);
+}
+
+static const struct rtc_ops snvs_rtc_ops = {
+ .get = snvs_rtc_get,
+ .set = snvs_rtc_set,
+};
+
+static int snvs_rtc_probe(struct udevice *dev)
+{
+ struct snvs_rtc_priv *priv = dev_get_priv(dev);
+ u32 offset;
+ int ret;
+
+ priv->base = dev_read_addr(dev->parent);
+ if (priv->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ ret = dev_read_u32(dev, "offset", &offset);
+ if (ret)
+ return ret;
+
+ priv->base += offset;
+
+ return snvs_rtc_enable(dev);
+}
+
+static const struct udevice_id snvs_rtc_ids[] = {
+ { .compatible = "fsl,sec-v4.0-mon-rtc-lp" },
+ { }
+};
+
+U_BOOT_DRIVER(rtc_snvs) = {
+ .name = "rtc-snvs",
+ .id = UCLASS_RTC,
+ .probe = snvs_rtc_probe,
+ .of_match = snvs_rtc_ids,
+ .ops = &snvs_rtc_ops,
+ .priv_auto = sizeof(struct snvs_rtc_priv),
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index e221800d5d0..ffc58d663ff 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -276,6 +276,14 @@ config DEBUG_UART_ATMEL
will need to provide parameters to make this work. The driver will
be available until the real driver-model serial is running.
+config DEBUG_UART_ESP32
+ bool "Espressif ESP32 UART"
+ depends on ESP32_SERIAL
+ help
+ Select this to enable a debug UART using the ESP32 UART driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
config DEBUG_UART_BCM6345
bool "BCM6345 UART"
depends on BCM6345_SERIAL
@@ -1069,6 +1077,13 @@ config HTIF_CONSOLE
console. The HTIF device is quite common in RISC-V emulators and
RISC-V ISS so this driver allows using U-Boot on such platforms.
+config ESP32_SERIAL
+ bool "Espressif ESP32 UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable UART support for Espressif ESP32 family
+ devices using the U-Boot driver model.
+
config SIFIVE_SERIAL
bool "SiFive UART support"
depends on DM_SERIAL
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 66088b44eb6..44fb2170f9a 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
obj-$(CONFIG_CORTINA_UART) += serial_cortina.o
obj-$(CONFIG_DEBUG_SBI_CONSOLE) += serial_sbi.o
obj-$(CONFIG_EFI_APP) += serial_efi.o
+obj-$(CONFIG_ESP32_SERIAL) += serial_esp32.o
obj-$(CONFIG_MCFUART) += serial_mcf.o
obj-$(CONFIG_SYS_NS16550) += ns16550.o
obj-$(CONFIG_S5P_SERIAL) += serial_s5p.o
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 7b381ca12a0..9be2ad270ad 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -190,6 +190,16 @@ int fetch_baud_from_dtb(void)
int serial_init(void)
{
#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
+ /*
+ * Skip serial device probe before relocation if debug UART is enabled
+ * and early DM is skipped. Debug UART will handle console output during
+ * early boot. Full serial initialization happens in serial_initialize()
+ * after relocation.
+ */
+ if ((CONFIG_IS_ENABLED(DEBUG_UART) && CONFIG_IS_ENABLED(SKIP_EARLY_DM)) &&
+ !(gd->flags & GD_FLG_RELOC))
+ return 0;
+
serial_find_console_or_panic();
if (gd->cur_serial_dev)
gd->flags |= GD_FLG_SERIAL_READY;
diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c
index b1f69f6998c..89da11ffa52 100644
--- a/drivers/serial/serial_coreboot.c
+++ b/drivers/serial/serial_coreboot.c
@@ -59,7 +59,8 @@ static int read_dbg2(struct ns16550_plat *plat)
log_debug("Not a serial port\n");
return -EPROTOTYPE;
}
- if (dbg->port_subtype != ACPI_DBG2_16550_COMPATIBLE) {
+ if (dbg->port_subtype != ACPI_DBG2_16550_COMPATIBLE &&
+ dbg->port_subtype != ACPI_DBG2_16550_WITH_GAS) {
log_debug("Incompatible serial port\n");
return -EPROTOTYPE;
}
diff --git a/drivers/serial/serial_esp32.c b/drivers/serial/serial_esp32.c
new file mode 100644
index 00000000000..a3c03b6fc1b
--- /dev/null
+++ b/drivers/serial/serial_esp32.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2026, Honbo He <[email protected]>
+ */
+
+#define LOG_CATEGORY UCLASS_SERIAL
+
+#include <clk.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <serial.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <linux/err.h>
+#include <linux/bitops.h>
+
+#define UART_FIFO 0x00
+#define UART_INT_ENA 0x0c
+#define UART_INT_CLR 0x10
+#define UART_CLKDIV 0x14
+#define UART_STATUS 0x1c
+#define UART_CONF0 0x20
+
+#define UART_CLKDIV_FRAG_SHIFT 20
+#define UART_CLKDIV_FRAG_MASK 0xf
+
+#define UART_TX_FLOW_EN BIT(13)
+#define UART_LOOPBACK BIT(12)
+#define UART_STOP_BIT_1 BIT(4)
+#define UART_PARITY_EN BIT(1)
+#define UART_PARITY BIT(0)
+
+#define UART_BIT_NUM_8 (3 << 2)
+
+#define UART_BIT_NUM_MASK GENMASK(3, 2)
+#define UART_STOP_BIT_MASK GENMASK(5, 4)
+
+#define UART_RXFIFO_CNT_SHIFT 0
+#define UART_TXFIFO_CNT_SHIFT 16
+#define UART_FIFO_LEN 128
+
+#define UART_UPDATE_TIMEOUT 10000
+
+struct esp32_uart_soc_data {
+ u32 reg_update; /* UART_ID_REG */
+ u32 reg_update_bit; /* UART_REG_UPDATE */
+ u32 clkdiv_mask;
+ u32 fifo_cnt_mask;
+ u32 rx_fifo_rst; /* UART_RXFIFO_RST */
+ u32 tx_fifo_rst; /* UART_TXFIFO_RST */
+
+ bool broken_fifo_rst; /* true for ESP32, false otherwise */
+};
+
+/* Information about a serial port */
+struct esp32_uart_plat {
+ void __iomem *base; /* address of registers in physical memory */
+ const struct esp32_uart_soc_data *data;
+ u32 clock_rate;
+};
+
+static const struct esp32_uart_soc_data esp32_uart_data = {
+ .clkdiv_mask = 0xfffff,
+ .fifo_cnt_mask = 0xff,
+ .rx_fifo_rst = BIT(17),
+ .tx_fifo_rst = BIT(18),
+
+ .broken_fifo_rst = true,
+};
+
+static const struct esp32_uart_soc_data esp32s3_uart_data = {
+ .reg_update = 0x80,
+ .reg_update_bit = BIT(31),
+ .clkdiv_mask = 0xfff,
+ .fifo_cnt_mask = 0x3ff,
+ .rx_fifo_rst = BIT(17),
+ .tx_fifo_rst = BIT(18),
+};
+
+static const struct esp32_uart_soc_data esp32s31_uart_data = {
+ .reg_update = 0x98,
+ .reg_update_bit = BIT(0),
+ .clkdiv_mask = 0xfff,
+ .fifo_cnt_mask = 0xff,
+ .rx_fifo_rst = BIT(22),
+ .tx_fifo_rst = BIT(23),
+};
+
+static u32 esp32_uart_read(void __iomem *base, u32 offset)
+{
+ return readl(base + offset);
+}
+
+static void esp32_uart_write(void __iomem *base, u32 offset, u32 val)
+{
+ writel(val, base + offset);
+}
+
+static u32 esp32_uart_field(u32 val, u32 mask, u32 shift)
+{
+ return (val >> shift) & mask;
+}
+
+static u32 esp32_uart_rx_fifo_count(void __iomem *base,
+ const struct esp32_uart_soc_data *data)
+{
+ u32 status = esp32_uart_read(base, UART_STATUS);
+
+ return esp32_uart_field(status, data->fifo_cnt_mask,
+ UART_RXFIFO_CNT_SHIFT);
+}
+
+static u32 esp32_uart_tx_fifo_count(void __iomem *base,
+ const struct esp32_uart_soc_data *data)
+{
+ u32 status = esp32_uart_read(base, UART_STATUS);
+
+ return esp32_uart_field(status, data->fifo_cnt_mask,
+ UART_TXFIFO_CNT_SHIFT);
+}
+
+static int esp32_uart_update(void __iomem *base,
+ const struct esp32_uart_soc_data *data)
+{
+ int timeout = UART_UPDATE_TIMEOUT;
+
+ if (!data->reg_update_bit)
+ return 0;
+
+ setbits_le32(base + data->reg_update, data->reg_update_bit);
+ while ((esp32_uart_read(base, data->reg_update) & data->reg_update_bit) &&
+ timeout--)
+ ;
+
+ return timeout < 0 ? -ETIMEDOUT : 0;
+}
+
+static int esp32_uart_reset_fifo(void __iomem *base,
+ const struct esp32_uart_soc_data *data)
+{
+ u32 mask = data->tx_fifo_rst;
+ int ret;
+
+ /*
+ * uart2 of ESP32 doesn't have any register to reset Tx_FIFO or Rx_FIFO,
+ * and the FIFO_RST of uart1 may impact the functioning of uart2
+ * so use soft reset instead
+ */
+ if (data->broken_fifo_rst) {
+ while (esp32_uart_rx_fifo_count(base, data))
+ esp32_uart_read(base, UART_FIFO);
+ return 0;
+ }
+ mask |= data->rx_fifo_rst;
+
+ setbits_le32(base + UART_CONF0, mask);
+ ret = esp32_uart_update(base, data);
+ if (ret)
+ return ret;
+
+ clrbits_le32(base + UART_CONF0, mask);
+ return esp32_uart_update(base, data);
+}
+
+/*
+ * div = clkdiv_int + clkdiv_frag / 16
+ * baudrate = uart_clk / div
+ */
+static int esp32_uart_setbrg(void __iomem *base,
+ const struct esp32_uart_soc_data *data,
+ u32 clock_rate, int baudrate)
+{
+ u32 div, int_div, frag;
+
+ if (!clock_rate || baudrate <= 0)
+ return -EINVAL;
+ if (clock_rate > (UINT_MAX >> 4))
+ return -EINVAL;
+
+ /* shifting left by 4 bits to preserve frag field */
+ div = (clock_rate << 4) / baudrate;
+ int_div = div >> 4;
+ frag = div & UART_CLKDIV_FRAG_MASK;
+
+ if (!int_div || int_div > data->clkdiv_mask)
+ return -EINVAL;
+
+ esp32_uart_write(base, UART_CLKDIV,
+ int_div | (frag << UART_CLKDIV_FRAG_SHIFT));
+
+ return esp32_uart_update(base, data);
+}
+
+static int esp32_uart_init(void __iomem *base,
+ const struct esp32_uart_soc_data *data)
+{
+ u32 conf0;
+
+ esp32_uart_write(base, UART_INT_ENA, 0);
+ esp32_uart_write(base, UART_INT_CLR, 0xffffffff);
+
+ conf0 = esp32_uart_read(base, UART_CONF0);
+ conf0 &= ~(UART_PARITY | UART_PARITY_EN |
+ UART_BIT_NUM_MASK | UART_STOP_BIT_MASK |
+ UART_LOOPBACK | UART_TX_FLOW_EN);
+ conf0 |= UART_BIT_NUM_8 | UART_STOP_BIT_1;
+ esp32_uart_write(base, UART_CONF0, conf0);
+
+ return esp32_uart_reset_fifo(base, data);
+}
+
+static int esp32_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct esp32_uart_plat *plat = dev_get_plat(dev);
+
+ return esp32_uart_setbrg(plat->base, plat->data, plat->clock_rate,
+ baudrate);
+}
+
+static int esp32_serial_getc(struct udevice *dev)
+{
+ struct esp32_uart_plat *plat = dev_get_plat(dev);
+
+ if (!esp32_uart_rx_fifo_count(plat->base, plat->data))
+ return -EAGAIN;
+
+ return esp32_uart_read(plat->base, UART_FIFO) & 0xff;
+}
+
+static int esp32_serial_putc(struct udevice *dev, const char ch)
+{
+ struct esp32_uart_plat *plat = dev_get_plat(dev);
+
+ if (esp32_uart_tx_fifo_count(plat->base, plat->data) >= UART_FIFO_LEN)
+ return -EAGAIN;
+
+ esp32_uart_write(plat->base, UART_FIFO, ch);
+
+ return 0;
+}
+
+static int esp32_serial_pending(struct udevice *dev, bool input)
+{
+ struct esp32_uart_plat *plat = dev_get_plat(dev);
+
+ if (input)
+ return esp32_uart_rx_fifo_count(plat->base, plat->data);
+
+ return esp32_uart_tx_fifo_count(plat->base, plat->data) ? 1 : 0;
+}
+
+static int esp32_serial_probe(struct udevice *dev)
+{
+ struct esp32_uart_plat *plat = dev_get_plat(dev);
+ const struct esp32_uart_soc_data *data;
+
+ data = (const struct esp32_uart_soc_data *)dev_get_driver_data(dev);
+ if (!data)
+ return -EINVAL;
+ plat->data = data;
+
+ return esp32_uart_init(plat->base, data);
+}
+
+static int esp32_serial_of_to_plat(struct udevice *dev)
+{
+ struct esp32_uart_plat *plat = dev_get_plat(dev);
+ fdt_addr_t addr;
+ struct clk clk;
+ int ret;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = (void __iomem *)(uintptr_t)addr;
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (!ret) {
+ ret = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(ret))
+ plat->clock_rate = ret;
+ } else if (ret != -ENOENT && ret != -ENODEV && ret != -ENOSYS) {
+ dev_err(dev, "failed to get clock: %d\n", ret);
+ return ret;
+ }
+
+ if (!plat->clock_rate)
+ plat->clock_rate = dev_read_u32_default(dev, "clock-frequency", 0);
+
+ if (!plat->clock_rate) {
+ dev_err(dev, "missing clock\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct dm_serial_ops esp32_serial_ops = {
+ .putc = esp32_serial_putc,
+ .pending = esp32_serial_pending,
+ .getc = esp32_serial_getc,
+ .setbrg = esp32_serial_setbrg,
+};
+
+static const struct udevice_id esp32_serial_ids[] = {
+ { .compatible = "esp,esp32-uart",
+ .data = (ulong)&esp32_uart_data },
+ { .compatible = "esp,esp32s3-uart",
+ .data = (ulong)&esp32s3_uart_data },
+ { .compatible = "esp,esp32s31-uart",
+ .data = (ulong)&esp32s31_uart_data },
+ { }
+};
+
+U_BOOT_DRIVER(serial_esp32) = {
+ .name = "serial_esp32",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(esp32_serial_ids),
+ .of_to_plat = of_match_ptr(esp32_serial_of_to_plat),
+ .plat_auto = sizeof(struct esp32_uart_plat),
+ .probe = esp32_serial_probe,
+ .ops = &esp32_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+};
+
+#ifdef CONFIG_DEBUG_UART_ESP32
+static inline const struct esp32_uart_soc_data *
+esp32_debug_uart_data(void)
+{
+#if defined(CONFIG_ESPRESSIF_ESP32S31)
+ return &esp32s31_uart_data;
+#elif defined(CONFIG_ESPRESSIF_ESP32S3)
+ return &esp32s3_uart_data;
+#else
+ return &esp32_uart_data;
+#endif
+}
+
+static inline void _debug_uart_init(void)
+{
+ void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE);
+ const struct esp32_uart_soc_data *data = esp32_debug_uart_data();
+
+ esp32_uart_setbrg(base, data,
+ CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+ esp32_uart_init(base, data);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE);
+ const struct esp32_uart_soc_data *data =
+ esp32_debug_uart_data();
+
+ while (esp32_uart_tx_fifo_count(base, data)
+ >= UART_FIFO_LEN)
+ ;
+ esp32_uart_write(base, UART_FIFO, ch);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/drivers/serial/serial_mcf.c b/drivers/serial/serial_mcf.c
index 76143575fa9..9a70b7d3d86 100644
--- a/drivers/serial/serial_mcf.c
+++ b/drivers/serial/serial_mcf.c
@@ -4,10 +4,10 @@
* TsiChung Liew, [email protected].
*
* Modified to add device model (DM) support
- * (C) Copyright 2015 Angelo Dureghello <[email protected]>
+ * (C) Copyright 2015 Angelo Dureghello <[email protected]>
*
* Modified to add DM and fdt support, removed non DM code
- * (C) Copyright 2018 Angelo Dureghello <[email protected]>
+ * (C) Copyright 2018 Angelo Dureghello <[email protected]>
*/
/*
diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c
index ae4015e0fdc..ff91e0018fa 100644
--- a/drivers/serial/serial_msm_geni.c
+++ b/drivers/serial/serial_msm_geni.c
@@ -555,8 +555,9 @@ static int msm_serial_probe(struct udevice *dev)
if (ret < 0)
return ret;
- /* No need to reinitialize the UART after relocation */
- if (gd->flags & GD_FLG_RELOC)
+ /* Skip re-init after relocation if debug UART and early DM skip are not enabled */
+ if ((!CONFIG_IS_ENABLED(DEBUG_UART) && !CONFIG_IS_ENABLED(SKIP_EARLY_DM)) &&
+ (gd->flags & GD_FLG_RELOC))
return 0;
geni_serial_init(dev);
diff --git a/drivers/serial/serial_sifive.c b/drivers/serial/serial_sifive.c
index e47828e4d6a..0203e2fc37c 100644
--- a/drivers/serial/serial_sifive.c
+++ b/drivers/serial/serial_sifive.c
@@ -144,23 +144,16 @@ static int sifive_serial_probe(struct udevice *dev)
static int sifive_serial_getc(struct udevice *dev)
{
- int c;
struct sifive_uart_plat *plat = dev_get_plat(dev);
- struct uart_sifive *regs = plat->regs;
-
- while ((c = _sifive_serial_getc(regs)) == -EAGAIN) ;
- return c;
+ return _sifive_serial_getc(plat->regs);
}
static int sifive_serial_putc(struct udevice *dev, const char ch)
{
- int rc;
struct sifive_uart_plat *plat = dev_get_plat(dev);
- while ((rc = _sifive_serial_putc(plat->regs, ch)) == -EAGAIN) ;
-
- return rc;
+ return _sifive_serial_putc(plat->regs, ch);
}
static int sifive_serial_pending(struct udevice *dev, bool input)
diff --git a/drivers/spi/cf_spi.c b/drivers/spi/cf_spi.c
index 84077c01d83..51f7f420202 100644
--- a/drivers/spi/cf_spi.c
+++ b/drivers/spi/cf_spi.c
@@ -8,7 +8,7 @@
* TsiChung Liew ([email protected])
*
* Support for DM and DT, non-DM code removed.
- * Copyright (C) 2018 Angelo Dureghello <[email protected]>
+ * Copyright (C) 2018 Angelo Dureghello <[email protected]>
*
* TODO: fsl_dspi.c should work as a driver for the DSPI module.
*/
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index b520c727900..0df9a4f5abd 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -497,6 +497,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
{
struct udevice *bus = dev->parent;
struct dw_spi_priv *priv = dev_get_priv(bus);
+ struct spi_slave *slave = dev_get_parent_priv(dev);
const u8 *tx = dout;
u8 *rx = din;
int ret = 0;
@@ -504,6 +505,17 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
u32 val;
u32 cs;
+ /* Get bits_per_word from slave (set by device driver) */
+ if (slave->bits_per_word >= 4 && slave->bits_per_word <= priv->max_xfer) {
+ priv->bits_per_word = slave->bits_per_word;
+ } else if (slave->bits_per_word == 0) {
+ priv->bits_per_word = 8; /* Default if not set */
+ } else {
+ dev_warn(dev, "Invalid bits_per_word %u, using 8\n",
+ slave->bits_per_word);
+ priv->bits_per_word = 8;
+ }
+
/* spi core configured to do 8 bit transfers */
if (bitlen % 8) {
dev_err(dev, "Non byte aligned SPI transfer.\n");
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 65ab3e306d7..5692510a558 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -267,6 +267,14 @@ static const struct fsl_qspi_devtype_data ls2080a_data = {
.little_endian = true,
};
+static const struct fsl_qspi_devtype_data spacemit_k1_data = {
+ .rxfifo = SZ_128,
+ .txfifo = SZ_256,
+ .ahb_buf_size = SZ_128,
+ .quirks = QUADSPI_QUIRK_TKT253890,
+ .little_endian = true,
+};
+
struct fsl_qspi {
struct udevice *dev;
void __iomem *iobase;
@@ -870,6 +878,7 @@ static const struct udevice_id fsl_qspi_ids[] = {
{ .compatible = "fsl,ls1021a-qspi", .data = (ulong)&ls1021a_data, },
{ .compatible = "fsl,ls1088a-qspi", .data = (ulong)&ls2080a_data, },
{ .compatible = "fsl,ls2080a-qspi", .data = (ulong)&ls2080a_data, },
+ { .compatible = "spacemit,k1-qspi", .data = (ulong)&spacemit_k1_data, },
{ }
};
diff --git a/drivers/spi/renesas_rpc_spi.c b/drivers/spi/renesas_rpc_spi.c
index 7103d786c7e..76eca5389a2 100644
--- a/drivers/spi/renesas_rpc_spi.c
+++ b/drivers/spi/renesas_rpc_spi.c
@@ -145,11 +145,11 @@
#define RPC_PHYCNT_WBUF BIT(2)
#define RPC_PHYCNT_MEM(v) (((v) & 0x3) << 0)
-#define RPCIF_PHYOFFSET1 0x0080 /* R/W */
-#define RPCIF_PHYOFFSET1_DDRTMG(v) (((v) & 0x3) << 28)
+#define RPC_PHYOFFSET1 0x0080 /* R/W */
+#define RPC_PHYOFFSET1_DDRTMG(v) (((v) & 0x3) << 28)
-#define RPCIF_PHYOFFSET2 0x0084 /* R/W */
-#define RPCIF_PHYOFFSET2_OCTTMG(v) (((v) & 0x7) << 8)
+#define RPC_PHYOFFSET2 0x0084 /* R/W */
+#define RPC_PHYOFFSET2_OCTTMG(v) (((v) & 0x7) << 8)
#define RPC_PHYINT 0x0088 /* R/W */
#define RPC_PHYINT_RSTEN BIT(18)
@@ -233,11 +233,11 @@ static int rpc_spi_claim_bus(struct udevice *dev, bool manual)
struct udevice *bus = dev->parent;
struct rpc_spi_priv *priv = dev_get_priv(bus);
- setbits_le32(priv->regs + RPCIF_PHYOFFSET1,
- RPCIF_PHYOFFSET1_DDRTMG(3));
- clrsetbits_le32(priv->regs + RPCIF_PHYOFFSET2,
- RPCIF_PHYOFFSET2_OCTTMG(7),
- RPCIF_PHYOFFSET2_OCTTMG(4));
+ setbits_le32(priv->regs + RPC_PHYOFFSET1,
+ RPC_PHYOFFSET1_DDRTMG(3));
+ clrsetbits_le32(priv->regs + RPC_PHYOFFSET2,
+ RPC_PHYOFFSET2_OCTTMG(7),
+ RPC_PHYOFFSET2_OCTTMG(4));
/* NOTE: The 0x260 are undocumented bits, but they must be set. */
writel(RPC_PHYCNT_CAL | rpc_spi_get_strobe_delay() | 0x260,
@@ -466,6 +466,7 @@ static const struct udevice_id rpc_spi_ids[] = {
{ .compatible = "renesas,r7s72100-rpc-if" },
{ .compatible = "renesas,rcar-gen3-rpc-if" },
{ .compatible = "renesas,rcar-gen4-rpc-if" },
+ { .compatible = "renesas,rcar-gen5-rpc-if" },
{ }
};
diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
index 08b603f04a2..4e91cf6b7fd 100644
--- a/drivers/spi/spi-sunxi.c
+++ b/drivers/spi/spi-sunxi.c
@@ -587,6 +587,10 @@ static const struct udevice_id sun4i_spi_ids[] = {
.compatible = "allwinner,sun50i-r329-spi",
.data = (ulong)&sun50i_r329_spi_variant,
},
+ {
+ .compatible = "allwinner,sun55i-a523-spi",
+ .data = (ulong)&sun50i_r329_spi_variant,
+ },
{ /* sentinel */ }
};
diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index 2a095d0c58e..f572f2b3f15 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -283,16 +283,21 @@ static u32 zynqmp_qspi_genfifo_mode(u8 buswidth)
}
}
-static void zynqmp_qspi_fill_gen_fifo(struct zynqmp_qspi_priv *priv,
- u32 gqspi_fifo_reg)
+static void zynqmp_qspi_write_gen_fifo(struct zynqmp_qspi_priv *priv,
+ u32 gqspi_fifo_reg)
{
struct zynqmp_qspi_regs *regs = priv->regs;
- u32 config_reg, ier;
- int ret = 0;
log_content("%s, GFIFO_CMD: 0x%X\n", __func__, gqspi_fifo_reg);
writel(gqspi_fifo_reg, &regs->genfifo);
+}
+
+static int zynqmp_qspi_start_gen_fifo(struct zynqmp_qspi_priv *priv)
+{
+ struct zynqmp_qspi_regs *regs = priv->regs;
+ u32 config_reg, ier;
+ int ret = 0;
config_reg = readl(&regs->confr);
/* Manual start if needed */
@@ -310,6 +315,15 @@ static void zynqmp_qspi_fill_gen_fifo(struct zynqmp_qspi_priv *priv,
if (ret)
log_warning("%s, Timeout\n", __func__);
+ return ret;
+}
+
+static int zynqmp_qspi_fill_gen_fifo(struct zynqmp_qspi_priv *priv,
+ u32 gqspi_fifo_reg)
+{
+ zynqmp_qspi_write_gen_fifo(priv, gqspi_fifo_reg);
+
+ return zynqmp_qspi_start_gen_fifo(priv);
}
static void zynqmp_qspi_chipselect(struct zynqmp_qspi_priv *priv, int is_on)
@@ -573,7 +587,7 @@ static void zynqmp_qspi_genfifo_cmd(struct zynqmp_qspi_priv *priv)
gen_fifo_cmd |= zynqmp_qspi_genfifo_mode(op->cmd.buswidth);
gen_fifo_cmd |= GQSPI_GFIFO_TX;
gen_fifo_cmd |= op->cmd.opcode;
- zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ zynqmp_qspi_write_gen_fifo(priv, gen_fifo_cmd);
/* Send address */
for (i = 0; i < op->addr.nbytes; i++) {
@@ -584,7 +598,7 @@ static void zynqmp_qspi_genfifo_cmd(struct zynqmp_qspi_priv *priv)
gen_fifo_cmd |= GQSPI_GFIFO_TX;
gen_fifo_cmd |= addr;
- zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ zynqmp_qspi_write_gen_fifo(priv, gen_fifo_cmd);
}
/* Send dummy */
@@ -596,7 +610,7 @@ static void zynqmp_qspi_genfifo_cmd(struct zynqmp_qspi_priv *priv)
gen_fifo_cmd &= ~(GQSPI_GFIFO_TX | GQSPI_GFIFO_RX);
gen_fifo_cmd |= GQSPI_GFIFO_DATA_XFR_MASK;
gen_fifo_cmd |= dummy_cycles;
- zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ zynqmp_qspi_write_gen_fifo(priv, gen_fifo_cmd);
}
}
@@ -644,7 +658,9 @@ static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv)
while (priv->len) {
len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
- zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ ret = zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ if (ret)
+ return ret;
if (gen_fifo_cmd & GQSPI_GFIFO_EXP_MASK)
ret = zynqmp_qspi_fill_tx_fifo(priv, 1 << len);
@@ -666,6 +682,7 @@ static int zynqmp_qspi_start_io(struct zynqmp_qspi_priv *priv,
struct zynqmp_qspi_regs *regs = priv->regs;
u32 last_bits;
u32 *traverse = buf;
+ int ret;
while (priv->len) {
len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
@@ -674,7 +691,9 @@ static int zynqmp_qspi_start_io(struct zynqmp_qspi_priv *priv,
priv->bytes_to_receive = (1 << len);
else
priv->bytes_to_receive = len;
- zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ ret = zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ if (ret)
+ return ret;
/* Manual start */
config_reg = readl(&regs->confr);
@@ -741,7 +760,9 @@ static int zynqmp_qspi_start_dma(struct zynqmp_qspi_priv *priv,
while (priv->len) {
zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
- zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ ret = zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
+ if (ret)
+ return ret;
}
ret = wait_for_bit_le32(&dma_regs->dmaisr,
@@ -886,6 +907,8 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave,
ret = zynqmp_qspi_genfifo_fill_rx(priv);
else if (op->data.dir == SPI_MEM_DATA_OUT)
ret = zynqmp_qspi_genfifo_fill_tx(priv);
+ else
+ ret = zynqmp_qspi_start_gen_fifo(priv);
zynqmp_qspi_chipselect(priv, 0);
diff --git a/drivers/sysinfo/Kconfig b/drivers/sysinfo/Kconfig
index 6922dac9170..adcf1aed8a8 100644
--- a/drivers/sysinfo/Kconfig
+++ b/drivers/sysinfo/Kconfig
@@ -63,6 +63,7 @@ config SYSINFO_TQ_EEPROM
bool "Enable TQ-Systems EEPROM sysinfo driver"
depends on I2C_EEPROM
depends on SPL_I2C_EEPROM || !SPL_SYSINFO
+ select NVMEM
help
Support querying EEPROM of TQ-Systems SOMs to determine board
information.
diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig
index c1b84bd7559..6dffdc00b32 100644
--- a/drivers/ufs/Kconfig
+++ b/drivers/ufs/Kconfig
@@ -10,7 +10,7 @@ config UFS
config UFS_AMD_VERSAL2
bool "AMD Versal Gen 2 UFS controller platform driver"
- depends on UFS && ZYNQMP_FIRMWARE
+ depends on UFS && ARCH_VERSAL2
help
This selects the AMD specific additions to UFSHCD platform driver.
UFS host on AMD needs some vendor specific configuration before accessing
diff --git a/drivers/ufs/ufs-amd-versal2.c b/drivers/ufs/ufs-amd-versal2.c
index 3369d32d924..48854792cbf 100644
--- a/drivers/ufs/ufs-amd-versal2.c
+++ b/drivers/ufs/ufs-amd-versal2.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2024-2025 Advanced Micro Devices, Inc.
+ * Copyright (C) 2024-2026 Advanced Micro Devices, Inc.
*/
#include <clk.h>
@@ -14,14 +14,12 @@
#include <linux/time.h>
#include <reset.h>
+#include <asm/arch/sys_proto.h>
+
#include "ufs.h"
#include "ufshcd-dwc.h"
#include "ufshci-dwc.h"
-#define SRAM_CSR_INIT_DONE_MASK BIT(0)
-#define SRAM_CSR_EXT_LD_DONE_MASK BIT(1)
-#define SRAM_CSR_BYPASS_MASK BIT(2)
-
#define MPHY_FAST_RX_AFE_CAL BIT(2)
#define MPHY_FW_CALIB_CFG_VAL BIT(8)
@@ -29,8 +27,6 @@
#define MPHY_RX_OVRD_VAL BIT(2)
#define MPHY_RX_ACK_MASK BIT(0)
-#define TX_RX_CFG_RDY_MASK GENMASK(3, 0)
-
#define TIMEOUT_MICROSEC 1000000L
struct ufs_versal2_priv {
@@ -227,7 +223,6 @@ static int ufs_versal2_setup_phy(struct ufs_hba *hba)
static int ufs_versal2_phy_init(struct ufs_hba *hba)
{
struct ufs_versal2_priv *priv = dev_get_priv(hba->dev);
- u32 reg, time_left;
int ret;
static const struct ufshcd_dme_attr_val rmmi_attrs[] = {
{ UIC_ARG_MIB(CBREFCLKCTRL2), CBREFREFCLK_GATE_OVR_EN, DME_LOCAL },
@@ -236,24 +231,15 @@ static int ufs_versal2_phy_init(struct ufs_hba *hba)
{ UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
};
- /* Wait for Tx/Rx config_rdy */
- time_left = TIMEOUT_MICROSEC;
- do {
- time_left--;
- ret = zynqmp_pm_ufs_get_txrx_cfgrdy(&reg);
- if (ret)
- return ret;
-
- reg &= TX_RX_CFG_RDY_MASK;
- if (!reg)
- break;
-
- mdelay(5);
- } while (time_left);
-
- if (!time_left) {
+ /*
+ * Wait for Tx/Rx config_rdy. The poll loop lives in the firmware
+ * backend (IO, EEMI or SCMI) so this driver stays backend-agnostic;
+ * the timeout budget stays here with the consumer.
+ */
+ ret = zynqmp_pm_wait_mphy_tx_rx_config_ready(TIMEOUT_MICROSEC);
+ if (ret) {
dev_err(hba->dev, "Tx/Rx configuration signal busy.\n");
- return -ETIMEDOUT;
+ return ret;
}
ret = ufshcd_dwc_dme_set_attrs(hba, rmmi_attrs, ARRAY_SIZE(rmmi_attrs));
@@ -267,24 +253,11 @@ static int ufs_versal2_phy_init(struct ufs_hba *hba)
return ret;
}
- /* Wait for SRAM init done */
- time_left = TIMEOUT_MICROSEC;
- do {
- time_left--;
- ret = zynqmp_pm_ufs_sram_csr_read(&reg);
- if (ret)
- return ret;
-
- reg &= SRAM_CSR_INIT_DONE_MASK;
- if (reg)
- break;
-
- mdelay(5);
- } while (time_left);
-
- if (!time_left) {
+ /* Wait for SRAM init done (poll handled by the firmware backend). */
+ ret = zynqmp_pm_wait_sram_init_done(TIMEOUT_MICROSEC);
+ if (ret) {
dev_err(hba->dev, "SRAM initialization failed.\n");
- return -ETIMEDOUT;
+ return ret;
}
ret = ufs_versal2_setup_phy(hba);
@@ -329,7 +302,32 @@ static int ufs_versal2_init(struct ufs_hba *hba)
return PTR_ERR(priv->rstphy);
}
- ret = zynqmp_pm_ufs_cal_reg(&cal);
+ /* Assert RST_UFS Reset for UFS block in PMX_IOU */
+ ret = reset_assert(priv->rstc);
+ if (ret) {
+ dev_err(hba->dev, "host reset assert failed, err = %d\n", ret);
+ return ret;
+ }
+
+ /* Assert PHY reset */
+ ret = reset_assert(priv->rstphy);
+ if (ret) {
+ dev_err(hba->dev, "phy reset assert failed, err = %d\n", ret);
+ return ret;
+ }
+
+ ret = zynqmp_pm_set_sram_bypass();
+ if (ret) {
+ dev_err(hba->dev, "Bypass SRAM interface failed, err = %d\n", ret);
+ return ret;
+ }
+
+ /* De Assert RST_UFS Reset for UFS block in PMX_IOU */
+ ret = reset_deassert(priv->rstc);
+ if (ret)
+ dev_err(hba->dev, "host reset deassert failed, err = %d\n", ret);
+
+ ret = zynqmp_pm_get_ufs_calibration_values(&cal);
if (ret)
return ret;
@@ -344,57 +342,12 @@ static int ufs_versal2_init(struct ufs_hba *hba)
static int ufs_versal2_hce_enable_notify(struct ufs_hba *hba,
enum ufs_notify_change_status status)
{
- struct ufs_versal2_priv *priv = dev_get_priv(hba->dev);
- u32 sram_csr;
- int ret;
-
- switch (status) {
- case PRE_CHANGE:
- /* Assert RST_UFS Reset for UFS block in PMX_IOU */
- ret = reset_assert(priv->rstc);
- if (ret) {
- dev_err(hba->dev, "ufshc reset assert failed, err = %d\n", ret);
- return ret;
- }
-
- /* Assert PHY reset */
- ret = reset_assert(priv->rstphy);
- if (ret) {
- dev_err(hba->dev, "ufsphy reset assert failed, err = %d\n", ret);
- return ret;
- }
-
- ret = zynqmp_pm_ufs_sram_csr_read(&sram_csr);
- if (ret)
- return ret;
-
- if (!priv->phy_mode) {
- sram_csr &= ~SRAM_CSR_EXT_LD_DONE_MASK;
- sram_csr |= SRAM_CSR_BYPASS_MASK;
- } else {
- dev_err(hba->dev, "Invalid phy-mode %d.\n", priv->phy_mode);
- return -EINVAL;
- }
-
- ret = zynqmp_pm_ufs_sram_csr_write(&sram_csr);
- if (ret)
- return ret;
-
- /* De Assert RST_UFS Reset for UFS block in PMX_IOU */
- ret = reset_deassert(priv->rstc);
- if (ret)
- dev_err(hba->dev, "ufshc reset deassert failed, err = %d\n", ret);
+ int ret = 0;
- break;
- case POST_CHANGE:
+ if (status == POST_CHANGE) {
ret = ufs_versal2_phy_init(hba);
if (ret)
dev_err(hba->dev, "Phy init failed (%d)\n", ret);
-
- break;
- default:
- ret = -EINVAL;
- break;
}
return ret;
diff --git a/drivers/ufs/ufs-renesas-rcar-gen5.c b/drivers/ufs/ufs-renesas-rcar-gen5.c
index a9473cd60b1..c6e436fe197 100644
--- a/drivers/ufs/ufs-renesas-rcar-gen5.c
+++ b/drivers/ufs/ufs-renesas-rcar-gen5.c
@@ -72,7 +72,7 @@ static int ufs_renesas_pre_init(struct ufs_hba *hba)
if (ret)
return ret;
- writew(0x0000, priv->phy_base + 0x20000);
+ clrbits_le16(priv->phy_base + 0x20000, BIT(0));
ufshcd_writel(hba, BIT(0), REG_CONTROLLER_ENABLE);
@@ -88,6 +88,9 @@ static int ufs_renesas_pre_init(struct ufs_hba *hba)
if (ret)
return ret;
+ ufshcd_rmwl(hba, 0xe000, 0, 0xc0);
+ ufshcd_rmwl(hba, 0x5000, 0x5000, 0xc0);
+
/* Skip IE because we cannot handle interrupts here */
ufs_dme_command(hba, 0x00000002, 0x81010000, 0x00000000, 0x00000005);
ufs_dme_command(hba, 0x00000002, 0x81150000, 0x00000000, 0x00000001);
@@ -133,6 +136,10 @@ static int ufs_renesas_pre_init(struct ufs_hba *hba)
if (ret)
return ret;
+ clrbits_le16(priv->phy_base + 0x20000, BIT(0));
+
+ ufs_dme_command(hba, 0x00000002, 0xd0890000, 0x00000000, 0x00000001);
+
priv->initialized = true;
return 0;
@@ -140,8 +147,7 @@ static int ufs_renesas_pre_init(struct ufs_hba *hba)
static int ufs_renesas_init(struct ufs_hba *hba)
{
- hba->quirks |= UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS | UFSHCD_QUIRK_HIBERN_FASTAUTO |
- UFSHCD_QUIRK_BROKEN_LCC;
+ hba->quirks |= UFSHCD_QUIRK_HIBERN_FASTAUTO | UFSHCD_QUIRK_BROKEN_LCC;
return 0;
}
@@ -180,12 +186,12 @@ static int ufs_renesas_get_max_pwr_mode(struct ufs_hba *hba,
{
max_pwr_info->info.gear_rx = UFS_HS_G5;
max_pwr_info->info.gear_tx = UFS_HS_G5;
- max_pwr_info->info.pwr_tx = FASTAUTO_MODE;
- max_pwr_info->info.pwr_rx = FASTAUTO_MODE;
- max_pwr_info->info.hs_rate = PA_HS_MODE_A;
+ max_pwr_info->info.pwr_tx = FAST_MODE;
+ max_pwr_info->info.pwr_rx = FAST_MODE;
+ max_pwr_info->info.hs_rate = PA_HS_MODE_B;
- max_pwr_info->info.lane_rx = 1;
- max_pwr_info->info.lane_tx = 1;
+ max_pwr_info->info.lane_rx = 2;
+ max_pwr_info->info.lane_tx = 2;
dev_info(hba->dev, "Max HS Gear: %d\n", max_pwr_info->info.gear_rx);
diff --git a/drivers/ufs/ufs-uclass.c b/drivers/ufs/ufs-uclass.c
index 6a51f337e47..6ef01f8e4aa 100644
--- a/drivers/ufs/ufs-uclass.c
+++ b/drivers/ufs/ufs-uclass.c
@@ -1008,6 +1008,7 @@ static int ufshcd_copy_query_response(struct ufs_hba *hba)
buf_len =
be16_to_cpu(hba->dev_cmd.query.request.upiu_req.length);
if (likely(buf_len >= resp_len)) {
+ ufshcd_cache_invalidate(descp, resp_len);
memcpy(hba->dev_cmd.query.descriptor, descp, resp_len);
} else {
dev_warn(hba->dev,
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 4729570c525..53796887dac 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -333,16 +333,16 @@ static void request_complete_list(struct usb_ep *ep, struct list_head *list, int
}
}
-static void ep_enable(int num, int in, int maxpacket)
+static void ep_enable(int num, int in, int type, int maxpacket)
{
struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
unsigned n;
n = readl(&udc->epctrl[num]);
if (in)
- n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK);
+ n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT(type));
else
- n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK);
+ n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT(type));
if (num != 0) {
struct ept_queue_head *head = ci_get_qh(num, in);
@@ -357,7 +357,7 @@ static int ci_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
{
struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
- int num, in;
+ int num, in, type;
num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
@@ -366,6 +366,7 @@ static int ci_ep_enable(struct usb_ep *ep,
return -EBUSY;
}
+ type = usb_endpoint_type(desc);
ci_ep->desc = desc;
ep->desc = desc;
@@ -380,7 +381,7 @@ static int ci_ep_enable(struct usb_ep *ep,
ep->maxpacket = max;
}
}
- ep_enable(num, in, ep->maxpacket);
+ ep_enable(num, in, type, ep->maxpacket);
DBG("%s: num=%d maxpacket=%d\n", __func__, num, ep->maxpacket);
return 0;
}
@@ -679,6 +680,8 @@ static int ci_ep_queue(struct usb_ep *ep,
if (ret)
return ret;
+ req->status = -EINPROGRESS;
+
DBG("ept%d %s pre-queue req %p, buffer %p\n",
num, in ? "in" : "out", ci_req, ci_req->hw_buf);
list_add_tail(&ci_req->queue, &ci_ep->queue);
@@ -730,6 +733,17 @@ static void handle_ep_complete(struct ci_ep *ci_ep)
ci_invalidate_qtd(num);
ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
+ /* Check all dtd are completed, otherwise return for next irq process */
+ next_td = item;
+ for (j = 0; j < ci_req->dtd_count; j++) {
+ ci_invalidate_td(next_td);
+ if (next_td->info & INFO_ACTIVE)
+ return;
+ if (j != ci_req->dtd_count - 1)
+ next_td = (struct ept_queue_item *)(unsigned long)
+ next_td->next;
+ }
+
next_td = item;
len = 0;
for (j = 0; j < ci_req->dtd_count; j++) {
@@ -753,6 +767,7 @@ static void handle_ep_complete(struct ci_ep *ci_ep)
ci_ep_submit_next_request(ci_ep);
ci_req->req.actual = ci_req->req.length - len;
+ ci_req->req.status = 0;
ci_debounce(ci_req, in);
DBG("ept%d %s req %p, complete %x\n",
@@ -783,7 +798,7 @@ static void handle_setup(void)
struct ept_queue_head *head;
struct usb_ctrlrequest r;
int status = 0;
- int num, in, _num, _in, i;
+ int num, in, _num, _in, i, type;
char *buf;
ci_req = controller.ep0_req;
@@ -837,8 +852,9 @@ static void handle_setup(void)
& USB_ENDPOINT_NUMBER_MASK;
in = (ep->desc->bEndpointAddress
& USB_DIR_IN) != 0;
+ type = usb_endpoint_type(ep->desc);
if ((num == _num) && (in == _in)) {
- ep_enable(num, in, ep->ep.maxpacket);
+ ep_enable(num, in, type, ep->ep.maxpacket);
usb_ep_queue(controller.gadget.ep0,
req, 0);
break;
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 807f2084c1e..f1c4537859e 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -74,8 +74,8 @@ struct ci_udc {
#define CTRL_TXR (1 << 22)
#define CTRL_RXE (1 << 7)
#define CTRL_RXR (1 << 6)
-#define CTRL_TXT_BULK (2 << 18)
-#define CTRL_RXT_BULK (2 << 2)
+#define CTRL_TXT(t) ((t) << 18)
+#define CTRL_RXT(t) ((t) << 2)
struct ci_req {
struct usb_request req;
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index e475b14b9ac..570fed347c9 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -828,7 +828,11 @@ static struct dwc2_udc memory = {
.ep = {
.name = ep0name,
.ops = &dwc2_ep_ops,
- .maxpacket = EP0_FIFO_SIZE,
+ .caps = {
+ .type_control = 1,
+ .dir_in = 1,
+ .dir_out = 1,
+ },
},
.dev = &memory,
@@ -843,7 +847,10 @@ static struct dwc2_udc memory = {
.ep = {
.name = "ep1in-bulk",
.ops = &dwc2_ep_ops,
- .maxpacket = EP_FIFO_SIZE,
+ .caps = {
+ .type_bulk = 1,
+ .dir_in = 1,
+ },
},
.dev = &memory,
@@ -858,7 +865,10 @@ static struct dwc2_udc memory = {
.ep = {
.name = "ep2out-bulk",
.ops = &dwc2_ep_ops,
- .maxpacket = EP_FIFO_SIZE,
+ .caps = {
+ .type_bulk = 1,
+ .dir_out = 1,
+ },
},
.dev = &memory,
@@ -873,7 +883,10 @@ static struct dwc2_udc memory = {
.ep = {
.name = "ep3in-int",
.ops = &dwc2_ep_ops,
- .maxpacket = EP_FIFO_SIZE,
+ .caps = {
+ .type_int = 1,
+ .dir_in = 1,
+ },
},
.dev = &memory,
@@ -893,6 +906,7 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata)
{
struct dwc2_udc *dev = &memory;
int retval = 0;
+ int i;
debug("%s: %p\n", __func__, pdata);
@@ -909,6 +923,10 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata)
the_controller = dev;
+ usb_ep_set_maxpacket_limit(&dev->ep[0].ep, EP0_FIFO_SIZE);
+ for (i = 1; i < DWC2_MAX_ENDPOINTS; i++)
+ usb_ep_set_maxpacket_limit(&dev->ep[i].ep, EP_FIFO_SIZE);
+
usb_ctrl = memalign(CONFIG_SYS_CACHELINE_SIZE,
ROUND(sizeof(struct usb_ctrlrequest),
CONFIG_SYS_CACHELINE_SIZE));
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 87ed25e8bb3..7eb667c130d 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -241,6 +241,7 @@
#include <config.h>
#include <div64.h>
+#include <env.h>
#include <hexdump.h>
#include <log.h>
#include <malloc.h>
@@ -2662,8 +2663,15 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_gadget *gadget = c->cdev->gadget;
int i;
struct usb_ep *ep;
+ char __maybe_unused *sn;
fsg->gadget = gadget;
+ if (CONFIG_IS_ENABLED(ENV_SUPPORT)) {
+ sn = env_get("serial#");
+ if (sn)
+ g_dnl_set_serialnumber(sn);
+ }
+
/* New interface */
i = usb_interface_id(c, f);
if (i < 0)
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index 8ad07a4b98c..3504a7cf42c 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -226,6 +226,11 @@ static int xhci_dwc3_probe(struct udevice *dev)
static int xhci_dwc3_remove(struct udevice *dev)
{
struct xhci_dwc3_plat *plat = dev_get_plat(dev);
+ int ret;
+
+ ret = xhci_deregister(dev);
+ if (ret)
+ return ret;
dwc3_shutdown_phy(dev, &plat->phys);
@@ -233,7 +238,7 @@ static int xhci_dwc3_remove(struct udevice *dev)
reset_release_bulk(&plat->resets);
- return xhci_deregister(dev);
+ return 0;
}
static const struct udevice_id xhci_dwc3_ids[] = {
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig
index 5ec498ec953..8623adfdf51 100644
--- a/drivers/usb/mtu3/Kconfig
+++ b/drivers/usb/mtu3/Kconfig
@@ -42,3 +42,42 @@ config USB_MTU3_DEBUG
Say Y here to enable debugging messages in the MTU3 Driver.
endif
+
+config SPL_USB_MTU3
+ bool "MediaTek USB3 controller support in SPL"
+ depends on ARCH_MEDIATEK
+ depends on SPL_DM_USB
+ depends on SPL_USB_HOST || (SPL_DM_USB_GADGET && SPL_USB_GADGET)
+ help
+ Enable the MediaTek USB3 controller in SPL. Select host or peripheral
+ mode below.
+
+if SPL_USB_MTU3
+
+choice
+ bool "MTU3 SPL Mode Selection"
+ default SPL_USB_MTU3_GADGET if SPL_USB_GADGET
+ default SPL_USB_MTU3_HOST if (SPL_USB_HOST && !SPL_USB_GADGET)
+ help
+ Select whether the MTU3 controller operates as an xHCI host or a USB
+ peripheral in SPL.
+
+config SPL_USB_MTU3_HOST
+ bool "Host mode in SPL"
+ depends on SPL_USB_HOST && USB_XHCI_HCD
+ select SPL_OF_TRANSLATE
+ help
+ Enable the MTU3 xHCI host controller in SPL so USB devices can be
+ accessed before U-Boot proper starts.
+
+config SPL_USB_MTU3_GADGET
+ bool "Gadget mode in SPL"
+ depends on SPL_DM_USB_GADGET && SPL_USB_GADGET
+ select USB_GADGET_DUALSPEED
+ help
+ Enable the MTU3 peripheral controller in SPL so USB gadget
+ functions can use it before U-Boot proper starts.
+
+endchoice
+
+endif
diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile
index 234f3a380a3..d1f0cd24875 100644
--- a/drivers/usb/mtu3/Makefile
+++ b/drivers/usb/mtu3/Makefile
@@ -1,11 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
-ccflags-$(CONFIG_USB_MTU3_DEBUG) += -DDEBUG
+ccflags-$(CONFIG_$(PHASE_)USB_MTU3_DEBUG) += -DDEBUG
-obj-$(CONFIG_USB_MTU3) += mtu3.o
+obj-$(CONFIG_$(PHASE_)USB_MTU3) += mtu3.o
mtu3-y := mtu3_plat.o
-obj-$(CONFIG_USB_MTU3_GADGET) += mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o
-obj-$(CONFIG_USB_MTU3_GADGET) += mtu3_qmu.o
-obj-$(CONFIG_USB_MTU3_HOST) += mtu3_host.o
+obj-$(CONFIG_$(PHASE_)USB_MTU3_GADGET) += mtu3_core.o mtu3_gadget_ep0.o
+obj-$(CONFIG_$(PHASE_)USB_MTU3_GADGET) += mtu3_gadget.o mtu3_qmu.o
+obj-$(CONFIG_$(PHASE_)USB_MTU3_HOST) += mtu3_host.o
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index 8a7ae83ee99..5e35e4754cd 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -137,15 +137,13 @@ enum mtu3_dr_force_mode {
};
/**
- * @mac_base: register base address of MAC, include xHCI and device
+ * @mac_base: register base address of the device MAC
* @ippc_base: register base address of IP Power and Clock interface (IPPC)
* @vusb33_supply: usb3.3V shared by device/host IP
* @vbus_supply: vbus 5v of OTG port
* @clks: optional clocks, include "sys_ck", "ref_ck", "mcu_ck",
* "dma_ck" and "xhci_ck"
* @phys: phys used
- * @dr_mode: works in which mode:
- * host only, device only or dual-role mode
*/
struct ssusb_mtk {
struct udevice *dev;
@@ -158,13 +156,14 @@ struct ssusb_mtk {
struct udevice *vbus_supply;
struct clk_bulk clks;
struct phy_bulk phys;
- /* otg */
- enum usb_dr_mode dr_mode;
};
/**
* @ctrl: xHCI controller, needs to come first in this struct!
* @hcd: xHCI's register base address
+ * @vusb33_supply: regulator from the xHCI child node
+ * @vbus_supply: regulator from the xHCI child node or its MTU3 parent
+ * @clks: clocks from the xHCI child node
* @u2_ports: number of usb2 host ports
* @u3_ports: number of usb3 host ports
* @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to
@@ -176,6 +175,9 @@ struct mtu3_host {
void __iomem *ippc_base;
struct ssusb_mtk *ssusb;
struct udevice *dev;
+ struct udevice *vusb33_supply;
+ struct udevice *vbus_supply;
+ struct clk_bulk clks;
u32 u2_ports;
u32 u3_ports;
u32 u3p_dis_msk;
@@ -408,7 +410,7 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set);
void mtu3_ep0_setup(struct mtu3 *mtu);
void mtu3_start(struct mtu3 *mtu);
void mtu3_stop(struct mtu3 *mtu);
-void mtu3_dev_on_off(struct mtu3 *mtu, int is_on);
+int mtu3_dev_on_off(struct mtu3 *mtu, int is_on);
void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed);
int mtu3_gadget_setup(struct mtu3 *mtu);
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c
index 2f5cc9b1480..f296a72cf18 100644
--- a/drivers/usb/mtu3/mtu3_core.c
+++ b/drivers/usb/mtu3/mtu3_core.c
@@ -10,10 +10,13 @@
#include <linux/log2.h>
#include <linux/bitmap.h>
+#include <linux/iopoll.h>
#include "mtu3.h"
#include "mtu3_dr.h"
+#define MTU3_TX_FIFO_DRAIN_TIMEOUT_US 1000
+
static int ep_fifo_alloc(struct mtu3_ep *mep, u32 seg_size)
{
struct mtu3_fifo_info *fifo = mep->fifo;
@@ -226,6 +229,34 @@ static void mtu3_ep_reset(struct mtu3_ep *mep)
mtu3_clrbits(mtu->mac_base, U3D_EP_RST, rst_bit);
}
+static int mtu3_wait_for_tx_fifo_empty(struct mtu3 *mtu)
+{
+ struct mtu3_ep *mep;
+ u32 value;
+ int err;
+ int ret = 0;
+ int i;
+
+ for (i = 1; i < mtu->num_eps; i++) {
+ mep = mtu->in_eps + i;
+ if (!(mep->flags & MTU3_EP_ENABLED) ||
+ !list_empty(&mep->req_list))
+ continue;
+
+ err = readl_poll_timeout(mtu->mac_base + MU3D_EP_TXCR0(i),
+ value, value & TX_FIFOEMPTY,
+ MTU3_TX_FIFO_DRAIN_TIMEOUT_US);
+ if (err) {
+ dev_warn(mtu->dev, "%s TX FIFO did not drain\n",
+ mep->name);
+ mtu3_ep_reset(mep);
+ ret = err;
+ }
+ }
+
+ return ret;
+}
+
/* set/clear the stall and toggle bits for non-ep0 */
void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set)
{
@@ -261,8 +292,15 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set)
set ? "SEND STALL" : "CLEAR STALL, with EP RESET");
}
-void mtu3_dev_on_off(struct mtu3 *mtu, int is_on)
+int mtu3_dev_on_off(struct mtu3 *mtu, int is_on)
{
+ int ret = 0;
+
+ /* QMU completion may precede transmission from the TX FIFO. */
+ if (!is_on)
+ ret = mtu3_wait_for_tx_fifo_empty(mtu);
+
+ /* Force the disconnect after a timeout; the failed endpoint was reset. */
if (mtu->is_u3_ip && mtu->speed >= USB_SPEED_SUPER)
mtu3_ss_func_set(mtu, is_on);
else
@@ -270,6 +308,8 @@ void mtu3_dev_on_off(struct mtu3 *mtu, int is_on)
dev_info(mtu->dev, "gadget (%s) pullup D%s\n",
usb_speed_string(mtu->speed), is_on ? "+" : "-");
+
+ return ret;
}
void mtu3_start(struct mtu3 *mtu)
@@ -802,8 +842,8 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb)
mtu->ippc_base = ssusb->ippc_base;
mtu->mac_base = ssusb->mac_base;
mtu->ssusb = ssusb;
- mtu->max_speed = usb_get_maximum_speed(dev_ofnode(dev));
- mtu->force_vbus = dev_read_bool(dev, "mediatek,force-vbus");
+ mtu->max_speed = usb_get_maximum_speed(dev_ofnode(ssusb->dev));
+ mtu->force_vbus = dev_read_bool(ssusb->dev, "mediatek,force-vbus");
ret = mtu3_hw_init(mtu);
if (ret) {
diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index ec0e50c04ca..89fbde03625 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -10,7 +10,7 @@
#ifndef _MTU3_DR_H_
#define _MTU3_DR_H_
-#if IS_ENABLED(CONFIG_USB_MTU3_HOST)
+#if CONFIG_IS_ENABLED(USB_MTU3_HOST)
int ssusb_host_init(struct ssusb_mtk *ssusb);
void ssusb_host_exit(struct ssusb_mtk *ssusb);
@@ -27,7 +27,7 @@ static inline void ssusb_host_exit(struct ssusb_mtk *ssusb)
#endif
-#if IS_ENABLED(CONFIG_USB_MTU3_GADGET)
+#if CONFIG_IS_ENABLED(USB_MTU3_GADGET)
int ssusb_gadget_init(struct ssusb_mtk *ssusb);
void ssusb_gadget_exit(struct ssusb_mtk *ssusb);
irqreturn_t mtu3_irq(int irq, void *data);
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c
index 027b7e61113..da633faae7b 100644
--- a/drivers/usb/mtu3/mtu3_gadget.c
+++ b/drivers/usb/mtu3/mtu3_gadget.c
@@ -451,6 +451,7 @@ static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on)
{
struct mtu3 *mtu = gadget_to_mtu3(gadget);
unsigned long flags;
+ int ret = 0;
dev_dbg(mtu->dev, "%s (%s) for %sactive device\n", __func__,
is_on ? "on" : "off", mtu->is_active ? "" : "in");
@@ -464,12 +465,12 @@ static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on)
mtu->softconnect = is_on;
} else if (is_on != mtu->softconnect) {
mtu->softconnect = is_on;
- mtu3_dev_on_off(mtu, is_on);
+ ret = mtu3_dev_on_off(mtu, is_on);
}
spin_unlock_irqrestore(&mtu->lock, flags);
- return 0;
+ return ret;
}
static int mtu3_gadget_start(struct usb_gadget *gadget,
diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c
index 8001fc2d9bd..f1675065c54 100644
--- a/drivers/usb/mtu3/mtu3_host.c
+++ b/drivers/usb/mtu3/mtu3_host.c
@@ -110,11 +110,11 @@ int ssusb_host_init(struct ssusb_mtk *ssusb)
int ret;
u3h->ssusb = ssusb;
- u3h->hcd = ssusb->mac_base;
u3h->ippc_base = ssusb->ippc_base;
/* optional property, ignore the error */
- dev_read_u32(dev, "mediatek,u3p-dis-msk", &u3h->u3p_dis_msk);
+ dev_read_u32(ssusb->dev, "mediatek,u3p-dis-msk",
+ &u3h->u3p_dis_msk);
host_ports_num_get(u3h);
ret = ssusb_host_enable(u3h);
@@ -123,12 +123,6 @@ int ssusb_host_init(struct ssusb_mtk *ssusb)
ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
- ret = regulator_set_enable(ssusb->vbus_supply, true);
- if (ret < 0 && ret != -ENOSYS) {
- dev_err(dev, "failed to enable vbus %d!\n", ret);
- return ret;
- }
-
dev_info(dev, "%s done...\n", __func__);
return 0;
@@ -136,6 +130,5 @@ int ssusb_host_init(struct ssusb_mtk *ssusb)
void ssusb_host_exit(struct ssusb_mtk *ssusb)
{
- regulator_set_enable(ssusb->vbus_supply, false);
ssusb_host_disable(ssusb->u3h);
}
diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h
index 9c2a7e1f466..2ac72953e34 100644
--- a/drivers/usb/mtu3/mtu3_hw_regs.h
+++ b/drivers/usb/mtu3/mtu3_hw_regs.h
@@ -11,12 +11,11 @@
#define _SSUSB_HW_REGS_H_
/* segment offset of MAC register */
-#define SSUSB_XCHI_BASE 0x0000
-#define SSUSB_DEV_BASE 0x1000
-#define SSUSB_EPCTL_CSR_BASE 0x1800
-#define SSUSB_USB3_MAC_CSR_BASE 0x2400
-#define SSUSB_USB3_SYS_CSR_BASE 0x2400
-#define SSUSB_USB2_CSR_BASE 0x3400
+#define SSUSB_DEV_BASE 0x0000
+#define SSUSB_EPCTL_CSR_BASE 0x0800
+#define SSUSB_USB3_MAC_CSR_BASE 0x1400
+#define SSUSB_USB3_SYS_CSR_BASE 0x1400
+#define SSUSB_USB2_CSR_BASE 0x2400
/* IPPC register in Infra */
#define SSUSB_SIFSLV_IPPC_BASE 0x0000
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 26fee141f6e..73107167ada 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -135,7 +135,6 @@ static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb)
static int get_ssusb_rscs(struct udevice *dev, struct ssusb_mtk *ssusb)
{
- struct udevice *child;
int ret;
ret = device_get_supply_regulator(dev, "vusb33-supply",
@@ -154,37 +153,20 @@ static int get_ssusb_rscs(struct udevice *dev, struct ssusb_mtk *ssusb)
return ret;
}
- ssusb->ippc_base = devfdt_remap_addr_name(dev, "ippc");
+ ssusb->ippc_base = dev_remap_addr_name(dev, "ippc");
if (!ssusb->ippc_base) {
dev_err(dev, "error mapping memory for ippc\n");
return -ENODEV;
}
- ret = device_find_first_child(dev, &child);
- if (ret || !child) {
- dev_err(dev, "failed to get child %d!\n", ret);
- return ret;
- }
-
- ssusb->mac_base = devfdt_remap_addr_name(child, "mac");
+ ssusb->mac_base = dev_remap_addr_name(dev, "mac");
if (!ssusb->mac_base) {
dev_err(dev, "error mapping memory for mac\n");
return -ENODEV;
}
- ssusb->dr_mode = usb_get_dr_mode(dev_ofnode(child));
-
- if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN ||
- ssusb->dr_mode == USB_DR_MODE_OTG)
- ssusb->dr_mode = USB_DR_MODE_PERIPHERAL;
-
- if (IS_ENABLED(CONFIG_USB_MTU3_GADGET))
- ssusb->dr_mode = USB_DR_MODE_PERIPHERAL;
- else if (IS_ENABLED(CONFIG_USB_MTU3_HOST))
- ssusb->dr_mode = USB_DR_MODE_HOST;
-
- dev_info(dev, "dr_mode: %d, ippc: 0x%p, mac: 0x%p\n",
- ssusb->dr_mode, ssusb->ippc_base, ssusb->mac_base);
+ dev_info(dev, "ippc: 0x%p, mac: 0x%p\n",
+ ssusb->ippc_base, ssusb->mac_base);
return 0;
}
@@ -217,11 +199,6 @@ static int mtu3_remove(struct udevice *dev)
return 0;
}
-static const struct udevice_id ssusb_of_match[] = {
- {.compatible = "mediatek,ssusb",},
- {},
-};
-
#if CONFIG_IS_ENABLED(DM_USB_GADGET)
static int mtu3_gadget_probe(struct udevice *dev)
{
@@ -257,16 +234,90 @@ static const struct usb_gadget_generic_ops mtu3_gadget_ops = {
U_BOOT_DRIVER(mtu3_peripheral) = {
.name = "mtu3-peripheral",
.id = UCLASS_USB_GADGET_GENERIC,
- .of_match = ssusb_of_match,
.ops = &mtu3_gadget_ops,
.probe = mtu3_gadget_probe,
.remove = mtu3_gadget_remove,
.priv_auto = sizeof(struct mtu3),
};
+
+static int mtu3_bind_gadget(struct udevice *parent)
+{
+ struct udevice *dev;
+ int ret;
+
+ /* Node-less device: name it after the controller for diagnostics. */
+ ret = device_bind_driver(parent, "mtu3-peripheral",
+ ofnode_get_name(dev_ofnode(parent)), &dev);
+ if (ret)
+ dev_err(parent, "failed to bind peripheral mode: %d\n", ret);
+
+ return ret;
+}
+#else
+static int mtu3_bind_gadget(struct udevice *parent)
+{
+ return -ENODEV;
+}
#endif
#if defined(CONFIG_SPL_USB_HOST) || \
(!defined(CONFIG_XPL_BUILD) && defined(CONFIG_USB_HOST))
+static int mtu3_host_rscs_init(struct mtu3_host *u3h)
+{
+ struct ssusb_mtk *ssusb = u3h->ssusb;
+ int ret;
+
+ ret = clk_get_bulk(u3h->dev, &u3h->clks);
+ if (ret) {
+ dev_err(u3h->dev, "failed to get clocks %d!\n", ret);
+ return ret;
+ }
+
+ ret = device_get_supply_regulator(u3h->dev, "vusb33-supply",
+ &u3h->vusb33_supply);
+ if (ret)
+ dev_dbg(u3h->dev, "can't get optional vusb33 %d\n", ret);
+
+ ret = device_get_supply_regulator(u3h->dev, "vbus-supply",
+ &u3h->vbus_supply);
+ if (ret) {
+ dev_dbg(u3h->dev, "can't get optional vbus regulator %d\n",
+ ret);
+ u3h->vbus_supply = ssusb->vbus_supply;
+ }
+
+ ret = regulator_set_enable_if_allowed(u3h->vusb33_supply, true);
+ if (ret && ret != -ENOSYS) {
+ dev_err(u3h->dev, "failed to enable vusb33 %d!\n", ret);
+ return ret;
+ }
+
+ ret = regulator_set_enable_if_allowed(u3h->vbus_supply, true);
+ if (ret && ret != -ENOSYS) {
+ dev_err(u3h->dev, "failed to enable vbus %d!\n", ret);
+ goto vbus_err;
+ }
+
+ ret = clk_enable_bulk(&u3h->clks);
+ if (ret)
+ goto clks_err;
+
+ return 0;
+
+clks_err:
+ regulator_set_enable_if_allowed(u3h->vbus_supply, false);
+vbus_err:
+ regulator_set_enable_if_allowed(u3h->vusb33_supply, false);
+ return ret;
+}
+
+static void mtu3_host_rscs_exit(struct mtu3_host *u3h)
+{
+ clk_disable_bulk(&u3h->clks);
+ regulator_set_enable_if_allowed(u3h->vbus_supply, false);
+ regulator_set_enable_if_allowed(u3h->vusb33_supply, false);
+}
+
static int mtu3_host_probe(struct udevice *dev)
{
struct ssusb_mtk *ssusb = dev_to_ssusb(dev->parent);
@@ -276,15 +327,36 @@ static int mtu3_host_probe(struct udevice *dev)
u3h->dev = dev;
ssusb->u3h = u3h;
- rc = ssusb_host_init(ssusb);
+ u3h->ssusb = ssusb;
+ u3h->hcd = dev_remap_addr_name(dev, "mac");
+ if (!u3h->hcd) {
+ dev_err(dev, "error mapping memory for xHCI mac\n");
+ return -ENODEV;
+ }
+
+ rc = mtu3_host_rscs_init(u3h);
if (rc)
return rc;
+ rc = ssusb_host_init(ssusb);
+ if (rc)
+ goto rscs_err;
+
u3h->ctrl.quirks = XHCI_MTK_HOST;
hcor = (struct xhci_hcor *)((uintptr_t)u3h->hcd +
HC_LENGTH(xhci_readl(&u3h->hcd->cr_capbase)));
- return xhci_register(dev, u3h->hcd, hcor);
+ rc = xhci_register(dev, u3h->hcd, hcor);
+ if (rc)
+ goto host_err;
+
+ return 0;
+
+host_err:
+ ssusb_host_exit(ssusb);
+rscs_err:
+ mtu3_host_rscs_exit(u3h);
+ return rc;
}
static int mtu3_host_remove(struct udevice *dev)
@@ -293,68 +365,99 @@ static int mtu3_host_remove(struct udevice *dev)
xhci_deregister(dev);
ssusb_host_exit(u3h->ssusb);
+ mtu3_host_rscs_exit(u3h);
return 0;
}
U_BOOT_DRIVER(mtu3_host) = {
.name = "mtu3-host",
.id = UCLASS_USB,
- .of_match = ssusb_of_match,
.probe = mtu3_host_probe,
.remove = mtu3_host_remove,
.priv_auto = sizeof(struct mtu3_host),
.ops = &xhci_usb_ops,
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
-#endif
-static int mtu3_glue_bind(struct udevice *parent)
+static int mtu3_bind_host(struct udevice *parent)
{
struct udevice *dev;
- enum usb_dr_mode dr_mode;
- const char *driver;
const char *name;
ofnode node;
int ret;
- node = ofnode_by_compatible(dev_ofnode(parent), "mediatek,ssusb");
- if (!ofnode_valid(node))
+ ofnode_for_each_subnode(node, dev_ofnode(parent)) {
+ if (ofnode_is_enabled(node) &&
+ ofnode_device_is_compatible(node, "mediatek,mtk-xhci"))
+ break;
+ }
+ if (!ofnode_valid(node)) {
+ dev_err(parent, "failed to find enabled xHCI child node\n");
return -ENODEV;
+ }
name = ofnode_get_name(node);
- dr_mode = usb_get_dr_mode(node);
+ ret = device_bind_driver_to_node(parent, "mtu3-host", name, node,
+ &dev);
+ if (ret)
+ dev_err(parent, "failed to bind host mode: %d\n", ret);
+
+ return ret;
+}
+#else
+static int mtu3_bind_host(struct udevice *parent)
+{
+ return -ENODEV;
+}
+#endif
+
+static int mtu3_glue_bind(struct udevice *parent)
+{
+ enum usb_dr_mode dr_mode;
+ ofnode node;
+
+ /* Reject the old layout before misinterpreting its register offsets. */
+ ofnode_for_each_subnode(node, dev_ofnode(parent)) {
+ if (ofnode_device_is_compatible(node, "mediatek,ssusb")) {
+ dev_err(parent,
+ "legacy mediatek,ssusb child is unsupported\n");
+ /* Only -ENODEV keeps the failure contained to USB. */
+ return -ENODEV;
+ }
+ }
+
+ dr_mode = usb_get_dr_mode(dev_ofnode(parent));
+ if (dr_mode == USB_DR_MODE_UNKNOWN) {
+ /* Absent defaults to otg, an unparsable value is an error. */
+ if (dev_read_string(parent, "dr_mode")) {
+ dev_err(parent, "invalid dr_mode\n");
+ return -ENODEV;
+ }
+
+ dr_mode = USB_DR_MODE_OTG;
+ }
switch (dr_mode) {
-#if CONFIG_IS_ENABLED(DM_USB_GADGET)
case USB_DR_MODE_PERIPHERAL:
- case USB_DR_MODE_OTG:
- dev_dbg(parent, "%s: dr_mode: peripheral\n", __func__);
- driver = "mtu3-peripheral";
+ if (CONFIG_IS_ENABLED(USB_MTU3_GADGET))
+ return mtu3_bind_gadget(parent);
break;
-#endif
-
-#if defined(CONFIG_SPL_USB_HOST) || \
- (!defined(CONFIG_XPL_BUILD) && defined(CONFIG_USB_HOST))
case USB_DR_MODE_HOST:
- dev_dbg(parent, "%s: dr_mode: host\n", __func__);
- driver = "mtu3-host";
+ if (CONFIG_IS_ENABLED(USB_MTU3_HOST))
+ return mtu3_bind_host(parent);
+ break;
+ case USB_DR_MODE_OTG:
+ if (CONFIG_IS_ENABLED(USB_MTU3_GADGET))
+ return mtu3_bind_gadget(parent);
+ if (CONFIG_IS_ENABLED(USB_MTU3_HOST))
+ return mtu3_bind_host(parent);
break;
-#endif
default:
- dev_err(parent, "%s: unsupported dr_mode %d\n",
- __func__, dr_mode);
- return -ENODEV;
- };
-
- dev_dbg(parent, "%s: node name: %s, driver %s, dr_mode %d\n",
- __func__, name, driver, dr_mode);
-
- ret = device_bind_driver_to_node(parent, driver, name, node, &dev);
- if (ret)
- dev_err(parent, "%s: not able to bind usb device mode\n",
- __func__);
+ break;
+ }
- return ret;
+ dev_err(parent, "dr_mode %d is unsupported by this build\n", dr_mode);
+ return -ENODEV;
}
static const struct udevice_id mtu3_of_match[] = {
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index b91727e1265..3c56c541505 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -130,11 +130,11 @@ config WDT_ASPEED
Second Boot.
config WDT_AST2600
- bool "Aspeed AST2600 watchdog timer support"
- depends on WDT && ASPEED_AST2600
+ bool "Aspeed AST2600/AST2700 watchdog timer support"
+ depends on WDT && (ASPEED_AST2600 || ASPEED_AST2700)
default y
help
- Select this to enable watchdog timer for Aspeed ast2500/ast2400 devices.
+ Select this to enable watchdog timer for Aspeed ast2600/ast2700 devices.
The watchdog timer is stopped when initialized. It performs reset, either
full SoC reset or CPU or just some peripherals, based on the flags.
diff --git a/drivers/watchdog/ast2600_wdt.c b/drivers/watchdog/ast2600_wdt.c
index 190490f3692..5eb9b4ba96f 100644
--- a/drivers/watchdog/ast2600_wdt.c
+++ b/drivers/watchdog/ast2600_wdt.c
@@ -87,6 +87,7 @@ static const struct wdt_ops ast2600_wdt_ops = {
static const struct udevice_id ast2600_wdt_ids[] = {
{ .compatible = "aspeed,ast2600-wdt" },
+ { .compatible = "aspeed,ast2700-wdt" },
{ }
};