mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/18] Add Rockchip RK3588 support
@ 2023-05-04  8:17 Sascha Hauer
  2023-05-04  8:17 ` [PATCH 01/18] firmware: make drivers/firmware/ obj-y Sascha Hauer
                   ` (17 more replies)
  0 siblings, 18 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

This adds support for the Rockchip RK3588 along with the Radxa ROCK 5B
board.

As the ROCK 5B has ethernet connected via PCIe this series adds support
for that as well. The existing r8169 driver needed a major update to
support the RTL8125 found on the board.

Unfortunately I didn't manage to get eMMC and SD working, so for now
the board has ethernet, but no storage at all.

Sascha

Sascha Hauer (18):
  firmware: make drivers/firmware/ obj-y
  stddef: add sizeof_field()
  pci: add pci_select_bars() helper
  pci: set upper word for 64bit base addresses
  ARM: SCMI: Use correct smc/hvc instructions on ARM64
  clk: rockchip: Add rk3588 support
  pinctrl: rockchip: Move struct definitions to separate header file
  pinctrl/gpio: rockchip: separate gpio from pinctrl driver
  pinctrl: Update pinctrl-rockchip from kernel
  phy: rockchip: naneng-combphy: add rk3588 support
  reset: Implement reset array support
  pci: designware: add rockchip support
  phy: realtek: Add RTL8125 internal phy support
  net: Update Realtek r8169 driver
  ARM: rockchip: Add rk3588 support
  ARM: dts: Add rk3588 device trees
  ARM: rockchip: rk3588: add memsize detection
  ARM: rockchip: Add Radxa ROCK 5B support

 arch/arm/Kconfig                              |    1 +
 arch/arm/boards/Makefile                      |    1 +
 arch/arm/boards/radxa-rock5/.gitignore        |    1 +
 arch/arm/boards/radxa-rock5/Makefile          |    3 +
 arch/arm/boards/radxa-rock5/board.c           |   55 +
 arch/arm/boards/radxa-rock5/lowlevel.c        |   25 +
 arch/arm/dts/Makefile                         |    1 +
 arch/arm/dts/rk3588-rock-5b.dts               |  110 +
 arch/arm/dts/rk3588.dtsi                      |  152 +
 arch/arm/dts/rk3588s.dtsi                     |  135 +
 arch/arm/mach-rockchip/Kconfig                |   12 +
 arch/arm/mach-rockchip/Makefile               |    1 +
 arch/arm/mach-rockchip/atf.c                  |   35 +
 arch/arm/mach-rockchip/dmc.c                  |   52 +-
 arch/arm/mach-rockchip/rk3588.c               |   20 +
 arch/arm/mach-rockchip/rockchip.c             |    5 +
 common/Kconfig                                |    9 +
 drivers/Makefile                              |    2 +-
 drivers/clk/rockchip/Makefile                 |    1 +
 drivers/clk/rockchip/clk-pll.c                |  226 +-
 drivers/clk/rockchip/clk-rk3588.c             | 2529 +++++++++++++
 drivers/clk/rockchip/clk.h                    |  145 +-
 drivers/clk/rockchip/rst-rk3588.c             |  855 +++++
 drivers/clk/rockchip/softrst.c                |   34 +-
 drivers/gpio/Kconfig                          |    7 +
 drivers/gpio/Makefile                         |    1 +
 drivers/gpio/gpio-rockchip.c                  |  196 +
 drivers/net/Kconfig                           |    1 +
 drivers/net/Makefile                          |    2 +-
 drivers/net/phy/realtek.c                     |    6 +
 drivers/net/r8169.h                           |   79 +
 drivers/net/r8169_firmware.c                  |  237 ++
 drivers/net/r8169_firmware.h                  |   36 +
 drivers/net/r8169_main.c                      | 3214 +++++++++++++++++
 drivers/net/r8169_phy_config.c                | 1156 ++++++
 drivers/net/rtl8169.c                         |  562 ---
 drivers/pci/Kconfig                           |    7 +
 drivers/pci/Makefile                          |    1 +
 drivers/pci/pci.c                             |   18 +-
 drivers/pci/pcie-dw-rockchip.c                |  299 ++
 .../rockchip/phy-rockchip-naneng-combphy.c    |  278 ++
 drivers/pinctrl/pinctrl-rockchip.c            | 3174 ++++++++++++----
 drivers/pinctrl/pinctrl-rockchip.h            |  452 +++
 drivers/reset/core.c                          |  127 +
 firmware/Makefile                             |    2 +
 images/Makefile.rockchip                      |    7 +
 include/linux/arm-smccc.h                     |    4 +-
 include/linux/pci.h                           |    1 +
 include/linux/reset.h                         |    7 +
 include/linux/stddef.h                        |    8 +
 include/mach/rockchip/atf.h                   |    6 +
 include/mach/rockchip/debug_ll.h              |    6 +
 include/mach/rockchip/dmc.h                   |    1 +
 include/mach/rockchip/rk3588-regs.h           |   20 +
 include/mach/rockchip/rockchip.h              |   10 +
 55 files changed, 12985 insertions(+), 1350 deletions(-)
 create mode 100644 arch/arm/boards/radxa-rock5/.gitignore
 create mode 100644 arch/arm/boards/radxa-rock5/Makefile
 create mode 100644 arch/arm/boards/radxa-rock5/board.c
 create mode 100644 arch/arm/boards/radxa-rock5/lowlevel.c
 create mode 100644 arch/arm/dts/rk3588-rock-5b.dts
 create mode 100644 arch/arm/dts/rk3588.dtsi
 create mode 100644 arch/arm/dts/rk3588s.dtsi
 create mode 100644 arch/arm/mach-rockchip/rk3588.c
 create mode 100644 drivers/clk/rockchip/clk-rk3588.c
 create mode 100644 drivers/clk/rockchip/rst-rk3588.c
 create mode 100644 drivers/gpio/gpio-rockchip.c
 create mode 100644 drivers/net/r8169.h
 create mode 100644 drivers/net/r8169_firmware.c
 create mode 100644 drivers/net/r8169_firmware.h
 create mode 100644 drivers/net/r8169_main.c
 create mode 100644 drivers/net/r8169_phy_config.c
 delete mode 100644 drivers/net/rtl8169.c
 create mode 100644 drivers/pci/pcie-dw-rockchip.c
 create mode 100644 drivers/pinctrl/pinctrl-rockchip.h
 create mode 100644 include/mach/rockchip/rk3588-regs.h

-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 01/18] firmware: make drivers/firmware/ obj-y
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 02/18] stddef: add sizeof_field() Sascha Hauer
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

drivers/firmware/ contains ARM SCMI support which doesn't depend on
CONFIG_FIRMWARE. Unconditionally compile drivers/firmware/ to make
sure SCMI support can be compiled in with CONFIG_FIRMWARE disabled.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/Makefile b/drivers/Makefile
index 41a2054db0..fa899a2ab8 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_REMOTEPROC) += remoteproc/
 obj-$(CONFIG_RESET_CONTROLLER) += reset/
 obj-$(CONFIG_PCI) += pci/
 obj-y += rtc/
-obj-$(CONFIG_FIRMWARE) += firmware/
+obj-y += firmware/
 obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_GENERIC_PHY) += phy/
 obj-$(CONFIG_HAB) += hab/
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 02/18] stddef: add sizeof_field()
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
  2023-05-04  8:17 ` [PATCH 01/18] firmware: make drivers/firmware/ obj-y Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 03/18] pci: add pci_select_bars() helper Sascha Hauer
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/linux/stddef.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index 5429a7b582..1044571c3f 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -24,4 +24,12 @@ typedef unsigned short wchar_t;
 #undef offsetof
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 
+/**
+ * sizeof_field() - Report the size of a struct field in bytes
+ *
+ * @TYPE: The structure containing the field of interest
+ * @MEMBER: The field to return the size of
+ */
+#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
+
 #endif
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 03/18] pci: add pci_select_bars() helper
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
  2023-05-04  8:17 ` [PATCH 01/18] firmware: make drivers/firmware/ obj-y Sascha Hauer
  2023-05-04  8:17 ` [PATCH 02/18] stddef: add sizeof_field() Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 04/18] pci: set upper word for 64bit base addresses Sascha Hauer
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

pci_select_bars() will be needed later in the updated RTL8169 driver.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pci.c   | 16 ++++++++++++++++
 include/linux/pci.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 53e8faeb3e..57a7a75f84 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -539,6 +539,22 @@ int pci_enable_device(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_enable_device);
 
+/**
+ * pci_select_bars - Make BAR mask from the type of resource
+ * @dev: the PCI device for which BAR mask is made
+ * @flags: resource type mask to be selected
+ *
+ * This helper routine makes bar mask from the type of resource.
+ */
+int pci_select_bars(struct pci_dev *dev, unsigned long flags)
+{
+	int i, bars = 0;
+	for (i = 0; i < PCI_NUM_RESOURCES; i++)
+		if (pci_resource_flags(dev, i) & flags)
+			bars |= (1 << i);
+	return bars;
+}
+
 static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
 				  u8 pos, int cap, int *ttl)
 {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 31488bf8ac..98d056624f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -326,6 +326,7 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where,
 void pci_set_master(struct pci_dev *dev);
 void pci_clear_master(struct pci_dev *dev);
 int pci_enable_device(struct pci_dev *dev);
+int pci_select_bars(struct pci_dev *dev, unsigned long flags);
 
 u8 pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
 u8 pci_find_capability(struct pci_dev *dev, int cap);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 04/18] pci: set upper word for 64bit base addresses
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (2 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 03/18] pci: add pci_select_bars() helper Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 05/18] ARM: SCMI: Use correct smc/hvc instructions on ARM64 Sascha Hauer
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Set the upper word correctly when the PCI address space is outside
the 32bit range.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 57a7a75f84..046711cd14 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -223,7 +223,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			*last_addr = ALIGN(*last_addr, size);
 			pci_write_config_dword(dev, pci_base_address_0, *last_addr);
 			if (mask & PCI_BASE_ADDRESS_MEM_TYPE_64)
-				pci_write_config_dword(dev, pci_base_address_1, 0);
+				pci_write_config_dword(dev, pci_base_address_1, *last_addr >> 32);
 			start = *last_addr;
 			*last_addr += size;
 		} else {
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 05/18] ARM: SCMI: Use correct smc/hvc instructions on ARM64
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (3 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 04/18] pci: set upper word for 64bit base addresses Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 06/18] clk: rockchip: Add rk3588 support Sascha Hauer
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

We don't have a CONFIG_ARM64 symbol, so we'll always select the ARM32
smc/hvc variants. Use the correct CONFIG_CPU_64 to fix that.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/linux/arm-smccc.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 64ee3863a6..f6942c6420 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -286,12 +286,12 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
 
 /* SMCCC v1.1 implementation madness follows */
-#ifdef CONFIG_ARM64
+#ifdef CONFIG_CPU_64
 
 #define SMCCC_SMC_INST	"smc	#0"
 #define SMCCC_HVC_INST	"hvc	#0"
 
-#elif defined(CONFIG_ARM)
+#elif defined(CONFIG_CPU_32)
 #include <asm/opcodes-sec.h>
 #include <asm/opcodes-virt.h>
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 06/18] clk: rockchip: Add rk3588 support
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (4 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 05/18] ARM: SCMI: Use correct smc/hvc instructions on ARM64 Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 07/18] pinctrl: rockchip: Move struct definitions to separate header file Sascha Hauer
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

This adds the rk3588 clk support from Linux-6.3-rc7 without much
changes.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/rockchip/Makefile     |    1 +
 drivers/clk/rockchip/clk-pll.c    |  226 ++-
 drivers/clk/rockchip/clk-rk3588.c | 2529 +++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h        |  145 +-
 drivers/clk/rockchip/rst-rk3588.c |  855 ++++++++++
 drivers/clk/rockchip/softrst.c    |   34 +-
 6 files changed, 3757 insertions(+), 33 deletions(-)
 create mode 100644 drivers/clk/rockchip/clk-rk3588.c
 create mode 100644 drivers/clk/rockchip/rst-rk3588.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 7adbaf266f..f01014da0c 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_ARCH_RK3188) += clk-rk3188.o
 obj-$(CONFIG_ARCH_RK3288) += clk-rk3288.o
 obj-$(CONFIG_ARCH_RK3399) += clk-rk3399.o
 obj-$(CONFIG_ARCH_RK3568) += clk-rk3568.o
+obj-$(CONFIG_ARCH_RK3588) += clk-rk3588.o rst-rk3588.o
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index a45a445de6..68e680d6ea 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -841,6 +841,213 @@ static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
 	.init = rockchip_rk3399_pll_init,
 };
 
+/*
+ * PLL used in RK3588
+ */
+
+#define RK3588_PLLCON(i)               (i * 0x4)
+#define RK3588_PLLCON0_M_MASK          0x3ff
+#define RK3588_PLLCON0_M_SHIFT         0
+#define RK3588_PLLCON1_P_MASK          0x3f
+#define RK3588_PLLCON1_P_SHIFT         0
+#define RK3588_PLLCON1_S_MASK          0x7
+#define RK3588_PLLCON1_S_SHIFT         6
+#define RK3588_PLLCON2_K_MASK          0xffff
+#define RK3588_PLLCON2_K_SHIFT         0
+#define RK3588_PLLCON1_PWRDOWN         BIT(13)
+#define RK3588_PLLCON6_LOCK_STATUS     BIT(15)
+
+static int rockchip_rk3588_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+	u32 pllcon;
+	int ret;
+
+	/*
+	 * Lock time typical 250, max 500 input clock cycles @24MHz
+	 * So define a very safe maximum of 1000us, meaning 24000 cycles.
+	 */
+	ret = readl_poll_timeout(pll->reg_base + RK3588_PLLCON(6),
+					 pllcon,
+					 pllcon & RK3588_PLLCON6_LOCK_STATUS,
+					 1000);
+	if (ret)
+		pr_err("%s: timeout waiting for pll to lock\n", __func__);
+
+	return ret;
+}
+
+static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll,
+					   struct rockchip_pll_rate_table *rate)
+{
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(0));
+	rate->m = ((pllcon >> RK3588_PLLCON0_M_SHIFT) & RK3588_PLLCON0_M_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1));
+	rate->p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) & RK3588_PLLCON1_P_MASK);
+	rate->s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) & RK3588_PLLCON1_S_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(2));
+	rate->k = ((pllcon >> RK3588_PLLCON2_K_SHIFT) & RK3588_PLLCON2_K_MASK);
+}
+
+static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	struct rockchip_pll_rate_table cur;
+	u64 rate64 = prate, postdiv;
+
+	rockchip_rk3588_pll_get_params(pll, &cur);
+
+	rate64 *= cur.m;
+	do_div(rate64, cur.p);
+
+	if (cur.k) {
+		/* fractional mode */
+		u64 frac_rate64 = prate * cur.k;
+
+		postdiv = cur.p * 65535;
+		do_div(frac_rate64, postdiv);
+		rate64 += frac_rate64;
+	}
+	rate64 = rate64 >> cur.s;
+
+	return (unsigned long)rate64;
+}
+
+static int rockchip_rk3588_pll_set_params(struct rockchip_clk_pll *pll,
+					  const struct rockchip_pll_rate_table *rate)
+{
+	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+	struct clk_mux *pll_mux = &pll->pll_mux;
+	struct rockchip_pll_rate_table cur;
+	int rate_change_remuxed = 0;
+	int cur_parent;
+	int ret;
+
+	pr_debug("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n",
+		 __func__, rate->rate, rate->p, rate->m, rate->s, rate->k);
+
+	rockchip_rk3588_pll_get_params(pll, &cur);
+	cur.rate = 0;
+
+	if (pll->type == pll_rk3588) {
+		cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+		if (cur_parent == PLL_MODE_NORM) {
+			pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+			rate_change_remuxed = 1;
+		}
+	}
+
+	/* set pll power down */
+	writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN,
+			     RK3588_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3399_PLLCON(1));
+
+	/* update pll values */
+	writel_relaxed(HIWORD_UPDATE(rate->m, RK3588_PLLCON0_M_MASK, RK3588_PLLCON0_M_SHIFT),
+		       pll->reg_base + RK3399_PLLCON(0));
+
+	writel_relaxed(HIWORD_UPDATE(rate->p, RK3588_PLLCON1_P_MASK, RK3588_PLLCON1_P_SHIFT) |
+		       HIWORD_UPDATE(rate->s, RK3588_PLLCON1_S_MASK, RK3588_PLLCON1_S_SHIFT),
+		       pll->reg_base + RK3399_PLLCON(1));
+
+	writel_relaxed(HIWORD_UPDATE(rate->k, RK3588_PLLCON2_K_MASK, RK3588_PLLCON2_K_SHIFT),
+		       pll->reg_base + RK3399_PLLCON(2));
+
+	/* set pll power up */
+	writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3588_PLLCON(1));
+
+	/* wait for the pll to lock */
+	ret = rockchip_rk3588_pll_wait_lock(pll);
+	if (ret) {
+		pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
+			__func__);
+		rockchip_rk3588_pll_set_params(pll, &cur);
+	}
+
+	if ((pll->type == pll_rk3588) && rate_change_remuxed)
+		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+	return ret;
+}
+
+static int rockchip_rk3588_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+
+	pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+		 __func__, clk_hw_get_name(hw), drate, prate);
+
+	/* Get required rate settings from table */
+	rate = rockchip_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, clk_hw_get_name(hw));
+		return -EINVAL;
+	}
+
+	return rockchip_rk3588_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3588_pll_enable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3588_PLLCON(1));
+	rockchip_rk3588_pll_wait_lock(pll);
+
+	return 0;
+}
+
+static void rockchip_rk3588_pll_disable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, RK3588_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3588_PLLCON(1));
+}
+
+static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	u32 pllcon = readl(pll->reg_base + RK3588_PLLCON(1));
+
+	return !(pllcon & RK3588_PLLCON1_PWRDOWN);
+}
+
+static int rockchip_rk3588_pll_init(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+		return 0;
+
+	return 0;
+}
+
+static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
+	.recalc_rate = rockchip_rk3588_pll_recalc_rate,
+	.enable = rockchip_rk3588_pll_enable,
+	.disable = rockchip_rk3588_pll_disable,
+	.is_enabled = rockchip_rk3588_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3588_pll_clk_ops = {
+	.recalc_rate = rockchip_rk3588_pll_recalc_rate,
+	.round_rate = rockchip_pll_round_rate,
+	.set_rate = rockchip_rk3588_pll_set_rate,
+	.enable = rockchip_rk3588_pll_enable,
+	.disable = rockchip_rk3588_pll_disable,
+	.is_enabled = rockchip_rk3588_pll_is_enabled,
+	.init = rockchip_rk3588_pll_init,
+};
+
 /*
  * Common registering of pll clocks
  */
@@ -853,7 +1060,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
 		struct rockchip_pll_rate_table *rate_table,
 		unsigned long flags, u8 clk_pll_flags)
 {
-	const char *pll_parents[3] = {};
+	const char *pll_parents[3];
 	struct clk_init_data init;
 	struct rockchip_clk_pll *pll;
 	struct clk_mux *pll_mux;
@@ -889,14 +1096,14 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
 	if (pll_type == pll_rk3036 ||
 	    pll_type == pll_rk3066 ||
 	    pll_type == pll_rk3328 ||
-	    pll_type == pll_rk3399)
+	    pll_type == pll_rk3399 ||
+	    pll_type == pll_rk3588)
 		pll_mux->flags |= CLK_MUX_HIWORD_MASK;
 
 	/* the actual muxing is xin24m, pll-output, xin32k */
 	pll_parents[0] = parent_names[0];
 	pll_parents[1] = pll_name;
-	if (num_parents > 1)
-		pll_parents[2] = parent_names[1];
+	pll_parents[2] = parent_names[1];
 
 	init.name = name;
 	init.flags = CLK_SET_RATE_PARENT;
@@ -940,7 +1147,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
 	switch (pll_type) {
 	case pll_rk3036:
 	case pll_rk3328:
-		if (!pll->rate_table || IS_ERR(ctx->grf))
+		if (!pll->rate_table)
 			init.ops = &rockchip_rk3036_pll_clk_norate_ops;
 		else
 			init.ops = &rockchip_rk3036_pll_clk_ops;
@@ -957,6 +1164,14 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
 		else
 			init.ops = &rockchip_rk3399_pll_clk_ops;
 		break;
+	case pll_rk3588:
+	case pll_rk3588_core:
+		if (!pll->rate_table)
+			init.ops = &rockchip_rk3588_pll_clk_norate_ops;
+		else
+			init.ops = &rockchip_rk3588_pll_clk_ops;
+		init.flags = flags;
+		break;
 	default:
 		pr_warn("%s: Unknown pll type for pll clk %s\n",
 			__func__, name);
@@ -981,6 +1196,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
 	return mux_clk;
 
 err_pll:
+	kfree(pll->rate_table);
 	clk_unregister(mux_clk);
 	mux_clk = pll_clk;
 err_mux:
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
new file mode 100644
index 0000000000..2d31a7f7d5
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3588.c
@@ -0,0 +1,2529 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#include <common.h>
+#include <linux/clk.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/barebox-wrapper.h>
+#include <init.h>
+#include <linux/spinlock.h>
+#include <of_device.h>
+#include <dt-bindings/clock/rockchip,rk3588-cru.h>
+#include "clk.h"
+
+/*
+ * GATE with additional linked clock. Downstream enables the linked clock
+ * (via runtime PM) whenever the gate is enabled. The downstream implementation
+ * does this via separate clock nodes for each of the linked gate clocks,
+ * which leaks parts of the clock tree into DT. It is unclear why this is
+ * actually needed and things work without it for simple use cases. Thus
+ * the linked clock is ignored for now.
+ */
+#define GATE_LINK(_id, cname, pname, linkname, f, o, b, gf) \
+	GATE(_id, cname, pname, f, o, b, gf)
+
+
+#define RK3588_GRF_SOC_STATUS0		0x600
+#define RK3588_PHYREF_ALT_GATE		0xc38
+
+enum rk3588_plls {
+	b0pll, b1pll, lpll, v0pll, aupll, cpll, gpll, npll, ppll,
+};
+
+static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
+	/* _mhz, _p, _m, _s, _k */
+	RK3588_PLL_RATE(2520000000, 2, 210, 0, 0),
+	RK3588_PLL_RATE(2496000000, 2, 208, 0, 0),
+	RK3588_PLL_RATE(2472000000, 2, 206, 0, 0),
+	RK3588_PLL_RATE(2448000000, 2, 204, 0, 0),
+	RK3588_PLL_RATE(2424000000, 2, 202, 0, 0),
+	RK3588_PLL_RATE(2400000000, 2, 200, 0, 0),
+	RK3588_PLL_RATE(2376000000, 2, 198, 0, 0),
+	RK3588_PLL_RATE(2352000000, 2, 196, 0, 0),
+	RK3588_PLL_RATE(2328000000, 2, 194, 0, 0),
+	RK3588_PLL_RATE(2304000000, 2, 192, 0, 0),
+	RK3588_PLL_RATE(2280000000, 2, 190, 0, 0),
+	RK3588_PLL_RATE(2256000000, 2, 376, 1, 0),
+	RK3588_PLL_RATE(2232000000, 2, 372, 1, 0),
+	RK3588_PLL_RATE(2208000000, 2, 368, 1, 0),
+	RK3588_PLL_RATE(2184000000, 2, 364, 1, 0),
+	RK3588_PLL_RATE(2160000000, 2, 360, 1, 0),
+	RK3588_PLL_RATE(2136000000, 2, 356, 1, 0),
+	RK3588_PLL_RATE(2112000000, 2, 352, 1, 0),
+	RK3588_PLL_RATE(2088000000, 2, 348, 1, 0),
+	RK3588_PLL_RATE(2064000000, 2, 344, 1, 0),
+	RK3588_PLL_RATE(2040000000, 2, 340, 1, 0),
+	RK3588_PLL_RATE(2016000000, 2, 336, 1, 0),
+	RK3588_PLL_RATE(1992000000, 2, 332, 1, 0),
+	RK3588_PLL_RATE(1968000000, 2, 328, 1, 0),
+	RK3588_PLL_RATE(1944000000, 2, 324, 1, 0),
+	RK3588_PLL_RATE(1920000000, 2, 320, 1, 0),
+	RK3588_PLL_RATE(1896000000, 2, 316, 1, 0),
+	RK3588_PLL_RATE(1872000000, 2, 312, 1, 0),
+	RK3588_PLL_RATE(1848000000, 2, 308, 1, 0),
+	RK3588_PLL_RATE(1824000000, 2, 304, 1, 0),
+	RK3588_PLL_RATE(1800000000, 2, 300, 1, 0),
+	RK3588_PLL_RATE(1776000000, 2, 296, 1, 0),
+	RK3588_PLL_RATE(1752000000, 2, 292, 1, 0),
+	RK3588_PLL_RATE(1728000000, 2, 288, 1, 0),
+	RK3588_PLL_RATE(1704000000, 2, 284, 1, 0),
+	RK3588_PLL_RATE(1680000000, 2, 280, 1, 0),
+	RK3588_PLL_RATE(1656000000, 2, 276, 1, 0),
+	RK3588_PLL_RATE(1632000000, 2, 272, 1, 0),
+	RK3588_PLL_RATE(1608000000, 2, 268, 1, 0),
+	RK3588_PLL_RATE(1584000000, 2, 264, 1, 0),
+	RK3588_PLL_RATE(1560000000, 2, 260, 1, 0),
+	RK3588_PLL_RATE(1536000000, 2, 256, 1, 0),
+	RK3588_PLL_RATE(1512000000, 2, 252, 1, 0),
+	RK3588_PLL_RATE(1488000000, 2, 248, 1, 0),
+	RK3588_PLL_RATE(1464000000, 2, 244, 1, 0),
+	RK3588_PLL_RATE(1440000000, 2, 240, 1, 0),
+	RK3588_PLL_RATE(1416000000, 2, 236, 1, 0),
+	RK3588_PLL_RATE(1392000000, 2, 232, 1, 0),
+	RK3588_PLL_RATE(1320000000, 2, 220, 1, 0),
+	RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
+	RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
+	RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
+	RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
+	RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
+	RK3588_PLL_RATE(983040000, 4, 655, 2, 23592),
+	RK3588_PLL_RATE(955520000, 3, 477, 2, 49806),
+	RK3588_PLL_RATE(903168000, 6, 903, 2, 11009),
+	RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
+	RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
+	RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
+	RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
+	RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
+	RK3588_PLL_RATE(785560000, 3, 392, 2, 51117),
+	RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
+	RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
+	RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
+	RK3588_PLL_RATE(408000000, 2, 272, 3, 0),
+	RK3588_PLL_RATE(312000000, 2, 208, 3, 0),
+	RK3588_PLL_RATE(216000000, 2, 288, 4, 0),
+	RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
+	RK3588_PLL_RATE(96000000, 2, 256, 5, 0),
+	{ /* sentinel */ },
+};
+
+#define RK3588_CLK_CORE_B0_SEL_CLEAN_MASK	0x3
+#define RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT	13
+#define RK3588_CLK_CORE_B1_SEL_CLEAN_MASK	0x3
+#define RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT	5
+#define RK3588_CLK_CORE_B0_GPLL_DIV_MASK	0x1f
+#define RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT	1
+#define RK3588_CLK_CORE_L_SEL_CLEAN_MASK	0x3
+#define RK3588_CLK_CORE_L1_SEL_CLEAN_SHIFT	12
+#define RK3588_CLK_CORE_L0_SEL_CLEAN_SHIFT	5
+#define RK3588_CLK_DSU_SEL_DF_MASK		0x1
+#define RK3588_CLK_DSU_SEL_DF_SHIFT		15
+#define RK3588_CLK_DSU_DF_SRC_MASK		0x3
+#define RK3588_CLK_DSU_DF_SRC_SHIFT		12
+#define RK3588_CLK_DSU_DF_DIV_MASK		0x1f
+#define RK3588_CLK_DSU_DF_DIV_SHIFT		7
+#define RK3588_ACLKM_DSU_DIV_MASK		0x1f
+#define RK3588_ACLKM_DSU_DIV_SHIFT		1
+#define RK3588_ACLKS_DSU_DIV_MASK		0x1f
+#define RK3588_ACLKS_DSU_DIV_SHIFT		6
+#define RK3588_ACLKMP_DSU_DIV_MASK		0x1f
+#define RK3588_ACLKMP_DSU_DIV_SHIFT		11
+#define RK3588_PERIPH_DSU_DIV_MASK		0x1f
+#define RK3588_PERIPH_DSU_DIV_SHIFT		0
+#define RK3588_ATCLK_DSU_DIV_MASK		0x1f
+#define RK3588_ATCLK_DSU_DIV_SHIFT		0
+#define RK3588_GICCLK_DSU_DIV_MASK		0x1f
+#define RK3588_GICCLK_DSU_DIV_SHIFT		5
+
+#define RK3588_CORE_B0_SEL(_apllcore)						\
+{										\
+	.reg = RK3588_BIGCORE0_CLKSEL_CON(0),					\
+	.val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B0_SEL_CLEAN_MASK,	\
+			RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT) |			\
+		HIWORD_UPDATE(0, RK3588_CLK_CORE_B0_GPLL_DIV_MASK,		\
+			RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT),			\
+}
+
+#define RK3588_CORE_B1_SEL(_apllcore)						\
+{										\
+	.reg = RK3588_BIGCORE0_CLKSEL_CON(1),					\
+	.val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B1_SEL_CLEAN_MASK,	\
+			RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT),			\
+}
+
+#define RK3588_CORE_B2_SEL(_apllcore)						\
+{										\
+	.reg = RK3588_BIGCORE1_CLKSEL_CON(0),					\
+	.val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B0_SEL_CLEAN_MASK,	\
+			RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT) |			\
+		HIWORD_UPDATE(0, RK3588_CLK_CORE_B0_GPLL_DIV_MASK,		\
+			RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT),			\
+}
+
+#define RK3588_CORE_B3_SEL(_apllcore)						\
+{										\
+	.reg = RK3588_BIGCORE1_CLKSEL_CON(1),					\
+	.val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B1_SEL_CLEAN_MASK,	\
+			RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT),			\
+}
+
+#define RK3588_CORE_L_SEL0(_offs, _apllcore)					\
+{										\
+	.reg = RK3588_DSU_CLKSEL_CON(6 + _offs),				\
+	.val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_L_SEL_CLEAN_MASK,	\
+			RK3588_CLK_CORE_L0_SEL_CLEAN_SHIFT) |			\
+		HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_L_SEL_CLEAN_MASK,	\
+			RK3588_CLK_CORE_L1_SEL_CLEAN_SHIFT),			\
+}
+
+#define RK3588_CORE_L_SEL1(_seldsu, _divdsu)				\
+{									\
+	.reg = RK3588_DSU_CLKSEL_CON(0),				\
+	.val = HIWORD_UPDATE(_seldsu, RK3588_CLK_DSU_DF_SRC_MASK,	\
+			RK3588_CLK_DSU_DF_SRC_SHIFT) |			\
+		HIWORD_UPDATE(_divdsu - 1, RK3588_CLK_DSU_DF_DIV_MASK,	\
+			RK3588_CLK_DSU_DF_DIV_SHIFT),			\
+}
+
+#define RK3588_CORE_L_SEL2(_aclkm, _aclkmp, _aclks)			\
+{									\
+	.reg = RK3588_DSU_CLKSEL_CON(1),				\
+	.val = HIWORD_UPDATE(_aclkm - 1, RK3588_ACLKM_DSU_DIV_MASK,	\
+			RK3588_ACLKM_DSU_DIV_SHIFT) |			\
+		HIWORD_UPDATE(_aclkmp - 1, RK3588_ACLKMP_DSU_DIV_MASK,	\
+			RK3588_ACLKMP_DSU_DIV_SHIFT) |			\
+		HIWORD_UPDATE(_aclks - 1, RK3588_ACLKS_DSU_DIV_MASK,	\
+			RK3588_ACLKS_DSU_DIV_SHIFT),			\
+}
+
+#define RK3588_CORE_L_SEL3(_periph)					\
+{									\
+	.reg = RK3588_DSU_CLKSEL_CON(2),				\
+	.val = HIWORD_UPDATE(_periph - 1, RK3588_PERIPH_DSU_DIV_MASK,	\
+			RK3588_PERIPH_DSU_DIV_SHIFT),			\
+}
+
+#define RK3588_CORE_L_SEL4(_gicclk, _atclk)				\
+{									\
+	.reg = RK3588_DSU_CLKSEL_CON(3),				\
+	.val = HIWORD_UPDATE(_gicclk - 1, RK3588_GICCLK_DSU_DIV_MASK,	\
+			RK3588_GICCLK_DSU_DIV_SHIFT) |			\
+		HIWORD_UPDATE(_atclk - 1, RK3588_ATCLK_DSU_DIV_MASK,	\
+			RK3588_ATCLK_DSU_DIV_SHIFT),			\
+}
+
+#define RK3588_CPUB01CLK_RATE(_prate, _apllcore)		\
+{								\
+	.prate = _prate##U,					\
+	.pre_muxs = {						\
+		RK3588_CORE_B0_SEL(0),				\
+		RK3588_CORE_B1_SEL(0),				\
+	},							\
+	.post_muxs = {						\
+		RK3588_CORE_B0_SEL(_apllcore),			\
+		RK3588_CORE_B1_SEL(_apllcore),			\
+	},							\
+}
+
+#define RK3588_CPUB23CLK_RATE(_prate, _apllcore)		\
+{								\
+	.prate = _prate##U,					\
+	.pre_muxs = {						\
+		RK3588_CORE_B2_SEL(0),				\
+		RK3588_CORE_B3_SEL(0),				\
+	},							\
+	.post_muxs = {						\
+		RK3588_CORE_B2_SEL(_apllcore),			\
+		RK3588_CORE_B3_SEL(_apllcore),			\
+	},							\
+}
+
+#define RK3588_CPULCLK_RATE(_prate, _apllcore, _seldsu, _divdsu) \
+{								\
+	.prate = _prate##U,					\
+	.pre_muxs = {						\
+		RK3588_CORE_L_SEL0(0, 0),			\
+		RK3588_CORE_L_SEL0(1, 0),			\
+		RK3588_CORE_L_SEL1(3, 2),			\
+		RK3588_CORE_L_SEL2(2, 3, 3),			\
+		RK3588_CORE_L_SEL3(4),				\
+		RK3588_CORE_L_SEL4(4, 4),			\
+	},							\
+	.post_muxs = {						\
+		RK3588_CORE_L_SEL0(0, _apllcore),		\
+		RK3588_CORE_L_SEL0(1, _apllcore),		\
+		RK3588_CORE_L_SEL1(_seldsu, _divdsu),		\
+	},							\
+}
+
+static struct rockchip_cpuclk_rate_table rk3588_cpub0clk_rates[] __initdata = {
+	RK3588_CPUB01CLK_RATE(2496000000, 1),
+	RK3588_CPUB01CLK_RATE(2400000000, 1),
+	RK3588_CPUB01CLK_RATE(2304000000, 1),
+	RK3588_CPUB01CLK_RATE(2208000000, 1),
+	RK3588_CPUB01CLK_RATE(2184000000, 1),
+	RK3588_CPUB01CLK_RATE(2088000000, 1),
+	RK3588_CPUB01CLK_RATE(2040000000, 1),
+	RK3588_CPUB01CLK_RATE(2016000000, 1),
+	RK3588_CPUB01CLK_RATE(1992000000, 1),
+	RK3588_CPUB01CLK_RATE(1896000000, 1),
+	RK3588_CPUB01CLK_RATE(1800000000, 1),
+	RK3588_CPUB01CLK_RATE(1704000000, 0),
+	RK3588_CPUB01CLK_RATE(1608000000, 0),
+	RK3588_CPUB01CLK_RATE(1584000000, 0),
+	RK3588_CPUB01CLK_RATE(1560000000, 0),
+	RK3588_CPUB01CLK_RATE(1536000000, 0),
+	RK3588_CPUB01CLK_RATE(1512000000, 0),
+	RK3588_CPUB01CLK_RATE(1488000000, 0),
+	RK3588_CPUB01CLK_RATE(1464000000, 0),
+	RK3588_CPUB01CLK_RATE(1440000000, 0),
+	RK3588_CPUB01CLK_RATE(1416000000, 0),
+	RK3588_CPUB01CLK_RATE(1392000000, 0),
+	RK3588_CPUB01CLK_RATE(1368000000, 0),
+	RK3588_CPUB01CLK_RATE(1344000000, 0),
+	RK3588_CPUB01CLK_RATE(1320000000, 0),
+	RK3588_CPUB01CLK_RATE(1296000000, 0),
+	RK3588_CPUB01CLK_RATE(1272000000, 0),
+	RK3588_CPUB01CLK_RATE(1248000000, 0),
+	RK3588_CPUB01CLK_RATE(1224000000, 0),
+	RK3588_CPUB01CLK_RATE(1200000000, 0),
+	RK3588_CPUB01CLK_RATE(1104000000, 0),
+	RK3588_CPUB01CLK_RATE(1008000000, 0),
+	RK3588_CPUB01CLK_RATE(912000000, 0),
+	RK3588_CPUB01CLK_RATE(816000000, 0),
+	RK3588_CPUB01CLK_RATE(696000000, 0),
+	RK3588_CPUB01CLK_RATE(600000000, 0),
+	RK3588_CPUB01CLK_RATE(408000000, 0),
+	RK3588_CPUB01CLK_RATE(312000000, 0),
+	RK3588_CPUB01CLK_RATE(216000000, 0),
+	RK3588_CPUB01CLK_RATE(96000000, 0),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpub0clk_data = {
+	.core_reg[0] = RK3588_BIGCORE0_CLKSEL_CON(0),
+	.div_core_shift[0] = 8,
+	.div_core_mask[0] = 0x1f,
+	.core_reg[1] = RK3588_BIGCORE0_CLKSEL_CON(1),
+	.div_core_shift[1] = 0,
+	.div_core_mask[1] = 0x1f,
+	.num_cores = 2,
+	.mux_core_alt = 1,
+	.mux_core_main = 2,
+	.mux_core_shift = 6,
+	.mux_core_mask = 0x3,
+};
+
+static struct rockchip_cpuclk_rate_table rk3588_cpub1clk_rates[] __initdata = {
+	RK3588_CPUB23CLK_RATE(2496000000, 1),
+	RK3588_CPUB23CLK_RATE(2400000000, 1),
+	RK3588_CPUB23CLK_RATE(2304000000, 1),
+	RK3588_CPUB23CLK_RATE(2208000000, 1),
+	RK3588_CPUB23CLK_RATE(2184000000, 1),
+	RK3588_CPUB23CLK_RATE(2088000000, 1),
+	RK3588_CPUB23CLK_RATE(2040000000, 1),
+	RK3588_CPUB23CLK_RATE(2016000000, 1),
+	RK3588_CPUB23CLK_RATE(1992000000, 1),
+	RK3588_CPUB23CLK_RATE(1896000000, 1),
+	RK3588_CPUB23CLK_RATE(1800000000, 1),
+	RK3588_CPUB23CLK_RATE(1704000000, 0),
+	RK3588_CPUB23CLK_RATE(1608000000, 0),
+	RK3588_CPUB23CLK_RATE(1584000000, 0),
+	RK3588_CPUB23CLK_RATE(1560000000, 0),
+	RK3588_CPUB23CLK_RATE(1536000000, 0),
+	RK3588_CPUB23CLK_RATE(1512000000, 0),
+	RK3588_CPUB23CLK_RATE(1488000000, 0),
+	RK3588_CPUB23CLK_RATE(1464000000, 0),
+	RK3588_CPUB23CLK_RATE(1440000000, 0),
+	RK3588_CPUB23CLK_RATE(1416000000, 0),
+	RK3588_CPUB23CLK_RATE(1392000000, 0),
+	RK3588_CPUB23CLK_RATE(1368000000, 0),
+	RK3588_CPUB23CLK_RATE(1344000000, 0),
+	RK3588_CPUB23CLK_RATE(1320000000, 0),
+	RK3588_CPUB23CLK_RATE(1296000000, 0),
+	RK3588_CPUB23CLK_RATE(1272000000, 0),
+	RK3588_CPUB23CLK_RATE(1248000000, 0),
+	RK3588_CPUB23CLK_RATE(1224000000, 0),
+	RK3588_CPUB23CLK_RATE(1200000000, 0),
+	RK3588_CPUB23CLK_RATE(1104000000, 0),
+	RK3588_CPUB23CLK_RATE(1008000000, 0),
+	RK3588_CPUB23CLK_RATE(912000000, 0),
+	RK3588_CPUB23CLK_RATE(816000000, 0),
+	RK3588_CPUB23CLK_RATE(696000000, 0),
+	RK3588_CPUB23CLK_RATE(600000000, 0),
+	RK3588_CPUB23CLK_RATE(408000000, 0),
+	RK3588_CPUB23CLK_RATE(312000000, 0),
+	RK3588_CPUB23CLK_RATE(216000000, 0),
+	RK3588_CPUB23CLK_RATE(96000000, 0),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpub1clk_data = {
+	.core_reg[0] = RK3588_BIGCORE1_CLKSEL_CON(0),
+	.div_core_shift[0] = 8,
+	.div_core_mask[0] = 0x1f,
+	.core_reg[1] = RK3588_BIGCORE1_CLKSEL_CON(1),
+	.div_core_shift[1] = 0,
+	.div_core_mask[1] = 0x1f,
+	.num_cores = 2,
+	.mux_core_alt = 1,
+	.mux_core_main = 2,
+	.mux_core_shift = 6,
+	.mux_core_mask = 0x3,
+};
+
+static struct rockchip_cpuclk_rate_table rk3588_cpulclk_rates[] __initdata = {
+	RK3588_CPULCLK_RATE(2208000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(2184000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(2088000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(2040000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(2016000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(1992000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(1896000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(1800000000, 1, 3, 1),
+	RK3588_CPULCLK_RATE(1704000000, 0, 3, 1),
+	RK3588_CPULCLK_RATE(1608000000, 0, 3, 1),
+	RK3588_CPULCLK_RATE(1584000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1560000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1536000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1512000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1488000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1464000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1440000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1416000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1392000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1368000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1344000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1320000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1296000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1272000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1248000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1224000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1200000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1104000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(1008000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(912000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(816000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(696000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(600000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(408000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(312000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(216000000, 0, 2, 1),
+	RK3588_CPULCLK_RATE(96000000, 0, 2, 1),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpulclk_data = {
+	.core_reg[0] = RK3588_DSU_CLKSEL_CON(6),
+	.div_core_shift[0] = 0,
+	.div_core_mask[0] = 0x1f,
+	.core_reg[1] = RK3588_DSU_CLKSEL_CON(6),
+	.div_core_shift[1] = 7,
+	.div_core_mask[1] = 0x1f,
+	.core_reg[2] = RK3588_DSU_CLKSEL_CON(7),
+	.div_core_shift[2] = 0,
+	.div_core_mask[2] = 0x1f,
+	.core_reg[3] = RK3588_DSU_CLKSEL_CON(7),
+	.div_core_shift[3] = 7,
+	.div_core_mask[3] = 0x1f,
+	.num_cores = 4,
+	.mux_core_reg = RK3588_DSU_CLKSEL_CON(5),
+	.mux_core_alt = 1,
+	.mux_core_main = 2,
+	.mux_core_shift = 14,
+	.mux_core_mask = 0x3,
+};
+
+PNAME(mux_pll_p)			= { "xin24m", "xin32k" };
+PNAME(mux_armclkl_p)			= { "xin24m", "gpll", "lpll" };
+PNAME(mux_armclkb01_p)			= { "xin24m", "gpll", "b0pll",};
+PNAME(mux_armclkb23_p)			= { "xin24m", "gpll", "b1pll",};
+PNAME(b0pll_b1pll_lpll_gpll_p)		= { "b0pll", "b1pll", "lpll", "gpll" };
+PNAME(gpll_24m_p)			= { "gpll", "xin24m" };
+PNAME(gpll_aupll_p)			= { "gpll", "aupll" };
+PNAME(gpll_lpll_p)			= { "gpll", "lpll" };
+PNAME(gpll_cpll_p)			= { "gpll", "cpll" };
+PNAME(gpll_spll_p)			= { "gpll", "spll" };
+PNAME(gpll_cpll_24m_p)			= { "gpll", "cpll", "xin24m"};
+PNAME(gpll_cpll_aupll_p)		= { "gpll", "cpll", "aupll"};
+PNAME(gpll_cpll_npll_p)			= { "gpll", "cpll", "npll"};
+PNAME(gpll_cpll_npll_v0pll_p)		= { "gpll", "cpll", "npll", "v0pll"};
+PNAME(gpll_cpll_24m_spll_p)		= { "gpll", "cpll", "xin24m", "spll" };
+PNAME(gpll_cpll_aupll_spll_p)		= { "gpll", "cpll", "aupll", "spll" };
+PNAME(gpll_cpll_aupll_npll_p)		= { "gpll", "cpll", "aupll", "npll" };
+PNAME(gpll_cpll_v0pll_aupll_p)		= { "gpll", "cpll", "v0pll", "aupll" };
+PNAME(gpll_cpll_v0pll_spll_p)		= { "gpll", "cpll", "v0pll", "spll" };
+PNAME(gpll_cpll_aupll_npll_spll_p)	= { "gpll", "cpll", "aupll", "npll", "spll" };
+PNAME(gpll_cpll_dmyaupll_npll_spll_p)	= { "gpll", "cpll", "dummy_aupll", "npll", "spll" };
+PNAME(gpll_cpll_npll_aupll_spll_p)	= { "gpll", "cpll", "npll", "aupll", "spll" };
+PNAME(gpll_cpll_npll_1000m_p)		= { "gpll", "cpll", "npll", "clk_1000m_src" };
+PNAME(mux_24m_spll_gpll_cpll_p)		= { "xin24m", "spll", "gpll", "cpll" };
+PNAME(mux_24m_32k_p)			= { "xin24m", "xin32k" };
+PNAME(mux_24m_100m_p)			= { "xin24m", "clk_100m_src" };
+PNAME(mux_200m_100m_p)			= { "clk_200m_src", "clk_100m_src" };
+PNAME(mux_100m_50m_24m_p)		= { "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_150m_50m_24m_p)		= { "clk_150m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_150m_100m_24m_p)		= { "clk_150m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_200m_150m_24m_p)		= { "clk_200m_src", "clk_150m_src", "xin24m" };
+PNAME(mux_150m_100m_50m_24m_p)		= { "clk_150m_src", "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_200m_100m_50m_24m_p)		= { "clk_200m_src", "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_300m_200m_100m_24m_p)		= { "clk_300m_src", "clk_200m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_700m_400m_200m_24m_p)		= { "clk_700m_src", "clk_400m_src", "clk_200m_src", "xin24m" };
+PNAME(mux_500m_250m_100m_24m_p)		= { "clk_500m_src", "clk_250m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_500m_300m_100m_24m_p)		= { "clk_500m_src", "clk_300m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_400m_200m_100m_24m_p)		= { "clk_400m_src", "clk_200m_src", "clk_100m_src", "xin24m" };
+PNAME(clk_i2s2_2ch_p)			= { "clk_i2s2_2ch_src", "clk_i2s2_2ch_frac", "i2s2_mclkin", "xin12m" };
+PNAME(i2s2_2ch_mclkout_p)		= { "mclk_i2s2_2ch", "xin12m" };
+PNAME(clk_i2s3_2ch_p)			= { "clk_i2s3_2ch_src", "clk_i2s3_2ch_frac", "i2s3_mclkin", "xin12m" };
+PNAME(i2s3_2ch_mclkout_p)		= { "mclk_i2s3_2ch", "xin12m" };
+PNAME(clk_i2s0_8ch_tx_p)		= { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "i2s0_mclkin", "xin12m" };
+PNAME(clk_i2s0_8ch_rx_p)		= { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "i2s0_mclkin", "xin12m" };
+PNAME(i2s0_8ch_mclkout_p)		= { "mclk_i2s0_8ch_tx", "mclk_i2s0_8ch_rx", "xin12m" };
+PNAME(clk_i2s1_8ch_tx_p)		= { "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_frac", "i2s1_mclkin", "xin12m" };
+PNAME(clk_i2s1_8ch_rx_p)		= { "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_frac", "i2s1_mclkin", "xin12m" };
+PNAME(i2s1_8ch_mclkout_p)		= { "mclk_i2s1_8ch_tx", "mclk_i2s1_8ch_rx", "xin12m" };
+PNAME(clk_i2s4_8ch_tx_p)		= { "clk_i2s4_8ch_tx_src", "clk_i2s4_8ch_tx_frac", "i2s4_mclkin", "xin12m" };
+PNAME(clk_i2s5_8ch_tx_p)		= { "clk_i2s5_8ch_tx_src", "clk_i2s5_8ch_tx_frac", "i2s5_mclkin", "xin12m" };
+PNAME(clk_i2s6_8ch_tx_p)		= { "clk_i2s6_8ch_tx_src", "clk_i2s6_8ch_tx_frac", "i2s6_mclkin", "xin12m" };
+PNAME(clk_i2s6_8ch_rx_p)		= { "clk_i2s6_8ch_rx_src", "clk_i2s6_8ch_rx_frac", "i2s6_mclkin", "xin12m" };
+PNAME(i2s6_8ch_mclkout_p)		= { "mclk_i2s6_8ch_tx", "mclk_i2s6_8ch_rx", "xin12m" };
+PNAME(clk_i2s7_8ch_rx_p)		= { "clk_i2s7_8ch_rx_src", "clk_i2s7_8ch_rx_frac", "i2s7_mclkin", "xin12m" };
+PNAME(clk_i2s8_8ch_tx_p)		= { "clk_i2s8_8ch_tx_src", "clk_i2s8_8ch_tx_frac", "i2s8_mclkin", "xin12m" };
+PNAME(clk_i2s9_8ch_rx_p)		= { "clk_i2s9_8ch_rx_src", "clk_i2s9_8ch_rx_frac", "i2s9_mclkin", "xin12m" };
+PNAME(clk_i2s10_8ch_rx_p)		= { "clk_i2s10_8ch_rx_src", "clk_i2s10_8ch_rx_frac", "i2s10_mclkin", "xin12m" };
+PNAME(clk_spdif0_p)			= { "clk_spdif0_src", "clk_spdif0_frac", "xin12m" };
+PNAME(clk_spdif1_p)			= { "clk_spdif1_src", "clk_spdif1_frac", "xin12m" };
+PNAME(clk_spdif2_dp0_p)			= { "clk_spdif2_dp0_src", "clk_spdif2_dp0_frac", "xin12m" };
+PNAME(clk_spdif3_p)			= { "clk_spdif3_src", "clk_spdif3_frac", "xin12m" };
+PNAME(clk_spdif4_p)			= { "clk_spdif4_src", "clk_spdif4_frac", "xin12m" };
+PNAME(clk_spdif5_dp1_p)			= { "clk_spdif5_dp1_src", "clk_spdif5_dp1_frac", "xin12m" };
+PNAME(clk_uart0_p)			= { "clk_uart0_src", "clk_uart0_frac", "xin24m" };
+PNAME(clk_uart1_p)			= { "clk_uart1_src", "clk_uart1_frac", "xin24m" };
+PNAME(clk_uart2_p)			= { "clk_uart2_src", "clk_uart2_frac", "xin24m" };
+PNAME(clk_uart3_p)			= { "clk_uart3_src", "clk_uart3_frac", "xin24m" };
+PNAME(clk_uart4_p)			= { "clk_uart4_src", "clk_uart4_frac", "xin24m" };
+PNAME(clk_uart5_p)			= { "clk_uart5_src", "clk_uart5_frac", "xin24m" };
+PNAME(clk_uart6_p)			= { "clk_uart6_src", "clk_uart6_frac", "xin24m" };
+PNAME(clk_uart7_p)			= { "clk_uart7_src", "clk_uart7_frac", "xin24m" };
+PNAME(clk_uart8_p)			= { "clk_uart8_src", "clk_uart8_frac", "xin24m" };
+PNAME(clk_uart9_p)			= { "clk_uart9_src", "clk_uart9_frac", "xin24m" };
+PNAME(clk_gmac0_ptp_ref_p)		= { "cpll", "clk_gmac0_ptpref_io" };
+PNAME(clk_gmac1_ptp_ref_p)		= { "cpll", "clk_gmac1_ptpref_io" };
+PNAME(clk_hdmirx_aud_p)			= { "clk_hdmirx_aud_src", "clk_hdmirx_aud_frac" };
+PNAME(aclk_hdcp1_root_p)		= { "gpll", "cpll", "clk_hdmitrx_refsrc" };
+PNAME(aclk_vop_sub_src_p)		= { "aclk_vop_root", "aclk_vop_div2_src" };
+PNAME(dclk_vop0_p)			= { "dclk_vop0_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(dclk_vop1_p)			= { "dclk_vop1_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(dclk_vop2_p)			= { "dclk_vop2_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(pmu_200m_100m_p)			= { "clk_pmu1_200m_src", "clk_pmu1_100m_src" };
+PNAME(pmu_300m_24m_p)			= { "clk_300m_src", "xin24m" };
+PNAME(pmu_400m_24m_p)			= { "clk_400m_src", "xin24m" };
+PNAME(pmu_100m_50m_24m_src_p)		= { "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" };
+PNAME(pmu_24m_32k_100m_src_p)		= { "xin24m", "32k", "clk_pmu1_100m_src" };
+PNAME(hclk_pmu1_root_p)			= { "clk_pmu1_200m_src", "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" };
+PNAME(hclk_pmu_cm0_root_p)		= { "clk_pmu1_400m_src", "clk_pmu1_200m_src", "clk_pmu1_100m_src", "xin24m" };
+PNAME(mclk_pdm0_p)			= { "clk_pmu1_300m_src", "clk_pmu1_200m_src" };
+PNAME(mux_24m_ppll_spll_p)		= { "xin24m", "ppll", "spll" };
+PNAME(mux_24m_ppll_p)			= { "xin24m", "ppll" };
+PNAME(clk_ref_pipe_phy0_p)		= { "clk_ref_pipe_phy0_osc_src", "clk_ref_pipe_phy0_pll_src" };
+PNAME(clk_ref_pipe_phy1_p)		= { "clk_ref_pipe_phy1_osc_src", "clk_ref_pipe_phy1_pll_src" };
+PNAME(clk_ref_pipe_phy2_p)		= { "clk_ref_pipe_phy2_osc_src", "clk_ref_pipe_phy2_pll_src" };
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3588_i2s0_8ch_tx_fracmux __initdata =
+	MUX(CLK_I2S0_8CH_TX, "clk_i2s0_8ch_tx", clk_i2s0_8ch_tx_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(26), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s0_8ch_rx_fracmux __initdata =
+	MUX(CLK_I2S0_8CH_RX, "clk_i2s0_8ch_rx", clk_i2s0_8ch_rx_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(28), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s1_8ch_tx_fracmux __initdata =
+	MUX(CLK_I2S1_8CH_TX, "clk_i2s1_8ch_tx", clk_i2s1_8ch_tx_p, CLK_SET_RATE_PARENT,
+			 RK3588_PMU_CLKSEL_CON(7), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s1_8ch_rx_fracmux __initdata =
+	MUX(CLK_I2S1_8CH_RX, "clk_i2s1_8ch_rx", clk_i2s1_8ch_rx_p, CLK_SET_RATE_PARENT,
+			 RK3588_PMU_CLKSEL_CON(9), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s2_2ch_fracmux __initdata =
+	MUX(CLK_I2S2_2CH, "clk_i2s2_2ch", clk_i2s2_2ch_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(30), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s3_2ch_fracmux __initdata =
+	MUX(CLK_I2S3_2CH, "clk_i2s3_2ch", clk_i2s3_2ch_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(32), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s4_8ch_tx_fracmux __initdata =
+	MUX(CLK_I2S4_8CH_TX, "clk_i2s4_8ch_tx", clk_i2s4_8ch_tx_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(120), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s5_8ch_tx_fracmux __initdata =
+	MUX(CLK_I2S5_8CH_TX, "clk_i2s5_8ch_tx", clk_i2s5_8ch_tx_p, CLK_SET_RATE_PARENT,
+			 RK3588_CLKSEL_CON(142), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s6_8ch_tx_fracmux __initdata =
+	MUX(CLK_I2S6_8CH_TX, "clk_i2s6_8ch_tx", clk_i2s6_8ch_tx_p, CLK_SET_RATE_PARENT,
+			 RK3588_CLKSEL_CON(146), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s6_8ch_rx_fracmux __initdata =
+	MUX(CLK_I2S6_8CH_RX, "clk_i2s6_8ch_rx", clk_i2s6_8ch_rx_p, CLK_SET_RATE_PARENT,
+			 RK3588_CLKSEL_CON(148), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s7_8ch_rx_fracmux __initdata =
+	MUX(CLK_I2S7_8CH_RX, "clk_i2s7_8ch_rx", clk_i2s7_8ch_rx_p, CLK_SET_RATE_PARENT,
+			 RK3588_CLKSEL_CON(131), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s8_8ch_tx_fracmux __initdata =
+	MUX(CLK_I2S8_8CH_TX, "clk_i2s8_8ch_tx", clk_i2s8_8ch_tx_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(122), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s9_8ch_rx_fracmux __initdata =
+	MUX(CLK_I2S9_8CH_RX, "clk_i2s9_8ch_rx", clk_i2s9_8ch_rx_p, CLK_SET_RATE_PARENT,
+			 RK3588_CLKSEL_CON(155), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s10_8ch_rx_fracmux __initdata =
+	MUX(CLK_I2S10_8CH_RX, "clk_i2s10_8ch_rx", clk_i2s10_8ch_rx_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(157), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif0_fracmux __initdata =
+	MUX(CLK_SPDIF0, "clk_spdif0", clk_spdif0_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(34), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif1_fracmux __initdata =
+	MUX(CLK_SPDIF1, "clk_spdif1", clk_spdif1_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(36), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif2_dp0_fracmux __initdata =
+	MUX(CLK_SPDIF2_DP0, "clk_spdif2_dp0", clk_spdif2_dp0_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(124), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif3_fracmux __initdata =
+	MUX(CLK_SPDIF3, "clk_spdif3", clk_spdif3_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(150), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif4_fracmux __initdata =
+	MUX(CLK_SPDIF4, "clk_spdif4", clk_spdif4_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(152), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif5_dp1_fracmux __initdata =
+	MUX(CLK_SPDIF5_DP1, "clk_spdif5_dp1", clk_spdif5_dp1_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(126), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart0_fracmux __initdata =
+	MUX(CLK_UART0, "clk_uart0", clk_uart0_p, CLK_SET_RATE_PARENT,
+			RK3588_PMU_CLKSEL_CON(5), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart1_fracmux __initdata =
+	MUX(CLK_UART1, "clk_uart1", clk_uart1_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(43), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart2_fracmux __initdata =
+	MUX(CLK_UART2, "clk_uart2", clk_uart2_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(45), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart3_fracmux __initdata =
+	MUX(CLK_UART3, "clk_uart3", clk_uart3_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(47), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart4_fracmux __initdata =
+	MUX(CLK_UART4, "clk_uart4", clk_uart4_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(49), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart5_fracmux __initdata =
+	MUX(CLK_UART5, "clk_uart5", clk_uart5_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(51), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart6_fracmux __initdata =
+	MUX(CLK_UART6, "clk_uart6", clk_uart6_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(53), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart7_fracmux __initdata =
+	MUX(CLK_UART7, "clk_uart7", clk_uart7_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(55), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart8_fracmux __initdata =
+	MUX(CLK_UART8, "clk_uart8", clk_uart8_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(57), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart9_fracmux __initdata =
+	MUX(CLK_UART9, "clk_uart9", clk_uart9_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(59), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_hdmirx_aud_fracmux __initdata =
+	MUX(CLK_HDMIRX_AUD_P_MUX, "clk_hdmirx_aud_mux", clk_hdmirx_aud_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(140), 0, 1, MFLAGS);
+
+static struct rockchip_pll_clock rk3588_pll_clks[] __initdata = {
+	[b0pll] = PLL(pll_rk3588_core, PLL_B0PLL, "b0pll", mux_pll_p,
+		     CLK_IGNORE_UNUSED, RK3588_B0_PLL_CON(0),
+		     RK3588_B0_PLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+	[b1pll] = PLL(pll_rk3588_core, PLL_B1PLL, "b1pll", mux_pll_p,
+		     CLK_IGNORE_UNUSED, RK3588_B1_PLL_CON(8),
+		     RK3588_B1_PLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+	[lpll] = PLL(pll_rk3588_core, PLL_LPLL, "lpll", mux_pll_p,
+		     CLK_IGNORE_UNUSED, RK3588_LPLL_CON(16),
+		     RK3588_LPLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+	[v0pll] = PLL(pll_rk3588, PLL_V0PLL, "v0pll", mux_pll_p,
+		     0, RK3588_PLL_CON(88),
+		     RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
+	[aupll] = PLL(pll_rk3588, PLL_AUPLL, "aupll", mux_pll_p,
+		     0, RK3588_PLL_CON(96),
+		     RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
+	[cpll] = PLL(pll_rk3588, PLL_CPLL, "cpll", mux_pll_p,
+		     CLK_IGNORE_UNUSED, RK3588_PLL_CON(104),
+		     RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
+	[gpll] = PLL(pll_rk3588, PLL_GPLL, "gpll", mux_pll_p,
+		     CLK_IGNORE_UNUSED, RK3588_PLL_CON(112),
+		     RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
+	[npll] = PLL(pll_rk3588, PLL_NPLL, "npll", mux_pll_p,
+		     0, RK3588_PLL_CON(120),
+		     RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+	[ppll] = PLL(pll_rk3588_core, PLL_PPLL, "ppll", mux_pll_p,
+		     CLK_IGNORE_UNUSED, RK3588_PMU_PLL_CON(128),
+		     RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
+};
+
+static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
+	/*
+	 * CRU Clock-Architecture
+	 */
+	/* fixed */
+	FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+	/* top */
+	COMPOSITE(CLK_50M_SRC, "clk_50m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 0, GFLAGS),
+	COMPOSITE(CLK_100M_SRC, "clk_100m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(0), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 1, GFLAGS),
+	COMPOSITE(CLK_150M_SRC, "clk_150m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(1), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 2, GFLAGS),
+	COMPOSITE(CLK_200M_SRC, "clk_200m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(1), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 3, GFLAGS),
+	COMPOSITE(CLK_250M_SRC, "clk_250m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(2), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 4, GFLAGS),
+	COMPOSITE(CLK_300M_SRC, "clk_300m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(2), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE(CLK_350M_SRC, "clk_350m_src", gpll_spll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(3), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 6, GFLAGS),
+	COMPOSITE(CLK_400M_SRC, "clk_400m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(3), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 7, GFLAGS),
+	COMPOSITE_HALFDIV(CLK_450M_SRC, "clk_450m_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(4), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 8, GFLAGS),
+	COMPOSITE(CLK_500M_SRC, "clk_500m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(4), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE(CLK_600M_SRC, "clk_600m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(5), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 10, GFLAGS),
+	COMPOSITE(CLK_650M_SRC, "clk_650m_src", gpll_lpll_p, 0,
+			RK3588_CLKSEL_CON(5), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 11, GFLAGS),
+	COMPOSITE(CLK_700M_SRC, "clk_700m_src", gpll_spll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(6), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 12, GFLAGS),
+	COMPOSITE(CLK_800M_SRC, "clk_800m_src", gpll_aupll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(6), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 13, GFLAGS),
+	COMPOSITE_HALFDIV(CLK_1000M_SRC, "clk_1000m_src", gpll_cpll_npll_v0pll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(7), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 14, GFLAGS),
+	COMPOSITE(CLK_1200M_SRC, "clk_1200m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(7), 12, 1, MFLAGS, 7, 5, DFLAGS,
+			RK3588_CLKGATE_CON(0), 15, GFLAGS),
+	COMPOSITE_NODIV(ACLK_TOP_M300_ROOT, "aclk_top_m300_root", mux_300m_200m_100m_24m_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(9), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(1), 10, GFLAGS),
+	COMPOSITE_NODIV(ACLK_TOP_M500_ROOT, "aclk_top_m500_root", mux_500m_300m_100m_24m_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(9), 2, 2, MFLAGS,
+			RK3588_CLKGATE_CON(1), 11, GFLAGS),
+	COMPOSITE_NODIV(ACLK_TOP_M400_ROOT, "aclk_top_m400_root", mux_400m_200m_100m_24m_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(9), 4, 2, MFLAGS,
+			RK3588_CLKGATE_CON(1), 12, GFLAGS),
+	COMPOSITE_NODIV(ACLK_TOP_S200_ROOT, "aclk_top_s200_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(9), 6, 2, MFLAGS,
+			RK3588_CLKGATE_CON(1), 13, GFLAGS),
+	COMPOSITE_NODIV(ACLK_TOP_S400_ROOT, "aclk_top_s400_root", mux_400m_200m_100m_24m_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(9), 8, 2, MFLAGS,
+			RK3588_CLKGATE_CON(1), 14, GFLAGS),
+	COMPOSITE(ACLK_TOP_ROOT, "aclk_top_root", gpll_cpll_aupll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(8), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(1), 0, GFLAGS),
+	COMPOSITE_NODIV(PCLK_TOP_ROOT, "pclk_top_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(8), 7, 2, MFLAGS,
+			RK3588_CLKGATE_CON(1), 1, GFLAGS),
+	COMPOSITE(ACLK_LOW_TOP_ROOT, "aclk_low_top_root", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(8), 14, 1, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(1), 2, GFLAGS),
+	COMPOSITE(CLK_MIPI_CAMARAOUT_M0, "clk_mipi_camaraout_m0", mux_24m_spll_gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(5), 9, GFLAGS),
+	COMPOSITE(CLK_MIPI_CAMARAOUT_M1, "clk_mipi_camaraout_m1", mux_24m_spll_gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(19), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(5), 10, GFLAGS),
+	COMPOSITE(CLK_MIPI_CAMARAOUT_M2, "clk_mipi_camaraout_m2", mux_24m_spll_gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(20), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(5), 11, GFLAGS),
+	COMPOSITE(CLK_MIPI_CAMARAOUT_M3, "clk_mipi_camaraout_m3", mux_24m_spll_gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(21), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(5), 12, GFLAGS),
+	COMPOSITE(CLK_MIPI_CAMARAOUT_M4, "clk_mipi_camaraout_m4", mux_24m_spll_gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(22), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(5), 13, GFLAGS),
+	COMPOSITE(MCLK_GMAC0_OUT, "mclk_gmac0_out", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(15), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(5), 3, GFLAGS),
+	COMPOSITE(REFCLKO25M_ETH0_OUT, "refclko25m_eth0_out", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(15), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3588_CLKGATE_CON(5), 4, GFLAGS),
+	COMPOSITE(REFCLKO25M_ETH1_OUT, "refclko25m_eth1_out", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(16), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(5), 5, GFLAGS),
+	COMPOSITE(CLK_CIFOUT_OUT, "clk_cifout_out", gpll_cpll_24m_spll_p, 0,
+			RK3588_CLKSEL_CON(17), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(5), 6, GFLAGS),
+	GATE(PCLK_MIPI_DCPHY0, "pclk_mipi_dcphy0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(3), 14, GFLAGS),
+	GATE(PCLK_MIPI_DCPHY1, "pclk_mipi_dcphy1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(4), 3, GFLAGS),
+	GATE(PCLK_CSIPHY0, "pclk_csiphy0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(1), 6, GFLAGS),
+	GATE(PCLK_CSIPHY1, "pclk_csiphy1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(1), 8, GFLAGS),
+	GATE(PCLK_CRU, "pclk_cru", "pclk_top_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(5), 0, GFLAGS),
+
+	/* bigcore0 */
+	COMPOSITE_NODIV(PCLK_BIGCORE0_ROOT, "pclk_bigcore0_root", mux_100m_50m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_BIGCORE0_CLKSEL_CON(2), 0, 2, MFLAGS,
+			RK3588_BIGCORE0_CLKGATE_CON(0), 14, GFLAGS),
+	GATE(PCLK_BIGCORE0_PVTM, "pclk_bigcore0_pvtm", "pclk_bigcore0_root", 0,
+			RK3588_BIGCORE0_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(CLK_BIGCORE0_PVTM, "clk_bigcore0_pvtm", "xin24m", 0,
+			RK3588_BIGCORE0_CLKGATE_CON(0), 12, GFLAGS),
+	GATE(CLK_CORE_BIGCORE0_PVTM, "clk_core_bigcore0_pvtm", "armclk_b01", 0,
+			RK3588_BIGCORE0_CLKGATE_CON(0), 13, GFLAGS),
+
+	/* bigcore1 */
+	COMPOSITE_NODIV(PCLK_BIGCORE1_ROOT, "pclk_bigcore1_root", mux_100m_50m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_BIGCORE1_CLKSEL_CON(2), 0, 2, MFLAGS,
+			RK3588_BIGCORE1_CLKGATE_CON(0), 14, GFLAGS),
+	GATE(PCLK_BIGCORE1_PVTM, "pclk_bigcore1_pvtm", "pclk_bigcore1_root", 0,
+			RK3588_BIGCORE1_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(CLK_BIGCORE1_PVTM, "clk_bigcore1_pvtm", "xin24m", 0,
+			RK3588_BIGCORE1_CLKGATE_CON(0), 12, GFLAGS),
+	GATE(CLK_CORE_BIGCORE1_PVTM, "clk_core_bigcore1_pvtm", "armclk_b23", 0,
+			RK3588_BIGCORE1_CLKGATE_CON(0), 13, GFLAGS),
+
+	/* dsu */
+	COMPOSITE(0, "sclk_dsu", b0pll_b1pll_lpll_gpll_p, CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(0), 12, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_DSU_CLKGATE_CON(0), 4, GFLAGS),
+	COMPOSITE_NOMUX(0, "atclk_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(1), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "gicclk_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(3), 5, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(1), 1, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclkmp_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(1), 11, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(0), 12, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclkm_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(1), 1, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(0), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclks_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(1), 6, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE_NOMUX(0, "periph_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(2), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(0), 13, GFLAGS),
+	COMPOSITE_NOMUX(0, "cntclk_dsu", "periph_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(2), 5, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(0), 14, GFLAGS),
+	COMPOSITE_NOMUX(0, "tsclk_dsu", "periph_dsu", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(2), 10, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3588_DSU_CLKGATE_CON(0), 15, GFLAGS),
+	COMPOSITE_NODIV(PCLK_DSU_S_ROOT, "pclk_dsu_s_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(4), 11, 2, MFLAGS,
+			RK3588_DSU_CLKGATE_CON(2), 2, GFLAGS),
+	COMPOSITE(PCLK_DSU_ROOT, "pclk_dsu_root", b0pll_b1pll_lpll_gpll_p, CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(4), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_DSU_CLKGATE_CON(1), 3, GFLAGS),
+	COMPOSITE_NODIV(PCLK_DSU_NS_ROOT, "pclk_dsu_ns_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+			RK3588_DSU_CLKSEL_CON(4), 7, 2, MFLAGS,
+			RK3588_DSU_CLKGATE_CON(1), 4, GFLAGS),
+	GATE(PCLK_LITCORE_PVTM, "pclk_litcore_pvtm", "pclk_dsu_ns_root", 0,
+			RK3588_DSU_CLKGATE_CON(2), 6, GFLAGS),
+	GATE(PCLK_DBG, "pclk_dbg", "pclk_dsu_root", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKGATE_CON(1), 7, GFLAGS),
+	GATE(PCLK_DSU, "pclk_dsu", "pclk_dsu_root", CLK_IS_CRITICAL,
+			RK3588_DSU_CLKGATE_CON(1), 6, GFLAGS),
+	GATE(PCLK_S_DAPLITE, "pclk_s_daplite", "pclk_dsu_ns_root", CLK_IGNORE_UNUSED,
+			RK3588_DSU_CLKGATE_CON(1), 8, GFLAGS),
+	GATE(PCLK_M_DAPLITE, "pclk_m_daplite", "pclk_dsu_root", CLK_IGNORE_UNUSED,
+			RK3588_DSU_CLKGATE_CON(1), 9, GFLAGS),
+	GATE(CLK_LITCORE_PVTM, "clk_litcore_pvtm", "xin24m", 0,
+			RK3588_DSU_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(CLK_CORE_LITCORE_PVTM, "clk_core_litcore_pvtm", "armclk_l", 0,
+			RK3588_DSU_CLKGATE_CON(2), 1, GFLAGS),
+
+	/* audio */
+	COMPOSITE_NODIV(HCLK_AUDIO_ROOT, "hclk_audio_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(24), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(7), 0, GFLAGS),
+	COMPOSITE_NODIV(PCLK_AUDIO_ROOT, "pclk_audio_root", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(24), 2, 2, MFLAGS,
+			RK3588_CLKGATE_CON(7), 1, GFLAGS),
+	GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_audio_root", 0,
+			RK3588_CLKGATE_CON(7), 12, GFLAGS),
+	GATE(HCLK_I2S3_2CH, "hclk_i2s3_2ch", "hclk_audio_root", 0,
+			RK3588_CLKGATE_CON(7), 13, GFLAGS),
+	COMPOSITE(CLK_I2S2_2CH_SRC, "clk_i2s2_2ch_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(28), 9, 1, MFLAGS, 4, 5, DFLAGS,
+			RK3588_CLKGATE_CON(7), 14, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S2_2CH_FRAC, "clk_i2s2_2ch_frac", "clk_i2s2_2ch_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(29), 0,
+			RK3588_CLKGATE_CON(7), 15, GFLAGS,
+			&rk3588_i2s2_2ch_fracmux),
+	GATE(MCLK_I2S2_2CH, "mclk_i2s2_2ch", "clk_i2s2_2ch", 0,
+			RK3588_CLKGATE_CON(8), 0, GFLAGS),
+	MUX(I2S2_2CH_MCLKOUT, "i2s2_2ch_mclkout", i2s2_2ch_mclkout_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(30), 2, 1, MFLAGS),
+
+	COMPOSITE(CLK_I2S3_2CH_SRC, "clk_i2s3_2ch_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(30), 8, 1, MFLAGS, 3, 5, DFLAGS,
+			RK3588_CLKGATE_CON(8), 1, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S3_2CH_FRAC, "clk_i2s3_2ch_frac", "clk_i2s3_2ch_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(31), 0,
+			RK3588_CLKGATE_CON(8), 2, GFLAGS,
+			&rk3588_i2s3_2ch_fracmux),
+	GATE(MCLK_I2S3_2CH, "mclk_i2s3_2ch", "clk_i2s3_2ch", 0,
+			RK3588_CLKGATE_CON(8), 3, GFLAGS),
+	GATE(CLK_DAC_ACDCDIG, "clk_dac_acdcdig", "mclk_i2s3_2ch", 0,
+			RK3588_CLKGATE_CON(8), 4, GFLAGS),
+	MUX(I2S3_2CH_MCLKOUT, "i2s3_2ch_mclkout", i2s3_2ch_mclkout_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(32), 2, 1, MFLAGS),
+	GATE(PCLK_ACDCDIG, "pclk_acdcdig", "pclk_audio_root", 0,
+			RK3588_CLKGATE_CON(7), 11, GFLAGS),
+	GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio_root", 0,
+			RK3588_CLKGATE_CON(7), 4, GFLAGS),
+
+	COMPOSITE(CLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(24), 9, 1, MFLAGS, 4, 5, DFLAGS,
+			RK3588_CLKGATE_CON(7), 5, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S0_8CH_TX_FRAC, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(25), 0,
+			RK3588_CLKGATE_CON(7), 6, GFLAGS,
+			&rk3588_i2s0_8ch_tx_fracmux),
+	GATE(MCLK_I2S0_8CH_TX, "mclk_i2s0_8ch_tx", "clk_i2s0_8ch_tx", 0,
+			RK3588_CLKGATE_CON(7), 7, GFLAGS),
+
+	COMPOSITE(CLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(26), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(7), 8, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S0_8CH_RX_FRAC, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(27), 0,
+			RK3588_CLKGATE_CON(7), 9, GFLAGS,
+			&rk3588_i2s0_8ch_rx_fracmux),
+	GATE(MCLK_I2S0_8CH_RX, "mclk_i2s0_8ch_rx", "clk_i2s0_8ch_rx", 0,
+			RK3588_CLKGATE_CON(7), 10, GFLAGS),
+	MUX(I2S0_8CH_MCLKOUT, "i2s0_8ch_mclkout", i2s0_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(28), 2, 2, MFLAGS),
+
+	GATE(HCLK_PDM1, "hclk_pdm1", "hclk_audio_root", 0,
+			RK3588_CLKGATE_CON(9), 6, GFLAGS),
+	COMPOSITE(MCLK_PDM1, "mclk_pdm1", gpll_cpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(36), 7, 2, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(9), 7, GFLAGS),
+
+	GATE(HCLK_SPDIF0, "hclk_spdif0", "hclk_audio_root", 0,
+			RK3588_CLKGATE_CON(8), 14, GFLAGS),
+	COMPOSITE(CLK_SPDIF0_SRC, "clk_spdif0_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(32), 8, 1, MFLAGS, 3, 5, DFLAGS,
+			RK3588_CLKGATE_CON(8), 15, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_SPDIF0_FRAC, "clk_spdif0_frac", "clk_spdif0_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(33), 0,
+			RK3588_CLKGATE_CON(9), 0, GFLAGS,
+			&rk3588_spdif0_fracmux),
+	GATE(MCLK_SPDIF0, "mclk_spdif0", "clk_spdif0", 0,
+			RK3588_CLKGATE_CON(9), 1, GFLAGS),
+
+	GATE(HCLK_SPDIF1, "hclk_spdif1", "hclk_audio_root", 0,
+			RK3588_CLKGATE_CON(9), 2, GFLAGS),
+	COMPOSITE(CLK_SPDIF1_SRC, "clk_spdif1_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(34), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(9), 3, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_SPDIF1_FRAC, "clk_spdif1_frac", "clk_spdif1_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(35), 0,
+			RK3588_CLKGATE_CON(9), 4, GFLAGS,
+			&rk3588_spdif1_fracmux),
+	GATE(MCLK_SPDIF1, "mclk_spdif1", "clk_spdif1", 0,
+			RK3588_CLKGATE_CON(9), 5, GFLAGS),
+
+	COMPOSITE(ACLK_AV1_ROOT, "aclk_av1_root", gpll_cpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(163), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(68), 0, GFLAGS),
+	COMPOSITE_NODIV(PCLK_AV1_ROOT, "pclk_av1_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(163), 7, 2, MFLAGS,
+			RK3588_CLKGATE_CON(68), 3, GFLAGS),
+
+	/* bus */
+	COMPOSITE(ACLK_BUS_ROOT, "aclk_bus_root", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(10), 0, GFLAGS),
+
+	GATE(PCLK_MAILBOX0, "pclk_mailbox0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(16), 11, GFLAGS),
+	GATE(PCLK_MAILBOX1, "pclk_mailbox1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(16), 12, GFLAGS),
+	GATE(PCLK_MAILBOX2, "pclk_mailbox2", "pclk_top_root", 0,
+		RK3588_CLKGATE_CON(16), 13, GFLAGS),
+	GATE(PCLK_PMU2, "pclk_pmu2", "pclk_top_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(19), 3, GFLAGS),
+	GATE(PCLK_PMUCM0_INTMUX, "pclk_pmucm0_intmux", "pclk_top_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(19), 4, GFLAGS),
+	GATE(PCLK_DDRCM0_INTMUX, "pclk_ddrcm0_intmux", "pclk_top_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(19), 5, GFLAGS),
+
+	GATE(PCLK_PWM1, "pclk_pwm1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(15), 3, GFLAGS),
+	COMPOSITE_NODIV(CLK_PWM1, "clk_pwm1", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(59), 12, 2, MFLAGS,
+			RK3588_CLKGATE_CON(15), 4, GFLAGS),
+	GATE(CLK_PWM1_CAPTURE, "clk_pwm1_capture", "xin24m", 0,
+			RK3588_CLKGATE_CON(15), 5, GFLAGS),
+	GATE(PCLK_PWM2, "pclk_pwm2", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(15), 6, GFLAGS),
+	COMPOSITE_NODIV(CLK_PWM2, "clk_pwm2", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(59), 14, 2, MFLAGS,
+			RK3588_CLKGATE_CON(15), 7, GFLAGS),
+	GATE(CLK_PWM2_CAPTURE, "clk_pwm2_capture", "xin24m", 0,
+			RK3588_CLKGATE_CON(15), 8, GFLAGS),
+	GATE(PCLK_PWM3, "pclk_pwm3", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(15), 9, GFLAGS),
+	COMPOSITE_NODIV(CLK_PWM3, "clk_pwm3", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(60), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(15), 10, GFLAGS),
+	GATE(CLK_PWM3_CAPTURE, "clk_pwm3_capture", "xin24m", 0,
+			RK3588_CLKGATE_CON(15), 11, GFLAGS),
+
+	GATE(PCLK_BUSTIMER0, "pclk_bustimer0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(15), 12, GFLAGS),
+	GATE(PCLK_BUSTIMER1, "pclk_bustimer1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(15), 13, GFLAGS),
+	COMPOSITE_NODIV(CLK_BUS_TIMER_ROOT, "clk_bus_timer_root", mux_24m_100m_p, 0,
+			RK3588_CLKSEL_CON(60), 2, 1, MFLAGS,
+			RK3588_CLKGATE_CON(15), 14, GFLAGS),
+	GATE(CLK_BUSTIMER0, "clk_bustimer0", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(15), 15, GFLAGS),
+	GATE(CLK_BUSTIMER1, "clk_bustimer1", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 0, GFLAGS),
+	GATE(CLK_BUSTIMER2, "clk_bustimer2", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 1, GFLAGS),
+	GATE(CLK_BUSTIMER3, "clk_bustimer3", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 2, GFLAGS),
+	GATE(CLK_BUSTIMER4, "clk_bustimer4", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 3, GFLAGS),
+	GATE(CLK_BUSTIMER5, "clk_bustimer5", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 4, GFLAGS),
+	GATE(CLK_BUSTIMER6, "clk_bustimer6", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 5, GFLAGS),
+	GATE(CLK_BUSTIMER7, "clk_bustimer7", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 6, GFLAGS),
+	GATE(CLK_BUSTIMER8, "clk_bustimer8", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 7, GFLAGS),
+	GATE(CLK_BUSTIMER9, "clk_bustimer9", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 8, GFLAGS),
+	GATE(CLK_BUSTIMER10, "clk_bustimer10", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 9, GFLAGS),
+	GATE(CLK_BUSTIMER11, "clk_bustimer11", "clk_bus_timer_root", 0,
+			RK3588_CLKGATE_CON(16), 10, GFLAGS),
+
+	GATE(PCLK_WDT0, "pclk_wdt0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(TCLK_WDT0, "tclk_wdt0", "xin24m", 0,
+			RK3588_CLKGATE_CON(15), 1, GFLAGS),
+
+	GATE(PCLK_CAN0, "pclk_can0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(11), 8, GFLAGS),
+	COMPOSITE(CLK_CAN0, "clk_can0", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(39), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(11), 9, GFLAGS),
+	GATE(PCLK_CAN1, "pclk_can1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(11), 10, GFLAGS),
+	COMPOSITE(CLK_CAN1, "clk_can1", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(39), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(11), 11, GFLAGS),
+	GATE(PCLK_CAN2, "pclk_can2", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(11), 12, GFLAGS),
+	COMPOSITE(CLK_CAN2, "clk_can2", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(40), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(11), 13, GFLAGS),
+
+	GATE(ACLK_DECOM, "aclk_decom", "aclk_bus_root", 0,
+			RK3588_CLKGATE_CON(17), 6, GFLAGS),
+	GATE(PCLK_DECOM, "pclk_decom", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(17), 7, GFLAGS),
+	COMPOSITE(DCLK_DECOM, "dclk_decom", gpll_spll_p, 0,
+			RK3588_CLKSEL_CON(62), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(17), 8, GFLAGS),
+	GATE(ACLK_DMAC0, "aclk_dmac0", "aclk_bus_root", 0,
+			RK3588_CLKGATE_CON(10), 5, GFLAGS),
+	GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_bus_root", 0,
+			RK3588_CLKGATE_CON(10), 6, GFLAGS),
+	GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_bus_root", 0,
+			RK3588_CLKGATE_CON(10), 7, GFLAGS),
+	GATE(ACLK_GIC, "aclk_gic", "aclk_bus_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(10), 3, GFLAGS),
+
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(16), 14, GFLAGS),
+	COMPOSITE(DBCLK_GPIO1, "dbclk_gpio1", mux_24m_32k_p, 0,
+			RK3588_CLKSEL_CON(60), 8, 1, MFLAGS, 3, 5, DFLAGS,
+			RK3588_CLKGATE_CON(16), 15, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(17), 0, GFLAGS),
+	COMPOSITE(DBCLK_GPIO2, "dbclk_gpio2", mux_24m_32k_p, 0,
+			RK3588_CLKSEL_CON(60), 14, 1, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(17), 1, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(17), 2, GFLAGS),
+	COMPOSITE(DBCLK_GPIO3, "dbclk_gpio3", mux_24m_32k_p, 0,
+			RK3588_CLKSEL_CON(61), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(17), 3, GFLAGS),
+	GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(17), 4, GFLAGS),
+	COMPOSITE(DBCLK_GPIO4, "dbclk_gpio4", mux_24m_32k_p, 0,
+			RK3588_CLKSEL_CON(61), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(17), 5, GFLAGS),
+
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 9, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_i2c3", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 10, GFLAGS),
+	GATE(PCLK_I2C4, "pclk_i2c4", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 11, GFLAGS),
+	GATE(PCLK_I2C5, "pclk_i2c5", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 12, GFLAGS),
+	GATE(PCLK_I2C6, "pclk_i2c6", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 13, GFLAGS),
+	GATE(PCLK_I2C7, "pclk_i2c7", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 14, GFLAGS),
+	GATE(PCLK_I2C8, "pclk_i2c8", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(10), 15, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C1, "clk_i2c1", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 6, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 0, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C2, "clk_i2c2", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 7, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 1, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C3, "clk_i2c3", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 8, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 2, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C4, "clk_i2c4", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 9, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 3, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C5, "clk_i2c5", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 10, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 4, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C6, "clk_i2c6", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 11, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 5, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C7, "clk_i2c7", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 12, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 6, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C8, "clk_i2c8", mux_200m_100m_p, 0,
+			RK3588_CLKSEL_CON(38), 13, 1, MFLAGS,
+			RK3588_CLKGATE_CON(11), 7, GFLAGS),
+
+	GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(18), 9, GFLAGS),
+	GATE(CLK_OTPC_NS, "clk_otpc_ns", "xin24m", 0,
+			RK3588_CLKGATE_CON(18), 10, GFLAGS),
+	GATE(CLK_OTPC_ARB, "clk_otpc_arb", "xin24m", 0,
+			RK3588_CLKGATE_CON(18), 11, GFLAGS),
+	GATE(CLK_OTP_PHY_G, "clk_otp_phy_g", "xin24m", 0,
+			RK3588_CLKGATE_CON(18), 13, GFLAGS),
+	GATE(CLK_OTPC_AUTO_RD_G, "clk_otpc_auto_rd_g", "xin24m", 0,
+			RK3588_CLKGATE_CON(18), 12, GFLAGS),
+
+	GATE(PCLK_SARADC, "pclk_saradc", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(11), 14, GFLAGS),
+	COMPOSITE(CLK_SARADC, "clk_saradc", gpll_24m_p, 0,
+			RK3588_CLKSEL_CON(40), 14, 1, MFLAGS, 6, 8, DFLAGS,
+			RK3588_CLKGATE_CON(11), 15, GFLAGS),
+
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(14), 6, GFLAGS),
+	GATE(PCLK_SPI1, "pclk_spi1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(14), 7, GFLAGS),
+	GATE(PCLK_SPI2, "pclk_spi2", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(PCLK_SPI3, "pclk_spi3", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(14), 9, GFLAGS),
+	GATE(PCLK_SPI4, "pclk_spi4", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(14), 10, GFLAGS),
+	COMPOSITE_NODIV(CLK_SPI0, "clk_spi0", mux_200m_150m_24m_p, 0,
+			RK3588_CLKSEL_CON(59), 2, 2, MFLAGS,
+			RK3588_CLKGATE_CON(14), 11, GFLAGS),
+	COMPOSITE_NODIV(CLK_SPI1, "clk_spi1", mux_200m_150m_24m_p, 0,
+			RK3588_CLKSEL_CON(59), 4, 2, MFLAGS,
+			RK3588_CLKGATE_CON(14), 12, GFLAGS),
+	COMPOSITE_NODIV(CLK_SPI2, "clk_spi2", mux_200m_150m_24m_p, 0,
+			RK3588_CLKSEL_CON(59), 6, 2, MFLAGS,
+			RK3588_CLKGATE_CON(14), 13, GFLAGS),
+	COMPOSITE_NODIV(CLK_SPI3, "clk_spi3", mux_200m_150m_24m_p, 0,
+			RK3588_CLKSEL_CON(59), 8, 2, MFLAGS,
+			RK3588_CLKGATE_CON(14), 14, GFLAGS),
+	COMPOSITE_NODIV(CLK_SPI4, "clk_spi4", mux_200m_150m_24m_p, 0,
+			RK3588_CLKSEL_CON(59), 10, 2, MFLAGS,
+			RK3588_CLKGATE_CON(14), 15, GFLAGS),
+
+	GATE(ACLK_SPINLOCK, "aclk_spinlock", "aclk_bus_root", CLK_IGNORE_UNUSED,
+			RK3588_CLKGATE_CON(18), 6, GFLAGS),
+	GATE(PCLK_TSADC, "pclk_tsadc", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 0, GFLAGS),
+	COMPOSITE(CLK_TSADC, "clk_tsadc", gpll_24m_p, 0,
+			RK3588_CLKSEL_CON(41), 8, 1, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(12), 1, GFLAGS),
+
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 2, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 3, GFLAGS),
+	GATE(PCLK_UART3, "pclk_uart3", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 4, GFLAGS),
+	GATE(PCLK_UART4, "pclk_uart4", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 5, GFLAGS),
+	GATE(PCLK_UART5, "pclk_uart5", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 6, GFLAGS),
+	GATE(PCLK_UART6, "pclk_uart6", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 7, GFLAGS),
+	GATE(PCLK_UART7, "pclk_uart7", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 8, GFLAGS),
+	GATE(PCLK_UART8, "pclk_uart8", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 9, GFLAGS),
+	GATE(PCLK_UART9, "pclk_uart9", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(12), 10, GFLAGS),
+
+	COMPOSITE(CLK_UART1_SRC, "clk_uart1_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(41), 14, 1, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(12), 11, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART1_FRAC, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(42), 0,
+			RK3588_CLKGATE_CON(12), 12, GFLAGS,
+			&rk3588_uart1_fracmux),
+	GATE(SCLK_UART1, "sclk_uart1", "clk_uart1", 0,
+			RK3588_CLKGATE_CON(12), 13, GFLAGS),
+	COMPOSITE(CLK_UART2_SRC, "clk_uart2_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(43), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(12), 14, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART2_FRAC, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(44), 0,
+			RK3588_CLKGATE_CON(12), 15, GFLAGS,
+			&rk3588_uart2_fracmux),
+	GATE(SCLK_UART2, "sclk_uart2", "clk_uart2", 0,
+			RK3588_CLKGATE_CON(13), 0, GFLAGS),
+	COMPOSITE(CLK_UART3_SRC, "clk_uart3_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(45), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(13), 1, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART3_FRAC, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(46), 0,
+			RK3588_CLKGATE_CON(13), 2, GFLAGS,
+			&rk3588_uart3_fracmux),
+	GATE(SCLK_UART3, "sclk_uart3", "clk_uart3", 0,
+			RK3588_CLKGATE_CON(13), 3, GFLAGS),
+	COMPOSITE(CLK_UART4_SRC, "clk_uart4_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(47), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(13), 4, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART4_FRAC, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(48), 0,
+			RK3588_CLKGATE_CON(13), 5, GFLAGS,
+			&rk3588_uart4_fracmux),
+	GATE(SCLK_UART4, "sclk_uart4", "clk_uart4", 0,
+			RK3588_CLKGATE_CON(13), 6, GFLAGS),
+	COMPOSITE(CLK_UART5_SRC, "clk_uart5_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(49), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(13), 7, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART5_FRAC, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(50), 0,
+			RK3588_CLKGATE_CON(13), 8, GFLAGS,
+			&rk3588_uart5_fracmux),
+	GATE(SCLK_UART5, "sclk_uart5", "clk_uart5", 0,
+			RK3588_CLKGATE_CON(13), 9, GFLAGS),
+	COMPOSITE(CLK_UART6_SRC, "clk_uart6_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(51), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(13), 10, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART6_FRAC, "clk_uart6_frac", "clk_uart6_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(52), 0,
+			RK3588_CLKGATE_CON(13), 11, GFLAGS,
+			&rk3588_uart6_fracmux),
+	GATE(SCLK_UART6, "sclk_uart6", "clk_uart6", 0,
+			RK3588_CLKGATE_CON(13), 12, GFLAGS),
+	COMPOSITE(CLK_UART7_SRC, "clk_uart7_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(53), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(13), 13, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART7_FRAC, "clk_uart7_frac", "clk_uart7_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(54), 0,
+			RK3588_CLKGATE_CON(13), 14, GFLAGS,
+			&rk3588_uart7_fracmux),
+	GATE(SCLK_UART7, "sclk_uart7", "clk_uart7", 0,
+			RK3588_CLKGATE_CON(13), 15, GFLAGS),
+	COMPOSITE(CLK_UART8_SRC, "clk_uart8_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(55), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(14), 0, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART8_FRAC, "clk_uart8_frac", "clk_uart8_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(56), 0,
+			RK3588_CLKGATE_CON(14), 1, GFLAGS,
+			&rk3588_uart8_fracmux),
+	GATE(SCLK_UART8, "sclk_uart8", "clk_uart8", 0,
+			RK3588_CLKGATE_CON(14), 2, GFLAGS),
+	COMPOSITE(CLK_UART9_SRC, "clk_uart9_src", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(57), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(14), 3, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART9_FRAC, "clk_uart9_frac", "clk_uart9_src", CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(58), 0,
+			RK3588_CLKGATE_CON(14), 4, GFLAGS,
+			&rk3588_uart9_fracmux),
+	GATE(SCLK_UART9, "sclk_uart9", "clk_uart9", 0,
+			RK3588_CLKGATE_CON(14), 5, GFLAGS),
+
+	/* center */
+	COMPOSITE_NODIV(ACLK_CENTER_ROOT, "aclk_center_root", mux_700m_400m_200m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(165), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(69), 0, GFLAGS),
+	COMPOSITE_NODIV(ACLK_CENTER_LOW_ROOT, "aclk_center_low_root", mux_500m_250m_100m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(165), 2, 2, MFLAGS,
+			RK3588_CLKGATE_CON(69), 1, GFLAGS),
+	COMPOSITE_NODIV(HCLK_CENTER_ROOT, "hclk_center_root", mux_400m_200m_100m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(165), 4, 2, MFLAGS,
+			RK3588_CLKGATE_CON(69), 2, GFLAGS),
+	COMPOSITE_NODIV(PCLK_CENTER_ROOT, "pclk_center_root", mux_200m_100m_50m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(165), 6, 2, MFLAGS | CLK_MUX_READ_ONLY,
+			RK3588_CLKGATE_CON(69), 3, GFLAGS),
+	GATE(ACLK_DMA2DDR, "aclk_dma2ddr", "aclk_center_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(69), 5, GFLAGS),
+	GATE(ACLK_DDR_SHAREMEM, "aclk_ddr_sharemem", "aclk_center_low_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(69), 6, GFLAGS),
+	COMPOSITE_NODIV(ACLK_CENTER_S200_ROOT, "aclk_center_s200_root", mux_200m_100m_50m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(165), 8, 2, MFLAGS,
+			RK3588_CLKGATE_CON(69), 8, GFLAGS),
+	COMPOSITE_NODIV(ACLK_CENTER_S400_ROOT, "aclk_center_s400_root", mux_400m_200m_100m_24m_p,
+			CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(165), 10, 2, MFLAGS,
+			RK3588_CLKGATE_CON(69), 9, GFLAGS),
+	GATE(FCLK_DDR_CM0_CORE, "fclk_ddr_cm0_core", "hclk_center_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(69), 14, GFLAGS),
+	COMPOSITE_NODIV(CLK_DDR_TIMER_ROOT, "clk_ddr_timer_root", mux_24m_100m_p, CLK_IGNORE_UNUSED,
+			RK3588_CLKSEL_CON(165), 12, 1, MFLAGS,
+			RK3588_CLKGATE_CON(69), 15, GFLAGS),
+	GATE(CLK_DDR_TIMER0, "clk_ddr_timer0", "clk_ddr_timer_root", 0,
+			RK3588_CLKGATE_CON(70), 0, GFLAGS),
+	GATE(CLK_DDR_TIMER1, "clk_ddr_timer1", "clk_ddr_timer_root", 0,
+			RK3588_CLKGATE_CON(70), 1, GFLAGS),
+	GATE(TCLK_WDT_DDR, "tclk_wdt_ddr", "xin24m", 0,
+			RK3588_CLKGATE_CON(70), 2, GFLAGS),
+	COMPOSITE(CLK_DDR_CM0_RTC, "clk_ddr_cm0_rtc", mux_24m_32k_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(166), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(70), 4, GFLAGS),
+	GATE(PCLK_WDT, "pclk_wdt", "pclk_center_root", 0,
+			RK3588_CLKGATE_CON(70), 7, GFLAGS),
+	GATE(PCLK_TIMER, "pclk_timer", "pclk_center_root", 0,
+			RK3588_CLKGATE_CON(70), 8, GFLAGS),
+	GATE(PCLK_DMA2DDR, "pclk_dma2ddr", "pclk_center_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(70), 9, GFLAGS),
+	GATE(PCLK_SHAREMEM, "pclk_sharemem", "pclk_center_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(70), 10, GFLAGS),
+
+	/* gpu */
+	COMPOSITE(CLK_GPU_SRC, "clk_gpu_src", gpll_cpll_aupll_npll_spll_p, 0,
+			RK3588_CLKSEL_CON(158), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(66), 1, GFLAGS),
+	GATE(CLK_GPU, "clk_gpu", "clk_gpu_src", 0,
+			RK3588_CLKGATE_CON(66), 4, GFLAGS),
+	GATE(CLK_GPU_COREGROUP, "clk_gpu_coregroup", "clk_gpu_src", 0,
+			RK3588_CLKGATE_CON(66), 6, GFLAGS),
+	COMPOSITE_NOMUX(CLK_GPU_STACKS, "clk_gpu_stacks", "clk_gpu_src", 0,
+			RK3588_CLKSEL_CON(159), 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(66), 7, GFLAGS),
+	GATE(CLK_GPU_PVTM, "clk_gpu_pvtm", "xin24m", 0,
+			RK3588_CLKGATE_CON(67), 0, GFLAGS),
+	GATE(CLK_CORE_GPU_PVTM, "clk_core_gpu_pvtm", "clk_gpu_src", 0,
+			RK3588_CLKGATE_CON(67), 1, GFLAGS),
+
+	/* isp1 */
+	COMPOSITE(ACLK_ISP1_ROOT, "aclk_isp1_root", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(67), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(26), 0, GFLAGS),
+	COMPOSITE_NODIV(HCLK_ISP1_ROOT, "hclk_isp1_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(67), 7, 2, MFLAGS,
+			RK3588_CLKGATE_CON(26), 1, GFLAGS),
+	COMPOSITE(CLK_ISP1_CORE, "clk_isp1_core", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(67), 14, 2, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(26), 2, GFLAGS),
+	GATE(CLK_ISP1_CORE_MARVIN, "clk_isp1_core_marvin", "clk_isp1_core", 0,
+			RK3588_CLKGATE_CON(26), 3, GFLAGS),
+	GATE(CLK_ISP1_CORE_VICAP, "clk_isp1_core_vicap", "clk_isp1_core", 0,
+			RK3588_CLKGATE_CON(26), 4, GFLAGS),
+
+	/* npu */
+	COMPOSITE_NODIV(HCLK_NPU_ROOT, "hclk_npu_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(73), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(29), 0, GFLAGS),
+	COMPOSITE(CLK_NPU_DSU0, "clk_npu_dsu0", gpll_cpll_aupll_npll_spll_p, 0,
+			RK3588_CLKSEL_CON(73), 7, 3, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(29), 1, GFLAGS),
+	COMPOSITE_NODIV(PCLK_NPU_ROOT, "pclk_npu_root", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(74), 1, 2, MFLAGS,
+			RK3588_CLKGATE_CON(29), 4, GFLAGS),
+	GATE(ACLK_NPU1, "aclk_npu1", "clk_npu_dsu0", 0,
+			RK3588_CLKGATE_CON(27), 0, GFLAGS),
+	GATE(HCLK_NPU1, "hclk_npu1", "hclk_npu_root", 0,
+			RK3588_CLKGATE_CON(27), 2, GFLAGS),
+	GATE(ACLK_NPU2, "aclk_npu2", "clk_npu_dsu0", 0,
+			RK3588_CLKGATE_CON(28), 0, GFLAGS),
+	GATE(HCLK_NPU2, "hclk_npu2", "hclk_npu_root", 0,
+			RK3588_CLKGATE_CON(28), 2, GFLAGS),
+	COMPOSITE_NODIV(HCLK_NPU_CM0_ROOT, "hclk_npu_cm0_root", mux_400m_200m_100m_24m_p, 0,
+			RK3588_CLKSEL_CON(74), 5, 2, MFLAGS,
+			RK3588_CLKGATE_CON(30), 1, GFLAGS),
+	GATE(FCLK_NPU_CM0_CORE, "fclk_npu_cm0_core", "hclk_npu_cm0_root", 0,
+			RK3588_CLKGATE_CON(30), 3, GFLAGS),
+	COMPOSITE(CLK_NPU_CM0_RTC, "clk_npu_cm0_rtc", mux_24m_32k_p, 0,
+			RK3588_CLKSEL_CON(74), 12, 1, MFLAGS, 7, 5, DFLAGS,
+			RK3588_CLKGATE_CON(30), 5, GFLAGS),
+	GATE(PCLK_NPU_PVTM, "pclk_npu_pvtm", "pclk_npu_root", 0,
+			RK3588_CLKGATE_CON(29), 12, GFLAGS),
+	GATE(PCLK_NPU_GRF, "pclk_npu_grf", "pclk_npu_root", CLK_IGNORE_UNUSED,
+			RK3588_CLKGATE_CON(29), 13, GFLAGS),
+	GATE(CLK_NPU_PVTM, "clk_npu_pvtm", "xin24m", 0,
+			RK3588_CLKGATE_CON(29), 14, GFLAGS),
+	GATE(CLK_CORE_NPU_PVTM, "clk_core_npu_pvtm", "clk_npu_dsu0", 0,
+			RK3588_CLKGATE_CON(29), 15, GFLAGS),
+	GATE(ACLK_NPU0, "aclk_npu0", "clk_npu_dsu0", 0,
+			RK3588_CLKGATE_CON(30), 6, GFLAGS),
+	GATE(HCLK_NPU0, "hclk_npu0", "hclk_npu_root", 0,
+			RK3588_CLKGATE_CON(30), 8, GFLAGS),
+	GATE(PCLK_NPU_TIMER, "pclk_npu_timer", "pclk_npu_root", 0,
+			RK3588_CLKGATE_CON(29), 6, GFLAGS),
+	COMPOSITE_NODIV(CLK_NPUTIMER_ROOT, "clk_nputimer_root", mux_24m_100m_p, 0,
+			RK3588_CLKSEL_CON(74), 3, 1, MFLAGS,
+			RK3588_CLKGATE_CON(29), 7, GFLAGS),
+	GATE(CLK_NPUTIMER0, "clk_nputimer0", "clk_nputimer_root", 0,
+			RK3588_CLKGATE_CON(29), 8, GFLAGS),
+	GATE(CLK_NPUTIMER1, "clk_nputimer1", "clk_nputimer_root", 0,
+			RK3588_CLKGATE_CON(29), 9, GFLAGS),
+	GATE(PCLK_NPU_WDT, "pclk_npu_wdt", "pclk_npu_root", 0,
+			RK3588_CLKGATE_CON(29), 10, GFLAGS),
+	GATE(TCLK_NPU_WDT, "tclk_npu_wdt", "xin24m", 0,
+			RK3588_CLKGATE_CON(29), 11, GFLAGS),
+
+	/* nvm */
+	COMPOSITE_NODIV(HCLK_NVM_ROOT,  "hclk_nvm_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(77), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(31), 0, GFLAGS),
+	COMPOSITE(ACLK_NVM_ROOT, "aclk_nvm_root", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(77), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(31), 1, GFLAGS),
+	GATE(ACLK_EMMC, "aclk_emmc", "aclk_nvm_root", 0,
+			RK3588_CLKGATE_CON(31), 5, GFLAGS),
+	COMPOSITE(CCLK_EMMC, "cclk_emmc", gpll_cpll_24m_p, 0,
+			RK3588_CLKSEL_CON(77), 14, 2, MFLAGS, 8, 6, DFLAGS,
+			RK3588_CLKGATE_CON(31), 6, GFLAGS),
+	COMPOSITE(BCLK_EMMC, "bclk_emmc", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(78), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(31), 7, GFLAGS),
+	GATE(TMCLK_EMMC, "tmclk_emmc", "xin24m", 0,
+			RK3588_CLKGATE_CON(31), 8, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", gpll_cpll_24m_p, 0,
+			RK3588_CLKSEL_CON(78), 12, 2, MFLAGS, 6, 6, DFLAGS,
+			RK3588_CLKGATE_CON(31), 9, GFLAGS),
+
+	/* php */
+	COMPOSITE(CLK_GMAC0_PTP_REF, "clk_gmac0_ptp_ref", clk_gmac0_ptp_ref_p, 0,
+			RK3588_CLKSEL_CON(81), 6, 1, MFLAGS, 0, 6, DFLAGS,
+			RK3588_CLKGATE_CON(34), 10, GFLAGS),
+	COMPOSITE(CLK_GMAC1_PTP_REF, "clk_gmac1_ptp_ref", clk_gmac1_ptp_ref_p, 0,
+			RK3588_CLKSEL_CON(81), 13, 1, MFLAGS, 7, 6, DFLAGS,
+			RK3588_CLKGATE_CON(34), 11, GFLAGS),
+	COMPOSITE(CLK_GMAC_125M, "clk_gmac_125m", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(83), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3588_CLKGATE_CON(35), 5, GFLAGS),
+	COMPOSITE(CLK_GMAC_50M, "clk_gmac_50m", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(84), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(35), 6, GFLAGS),
+
+	COMPOSITE(ACLK_PCIE_ROOT, "aclk_pcie_root", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(80), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(32), 6, GFLAGS),
+	COMPOSITE(ACLK_PHP_ROOT, "aclk_php_root", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(80), 13, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3588_CLKGATE_CON(32), 7, GFLAGS),
+	COMPOSITE_NODIV(PCLK_PHP_ROOT, "pclk_php_root", mux_150m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(80), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(32), 0, GFLAGS),
+	GATE(ACLK_PHP_GIC_ITS, "aclk_php_gic_its", "aclk_pcie_root", CLK_IS_CRITICAL,
+			RK3588_CLKGATE_CON(34), 6, GFLAGS),
+	GATE(ACLK_PCIE_BRIDGE, "aclk_pcie_bridge", "aclk_pcie_root", 0,
+			RK3588_CLKGATE_CON(32), 8, GFLAGS),
+	GATE(ACLK_MMU_PCIE, "aclk_mmu_pcie", "aclk_pcie_bridge", 0,
+			RK3588_CLKGATE_CON(34), 7, GFLAGS),
+	GATE(ACLK_MMU_PHP, "aclk_mmu_php", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(34), 8, GFLAGS),
+	GATE(ACLK_PCIE_4L_DBI, "aclk_pcie_4l_dbi", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(32), 13, GFLAGS),
+	GATE(ACLK_PCIE_2L_DBI, "aclk_pcie_2l_dbi", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(32), 14, GFLAGS),
+	GATE(ACLK_PCIE_1L0_DBI, "aclk_pcie_1l0_dbi", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(32), 15, GFLAGS),
+	GATE(ACLK_PCIE_1L1_DBI, "aclk_pcie_1l1_dbi", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 0, GFLAGS),
+	GATE(ACLK_PCIE_1L2_DBI, "aclk_pcie_1l2_dbi", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 1, GFLAGS),
+	GATE(ACLK_PCIE_4L_MSTR, "aclk_pcie_4l_mstr", "aclk_mmu_pcie", 0,
+			RK3588_CLKGATE_CON(33), 2, GFLAGS),
+	GATE(ACLK_PCIE_2L_MSTR, "aclk_pcie_2l_mstr", "aclk_mmu_pcie", 0,
+			RK3588_CLKGATE_CON(33), 3, GFLAGS),
+	GATE(ACLK_PCIE_1L0_MSTR, "aclk_pcie_1l0_mstr", "aclk_mmu_pcie", 0,
+			RK3588_CLKGATE_CON(33), 4, GFLAGS),
+	GATE(ACLK_PCIE_1L1_MSTR, "aclk_pcie_1l1_mstr", "aclk_mmu_pcie", 0,
+			RK3588_CLKGATE_CON(33), 5, GFLAGS),
+	GATE(ACLK_PCIE_1L2_MSTR, "aclk_pcie_1l2_mstr", "aclk_mmu_pcie", 0,
+			RK3588_CLKGATE_CON(33), 6, GFLAGS),
+	GATE(ACLK_PCIE_4L_SLV, "aclk_pcie_4l_slv", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 7, GFLAGS),
+	GATE(ACLK_PCIE_2L_SLV, "aclk_pcie_2l_slv", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 8, GFLAGS),
+	GATE(ACLK_PCIE_1L0_SLV, "aclk_pcie_1l0_slv", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 9, GFLAGS),
+	GATE(ACLK_PCIE_1L1_SLV, "aclk_pcie_1l1_slv", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 10, GFLAGS),
+	GATE(ACLK_PCIE_1L2_SLV, "aclk_pcie_1l2_slv", "aclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 11, GFLAGS),
+	GATE(PCLK_PCIE_4L, "pclk_pcie_4l", "pclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 12, GFLAGS),
+	GATE(PCLK_PCIE_2L, "pclk_pcie_2l", "pclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 13, GFLAGS),
+	GATE(PCLK_PCIE_1L0, "pclk_pcie_1l0", "pclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 14, GFLAGS),
+	GATE(PCLK_PCIE_1L1, "pclk_pcie_1l1", "pclk_php_root", 0,
+			RK3588_CLKGATE_CON(33), 15, GFLAGS),
+	GATE(PCLK_PCIE_1L2, "pclk_pcie_1l2", "pclk_php_root", 0,
+			RK3588_CLKGATE_CON(34), 0, GFLAGS),
+	GATE(CLK_PCIE_AUX0, "clk_pcie_aux0", "xin24m", 0,
+			RK3588_CLKGATE_CON(34), 1, GFLAGS),
+	GATE(CLK_PCIE_AUX1, "clk_pcie_aux1", "xin24m", 0,
+			RK3588_CLKGATE_CON(34), 2, GFLAGS),
+	GATE(CLK_PCIE_AUX2, "clk_pcie_aux2", "xin24m", 0,
+			RK3588_CLKGATE_CON(34), 3, GFLAGS),
+	GATE(CLK_PCIE_AUX3, "clk_pcie_aux3", "xin24m", 0,
+			RK3588_CLKGATE_CON(34), 4, GFLAGS),
+	GATE(CLK_PCIE_AUX4, "clk_pcie_aux4", "xin24m", 0,
+			RK3588_CLKGATE_CON(34), 5, GFLAGS),
+	GATE(CLK_PIPEPHY0_REF, "clk_pipephy0_ref", "xin24m", 0,
+			RK3588_CLKGATE_CON(37), 0, GFLAGS),
+	GATE(CLK_PIPEPHY1_REF, "clk_pipephy1_ref", "xin24m", 0,
+			RK3588_CLKGATE_CON(37), 1, GFLAGS),
+	GATE(CLK_PIPEPHY2_REF, "clk_pipephy2_ref", "xin24m", 0,
+			RK3588_CLKGATE_CON(37), 2, GFLAGS),
+	GATE(PCLK_GMAC0, "pclk_gmac0", "pclk_php_root", 0,
+			RK3588_CLKGATE_CON(32), 3, GFLAGS),
+	GATE(PCLK_GMAC1, "pclk_gmac1", "pclk_php_root", 0,
+			RK3588_CLKGATE_CON(32), 4, GFLAGS),
+	GATE(ACLK_GMAC0, "aclk_gmac0", "aclk_mmu_php", 0,
+			RK3588_CLKGATE_CON(32), 10, GFLAGS),
+	GATE(ACLK_GMAC1, "aclk_gmac1", "aclk_mmu_php", 0,
+			RK3588_CLKGATE_CON(32), 11, GFLAGS),
+	GATE(CLK_PMALIVE0, "clk_pmalive0", "xin24m", 0,
+			RK3588_CLKGATE_CON(37), 4, GFLAGS),
+	GATE(CLK_PMALIVE1, "clk_pmalive1", "xin24m", 0,
+			RK3588_CLKGATE_CON(37), 5, GFLAGS),
+	GATE(CLK_PMALIVE2, "clk_pmalive2", "xin24m", 0,
+			RK3588_CLKGATE_CON(37), 6, GFLAGS),
+	GATE(ACLK_SATA0, "aclk_sata0", "aclk_mmu_php", 0,
+			RK3588_CLKGATE_CON(37), 7, GFLAGS),
+	GATE(ACLK_SATA1, "aclk_sata1", "aclk_mmu_php", 0,
+			RK3588_CLKGATE_CON(37), 8, GFLAGS),
+	GATE(ACLK_SATA2, "aclk_sata2", "aclk_mmu_php", 0,
+			RK3588_CLKGATE_CON(37), 9, GFLAGS),
+	COMPOSITE(CLK_RXOOB0, "clk_rxoob0", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(82), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(37), 10, GFLAGS),
+	COMPOSITE(CLK_RXOOB1, "clk_rxoob1", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(82), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3588_CLKGATE_CON(37), 11, GFLAGS),
+	COMPOSITE(CLK_RXOOB2, "clk_rxoob2", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(83), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(37), 12, GFLAGS),
+	GATE(ACLK_USB3OTG2, "aclk_usb3otg2", "aclk_mmu_php", 0,
+			RK3588_CLKGATE_CON(35), 7, GFLAGS),
+	GATE(SUSPEND_CLK_USB3OTG2, "suspend_clk_usb3otg2", "xin24m", 0,
+			RK3588_CLKGATE_CON(35), 8, GFLAGS),
+	GATE(REF_CLK_USB3OTG2, "ref_clk_usb3otg2", "xin24m", 0,
+			RK3588_CLKGATE_CON(35), 9, GFLAGS),
+	COMPOSITE(CLK_UTMI_OTG2, "clk_utmi_otg2", mux_150m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(84), 12, 2, MFLAGS, 8, 4, DFLAGS,
+			RK3588_CLKGATE_CON(35), 10, GFLAGS),
+	GATE(PCLK_PCIE_COMBO_PIPE_PHY0, "pclk_pcie_combo_pipe_phy0", "pclk_top_root", 0,
+			RK3588_PHP_CLKGATE_CON(0), 5, GFLAGS),
+	GATE(PCLK_PCIE_COMBO_PIPE_PHY1, "pclk_pcie_combo_pipe_phy1", "pclk_top_root", 0,
+			RK3588_PHP_CLKGATE_CON(0), 6, GFLAGS),
+	GATE(PCLK_PCIE_COMBO_PIPE_PHY2, "pclk_pcie_combo_pipe_phy2", "pclk_top_root", 0,
+			RK3588_PHP_CLKGATE_CON(0), 7, GFLAGS),
+	GATE(PCLK_PCIE_COMBO_PIPE_PHY, "pclk_pcie_combo_pipe_phy", "pclk_top_root", 0,
+			RK3588_PHP_CLKGATE_CON(0), 8, GFLAGS),
+
+	/* rga */
+	COMPOSITE(CLK_RGA3_1_CORE, "clk_rga3_1_core", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(174), 14, 2, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(76), 6, GFLAGS),
+	COMPOSITE(ACLK_RGA3_ROOT, "aclk_rga3_root", gpll_cpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(174), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(76), 0, GFLAGS),
+	COMPOSITE_NODIV(HCLK_RGA3_ROOT, "hclk_rga3_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(174), 7, 2, MFLAGS,
+			RK3588_CLKGATE_CON(76), 1, GFLAGS),
+	GATE(HCLK_RGA3_1, "hclk_rga3_1", "hclk_rga3_root", 0,
+			RK3588_CLKGATE_CON(76), 4, GFLAGS),
+	GATE(ACLK_RGA3_1, "aclk_rga3_1", "aclk_rga3_root", 0,
+			RK3588_CLKGATE_CON(76), 5, GFLAGS),
+
+	/* vdec */
+	COMPOSITE_NODIV(0, "hclk_rkvdec0_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(89), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(40), 0, GFLAGS),
+	COMPOSITE(0, "aclk_rkvdec0_root", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(89), 7, 2, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(40), 1, GFLAGS),
+	COMPOSITE(ACLK_RKVDEC_CCU, "aclk_rkvdec_ccu", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(89), 14, 2, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(40), 2, GFLAGS),
+	COMPOSITE(CLK_RKVDEC0_CA, "clk_rkvdec0_ca", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(90), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(40), 7, GFLAGS),
+	COMPOSITE(CLK_RKVDEC0_HEVC_CA, "clk_rkvdec0_hevc_ca", gpll_cpll_npll_1000m_p, 0,
+			RK3588_CLKSEL_CON(90), 11, 2, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(40), 8, GFLAGS),
+	COMPOSITE(CLK_RKVDEC0_CORE, "clk_rkvdec0_core", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(91), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(40), 9, GFLAGS),
+	COMPOSITE_NODIV(0, "hclk_rkvdec1_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(93), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(41), 0, GFLAGS),
+	COMPOSITE(0, "aclk_rkvdec1_root", gpll_cpll_aupll_npll_p, 0,
+			RK3588_CLKSEL_CON(93), 7, 2, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(41), 1, GFLAGS),
+	COMPOSITE(CLK_RKVDEC1_CA, "clk_rkvdec1_ca", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(93), 14, 1, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(41), 6, GFLAGS),
+	COMPOSITE(CLK_RKVDEC1_HEVC_CA, "clk_rkvdec1_hevc_ca", gpll_cpll_npll_1000m_p, 0,
+			RK3588_CLKSEL_CON(94), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(41), 7, GFLAGS),
+	COMPOSITE(CLK_RKVDEC1_CORE, "clk_rkvdec1_core", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(94), 12, 1, MFLAGS, 7, 5, DFLAGS,
+			RK3588_CLKGATE_CON(41), 8, GFLAGS),
+
+	/* sdio */
+	COMPOSITE_NODIV(0, "hclk_sdio_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(172), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(75), 0, GFLAGS),
+	COMPOSITE(CCLK_SRC_SDIO, "cclk_src_sdio", gpll_cpll_24m_p, 0,
+			RK3588_CLKSEL_CON(172), 8, 2, MFLAGS, 2, 6, DFLAGS,
+			RK3588_CLKGATE_CON(75), 3, GFLAGS),
+	MMC(SCLK_SDIO_DRV, "sdio_drv", "cclk_src_sdio", RK3588_SDIO_CON0, 1),
+	MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "cclk_src_sdio", RK3588_SDIO_CON1, 1),
+
+	/* usb */
+	COMPOSITE(ACLK_USB_ROOT, "aclk_usb_root", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(96), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(42), 0, GFLAGS),
+	COMPOSITE_NODIV(HCLK_USB_ROOT, "hclk_usb_root", mux_150m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(96), 6, 2, MFLAGS,
+			RK3588_CLKGATE_CON(42), 1, GFLAGS),
+	GATE(SUSPEND_CLK_USB3OTG0, "suspend_clk_usb3otg0", "xin24m", 0,
+			RK3588_CLKGATE_CON(42), 5, GFLAGS),
+	GATE(REF_CLK_USB3OTG0, "ref_clk_usb3otg0", "xin24m", 0,
+			RK3588_CLKGATE_CON(42), 6, GFLAGS),
+	GATE(SUSPEND_CLK_USB3OTG1, "suspend_clk_usb3otg1", "xin24m", 0,
+			RK3588_CLKGATE_CON(42), 8, GFLAGS),
+	GATE(REF_CLK_USB3OTG1, "ref_clk_usb3otg1", "xin24m", 0,
+			RK3588_CLKGATE_CON(42), 9, GFLAGS),
+
+	/* vdpu */
+	COMPOSITE(ACLK_VDPU_ROOT, "aclk_vdpu_root", gpll_cpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(98), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(44), 0, GFLAGS),
+	COMPOSITE_NODIV(ACLK_VDPU_LOW_ROOT, "aclk_vdpu_low_root", mux_400m_200m_100m_24m_p, 0,
+			RK3588_CLKSEL_CON(98), 7, 2, MFLAGS,
+			RK3588_CLKGATE_CON(44), 1, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VDPU_ROOT, "hclk_vdpu_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(98), 9, 2, MFLAGS,
+			RK3588_CLKGATE_CON(44), 2, GFLAGS),
+	COMPOSITE(ACLK_JPEG_DECODER_ROOT, "aclk_jpeg_decoder_root", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(99), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(44), 3, GFLAGS),
+	GATE(HCLK_IEP2P0, "hclk_iep2p0", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(45), 4, GFLAGS),
+	COMPOSITE(CLK_IEP2P0_CORE, "clk_iep2p0_core", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(99), 12, 1, MFLAGS, 7, 5, DFLAGS,
+			RK3588_CLKGATE_CON(45), 6, GFLAGS),
+	GATE(HCLK_JPEG_ENCODER0, "hclk_jpeg_encoder0", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(44), 11, GFLAGS),
+	GATE(HCLK_JPEG_ENCODER1, "hclk_jpeg_encoder1", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(44), 13, GFLAGS),
+	GATE(HCLK_JPEG_ENCODER2, "hclk_jpeg_encoder2", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(44), 15, GFLAGS),
+	GATE(HCLK_JPEG_ENCODER3, "hclk_jpeg_encoder3", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(45), 1, GFLAGS),
+	GATE(HCLK_JPEG_DECODER, "hclk_jpeg_decoder", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(45), 3, GFLAGS),
+	GATE(HCLK_RGA2, "hclk_rga2", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(45), 7, GFLAGS),
+	GATE(ACLK_RGA2, "aclk_rga2", "aclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(45), 8, GFLAGS),
+	COMPOSITE(CLK_RGA2_CORE, "clk_rga2_core", gpll_cpll_npll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(100), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(45), 9, GFLAGS),
+	GATE(HCLK_RGA3_0, "hclk_rga3_0", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(45), 10, GFLAGS),
+	GATE(ACLK_RGA3_0, "aclk_rga3_0", "aclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(45), 11, GFLAGS),
+	COMPOSITE(CLK_RGA3_0_CORE, "clk_rga3_0_core", gpll_cpll_npll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(100), 13, 3, MFLAGS, 8, 5, DFLAGS,
+			RK3588_CLKGATE_CON(45), 12, GFLAGS),
+	GATE(HCLK_VPU, "hclk_vpu", "hclk_vdpu_root", 0,
+			RK3588_CLKGATE_CON(44), 9, GFLAGS),
+
+	/* venc */
+	COMPOSITE_NODIV(HCLK_RKVENC1_ROOT, "hclk_rkvenc1_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(104), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(48), 0, GFLAGS),
+	COMPOSITE(ACLK_RKVENC1_ROOT, "aclk_rkvenc1_root", gpll_cpll_npll_p, 0,
+			RK3588_CLKSEL_CON(104), 7, 2, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(48), 1, GFLAGS),
+	COMPOSITE_NODIV(HCLK_RKVENC0_ROOT, "hclk_rkvenc0_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(102), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(47), 0, GFLAGS),
+	COMPOSITE(ACLK_RKVENC0_ROOT, "aclk_rkvenc0_root", gpll_cpll_npll_p, 0,
+			RK3588_CLKSEL_CON(102), 7, 2, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(47), 1, GFLAGS),
+	GATE(HCLK_RKVENC0, "hclk_rkvenc0", "hclk_rkvenc0_root", 0,
+			RK3588_CLKGATE_CON(47), 4, GFLAGS),
+	GATE(ACLK_RKVENC0, "aclk_rkvenc0", "aclk_rkvenc0_root", 0,
+			RK3588_CLKGATE_CON(47), 5, GFLAGS),
+	COMPOSITE(CLK_RKVENC0_CORE, "clk_rkvenc0_core", gpll_cpll_aupll_npll_p, 0,
+			RK3588_CLKSEL_CON(102), 14, 2, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(47), 6, GFLAGS),
+	COMPOSITE(CLK_RKVENC1_CORE, "clk_rkvenc1_core", gpll_cpll_aupll_npll_p, 0,
+			RK3588_CLKSEL_CON(104), 14, 2, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(48), 6, GFLAGS),
+
+	/* vi */
+	COMPOSITE(ACLK_VI_ROOT, "aclk_vi_root", gpll_cpll_npll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(106), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(49), 0, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VI_ROOT, "hclk_vi_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(106), 8, 2, MFLAGS,
+			RK3588_CLKGATE_CON(49), 1, GFLAGS),
+	COMPOSITE_NODIV(PCLK_VI_ROOT, "pclk_vi_root", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(106), 10, 2, MFLAGS,
+			RK3588_CLKGATE_CON(49), 2, GFLAGS),
+	COMPOSITE_NODIV(ICLK_CSIHOST01, "iclk_csihost01", mux_400m_200m_100m_24m_p, 0,
+			RK3588_CLKSEL_CON(108), 14, 2, MFLAGS,
+			RK3588_CLKGATE_CON(51), 10, GFLAGS),
+	GATE(ICLK_CSIHOST0, "iclk_csihost0", "iclk_csihost01", 0,
+			RK3588_CLKGATE_CON(51), 11, GFLAGS),
+	GATE(ICLK_CSIHOST1, "iclk_csihost1", "iclk_csihost01", 0,
+			RK3588_CLKGATE_CON(51), 12, GFLAGS),
+	GATE(PCLK_CSI_HOST_0, "pclk_csi_host_0", "pclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 4, GFLAGS),
+	GATE(PCLK_CSI_HOST_1, "pclk_csi_host_1", "pclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 5, GFLAGS),
+	GATE(PCLK_CSI_HOST_2, "pclk_csi_host_2", "pclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 6, GFLAGS),
+	GATE(PCLK_CSI_HOST_3, "pclk_csi_host_3", "pclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 7, GFLAGS),
+	GATE(PCLK_CSI_HOST_4, "pclk_csi_host_4", "pclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 8, GFLAGS),
+	GATE(PCLK_CSI_HOST_5, "pclk_csi_host_5", "pclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 9, GFLAGS),
+	GATE(ACLK_FISHEYE0, "aclk_fisheye0", "aclk_vi_root", 0,
+			RK3588_CLKGATE_CON(49), 14, GFLAGS),
+	GATE(HCLK_FISHEYE0, "hclk_fisheye0", "hclk_vi_root", 0,
+			RK3588_CLKGATE_CON(49), 15, GFLAGS),
+	COMPOSITE(CLK_FISHEYE0_CORE, "clk_fisheye0_core", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(108), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(50), 0, GFLAGS),
+	GATE(ACLK_FISHEYE1, "aclk_fisheye1", "aclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 1, GFLAGS),
+	GATE(HCLK_FISHEYE1, "hclk_fisheye1", "hclk_vi_root", 0,
+			RK3588_CLKGATE_CON(50), 2, GFLAGS),
+	COMPOSITE(CLK_FISHEYE1_CORE, "clk_fisheye1_core", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(108), 12, 2, MFLAGS, 7, 5, DFLAGS,
+			RK3588_CLKGATE_CON(50), 3, GFLAGS),
+	COMPOSITE(CLK_ISP0_CORE, "clk_isp0_core", gpll_cpll_aupll_spll_p, 0,
+			RK3588_CLKSEL_CON(107), 11, 2, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(49), 9, GFLAGS),
+	GATE(CLK_ISP0_CORE_MARVIN, "clk_isp0_core_marvin", "clk_isp0_core", 0,
+			RK3588_CLKGATE_CON(49), 10, GFLAGS),
+	GATE(CLK_ISP0_CORE_VICAP, "clk_isp0_core_vicap", "clk_isp0_core", 0,
+			RK3588_CLKGATE_CON(49), 11, GFLAGS),
+	GATE(ACLK_ISP0, "aclk_isp0", "aclk_vi_root", 0,
+			RK3588_CLKGATE_CON(49), 12, GFLAGS),
+	GATE(HCLK_ISP0, "hclk_isp0", "hclk_vi_root", 0,
+			RK3588_CLKGATE_CON(49), 13, GFLAGS),
+	COMPOSITE(DCLK_VICAP, "dclk_vicap", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(107), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(49), 6, GFLAGS),
+	GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi_root", 0,
+			RK3588_CLKGATE_CON(49), 7, GFLAGS),
+	GATE(HCLK_VICAP, "hclk_vicap", "hclk_vi_root", 0,
+			RK3588_CLKGATE_CON(49), 8, GFLAGS),
+
+	/* vo0 */
+	COMPOSITE(ACLK_VO0_ROOT, "aclk_vo0_root", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(116), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(55), 0, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VO0_ROOT, "hclk_vo0_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(116), 6, 2, MFLAGS,
+			RK3588_CLKGATE_CON(55), 1, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VO0_S_ROOT, "hclk_vo0_s_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(116), 8, 2, MFLAGS,
+			RK3588_CLKGATE_CON(55), 2, GFLAGS),
+	COMPOSITE_NODIV(PCLK_VO0_ROOT, "pclk_vo0_root", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(116), 10, 2, MFLAGS,
+			RK3588_CLKGATE_CON(55), 3, GFLAGS),
+	COMPOSITE_NODIV(PCLK_VO0_S_ROOT, "pclk_vo0_s_root", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(116), 12, 2, MFLAGS,
+			RK3588_CLKGATE_CON(55), 4, GFLAGS),
+	GATE(PCLK_DP0, "pclk_dp0", "pclk_vo0_root", 0,
+			RK3588_CLKGATE_CON(56), 4, GFLAGS),
+	GATE(PCLK_DP1, "pclk_dp1", "pclk_vo0_root", 0,
+			RK3588_CLKGATE_CON(56), 5, GFLAGS),
+	GATE(PCLK_S_DP0, "pclk_s_dp0", "pclk_vo0_s_root", 0,
+			RK3588_CLKGATE_CON(56), 6, GFLAGS),
+	GATE(PCLK_S_DP1, "pclk_s_dp1", "pclk_vo0_s_root", 0,
+			RK3588_CLKGATE_CON(56), 7, GFLAGS),
+	GATE(CLK_DP0, "clk_dp0", "aclk_vo0_root", 0,
+			RK3588_CLKGATE_CON(56), 8, GFLAGS),
+	GATE(CLK_DP1, "clk_dp1", "aclk_vo0_root", 0,
+			RK3588_CLKGATE_CON(56), 9, GFLAGS),
+	GATE(HCLK_HDCP_KEY0, "hclk_hdcp_key0", "hclk_vo0_s_root", 0,
+			RK3588_CLKGATE_CON(55), 11, GFLAGS),
+	GATE(PCLK_HDCP0, "pclk_hdcp0", "pclk_vo0_root", 0,
+			RK3588_CLKGATE_CON(55), 14, GFLAGS),
+	GATE(ACLK_TRNG0, "aclk_trng0", "aclk_vo0_root", 0,
+			RK3588_CLKGATE_CON(56), 0, GFLAGS),
+	GATE(PCLK_TRNG0, "pclk_trng0", "pclk_vo0_root", 0,
+			RK3588_CLKGATE_CON(56), 1, GFLAGS),
+	GATE(PCLK_VO0GRF, "pclk_vo0grf", "pclk_vo0_root", CLK_IGNORE_UNUSED,
+			RK3588_CLKGATE_CON(55), 10, GFLAGS),
+	COMPOSITE(CLK_I2S4_8CH_TX_SRC, "clk_i2s4_8ch_tx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(118), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(56), 11, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S4_8CH_TX_FRAC, "clk_i2s4_8ch_tx_frac", "clk_i2s4_8ch_tx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(119), 0,
+			RK3588_CLKGATE_CON(56), 12, GFLAGS,
+			&rk3588_i2s4_8ch_tx_fracmux),
+	GATE(MCLK_I2S4_8CH_TX, "mclk_i2s4_8ch_tx", "clk_i2s4_8ch_tx", 0,
+			RK3588_CLKGATE_CON(56), 13, GFLAGS),
+	COMPOSITE(CLK_I2S8_8CH_TX_SRC, "clk_i2s8_8ch_tx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(120), 8, 1, MFLAGS, 3, 5, DFLAGS,
+			RK3588_CLKGATE_CON(56), 15, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S8_8CH_TX_FRAC, "clk_i2s8_8ch_tx_frac", "clk_i2s8_8ch_tx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(121), 0,
+			RK3588_CLKGATE_CON(57), 0, GFLAGS,
+			&rk3588_i2s8_8ch_tx_fracmux),
+	GATE(MCLK_I2S8_8CH_TX, "mclk_i2s8_8ch_tx", "clk_i2s8_8ch_tx", 0,
+			RK3588_CLKGATE_CON(57), 1, GFLAGS),
+	COMPOSITE(CLK_SPDIF2_DP0_SRC, "clk_spdif2_dp0_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(122), 8, 1, MFLAGS, 3, 5, DFLAGS,
+			RK3588_CLKGATE_CON(57), 3, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_SPDIF2_DP0_FRAC, "clk_spdif2_dp0_frac", "clk_spdif2_dp0_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(123), 0,
+			RK3588_CLKGATE_CON(57), 4, GFLAGS,
+			&rk3588_spdif2_dp0_fracmux),
+	GATE(MCLK_SPDIF2_DP0, "mclk_spdif2_dp0", "clk_spdif2_dp0", 0,
+			RK3588_CLKGATE_CON(57), 5, GFLAGS),
+	GATE(MCLK_SPDIF2, "mclk_spdif2", "clk_spdif2_dp0", 0,
+			RK3588_CLKGATE_CON(57), 6, GFLAGS),
+	COMPOSITE(CLK_SPDIF5_DP1_SRC, "clk_spdif5_dp1_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(124), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(57), 8, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_SPDIF5_DP1_FRAC, "clk_spdif5_dp1_frac", "clk_spdif5_dp1_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(125), 0,
+			RK3588_CLKGATE_CON(57), 9, GFLAGS,
+			&rk3588_spdif5_dp1_fracmux),
+	GATE(MCLK_SPDIF5_DP1, "mclk_spdif5_dp1", "clk_spdif5_dp1", 0,
+			RK3588_CLKGATE_CON(57), 10, GFLAGS),
+	GATE(MCLK_SPDIF5, "mclk_spdif5", "clk_spdif5_dp1", 0,
+			RK3588_CLKGATE_CON(57), 11, GFLAGS),
+	COMPOSITE_NOMUX(CLK_AUX16M_0, "clk_aux16m_0", "gpll", 0,
+			RK3588_CLKSEL_CON(117), 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(56), 2, GFLAGS),
+	COMPOSITE_NOMUX(CLK_AUX16M_1, "clk_aux16m_1", "gpll", 0,
+			RK3588_CLKSEL_CON(117), 8, 8, DFLAGS,
+			RK3588_CLKGATE_CON(56), 3, GFLAGS),
+
+	/* vo1 */
+	COMPOSITE_HALFDIV(CLK_HDMITRX_REFSRC, "clk_hdmitrx_refsrc", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(157), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(65), 9, GFLAGS),
+	COMPOSITE(ACLK_HDCP1_ROOT, "aclk_hdcp1_root", aclk_hdcp1_root_p, 0,
+			RK3588_CLKSEL_CON(128), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(59), 0, GFLAGS),
+	COMPOSITE(ACLK_HDMIRX_ROOT, "aclk_hdmirx_root", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(128), 12, 1, MFLAGS, 7, 5, DFLAGS,
+			RK3588_CLKGATE_CON(59), 1, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VO1_ROOT, "hclk_vo1_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(128), 13, 2, MFLAGS,
+			RK3588_CLKGATE_CON(59), 2, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VO1_S_ROOT, "hclk_vo1_s_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(129), 0, 2, MFLAGS,
+			RK3588_CLKGATE_CON(59), 3, GFLAGS),
+	COMPOSITE_NODIV(PCLK_VO1_ROOT, "pclk_vo1_root", mux_150m_100m_24m_p, 0,
+			RK3588_CLKSEL_CON(129), 2, 2, MFLAGS,
+			RK3588_CLKGATE_CON(59), 4, GFLAGS),
+	COMPOSITE_NODIV(PCLK_VO1_S_ROOT, "pclk_vo1_s_root", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(129), 4, 2, MFLAGS,
+			RK3588_CLKGATE_CON(59), 5, GFLAGS),
+	COMPOSITE(ACLK_VOP_ROOT, "aclk_vop_root", gpll_cpll_dmyaupll_npll_spll_p, 0,
+			RK3588_CLKSEL_CON(110), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(52), 0, GFLAGS),
+	COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, 0,
+			RK3588_CLKSEL_CON(110), 8, 2, MFLAGS,
+			RK3588_CLKGATE_CON(52), 1, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VOP_ROOT, "hclk_vop_root", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(110), 10, 2, MFLAGS,
+			RK3588_CLKGATE_CON(52), 2, GFLAGS),
+	COMPOSITE_NODIV(PCLK_VOP_ROOT, "pclk_vop_root", mux_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(110), 12, 2, MFLAGS,
+			RK3588_CLKGATE_CON(52), 3, GFLAGS),
+	COMPOSITE(ACLK_VO1USB_TOP_ROOT, "aclk_vo1usb_top_root", gpll_cpll_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(170), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(74), 0, GFLAGS),
+	COMPOSITE_NODIV(HCLK_VO1USB_TOP_ROOT, "hclk_vo1usb_top_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL,
+			RK3588_CLKSEL_CON(170), 6, 2, MFLAGS,
+			RK3588_CLKGATE_CON(74), 2, GFLAGS),
+	MUX(ACLK_VOP_SUB_SRC, "aclk_vop_sub_src", aclk_vop_sub_src_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(115), 9, 1, MFLAGS),
+	GATE(PCLK_EDP0, "pclk_edp0", "pclk_vo1_root", 0,
+			RK3588_CLKGATE_CON(62), 0, GFLAGS),
+	GATE(CLK_EDP0_24M, "clk_edp0_24m", "xin24m", 0,
+			RK3588_CLKGATE_CON(62), 1, GFLAGS),
+	COMPOSITE_NODIV(CLK_EDP0_200M, "clk_edp0_200m", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(140), 1, 2, MFLAGS,
+			RK3588_CLKGATE_CON(62), 2, GFLAGS),
+	GATE(PCLK_EDP1, "pclk_edp1", "pclk_vo1_root", 0,
+			RK3588_CLKGATE_CON(62), 3, GFLAGS),
+	GATE(CLK_EDP1_24M, "clk_edp1_24m", "xin24m", 0,
+			RK3588_CLKGATE_CON(62), 4, GFLAGS),
+	COMPOSITE_NODIV(CLK_EDP1_200M, "clk_edp1_200m", mux_200m_100m_50m_24m_p, 0,
+			RK3588_CLKSEL_CON(140), 3, 2, MFLAGS,
+			RK3588_CLKGATE_CON(62), 5, GFLAGS),
+	GATE(HCLK_HDCP_KEY1, "hclk_hdcp_key1", "hclk_vo1_s_root", 0,
+			RK3588_CLKGATE_CON(60), 4, GFLAGS),
+	GATE(PCLK_HDCP1, "pclk_hdcp1", "pclk_vo1_root", 0,
+			RK3588_CLKGATE_CON(60), 7, GFLAGS),
+	GATE(ACLK_HDMIRX, "aclk_hdmirx", "aclk_hdmirx_root", 0,
+			RK3588_CLKGATE_CON(61), 9, GFLAGS),
+	GATE(PCLK_HDMIRX, "pclk_hdmirx", "pclk_vo1_root", 0,
+			RK3588_CLKGATE_CON(61), 10, GFLAGS),
+	GATE(CLK_HDMIRX_REF, "clk_hdmirx_ref", "aclk_hdcp1_root", 0,
+			RK3588_CLKGATE_CON(61), 11, GFLAGS),
+	COMPOSITE(CLK_HDMIRX_AUD_SRC, "clk_hdmirx_aud_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(138), 8, 1, MFLAGS, 0, 8, DFLAGS,
+			RK3588_CLKGATE_CON(61), 12, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_HDMIRX_AUD_FRAC, "clk_hdmirx_aud_frac", "clk_hdmirx_aud_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(139), 0,
+			RK3588_CLKGATE_CON(61), 13, GFLAGS,
+			&rk3588_hdmirx_aud_fracmux),
+	GATE(CLK_HDMIRX_AUD, "clk_hdmirx_aud", "clk_hdmirx_aud_mux", 0,
+			RK3588_CLKGATE_CON(61), 14, GFLAGS),
+	GATE(PCLK_HDMITX0, "pclk_hdmitx0", "pclk_vo1_root", 0,
+			RK3588_CLKGATE_CON(60), 11, GFLAGS),
+	COMPOSITE(CLK_HDMITX0_EARC, "clk_hdmitx0_earc", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(133), 6, 1, MFLAGS, 1, 5, DFLAGS,
+			RK3588_CLKGATE_CON(60), 15, GFLAGS),
+	GATE(CLK_HDMITX0_REF, "clk_hdmitx0_ref", "aclk_hdcp1_root", 0,
+			RK3588_CLKGATE_CON(61), 0, GFLAGS),
+	GATE(PCLK_HDMITX1, "pclk_hdmitx1", "pclk_vo1_root", 0,
+			RK3588_CLKGATE_CON(61), 2, GFLAGS),
+	COMPOSITE(CLK_HDMITX1_EARC, "clk_hdmitx1_earc", gpll_cpll_p, 0,
+			RK3588_CLKSEL_CON(136), 6, 1, MFLAGS, 1, 5, DFLAGS,
+			RK3588_CLKGATE_CON(61), 6, GFLAGS),
+	GATE(CLK_HDMITX1_REF, "clk_hdmitx1_ref", "aclk_hdcp1_root", 0,
+			RK3588_CLKGATE_CON(61), 7, GFLAGS),
+	GATE(ACLK_TRNG1, "aclk_trng1", "aclk_hdcp1_root", 0,
+			RK3588_CLKGATE_CON(60), 9, GFLAGS),
+	GATE(PCLK_TRNG1, "pclk_trng1", "pclk_vo1_root", 0,
+			RK3588_CLKGATE_CON(60), 10, GFLAGS),
+	GATE(0, "pclk_vo1grf", "pclk_vo1_root", CLK_IGNORE_UNUSED,
+			RK3588_CLKGATE_CON(59), 12, GFLAGS),
+	GATE(PCLK_S_EDP0, "pclk_s_edp0", "pclk_vo1_s_root", 0,
+			RK3588_CLKGATE_CON(59), 14, GFLAGS),
+	GATE(PCLK_S_EDP1, "pclk_s_edp1", "pclk_vo1_s_root", 0,
+			RK3588_CLKGATE_CON(59), 15, GFLAGS),
+	GATE(PCLK_S_HDMIRX, "pclk_s_hdmirx", "pclk_vo1_s_root", 0,
+			RK3588_CLKGATE_CON(65), 8, GFLAGS),
+	COMPOSITE(CLK_I2S10_8CH_RX_SRC, "clk_i2s10_8ch_rx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(155), 8, 1, MFLAGS, 3, 5, DFLAGS,
+			RK3588_CLKGATE_CON(65), 5, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S10_8CH_RX_FRAC, "clk_i2s10_8ch_rx_frac", "clk_i2s10_8ch_rx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(156), 0,
+			RK3588_CLKGATE_CON(65), 6, GFLAGS,
+			&rk3588_i2s10_8ch_rx_fracmux),
+	GATE(MCLK_I2S10_8CH_RX, "mclk_i2s10_8ch_rx", "clk_i2s10_8ch_rx", 0,
+			RK3588_CLKGATE_CON(65), 7, GFLAGS),
+	COMPOSITE(CLK_I2S7_8CH_RX_SRC, "clk_i2s7_8ch_rx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(129), 11, 1, MFLAGS, 6, 5, DFLAGS,
+			RK3588_CLKGATE_CON(60), 1, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S7_8CH_RX_FRAC, "clk_i2s7_8ch_rx_frac", "clk_i2s7_8ch_rx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(130), 0,
+			RK3588_CLKGATE_CON(60), 2, GFLAGS,
+			&rk3588_i2s7_8ch_rx_fracmux),
+	GATE(MCLK_I2S7_8CH_RX, "mclk_i2s7_8ch_rx", "clk_i2s7_8ch_rx", 0,
+			RK3588_CLKGATE_CON(60), 3, GFLAGS),
+	COMPOSITE(CLK_I2S9_8CH_RX_SRC, "clk_i2s9_8ch_rx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(153), 12, 1, MFLAGS, 7, 5, DFLAGS,
+			RK3588_CLKGATE_CON(65), 1, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S9_8CH_RX_FRAC, "clk_i2s9_8ch_rx_frac", "clk_i2s9_8ch_rx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(154), 0,
+			RK3588_CLKGATE_CON(65), 2, GFLAGS,
+			&rk3588_i2s9_8ch_rx_fracmux),
+	GATE(MCLK_I2S9_8CH_RX, "mclk_i2s9_8ch_rx", "clk_i2s9_8ch_rx", 0,
+			RK3588_CLKGATE_CON(65), 3, GFLAGS),
+	COMPOSITE(CLK_I2S5_8CH_TX_SRC, "clk_i2s5_8ch_tx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(140), 10, 1, MFLAGS, 5, 5, DFLAGS,
+			RK3588_CLKGATE_CON(62), 6, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S5_8CH_TX_FRAC, "clk_i2s5_8ch_tx_frac", "clk_i2s5_8ch_tx_src", 0,
+			RK3588_CLKSEL_CON(141), 0,
+			RK3588_CLKGATE_CON(62), 7, GFLAGS,
+			&rk3588_i2s5_8ch_tx_fracmux),
+	GATE(MCLK_I2S5_8CH_TX, "mclk_i2s5_8ch_tx", "clk_i2s5_8ch_tx", 0,
+			RK3588_CLKGATE_CON(62), 8, GFLAGS),
+	COMPOSITE(CLK_I2S6_8CH_TX_SRC, "clk_i2s6_8ch_tx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(144), 8, 1, MFLAGS, 3, 5, DFLAGS,
+			RK3588_CLKGATE_CON(62), 13, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S6_8CH_TX_FRAC, "clk_i2s6_8ch_tx_frac", "clk_i2s6_8ch_tx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(145), 0,
+			RK3588_CLKGATE_CON(62), 14, GFLAGS,
+			&rk3588_i2s6_8ch_tx_fracmux),
+	GATE(MCLK_I2S6_8CH_TX, "mclk_i2s6_8ch_tx", "clk_i2s6_8ch_tx", 0,
+			RK3588_CLKGATE_CON(62), 15, GFLAGS),
+	COMPOSITE(CLK_I2S6_8CH_RX_SRC, "clk_i2s6_8ch_rx_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(146), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(63), 0, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S6_8CH_RX_FRAC, "clk_i2s6_8ch_rx_frac", "clk_i2s6_8ch_rx_src", 0,
+			RK3588_CLKSEL_CON(147), 0,
+			RK3588_CLKGATE_CON(63), 1, GFLAGS,
+			&rk3588_i2s6_8ch_rx_fracmux),
+	GATE(MCLK_I2S6_8CH_RX, "mclk_i2s6_8ch_rx", "clk_i2s6_8ch_rx", 0,
+			RK3588_CLKGATE_CON(63), 2, GFLAGS),
+	MUX(I2S6_8CH_MCLKOUT, "i2s6_8ch_mclkout", i2s6_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(148), 2, 2, MFLAGS),
+	COMPOSITE(CLK_SPDIF3_SRC, "clk_spdif3_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(148), 9, 1, MFLAGS, 4, 5, DFLAGS,
+			RK3588_CLKGATE_CON(63), 5, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_SPDIF3_FRAC, "clk_spdif3_frac", "clk_spdif3_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(149), 0,
+			RK3588_CLKGATE_CON(63), 6, GFLAGS,
+			&rk3588_spdif3_fracmux),
+	GATE(MCLK_SPDIF3, "mclk_spdif3", "clk_spdif3", 0,
+			RK3588_CLKGATE_CON(63), 7, GFLAGS),
+	COMPOSITE(CLK_SPDIF4_SRC, "clk_spdif4_src", gpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(150), 7, 1, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(63), 9, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_SPDIF4_FRAC, "clk_spdif4_frac", "clk_spdif4_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(151), 0,
+			RK3588_CLKGATE_CON(63), 10, GFLAGS,
+			&rk3588_spdif4_fracmux),
+	GATE(MCLK_SPDIF4, "mclk_spdif4", "clk_spdif4", 0,
+			RK3588_CLKGATE_CON(63), 11, GFLAGS),
+	COMPOSITE(MCLK_SPDIFRX0, "mclk_spdifrx0", gpll_cpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(152), 7, 2, MFLAGS, 2, 5, DFLAGS,
+			RK3588_CLKGATE_CON(63), 13, GFLAGS),
+	COMPOSITE(MCLK_SPDIFRX1, "mclk_spdifrx1", gpll_cpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(152), 14, 2, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(63), 15, GFLAGS),
+	COMPOSITE(MCLK_SPDIFRX2, "mclk_spdifrx2", gpll_cpll_aupll_p, 0,
+			RK3588_CLKSEL_CON(153), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(64), 1, GFLAGS),
+	GATE(CLK_HDMIHDP0, "clk_hdmihdp0", "xin24m", 0,
+			RK3588_CLKGATE_CON(73), 12, GFLAGS),
+	GATE(CLK_HDMIHDP1, "clk_hdmihdp1", "xin24m", 0,
+			RK3588_CLKGATE_CON(73), 13, GFLAGS),
+	GATE(PCLK_HDPTX0, "pclk_hdptx0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(72), 5, GFLAGS),
+	GATE(PCLK_HDPTX1, "pclk_hdptx1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(72), 6, GFLAGS),
+	GATE(PCLK_USBDPPHY0, "pclk_usbdpphy0", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(72), 2, GFLAGS),
+	GATE(PCLK_USBDPPHY1, "pclk_usbdpphy1", "pclk_top_root", 0,
+			RK3588_CLKGATE_CON(72), 4, GFLAGS),
+	GATE(HCLK_VOP, "hclk_vop", "hclk_vop_root", 0,
+			RK3588_CLKGATE_CON(52), 8, GFLAGS),
+	GATE(ACLK_VOP, "aclk_vop", "aclk_vop_sub_src", 0,
+			RK3588_CLKGATE_CON(52), 9, GFLAGS),
+	COMPOSITE(DCLK_VOP0_SRC, "dclk_vop0_src", gpll_cpll_v0pll_aupll_p, 0,
+			RK3588_CLKSEL_CON(111), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(52), 10, GFLAGS),
+	COMPOSITE(DCLK_VOP1_SRC, "dclk_vop1_src", gpll_cpll_v0pll_aupll_p, 0,
+			RK3588_CLKSEL_CON(111), 14, 2, MFLAGS, 9, 5, DFLAGS,
+			RK3588_CLKGATE_CON(52), 11, GFLAGS),
+	COMPOSITE(DCLK_VOP2_SRC, "dclk_vop2_src", gpll_cpll_v0pll_aupll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			RK3588_CLKSEL_CON(112), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_CLKGATE_CON(52), 12, GFLAGS),
+	COMPOSITE_NODIV(DCLK_VOP0, "dclk_vop0", dclk_vop0_p,
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			RK3588_CLKSEL_CON(112), 7, 2, MFLAGS,
+			RK3588_CLKGATE_CON(52), 13, GFLAGS),
+	COMPOSITE_NODIV(DCLK_VOP1, "dclk_vop1", dclk_vop1_p,
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			RK3588_CLKSEL_CON(112), 9, 2, MFLAGS,
+			RK3588_CLKGATE_CON(53), 0, GFLAGS),
+	COMPOSITE_NODIV(DCLK_VOP2, "dclk_vop2", dclk_vop2_p,
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			RK3588_CLKSEL_CON(112), 11, 2, MFLAGS,
+			RK3588_CLKGATE_CON(53), 1, GFLAGS),
+	COMPOSITE(DCLK_VOP3, "dclk_vop3", gpll_cpll_v0pll_aupll_p, 0,
+			RK3588_CLKSEL_CON(113), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(53), 2, GFLAGS),
+	GATE(PCLK_DSIHOST0, "pclk_dsihost0", "pclk_vop_root", 0,
+			RK3588_CLKGATE_CON(53), 4, GFLAGS),
+	GATE(PCLK_DSIHOST1, "pclk_dsihost1", "pclk_vop_root", 0,
+			RK3588_CLKGATE_CON(53), 5, GFLAGS),
+	COMPOSITE(CLK_DSIHOST0, "clk_dsihost0", gpll_cpll_v0pll_spll_p, 0,
+			RK3588_CLKSEL_CON(114), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(53), 6, GFLAGS),
+	COMPOSITE(CLK_DSIHOST1, "clk_dsihost1", gpll_cpll_v0pll_spll_p, 0,
+			RK3588_CLKSEL_CON(115), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3588_CLKGATE_CON(53), 7, GFLAGS),
+	GATE(CLK_VOP_PMU, "clk_vop_pmu", "xin24m", CLK_IGNORE_UNUSED,
+			RK3588_CLKGATE_CON(53), 8, GFLAGS),
+	GATE(ACLK_VOP_DOBY, "aclk_vop_doby", "aclk_vop_root", 0,
+			RK3588_CLKGATE_CON(53), 10, GFLAGS),
+	GATE(CLK_USBDP_PHY0_IMMORTAL, "clk_usbdp_phy0_immortal", "xin24m", CLK_IGNORE_UNUSED,
+			RK3588_CLKGATE_CON(2), 8, GFLAGS),
+	GATE(CLK_USBDP_PHY1_IMMORTAL, "clk_usbdp_phy1_immortal", "xin24m", CLK_IGNORE_UNUSED,
+			RK3588_CLKGATE_CON(2), 15, GFLAGS),
+
+	GATE(CLK_REF_PIPE_PHY0_OSC_SRC, "clk_ref_pipe_phy0_osc_src", "xin24m", 0,
+			RK3588_CLKGATE_CON(77), 0, GFLAGS),
+	GATE(CLK_REF_PIPE_PHY1_OSC_SRC, "clk_ref_pipe_phy1_osc_src", "xin24m", 0,
+			RK3588_CLKGATE_CON(77), 1, GFLAGS),
+	GATE(CLK_REF_PIPE_PHY2_OSC_SRC, "clk_ref_pipe_phy2_osc_src", "xin24m", 0,
+			RK3588_CLKGATE_CON(77), 2, GFLAGS),
+	COMPOSITE_NOMUX(CLK_REF_PIPE_PHY0_PLL_SRC, "clk_ref_pipe_phy0_pll_src", "ppll", 0,
+			RK3588_CLKSEL_CON(176), 0, 6, DFLAGS,
+			RK3588_CLKGATE_CON(77), 3, GFLAGS),
+	COMPOSITE_NOMUX(CLK_REF_PIPE_PHY1_PLL_SRC, "clk_ref_pipe_phy1_pll_src", "ppll", 0,
+			RK3588_CLKSEL_CON(176), 6, 6, DFLAGS,
+			RK3588_CLKGATE_CON(77), 4, GFLAGS),
+	COMPOSITE_NOMUX(CLK_REF_PIPE_PHY2_PLL_SRC, "clk_ref_pipe_phy2_pll_src", "ppll", 0,
+			RK3588_CLKSEL_CON(177), 0, 6, DFLAGS,
+			RK3588_CLKGATE_CON(77), 5, GFLAGS),
+	MUX(CLK_REF_PIPE_PHY0, "clk_ref_pipe_phy0", clk_ref_pipe_phy0_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(177), 6, 1, MFLAGS),
+	MUX(CLK_REF_PIPE_PHY1, "clk_ref_pipe_phy1", clk_ref_pipe_phy1_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(177), 7, 1, MFLAGS),
+	MUX(CLK_REF_PIPE_PHY2, "clk_ref_pipe_phy2", clk_ref_pipe_phy2_p, CLK_SET_RATE_PARENT,
+			RK3588_CLKSEL_CON(177), 8, 1, MFLAGS),
+
+	/* pmu */
+	COMPOSITE(CLK_PMU1_300M_SRC, "clk_pmu1_300m_src", pmu_300m_24m_p, 0,
+			RK3588_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 10, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 3, GFLAGS),
+	COMPOSITE(CLK_PMU1_400M_SRC, "clk_pmu1_400m_src", pmu_400m_24m_p, 0,
+			RK3588_PMU_CLKSEL_CON(1), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 4, GFLAGS),
+	COMPOSITE_NOMUX(CLK_PMU1_50M_SRC, "clk_pmu1_50m_src", "clk_pmu1_400m_src", 0,
+			RK3588_PMU_CLKSEL_CON(0), 0, 4, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 0, GFLAGS),
+	COMPOSITE_NOMUX(CLK_PMU1_100M_SRC, "clk_pmu1_100m_src", "clk_pmu1_400m_src", 0,
+			RK3588_PMU_CLKSEL_CON(0), 4, 3, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 1, GFLAGS),
+	COMPOSITE_NOMUX(CLK_PMU1_200M_SRC, "clk_pmu1_200m_src", "clk_pmu1_400m_src", 0,
+			RK3588_PMU_CLKSEL_CON(0), 7, 3, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 2, GFLAGS),
+	COMPOSITE_NODIV(HCLK_PMU1_ROOT, "hclk_pmu1_root", hclk_pmu1_root_p, CLK_IS_CRITICAL,
+			RK3588_PMU_CLKSEL_CON(1), 6, 2, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NODIV(PCLK_PMU1_ROOT, "pclk_pmu1_root", pmu_100m_50m_24m_src_p, CLK_IS_CRITICAL,
+			RK3588_PMU_CLKSEL_CON(1), 8, 2, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 7, GFLAGS),
+	GATE(PCLK_PMU0_ROOT, "pclk_pmu0_root", "pclk_pmu1_root", CLK_IS_CRITICAL,
+			RK3588_PMU_CLKGATE_CON(5), 0, GFLAGS),
+	COMPOSITE_NODIV(HCLK_PMU_CM0_ROOT, "hclk_pmu_cm0_root", hclk_pmu_cm0_root_p, CLK_IS_CRITICAL,
+			RK3588_PMU_CLKSEL_CON(1), 10, 2, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 8, GFLAGS),
+	GATE(CLK_PMU0, "clk_pmu0", "xin24m", CLK_IS_CRITICAL,
+			RK3588_PMU_CLKGATE_CON(5), 1, GFLAGS),
+	GATE(PCLK_PMU0, "pclk_pmu0", "pclk_pmu0_root", CLK_IS_CRITICAL,
+			RK3588_PMU_CLKGATE_CON(5), 2, GFLAGS),
+	GATE(PCLK_PMU0IOC, "pclk_pmu0ioc", "pclk_pmu0_root", CLK_IS_CRITICAL,
+			RK3588_PMU_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pmu0_root", 0,
+			RK3588_PMU_CLKGATE_CON(5), 5, GFLAGS),
+	COMPOSITE_NODIV(DBCLK_GPIO0, "dbclk_gpio0", mux_24m_32k_p, 0,
+			RK3588_PMU_CLKSEL_CON(17), 0, 1, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(5), 6, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pmu0_root", 0,
+			RK3588_PMU_CLKGATE_CON(2), 1, GFLAGS),
+	COMPOSITE_NODIV(CLK_I2C0, "clk_i2c0", pmu_200m_100m_p, 0,
+			RK3588_PMU_CLKSEL_CON(3), 6, 1, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(2), 2, GFLAGS),
+	GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_pmu1_root", 0,
+			RK3588_PMU_CLKGATE_CON(2), 7, GFLAGS),
+	COMPOSITE_NOMUX(CLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", "cpll", 0,
+			RK3588_PMU_CLKSEL_CON(5), 2, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(2), 8, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S1_8CH_TX_FRAC, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_PMU_CLKSEL_CON(6), 0,
+			RK3588_PMU_CLKGATE_CON(2), 9, GFLAGS,
+			&rk3588_i2s1_8ch_tx_fracmux),
+	GATE(MCLK_I2S1_8CH_TX, "mclk_i2s1_8ch_tx", "clk_i2s1_8ch_tx", 0,
+			RK3588_PMU_CLKGATE_CON(2), 10, GFLAGS),
+	COMPOSITE_NOMUX(CLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", "cpll", 0,
+			RK3588_PMU_CLKSEL_CON(7), 2, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(2), 11, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_I2S1_8CH_RX_FRAC, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_src",
+			CLK_SET_RATE_PARENT,
+			RK3588_PMU_CLKSEL_CON(8), 0,
+			RK3588_PMU_CLKGATE_CON(2), 12, GFLAGS,
+			&rk3588_i2s1_8ch_rx_fracmux),
+	GATE(MCLK_I2S1_8CH_RX, "mclk_i2s1_8ch_rx", "clk_i2s1_8ch_rx", 0,
+			RK3588_PMU_CLKGATE_CON(2), 13, GFLAGS),
+	MUX(I2S1_8CH_MCLKOUT, "i2s1_8ch_mclkout", i2s1_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+			RK3588_PMU_CLKSEL_CON(9), 2, 2, MFLAGS),
+	GATE(PCLK_PMU1, "pclk_pmu1", "pclk_pmu0_root", CLK_IS_CRITICAL,
+			RK3588_PMU_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(CLK_DDR_FAIL_SAFE, "clk_ddr_fail_safe", "clk_pmu0", CLK_IGNORE_UNUSED,
+			RK3588_PMU_CLKGATE_CON(1), 1, GFLAGS),
+	GATE(CLK_PMU1, "clk_pmu1", "clk_pmu0", CLK_IS_CRITICAL,
+			RK3588_PMU_CLKGATE_CON(1), 3, GFLAGS),
+	GATE(HCLK_PDM0, "hclk_pdm0", "hclk_pmu1_root", 0,
+			RK3588_PMU_CLKGATE_CON(2), 14, GFLAGS),
+	COMPOSITE_NODIV(MCLK_PDM0, "mclk_pdm0", mclk_pdm0_p, 0,
+			RK3588_PMU_CLKSEL_CON(9), 4, 1, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(2), 15, GFLAGS),
+	GATE(HCLK_VAD, "hclk_vad", "hclk_pmu1_root", 0,
+			RK3588_PMU_CLKGATE_CON(3), 0, GFLAGS),
+	GATE(FCLK_PMU_CM0_CORE, "fclk_pmu_cm0_core", "hclk_pmu_cm0_root", CLK_IS_CRITICAL,
+			RK3588_PMU_CLKGATE_CON(0), 13, GFLAGS),
+	COMPOSITE(CLK_PMU_CM0_RTC, "clk_pmu_cm0_rtc", mux_24m_32k_p, CLK_IS_CRITICAL,
+			RK3588_PMU_CLKSEL_CON(2), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(0), 15, GFLAGS),
+	GATE(PCLK_PMU1_IOC, "pclk_pmu1_ioc", "pclk_pmu0_root", CLK_IGNORE_UNUSED,
+			RK3588_PMU_CLKGATE_CON(1), 5, GFLAGS),
+	GATE(PCLK_PMU1PWM, "pclk_pmu1pwm", "pclk_pmu0_root", 0,
+			RK3588_PMU_CLKGATE_CON(1), 12, GFLAGS),
+	COMPOSITE_NODIV(CLK_PMU1PWM, "clk_pmu1pwm", pmu_100m_50m_24m_src_p, 0,
+			RK3588_PMU_CLKSEL_CON(2), 9, 2, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(1), 13, GFLAGS),
+	GATE(CLK_PMU1PWM_CAPTURE, "clk_pmu1pwm_capture", "xin24m", 0,
+			RK3588_PMU_CLKGATE_CON(1), 14, GFLAGS),
+	GATE(PCLK_PMU1TIMER, "pclk_pmu1timer", "pclk_pmu0_root", 0,
+			RK3588_PMU_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_NODIV(CLK_PMU1TIMER_ROOT, "clk_pmu1timer_root", pmu_24m_32k_100m_src_p, 0,
+			RK3588_PMU_CLKSEL_CON(2), 7, 2, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(1), 9, GFLAGS),
+	GATE(CLK_PMU1TIMER0, "clk_pmu1timer0", "clk_pmu1timer_root", 0,
+			RK3588_PMU_CLKGATE_CON(1), 10, GFLAGS),
+	GATE(CLK_PMU1TIMER1, "clk_pmu1timer1", "clk_pmu1timer_root", 0,
+			RK3588_PMU_CLKGATE_CON(1), 11, GFLAGS),
+	COMPOSITE_NOMUX(CLK_UART0_SRC, "clk_uart0_src", "cpll", 0,
+			RK3588_PMU_CLKSEL_CON(3), 7, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(2), 3, GFLAGS),
+	COMPOSITE_FRACMUX(CLK_UART0_FRAC, "clk_uart0_frac", "clk_uart0_src", CLK_SET_RATE_PARENT,
+			RK3588_PMU_CLKSEL_CON(4), 0,
+			RK3588_PMU_CLKGATE_CON(2), 4, GFLAGS,
+			&rk3588_uart0_fracmux),
+	GATE(SCLK_UART0, "sclk_uart0", "clk_uart0", 0,
+			RK3588_PMU_CLKGATE_CON(2), 5, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_pmu0_root", 0,
+			RK3588_PMU_CLKGATE_CON(2), 6, GFLAGS),
+	GATE(PCLK_PMU1WDT, "pclk_pmu1wdt", "pclk_pmu0_root", 0,
+			RK3588_PMU_CLKGATE_CON(1), 6, GFLAGS),
+	COMPOSITE_NODIV(TCLK_PMU1WDT, "tclk_pmu1wdt", mux_24m_32k_p, 0,
+			RK3588_PMU_CLKSEL_CON(2), 6, 1, MFLAGS,
+			RK3588_PMU_CLKGATE_CON(1), 7, GFLAGS),
+	COMPOSITE(CLK_CR_PARA, "clk_cr_para", mux_24m_ppll_spll_p, 0,
+			RK3588_PMU_CLKSEL_CON(15), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(4), 11, GFLAGS),
+	COMPOSITE(CLK_USB2PHY_HDPTXRXPHY_REF, "clk_usb2phy_hdptxrxphy_ref", mux_24m_ppll_p,
+			CLK_IS_CRITICAL,
+			RK3588_PMU_CLKSEL_CON(14), 14, 1, MFLAGS, 9, 5, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(4), 7, GFLAGS),
+	COMPOSITE(CLK_USBDPPHY_MIPIDCPPHY_REF, "clk_usbdpphy_mipidcpphy_ref", mux_24m_ppll_spll_p,
+			CLK_IS_CRITICAL,
+			RK3588_PMU_CLKSEL_CON(14), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3588_PMU_CLKGATE_CON(4), 3, GFLAGS),
+
+	GATE(CLK_PHY0_REF_ALT_P, "clk_phy0_ref_alt_p", "ppll", 0,
+			RK3588_PHYREF_ALT_GATE, 0, GFLAGS),
+	GATE(CLK_PHY0_REF_ALT_M, "clk_phy0_ref_alt_m", "ppll", 0,
+			RK3588_PHYREF_ALT_GATE, 1, GFLAGS),
+	GATE(CLK_PHY1_REF_ALT_P, "clk_phy1_ref_alt_p", "ppll", 0,
+			RK3588_PHYREF_ALT_GATE, 2, GFLAGS),
+	GATE(CLK_PHY1_REF_ALT_M, "clk_phy1_ref_alt_m", "ppll", 0,
+			RK3588_PHYREF_ALT_GATE, 3, GFLAGS),
+
+	GATE(HCLK_SPDIFRX0, "hclk_spdifrx0", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(63), 12, GFLAGS),
+	GATE(HCLK_SPDIFRX1, "hclk_spdifrx1", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(63), 14, GFLAGS),
+	GATE(HCLK_SPDIFRX2, "hclk_spdifrx2", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(64), 0, GFLAGS),
+	GATE(HCLK_SPDIF4, "hclk_spdif4", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(63), 8, GFLAGS),
+	GATE(HCLK_SPDIF3, "hclk_spdif3", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(63), 4, GFLAGS),
+	GATE(HCLK_I2S6_8CH, "hclk_i2s6_8ch", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(63), 3, GFLAGS),
+	GATE(HCLK_I2S5_8CH, "hclk_i2s5_8ch", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(62), 12, GFLAGS),
+	GATE(HCLK_I2S9_8CH, "hclk_i2s9_8ch", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(65), 0, GFLAGS),
+	GATE(HCLK_I2S7_8CH, "hclk_i2s7_8ch", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(60), 0, GFLAGS),
+	GATE(HCLK_I2S10_8CH, "hclk_i2s10_8ch", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(65), 4, GFLAGS),
+	GATE(ACLK_HDCP1, "aclk_hdcp1", "aclk_hdcp1_pre", 0,
+			RK3588_CLKGATE_CON(60), 5, GFLAGS),
+	GATE(HCLK_HDCP1, "hclk_hdcp1", "hclk_vo1", 0,
+			RK3588_CLKGATE_CON(60), 6, GFLAGS),
+	GATE(HCLK_SPDIF5_DP1, "hclk_spdif5_dp1", "hclk_vo0", 0,
+			RK3588_CLKGATE_CON(57), 7, GFLAGS),
+	GATE(HCLK_SPDIF2_DP0, "hclk_spdif2_dp0", "hclk_vo0", 0,
+			RK3588_CLKGATE_CON(57), 2, GFLAGS),
+	GATE(HCLK_I2S8_8CH, "hclk_i2s8_8ch", "hclk_vo0", 0,
+			RK3588_CLKGATE_CON(56), 14, GFLAGS),
+	GATE(HCLK_I2S4_8CH, "hclk_i2s4_8ch", "hclk_vo0", 0,
+			RK3588_CLKGATE_CON(56), 10, GFLAGS),
+	GATE(ACLK_HDCP0, "aclk_hdcp0", "aclk_hdcp0_pre", 0,
+			RK3588_CLKGATE_CON(55), 12, GFLAGS),
+	GATE(HCLK_HDCP0, "hclk_hdcp0", "hclk_vo0", 0,
+			RK3588_CLKGATE_CON(55), 13, GFLAGS),
+	GATE(HCLK_RKVENC1, "hclk_rkvenc1", "hclk_rkvenc1_pre", 0,
+			RK3588_CLKGATE_CON(48), 4, GFLAGS),
+	GATE(ACLK_RKVENC1, "aclk_rkvenc1", "aclk_rkvenc1_pre", 0,
+			RK3588_CLKGATE_CON(48), 5, GFLAGS),
+	GATE(ACLK_VPU, "aclk_vpu", "aclk_vdpu_low_pre", 0,
+			RK3588_CLKGATE_CON(44), 8, GFLAGS),
+	GATE(ACLK_IEP2P0, "aclk_iep2p0", "aclk_vdpu_low_pre", 0,
+			RK3588_CLKGATE_CON(45), 5, GFLAGS),
+	GATE(ACLK_JPEG_ENCODER0, "aclk_jpeg_encoder0", "aclk_vdpu_low_pre", 0,
+			RK3588_CLKGATE_CON(44), 10, GFLAGS),
+	GATE(ACLK_JPEG_ENCODER1, "aclk_jpeg_encoder1", "aclk_vdpu_low_pre", 0,
+			RK3588_CLKGATE_CON(44), 12, GFLAGS),
+	GATE(ACLK_JPEG_ENCODER2, "aclk_jpeg_encoder2", "aclk_vdpu_low_pre", 0,
+			RK3588_CLKGATE_CON(44), 14, GFLAGS),
+	GATE(ACLK_JPEG_ENCODER3, "aclk_jpeg_encoder3", "aclk_vdpu_low_pre", 0,
+			RK3588_CLKGATE_CON(45), 0, GFLAGS),
+	GATE(ACLK_JPEG_DECODER, "aclk_jpeg_decoder", "aclk_jpeg_decoder_pre", 0,
+			RK3588_CLKGATE_CON(45), 2, GFLAGS),
+	GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb", 0,
+			RK3588_CLKGATE_CON(42), 7, GFLAGS),
+	GATE(HCLK_HOST0, "hclk_host0", "hclk_usb", 0,
+			RK3588_CLKGATE_CON(42), 10, GFLAGS),
+	GATE(HCLK_HOST_ARB0, "hclk_host_arb0", "hclk_usb", 0,
+			RK3588_CLKGATE_CON(42), 11, GFLAGS),
+	GATE(HCLK_HOST1, "hclk_host1", "hclk_usb", 0,
+			RK3588_CLKGATE_CON(42), 12, GFLAGS),
+	GATE(HCLK_HOST_ARB1, "hclk_host_arb1", "hclk_usb", 0,
+			RK3588_CLKGATE_CON(42), 13, GFLAGS),
+	GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb", 0,
+			RK3588_CLKGATE_CON(42), 4, GFLAGS),
+	MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "scmi_cclk_sd", RK3588_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "scmi_cclk_sd", RK3588_SDMMC_CON1, 1),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_sdio_pre", 0,
+			RK3588_CLKGATE_CON(75), 2, GFLAGS),
+	GATE(HCLK_RKVDEC1, "hclk_rkvdec1", "hclk_rkvdec1_pre", 0,
+			RK3588_CLKGATE_CON(41), 2, GFLAGS),
+	GATE(ACLK_RKVDEC1, "aclk_rkvdec1", "aclk_rkvdec1_pre", 0,
+			RK3588_CLKGATE_CON(41), 3, GFLAGS),
+	GATE(HCLK_RKVDEC0, "hclk_rkvdec0", "hclk_rkvdec0_pre", 0,
+			RK3588_CLKGATE_CON(40), 3, GFLAGS),
+	GATE(ACLK_RKVDEC0, "aclk_rkvdec0", "aclk_rkvdec0_pre", 0,
+			RK3588_CLKGATE_CON(40), 4, GFLAGS),
+	GATE(CLK_PCIE4L_PIPE, "clk_pcie4l_pipe", "clk_pipe30phy_pipe0_i", 0,
+			RK3588_CLKGATE_CON(39), 0, GFLAGS),
+	GATE(CLK_PCIE2L_PIPE, "clk_pcie2l_pipe", "clk_pipe30phy_pipe2_i", 0,
+			RK3588_CLKGATE_CON(39), 1, GFLAGS),
+	GATE(CLK_PIPEPHY0_PIPE_G, "clk_pipephy0_pipe_g", "clk_pipephy0_pipe_i", 0,
+			RK3588_CLKGATE_CON(38), 3, GFLAGS),
+	GATE(CLK_PIPEPHY1_PIPE_G, "clk_pipephy1_pipe_g", "clk_pipephy1_pipe_i", 0,
+			RK3588_CLKGATE_CON(38), 4, GFLAGS),
+	GATE(CLK_PIPEPHY2_PIPE_G, "clk_pipephy2_pipe_g", "clk_pipephy2_pipe_i", 0,
+			RK3588_CLKGATE_CON(38), 5, GFLAGS),
+	GATE(CLK_PIPEPHY0_PIPE_ASIC_G, "clk_pipephy0_pipe_asic_g", "clk_pipephy0_pipe_i", 0,
+			RK3588_CLKGATE_CON(38), 6, GFLAGS),
+	GATE(CLK_PIPEPHY1_PIPE_ASIC_G, "clk_pipephy1_pipe_asic_g", "clk_pipephy1_pipe_i", 0,
+			RK3588_CLKGATE_CON(38), 7, GFLAGS),
+	GATE(CLK_PIPEPHY2_PIPE_ASIC_G, "clk_pipephy2_pipe_asic_g", "clk_pipephy2_pipe_i", 0,
+			RK3588_CLKGATE_CON(38), 8, GFLAGS),
+	GATE(CLK_PIPEPHY2_PIPE_U3_G, "clk_pipephy2_pipe_u3_g", "clk_pipephy2_pipe_i", 0,
+			RK3588_CLKGATE_CON(38), 9, GFLAGS),
+	GATE(CLK_PCIE1L2_PIPE, "clk_pcie1l2_pipe", "clk_pipephy0_pipe_g", 0,
+			RK3588_CLKGATE_CON(38), 13, GFLAGS),
+	GATE(CLK_PCIE1L0_PIPE, "clk_pcie1l0_pipe", "clk_pipephy1_pipe_g", 0,
+			RK3588_CLKGATE_CON(38), 14, GFLAGS),
+	GATE(CLK_PCIE1L1_PIPE, "clk_pcie1l1_pipe", "clk_pipephy2_pipe_g", 0,
+			RK3588_CLKGATE_CON(38), 15, GFLAGS),
+	GATE(HCLK_SFC, "hclk_sfc", "hclk_nvm", 0,
+			RK3588_CLKGATE_CON(31), 10, GFLAGS),
+	GATE(HCLK_SFC_XIP, "hclk_sfc_xip", "hclk_nvm", 0,
+			RK3588_CLKGATE_CON(31), 11, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_nvm", 0,
+			RK3588_CLKGATE_CON(31), 4, GFLAGS),
+	GATE(ACLK_ISP1, "aclk_isp1", "aclk_isp1_pre", 0,
+			RK3588_CLKGATE_CON(26), 5, GFLAGS),
+	GATE(HCLK_ISP1, "hclk_isp1", "hclk_isp1_pre", 0,
+			RK3588_CLKGATE_CON(26), 7, GFLAGS),
+	GATE(PCLK_AV1, "pclk_av1", "pclk_av1_pre", 0,
+			RK3588_CLKGATE_CON(68), 5, GFLAGS),
+	GATE(ACLK_AV1, "aclk_av1", "aclk_av1_pre", 0,
+			RK3588_CLKGATE_CON(68), 2, GFLAGS),
+
+	GATE_LINK(ACLK_ISP1_PRE, "aclk_isp1_pre", "aclk_isp1_root", "aclk_vi_root", 0, RK3588_CLKGATE_CON(26), 6, GFLAGS),
+	GATE_LINK(HCLK_ISP1_PRE, "hclk_isp1_pre", "hclk_isp1_root", "hclk_vi_root", 0, RK3588_CLKGATE_CON(26), 8, GFLAGS),
+	GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", "aclk_nvm_root", 0, RK3588_CLKGATE_CON(31), 2, GFLAGS),
+	GATE_LINK(ACLK_USB, "aclk_usb", "aclk_usb_root", "aclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 2, GFLAGS),
+	GATE_LINK(HCLK_USB, "hclk_usb", "hclk_usb_root", "hclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 3, GFLAGS),
+	GATE_LINK(ACLK_JPEG_DECODER_PRE, "aclk_jpeg_decoder_pre", "aclk_jpeg_decoder_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 7, GFLAGS),
+	GATE_LINK(ACLK_VDPU_LOW_PRE, "aclk_vdpu_low_pre", "aclk_vdpu_low_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 5, GFLAGS),
+	GATE_LINK(ACLK_RKVENC1_PRE, "aclk_rkvenc1_pre", "aclk_rkvenc1_root", "aclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 3, GFLAGS),
+	GATE_LINK(HCLK_RKVENC1_PRE, "hclk_rkvenc1_pre", "hclk_rkvenc1_root", "hclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 2, GFLAGS),
+	GATE_LINK(HCLK_RKVDEC0_PRE, "hclk_rkvdec0_pre", "hclk_rkvdec0_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 5, GFLAGS),
+	GATE_LINK(ACLK_RKVDEC0_PRE, "aclk_rkvdec0_pre", "aclk_rkvdec0_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 6, GFLAGS),
+	GATE_LINK(HCLK_RKVDEC1_PRE, "hclk_rkvdec1_pre", "hclk_rkvdec1_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(41), 4, GFLAGS),
+	GATE_LINK(ACLK_RKVDEC1_PRE, "aclk_rkvdec1_pre", "aclk_rkvdec1_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(41), 5, GFLAGS),
+	GATE_LINK(ACLK_HDCP0_PRE, "aclk_hdcp0_pre", "aclk_vo0_root", "aclk_vop_low_root", 0, RK3588_CLKGATE_CON(55), 9, GFLAGS),
+	GATE_LINK(HCLK_VO0, "hclk_vo0", "hclk_vo0_root", "hclk_vop_root", 0, RK3588_CLKGATE_CON(55), 5, GFLAGS),
+	GATE_LINK(ACLK_HDCP1_PRE, "aclk_hdcp1_pre", "aclk_hdcp1_root", "aclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(59), 6, GFLAGS),
+	GATE_LINK(HCLK_VO1, "hclk_vo1", "hclk_vo1_root", "hclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(59), 9, GFLAGS),
+	GATE_LINK(ACLK_AV1_PRE, "aclk_av1_pre", "aclk_av1_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(68), 1, GFLAGS),
+	GATE_LINK(PCLK_AV1_PRE, "pclk_av1_pre", "pclk_av1_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(68), 4, GFLAGS),
+	GATE_LINK(HCLK_SDIO_PRE, "hclk_sdio_pre", "hclk_sdio_root", "hclk_nvm", 0, RK3588_CLKGATE_CON(75), 1, GFLAGS),
+};
+
+static void __init rk3588_clk_init(struct device_node *np)
+{
+	struct rockchip_clk_provider *ctx;
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		return;
+	}
+
+	rockchip_clk_register_plls(ctx, rk3588_pll_clks,
+				   ARRAY_SIZE(rk3588_pll_clks),
+				   RK3588_GRF_SOC_STATUS0);
+
+	rockchip_clk_register_armclk(ctx, ARMCLK_L, "armclk_l",
+			mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+			&rk3588_cpulclk_data, rk3588_cpulclk_rates,
+			ARRAY_SIZE(rk3588_cpulclk_rates));
+	rockchip_clk_register_armclk(ctx, ARMCLK_B01, "armclk_b01",
+			mux_armclkb01_p, ARRAY_SIZE(mux_armclkb01_p),
+			&rk3588_cpub0clk_data, rk3588_cpub0clk_rates,
+			ARRAY_SIZE(rk3588_cpub0clk_rates));
+	rockchip_clk_register_armclk(ctx, ARMCLK_B23, "armclk_b23",
+			mux_armclkb23_p, ARRAY_SIZE(mux_armclkb23_p),
+			&rk3588_cpub1clk_data, rk3588_cpub1clk_rates,
+			ARRAY_SIZE(rk3588_cpub1clk_rates));
+
+	rockchip_clk_register_branches(ctx, rk3588_clk_branches,
+				       ARRAY_SIZE(rk3588_clk_branches));
+
+	rk3588_rst_init(np, reg_base);
+
+	rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST);
+
+	rockchip_clk_of_add_provider(np, ctx);
+}
+
+struct clk_rk3588_inits {
+	void (*inits)(struct device_node *np);
+};
+
+static const struct clk_rk3588_inits clk_3588_cru_init = {
+	.inits = rk3588_clk_init,
+};
+
+static const struct of_device_id clk_rk3588_match_table[] = {
+	{
+		.compatible = "rockchip,rk3588-cru",
+		.data = &clk_3588_cru_init,
+	},
+	{ }
+};
+
+static int __init clk_rk3588_probe(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	const struct clk_rk3588_inits *init_data;
+
+	init_data = of_device_get_match_data(dev);
+	if (init_data->inits)
+		init_data->inits(np);
+
+	return 0;
+}
+
+static struct driver clk_rk3588_driver = {
+	.probe = clk_rk3588_probe,
+	.name = "clk-rk3588",
+	.of_compatible = DRV_OF_COMPAT(clk_rk3588_match_table),
+};
+
+core_platform_driver(clk_rk3588_driver);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index a3db88dfc8..df819c61f1 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -215,11 +215,58 @@
 #define RK3568_PMU_CLKGATE_CON(x)	((x) * 0x4 + 0x180)
 #define RK3568_PMU_SOFTRST_CON(x)	((x) * 0x4 + 0x200)
 
+#define RK3588_PHP_CRU_BASE		0x8000
+#define RK3588_PMU_CRU_BASE		0x30000
+#define RK3588_BIGCORE0_CRU_BASE	0x50000
+#define RK3588_BIGCORE1_CRU_BASE	0x52000
+#define RK3588_DSU_CRU_BASE		0x58000
+
+#define RK3588_PLL_CON(x)		RK2928_PLL_CON(x)
+#define RK3588_MODE_CON0		0x280
+#define RK3588_B0_PLL_MODE_CON0		(RK3588_BIGCORE0_CRU_BASE + 0x280)
+#define RK3588_B1_PLL_MODE_CON0		(RK3588_BIGCORE1_CRU_BASE + 0x280)
+#define RK3588_LPLL_MODE_CON0		(RK3588_DSU_CRU_BASE + 0x280)
+#define RK3588_CLKSEL_CON(x)		((x) * 0x4 + 0x300)
+#define RK3588_CLKGATE_CON(x)		((x) * 0x4 + 0x800)
+#define RK3588_SOFTRST_CON(x)		((x) * 0x4 + 0xa00)
+#define RK3588_GLB_CNT_TH		0xc00
+#define RK3588_GLB_SRST_FST		0xc08
+#define RK3588_GLB_SRST_SND		0xc0c
+#define RK3588_GLB_RST_CON		0xc10
+#define RK3588_GLB_RST_ST		0xc04
+#define RK3588_SDIO_CON0		0xC24
+#define RK3588_SDIO_CON1		0xC28
+#define RK3588_SDMMC_CON0		0xC30
+#define RK3588_SDMMC_CON1		0xC34
+
+#define RK3588_PHP_CLKGATE_CON(x)	((x) * 0x4 + RK3588_PHP_CRU_BASE + 0x800)
+#define RK3588_PHP_SOFTRST_CON(x)	((x) * 0x4 + RK3588_PHP_CRU_BASE + 0xa00)
+
+#define RK3588_PMU_PLL_CON(x)		((x) * 0x4 + RK3588_PHP_CRU_BASE)
+#define RK3588_PMU_CLKSEL_CON(x)	((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x300)
+#define RK3588_PMU_CLKGATE_CON(x)	((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x800)
+#define RK3588_PMU_SOFTRST_CON(x)	((x) * 0x4 + RK3588_PMU_CRU_BASE + 0xa00)
+
+#define RK3588_B0_PLL_CON(x)		((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE)
+#define RK3588_BIGCORE0_CLKSEL_CON(x)	((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x300)
+#define RK3588_BIGCORE0_CLKGATE_CON(x)	((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x800)
+#define RK3588_BIGCORE0_SOFTRST_CON(x)	((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0xa00)
+#define RK3588_B1_PLL_CON(x)		((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE)
+#define RK3588_BIGCORE1_CLKSEL_CON(x)	((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x300)
+#define RK3588_BIGCORE1_CLKGATE_CON(x)	((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x800)
+#define RK3588_BIGCORE1_SOFTRST_CON(x)	((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0xa00)
+#define RK3588_LPLL_CON(x)		((x) * 0x4 + RK3588_DSU_CRU_BASE)
+#define RK3588_DSU_CLKSEL_CON(x)	((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x300)
+#define RK3588_DSU_CLKGATE_CON(x)	((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x800)
+#define RK3588_DSU_SOFTRST_CON(x)	((x) * 0x4 + RK3588_DSU_CRU_BASE + 0xa00)
+
 enum rockchip_pll_type {
 	pll_rk3036,
 	pll_rk3066,
 	pll_rk3328,
 	pll_rk3399,
+	pll_rk3588,
+	pll_rk3588_core,
 };
 
 #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
@@ -252,6 +299,15 @@ enum rockchip_pll_type {
 	.nb = _nb,						\
 }
 
+#define RK3588_PLL_RATE(_rate, _p, _m, _s, _k)			\
+{								\
+	.rate   = _rate##U,					\
+	.p = _p,						\
+	.m = _m,						\
+	.s = _s,						\
+	.k = _k,						\
+}
+
 /**
  * struct rockchip_clk_provider - information about clock provider
  * @reg_base: virtual address for the register base.
@@ -272,17 +328,31 @@ struct rockchip_clk_provider {
 
 struct rockchip_pll_rate_table {
 	unsigned long rate;
-	unsigned int nr;
-	unsigned int nf;
-	unsigned int no;
-	unsigned int nb;
-	/* for RK3036/RK3399 */
-	unsigned int fbdiv;
-	unsigned int postdiv1;
-	unsigned int refdiv;
-	unsigned int postdiv2;
-	unsigned int dsmpd;
-	unsigned int frac;
+	union {
+		struct {
+			/* for RK3066 */
+			unsigned int nr;
+			unsigned int nf;
+			unsigned int no;
+			unsigned int nb;
+		};
+		struct {
+			/* for RK3036/RK3399 */
+			unsigned int fbdiv;
+			unsigned int postdiv1;
+			unsigned int refdiv;
+			unsigned int postdiv2;
+			unsigned int dsmpd;
+			unsigned int frac;
+		};
+		struct {
+			/* for RK3588 */
+			unsigned int m;
+			unsigned int p;
+			unsigned int s;
+			unsigned int k;
+		};
+	};
 };
 
 /**
@@ -351,11 +421,13 @@ struct rockchip_cpuclk_clksel {
 	u32 val;
 };
 
-#define ROCKCHIP_CPUCLK_NUM_DIVIDERS	5
+#define ROCKCHIP_CPUCLK_NUM_DIVIDERS	6
 #define ROCKCHIP_CPUCLK_MAX_CORES	4
 struct rockchip_cpuclk_rate_table {
 	unsigned long prate;
 	struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
+	struct rockchip_cpuclk_clksel pre_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
+	struct rockchip_cpuclk_clksel post_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
 };
 
 /**
@@ -364,6 +436,8 @@ struct rockchip_cpuclk_rate_table {
  * @div_core_shift[]:	cores divider offset used to divide the pll value
  * @div_core_mask[]:	cores divider mask
  * @num_cores:	number of cpu cores
+ * @mux_core_reg:       register offset of the cores select parent
+ * @mux_core_alt:       mux value to select alternate parent
  * @mux_core_main:	mux value to select main parent of core
  * @mux_core_shift:	offset of the core multiplexer
  * @mux_core_mask:	core multiplexer mask
@@ -373,6 +447,7 @@ struct rockchip_cpuclk_reg_data {
 	u8	div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES];
 	u32	div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES];
 	int	num_cores;
+	int	mux_core_reg;
 	u8	mux_core_alt;
 	u8	mux_core_main;
 	u8	mux_core_shift;
@@ -782,6 +857,27 @@ struct rockchip_clk_branch {
 		.gate_flags	= gf,				\
 	}
 
+#define COMPOSITE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
+			  df, go, gs, gf)				\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_half_divider,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.mux_shift	= ms,				\
+		.mux_width	= mw,				\
+		.mux_flags	= mf,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+	}
+
 /* SGRF clocks are only accessible from secure mode, so not controllable */
 #define SGRF_GATE(_id, cname, pname)				\
 		FACTOR(_id, cname, pname, 0, 1, 1)
@@ -808,18 +904,29 @@ void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
 void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
 					unsigned int reg);
 
+#define ROCKCHIP_SOFTRST_HIWORD_MASK	BIT(0)
+
 #ifdef CONFIG_RESET_CONTROLLER
-void rockchip_register_softrst(struct device_node *np,
-			       unsigned int num_regs,
-			       void __iomem *base, u8 flags);
+void rockchip_register_softrst_lut(struct device_node *np,
+				   const int *lookup_table,
+				   unsigned int num_regs,
+				   void __iomem *base, u8 flags);
 #else
-static inline void rockchip_register_softrst(struct device_node *np,
-			       unsigned int num_regs,
-			       void __iomem *base, u8 flags)
+static inline void rockchip_register_softrst_lut(struct device_node *np,
+				   const int *lookup_table,
+				   unsigned int num_regs,
+				   void __iomem *base, u8 flags)
 {
 }
 #endif
 
-#define ROCKCHIP_SOFTRST_HIWORD_MASK	BIT(0)
+static inline void rockchip_register_softrst(struct device_node *np,
+					     unsigned int num_regs,
+					     void __iomem *base, u8 flags)
+{
+	return rockchip_register_softrst_lut(np, NULL, num_regs, base, flags);
+}
+
+void rk3588_rst_init(struct device_node *np, void __iomem *reg_base);
 
 #endif
diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c
new file mode 100644
index 0000000000..7501b92b45
--- /dev/null
+++ b/drivers/clk/rockchip/rst-rk3588.c
@@ -0,0 +1,855 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Collabora Ltd.
+ * Author: Sebastian Reichel <sebastian.reichel@collabora.com>
+ */
+
+#include <dt-bindings/reset/rockchip,rk3588-cru.h>
+#include "clk.h"
+
+/* 0xFD7C0000 + 0x0A00 */
+#define RK3588_CRU_RESET_OFFSET(id, reg, bit) [id] = (0 + reg * 16 + bit)
+
+/* 0xFD7C8000 + 0x0A00 */
+#define RK3588_PHPTOPCRU_RESET_OFFSET(id, reg, bit) [id] = (0x8000*4 + reg * 16 + bit)
+
+/* 0xFD7D0000 + 0x0A00 */
+#define RK3588_SECURECRU_RESET_OFFSET(id, reg, bit) [id] = (0x10000*4 + reg * 16 + bit)
+
+/* 0xFD7F0000 + 0x0A00 */
+#define RK3588_PMU1CRU_RESET_OFFSET(id, reg, bit) [id] = (0x30000*4 + reg * 16 + bit)
+
+/* mapping table for reset ID to register offset */
+static const int rk3588_register_offset[] = {
+	/* SOFTRST_CON01 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_TOP_BIU, 1, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_TOP_BIU, 1, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSIPHY0, 1, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_CSIPHY0, 1, 7), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSIPHY1, 1, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_CSIPHY1, 1, 9), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M500_BIU, 1, 15),
+
+	/* SOFTRST_CON02 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M400_BIU, 2, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_A_TOP_S200_BIU, 2, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_A_TOP_S400_BIU, 2, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M300_BIU, 2, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_INIT, 2, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_CMN, 2, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_LANE, 2, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_PCS, 2, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_INIT, 2, 15),
+
+	/* SOFTRST_CON03 */
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_CMN, 3, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_LANE, 3, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_PCS, 3, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_DCPHY0, 3, 11), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY0, 3, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY0_GRF, 3, 15),
+
+	/* SOFTRST_CON04 */
+	RK3588_CRU_RESET_OFFSET(SRST_DCPHY1, 4, 0), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY1, 4, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY1_GRF, 4, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CDPHY, 4, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CSIPHY, 4, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_VCCIO3_5, 4, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_VCCIO6, 4, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_EMMCIO, 4, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_IOC_TOP, 4, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_IOC_RIGHT, 4, 11),
+
+	/* SOFTRST_CON05 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_CRU, 5, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_A_CHANNEL_SECURE2VO1USB, 5, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_CHANNEL_SECURE2CENTER, 5, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_H_CHANNEL_SECURE2VO1USB, 5, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_H_CHANNEL_SECURE2CENTER, 5, 15),
+
+	/* SOFTRST_CON06 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_CHANNEL_SECURE2VO1USB, 6, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CHANNEL_SECURE2CENTER, 6, 1),
+
+	/* SOFTRST_CON07 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_AUDIO_BIU, 7, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_AUDIO_BIU, 7, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S0_8CH, 7, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S0_8CH_TX, 7, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S0_8CH_RX, 7, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_ACDCDIG, 7, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S2_2CH, 7, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S3_2CH, 7, 13),
+
+	/* SOFTRST_CON08 */
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S2_2CH, 8, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S3_2CH, 8, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_DAC_ACDCDIG, 8, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF0, 8, 14),
+
+	/* SOFTRST_CON09 */
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF0, 9, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF1, 9, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF1, 9, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_H_PDM1, 9, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_PDM1, 9, 7),
+
+	/* SOFTRST_CON10 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_BUS_BIU, 10, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_BUS_BIU, 10, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_GIC, 10, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_A_GIC_DBG, 10, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DMAC0, 10, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DMAC1, 10, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DMAC2, 10, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C1, 10, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C2, 10, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C3, 10, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C4, 10, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C5, 10, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C6, 10, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C7, 10, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_P_I2C8, 10, 15),
+
+	/* SOFTRST_CON11 */
+	RK3588_CRU_RESET_OFFSET(SRST_I2C1, 11, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_I2C2, 11, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_I2C3, 11, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_I2C4, 11, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_I2C5, 11, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_I2C6, 11, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_I2C7, 11, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_I2C8, 11, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CAN0, 11, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_CAN0, 11, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CAN1, 11, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_CAN1, 11, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CAN2, 11, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_CAN2, 11, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SARADC, 11, 14),
+
+	/* SOFTRST_CON12 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_TSADC, 12, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_TSADC, 12, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART1, 12, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART2, 12, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART3, 12, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART4, 12, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART5, 12, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART6, 12, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART7, 12, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART8, 12, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_UART9, 12, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART1, 12, 13),
+
+	/* SOFTRST_CON13 */
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART2, 13, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART3, 13, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART4, 13, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART5, 13, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART6, 13, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART7, 13, 15),
+
+	/* SOFTRST_CON14 */
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART8, 14, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_S_UART9, 14, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SPI0, 14, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SPI1, 14, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SPI2, 14, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SPI3, 14, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SPI4, 14, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_SPI0, 14, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_SPI1, 14, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_SPI2, 14, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_SPI3, 14, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_SPI4, 14, 15),
+
+	/* SOFTRST_CON15 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_WDT0, 15, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_T_WDT0, 15, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SYS_GRF, 15, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PWM1, 15, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_PWM1, 15, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PWM2, 15, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_PWM2, 15, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PWM3, 15, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_PWM3, 15, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_BUSTIMER0, 15, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_BUSTIMER1, 15, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER0, 15, 15),
+
+	/* SOFTRST_CON16 */
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER1, 16, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER2, 16, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER3, 16, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER4, 16, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER5, 16, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER6, 16, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER7, 16, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER8, 16, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER9, 16, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER10, 16, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER11, 16, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX0, 16, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX1, 16, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX2, 16, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_P_GPIO1, 16, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_GPIO1, 16, 15),
+
+	/* SOFTRST_CON17 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_GPIO2, 17, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_GPIO2, 17, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_GPIO3, 17, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_GPIO3, 17, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_GPIO4, 17, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_GPIO4, 17, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DECOM, 17, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DECOM, 17, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_D_DECOM, 17, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_TOP, 17, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_A_GICADB_GIC2CORE_BUS, 17, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DFT2APB, 17, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_TOP, 17, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_CDPHY, 17, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_BOT_RIGHT, 17, 15),
+
+	/* SOFTRST_CON18 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_IOC_TOP, 18, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_IOC_RIGHT, 18, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_CSIPHY, 18, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_VCCIO3_5, 18, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_VCCIO6, 18, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_EMMCIO, 18, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_SPINLOCK, 18, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_OTPC_NS, 18, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_OTPC_NS, 18, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_OTPC_ARB, 18, 11),
+
+	/* SOFTRST_CON19 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_BUSIOC, 19, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PMUCM0_INTMUX, 19, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDRCM0_INTMUX, 19, 5),
+
+	/* SOFTRST_CON20 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH0, 20, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH0, 20, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH0, 20, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH0, 20, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH0, 20, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_GRF_CH01, 20, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_DFI_CH0, 20, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_SBR_CH0, 20, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH0, 20, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH0, 20, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH0, 20, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH0, 20, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH0, 20, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH1, 20, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH1, 20, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH1, 20, 15),
+
+	/* SOFTRST_CON21 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH1, 21, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH1, 21, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_DFI_CH1, 21, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_SBR_CH1, 21, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH1, 21, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH1, 21, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH1, 21, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH1, 21, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH1, 21, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH0, 21, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_RS_MSCH0, 21, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_MSCH0, 21, 15),
+
+	/* SOFTRST_CON22 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_SCRAMBLE0, 22, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_SCRAMBLE0, 22, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH1, 22, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_RS_MSCH1, 22, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_MSCH1, 22, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_SCRAMBLE1, 22, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_SCRAMBLE1, 22, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH0, 22, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH1, 22, 8),
+
+	/* SOFTRST_CON23 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH2, 23, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH2, 23, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH2, 23, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH2, 23, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH2, 23, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_GRF_CH23, 23, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_DFI_CH2, 23, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_SBR_CH2, 23, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH2, 23, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH2, 23, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH2, 23, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH2, 23, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH2, 23, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH3, 23, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH3, 23, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH3, 23, 15),
+
+	/* SOFTRST_CON24 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH3, 24, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH3, 24, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_DFI_CH3, 24, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_SBR_CH3, 24, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH3, 24, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH3, 24, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH3, 24, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH3, 24, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH3, 24, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_MSCH2, 24, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_RS_MSCH2, 24, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_MSCH2, 24, 15),
+
+	/* SOFTRST_CON25 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_SCRAMBLE2, 25, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_SCRAMBLE2, 25, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_MSCH3, 25, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_RS_MSCH3, 25, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_MSCH3, 25, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_SCRAMBLE3, 25, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_SCRAMBLE3, 25, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR23_MSCH2, 25, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DDR23_MSCH3, 25, 8),
+
+	/* SOFTRST_CON26 */
+	RK3588_CRU_RESET_OFFSET(SRST_ISP1, 26, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_ISP1_VICAP, 26, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_ISP1_BIU, 26, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_H_ISP1_BIU, 26, 8),
+
+	/* SOFTRST_CON27 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKNN1, 27, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKNN1_BIU, 27, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKNN1, 27, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKNN1_BIU, 27, 3),
+
+	/* SOFTRST_CON28 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKNN2, 28, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKNN2_BIU, 28, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKNN2, 28, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKNN2_BIU, 28, 3),
+
+	/* SOFTRST_CON29 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKNN_DSU0, 29, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_NPUTOP_BIU, 29, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_P_NPU_TIMER, 29, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_NPUTIMER0, 29, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_NPUTIMER1, 29, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_NPU_WDT, 29, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_T_NPU_WDT, 29, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_P_NPU_PVTM, 29, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_NPU_GRF, 29, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_NPU_PVTM, 29, 14),
+
+	/* SOFTRST_CON30 */
+	RK3588_CRU_RESET_OFFSET(SRST_NPU_PVTPLL, 30, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_H_NPU_CM0_BIU, 30, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_F_NPU_CM0_CORE, 30, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_T_NPU_CM0_JTAG, 30, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKNN0, 30, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKNN0_BIU, 30, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKNN0, 30, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKNN0_BIU, 30, 9),
+
+	/* SOFTRST_CON31 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_NVM_BIU, 31, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_NVM_BIU, 31, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_EMMC, 31, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_EMMC, 31, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_C_EMMC, 31, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_B_EMMC, 31, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_T_EMMC, 31, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_S_SFC, 31, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SFC, 31, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SFC_XIP, 31, 11),
+
+	/* SOFTRST_CON32 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_GRF, 32, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DEC_BIU, 32, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PHP_BIU, 32, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_PCIE_GRIDGE, 32, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_PHP_BIU, 32, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_A_GMAC0, 32, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_A_GMAC1, 32, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_A_PCIE_BIU, 32, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_PCIE0_POWER_UP, 32, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_PCIE1_POWER_UP, 32, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_PCIE2_POWER_UP, 32, 15),
+
+	/* SOFTRST_CON33 */
+	RK3588_CRU_RESET_OFFSET(SRST_PCIE3_POWER_UP, 33, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_PCIE4_POWER_UP, 33, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PCIE0, 33, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PCIE1, 33, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PCIE2, 33, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_P_PCIE3, 33, 15),
+
+	/* SOFTRST_CON34 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_PCIE4, 34, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_A_PHP_GIC_ITS, 34, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_MMU_PCIE, 34, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_MMU_PHP, 34, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_MMU_BIU, 34, 9),
+
+	/* SOFTRST_CON35 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG2, 35, 7),
+
+	/* SOFTRST_CON37 */
+	RK3588_CRU_RESET_OFFSET(SRST_PMALIVE0, 37, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_PMALIVE1, 37, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_PMALIVE2, 37, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_SATA0, 37, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_SATA1, 37, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_SATA2, 37, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_RXOOB0, 37, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_RXOOB1, 37, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_RXOOB2, 37, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_ASIC0, 37, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_ASIC1, 37, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_ASIC2, 37, 15),
+
+	/* SOFTRST_CON40 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC_CCU, 40, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC0, 40, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC0, 40, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC0_BIU, 40, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC0_BIU, 40, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_CA, 40, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_HEVC_CA, 40, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_CORE, 40, 9),
+
+	/* SOFTRST_CON41 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC1, 41, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC1, 41, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC1_BIU, 41, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC1_BIU, 41, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_CA, 41, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_HEVC_CA, 41, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_CORE, 41, 8),
+
+	/* SOFTRST_CON42 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_USB_BIU, 42, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_H_USB_BIU, 42, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG0, 42, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG1, 42, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HOST0, 42, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HOST_ARB0, 42, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HOST1, 42, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HOST_ARB1, 42, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_A_USB_GRF, 42, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_C_USB2P0_HOST0, 42, 15),
+
+	/* SOFTRST_CON43 */
+	RK3588_CRU_RESET_OFFSET(SRST_C_USB2P0_HOST1, 43, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_HOST_UTMI0, 43, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_HOST_UTMI1, 43, 2),
+
+	/* SOFTRST_CON44 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_VDPU_BIU, 44, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_VDPU_LOW_BIU, 44, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VDPU_BIU, 44, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_DECODER_BIU, 44, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_VPU, 44, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VPU, 44, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER0, 44, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER0, 44, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER1, 44, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER1, 44, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER2, 44, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER2, 44, 15),
+
+	/* SOFTRST_CON45 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER3, 45, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER3, 45, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_DECODER, 45, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_DECODER, 45, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_IEP2P0, 45, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_IEP2P0, 45, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_IEP2P0_CORE, 45, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RGA2, 45, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RGA2, 45, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_RGA2_CORE, 45, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_0, 45, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_0, 45, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_RGA3_0_CORE, 45, 12),
+
+	/* SOFTRST_CON47 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC0_BIU, 47, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC0_BIU, 47, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC0, 47, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC0, 47, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVENC0_CORE, 47, 6),
+
+	/* SOFTRST_CON48 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC1_BIU, 48, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC1_BIU, 48, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC1, 48, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC1, 48, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_RKVENC1_CORE, 48, 6),
+
+	/* SOFTRST_CON49 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_VI_BIU, 49, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VI_BIU, 49, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VI_BIU, 49, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_D_VICAP, 49, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_VICAP, 49, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VICAP, 49, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_ISP0, 49, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_ISP0_VICAP, 49, 11),
+
+	/* SOFTRST_CON50 */
+	RK3588_CRU_RESET_OFFSET(SRST_FISHEYE0, 50, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_FISHEYE1, 50, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_0, 50, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_1, 50, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_2, 50, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_3, 50, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_4, 50, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_5, 50, 9),
+
+	/* SOFTRST_CON51 */
+	RK3588_CRU_RESET_OFFSET(SRST_CSIHOST0_VICAP, 51, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_CSIHOST1_VICAP, 51, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_CSIHOST2_VICAP, 51, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_CSIHOST3_VICAP, 51, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_CSIHOST4_VICAP, 51, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_CSIHOST5_VICAP, 51, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_CIFIN, 51, 13),
+
+	/* SOFTRST_CON52 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_VOP_BIU, 52, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_VOP_LOW_BIU, 52, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VOP_BIU, 52, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VOP_BIU, 52, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VOP, 52, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_VOP, 52, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_D_VOP0, 52, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_D_VOP2HDMI_BRIDGE0, 52, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_D_VOP2HDMI_BRIDGE1, 52, 15),
+
+	/* SOFTRST_CON53 */
+	RK3588_CRU_RESET_OFFSET(SRST_D_VOP1, 53, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_D_VOP2, 53, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_D_VOP3, 53, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VOPGRF, 53, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DSIHOST0, 53, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DSIHOST1, 53, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_DSIHOST0, 53, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_DSIHOST1, 53, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_VOP_PMU, 53, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VOP_CHANNEL_BIU, 53, 9),
+
+	/* SOFTRST_CON55 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_VO0_BIU, 55, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VO0_S_BIU, 55, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VO0_BIU, 55, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VO0_S_BIU, 55, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_HDCP0_BIU, 55, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VO0GRF, 55, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HDCP_KEY0, 55, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_A_HDCP0, 55, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HDCP0, 55, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_HDCP0, 55, 15),
+
+	/* SOFTRST_CON56 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_TRNG0, 56, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_DP0, 56, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_DP1, 56, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S4_8CH, 56, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S4_8CH_TX, 56, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S8_8CH, 56, 14),
+
+	/* SOFTRST_CON57 */
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S8_8CH_TX, 57, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF2_DP0, 57, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF2_DP0, 57, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF5_DP1, 57, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF5_DP1, 57, 11),
+
+	/* SOFTRST_CON59 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_HDCP1_BIU, 59, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_VO1_BIU, 59, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_BIU, 59, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_S_BIU, 59, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VOP1_BIU, 59, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VO1GRF, 59, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_VO1_S_BIU, 59, 13),
+
+	/* SOFTRST_CON60 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S7_8CH, 60, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S7_8CH_RX, 60, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HDCP_KEY1, 60, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_HDCP1, 60, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_H_HDCP1, 60, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_HDCP1, 60, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_TRNG1, 60, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_HDMITX0, 60, 11),
+
+	/* SOFTRST_CON61 */
+	RK3588_CRU_RESET_OFFSET(SRST_HDMITX0_REF, 61, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_P_HDMITX1, 61, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_HDMITX1_REF, 61, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_HDMIRX, 61, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_HDMIRX, 61, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_HDMIRX_REF, 61, 11),
+
+	/* SOFTRST_CON62 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_EDP0, 62, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_EDP0_24M, 62, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_EDP1, 62, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_EDP1_24M, 62, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S5_8CH_TX, 62, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S5_8CH, 62, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S6_8CH_TX, 62, 15),
+
+	/* SOFTRST_CON63 */
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S6_8CH_RX, 63, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S6_8CH, 63, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF3, 63, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF3, 63, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF4, 63, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF4, 63, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX0, 63, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX0, 63, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX1, 63, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX1, 63, 15),
+
+	/* SOFTRST_CON64 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX2, 64, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX2, 64, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_LINKSYM_HDMITXPHY0, 64, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_LINKSYM_HDMITXPHY1, 64, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_VO1_BRIDGE0, 64, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_VO1_BRIDGE1, 64, 15),
+
+	/* SOFTRST_CON65 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S9_8CH, 65, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S9_8CH_RX, 65, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_I2S10_8CH, 65, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_M_I2S10_8CH_RX, 65, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_S_HDMIRX, 65, 8),
+
+	/* SOFTRST_CON66 */
+	RK3588_CRU_RESET_OFFSET(SRST_GPU, 66, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_SYS_GPU, 66, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_S_GPU_BIU, 66, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_A_M0_GPU_BIU, 66, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_A_M1_GPU_BIU, 66, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_A_M2_GPU_BIU, 66, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_A_M3_GPU_BIU, 66, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_P_GPU_BIU, 66, 14),
+	RK3588_CRU_RESET_OFFSET(SRST_P_GPU_PVTM, 66, 15),
+
+	/* SOFTRST_CON67 */
+	RK3588_CRU_RESET_OFFSET(SRST_GPU_PVTM, 67, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_P_GPU_GRF, 67, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_GPU_PVTPLL, 67, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_GPU_JTAG, 67, 4),
+
+	/* SOFTRST_CON68 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_AV1_BIU, 68, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_A_AV1, 68, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_AV1_BIU, 68, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_AV1, 68, 5),
+
+	/* SOFTRST_CON69 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR_BIU, 69, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DMA2DDR, 69, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM, 69, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM_BIU, 69, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_A_CENTER_S200_BIU, 69, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_A_CENTER_S400_BIU, 69, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_H_AHB2APB, 69, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_H_CENTER_BIU, 69, 13),
+	RK3588_CRU_RESET_OFFSET(SRST_F_DDR_CM0_CORE, 69, 14),
+
+	/* SOFTRST_CON70 */
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_TIMER0, 70, 0),
+	RK3588_CRU_RESET_OFFSET(SRST_DDR_TIMER1, 70, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_T_WDT_DDR, 70, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_T_DDR_CM0_JTAG, 70, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_GRF, 70, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_P_AHB2APB, 70, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_WDT, 70, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_TIMER, 70, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_DMA2DDR, 70, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_SHAREMEM, 70, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_BIU, 70, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_CHANNEL_BIU, 70, 12),
+
+	/* SOFTRST_CON72 */
+	RK3588_CRU_RESET_OFFSET(SRST_P_USBDPGRF0, 72, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_P_USBDPPHY0, 72, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_P_USBDPGRF1, 72, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_P_USBDPPHY1, 72, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_P_HDPTX0, 72, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_P_HDPTX1, 72, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_BOT_RIGHT, 72, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U3_0_GRF0, 72, 8),
+	RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U3_1_GRF0, 72, 9),
+	RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U2_0_GRF0, 72, 10),
+	RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U2_1_GRF0, 72, 11),
+	RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_ROPLL, 72, 12), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_LCPLL, 72, 13), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_HDPTX0, 72, 14), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_HDPTX1_ROPLL, 72, 15), // missing in TRM
+
+	/* SOFTRST_CON73 */
+	RK3588_CRU_RESET_OFFSET(SRST_HDPTX1_LCPLL, 73, 0), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_HDPTX1, 73, 1), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_HDMIRXPHY_SET, 73, 2), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0, 73, 3), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_LCPLL, 73, 4), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_ROPLL, 73, 5), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_PCS_HS, 73, 6), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1, 73, 7), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_LCPLL, 73, 8), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_ROPLL, 73, 9), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_PCS_HS, 73, 10), // missing in TRM
+	RK3588_CRU_RESET_OFFSET(SRST_HDMIHDP0, 73, 12),
+	RK3588_CRU_RESET_OFFSET(SRST_HDMIHDP1, 73, 13),
+
+	/* SOFTRST_CON74 */
+	RK3588_CRU_RESET_OFFSET(SRST_A_VO1USB_TOP_BIU, 74, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_H_VO1USB_TOP_BIU, 74, 3),
+
+	/* SOFTRST_CON75 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_SDIO_BIU, 75, 1),
+	RK3588_CRU_RESET_OFFSET(SRST_H_SDIO, 75, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_SDIO, 75, 3),
+
+	/* SOFTRST_CON76 */
+	RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_BIU, 76, 2),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_BIU, 76, 3),
+	RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_1, 76, 4),
+	RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_1, 76, 5),
+	RK3588_CRU_RESET_OFFSET(SRST_RGA3_1_CORE, 76, 6),
+
+	/* SOFTRST_CON77 */
+	RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY0, 77, 6),
+	RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY1, 77, 7),
+	RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY2, 77, 8),
+
+	/* PHPTOPCRU_SOFTRST_CON00 */
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PHPTOP_CRU, 0, 1),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF0, 0, 2),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF1, 0, 3),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF2, 0, 4),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY0, 0, 5),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY1, 0, 6),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY2, 0, 7),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE3_PHY, 0, 8),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CHIP_TOP, 0, 9),
+	RK3588_PHPTOPCRU_RESET_OFFSET(SRST_PCIE30_PHY, 0, 10),
+
+	/* PMU1CRU_SOFTRST_CON00 */
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PMU1_BIU, 0, 10),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_BIU, 0, 11),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PMU_CM0_BIU, 0, 12),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_F_PMU_CM0_CORE, 0, 13),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_T_PMU1_CM0_JTAG, 0, 14),
+
+	/* PMU1CRU_SOFTRST_CON01 */
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_DDR_FAIL_SAFE, 1, 1),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_CRU_PMU1, 1, 2),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_GRF, 1, 4),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_IOC, 1, 5),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1WDT, 1, 6),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_T_PMU1WDT, 1, 7),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1TIMER, 1, 8),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1TIMER0, 1, 10),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1TIMER1, 1, 11),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1PWM, 1, 12),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1PWM, 1, 13),
+
+	/* PMU1CRU_SOFTRST_CON02 */
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_I2C0, 2, 1),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_I2C0, 2, 2),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_S_UART0, 2, 5),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_UART0, 2, 6),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_H_I2S1_8CH, 2, 7),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_M_I2S1_8CH_TX, 2, 10),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_M_I2S1_8CH_RX, 2, 13),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PDM0, 2, 14),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_PDM0, 2, 15),
+
+	/* PMU1CRU_SOFTRST_CON03 */
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_H_VAD, 3, 0),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_INIT, 3, 11),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_CMN, 3, 12),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_LANE, 3, 13),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_INIT, 3, 15),
+
+	/* PMU1CRU_SOFTRST_CON04 */
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_CMN, 4, 0),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_LANE, 4, 1),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_M_MIPI_DCPHY0, 4, 3),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_S_MIPI_DCPHY0, 4, 4),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_M_MIPI_DCPHY1, 4, 5),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_S_MIPI_DCPHY1, 4, 6),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U3_0, 4, 7),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U3_1, 4, 8),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U2_0, 4, 9),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U2_1, 4, 10),
+
+	/* PMU1CRU_SOFTRST_CON05 */
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0GRF, 5, 3),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0IOC, 5, 4),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_P_GPIO0, 5, 5),
+	RK3588_PMU1CRU_RESET_OFFSET(SRST_GPIO0, 5, 6),
+
+	/* SECURECRU_SOFTRST_CON00 */
+	RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_NS_BIU, 0, 10),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_NS_BIU, 0, 11),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_S_BIU, 0, 12),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_S_BIU, 0, 13),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_P_SECURE_S_BIU, 0, 14),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_CORE, 0, 15),
+
+	/* SECURECRU_SOFTRST_CON01 */
+	RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_PKA, 1, 0),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_RNG, 1, 1),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_A_CRYPTO, 1, 2),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_CRYPTO, 1, 3),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_CORE, 1, 9),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_RNG, 1, 10),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_A_KEYLADDER, 1, 11),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_KEYLADDER, 1, 12),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_P_OTPC_S, 1, 13),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_OTPC_S, 1, 14),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_WDT_S, 1, 15),
+
+	/* SECURECRU_SOFTRST_CON02 */
+	RK3588_SECURECRU_RESET_OFFSET(SRST_T_WDT_S, 2, 0),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM, 2, 1),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_A_DCF, 2, 2),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_P_DCF, 2, 3),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM_NS, 2, 5),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_P_KEYLADDER, 2, 14),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_S, 2, 15),
+
+	/* SECURECRU_SOFTRST_CON03 */
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_NS, 3, 0),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_D_SDMMC_BUFFER, 3, 1),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC, 3, 2),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC_BUFFER, 3, 3),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_SDMMC, 3, 4),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_P_TRNG_CHK, 3, 5),
+	RK3588_SECURECRU_RESET_OFFSET(SRST_TRNG_S, 3, 6),
+};
+
+void rk3588_rst_init(struct device_node *np, void __iomem *reg_base)
+{
+	rockchip_register_softrst_lut(np,
+				      rk3588_register_offset,
+				      ARRAY_SIZE(rk3588_register_offset),
+				      reg_base + RK3588_SOFTRST_CON(0),
+				      ROCKCHIP_SOFTRST_HIWORD_MASK);
+}
diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c
index e3f3937ca0..929b227154 100644
--- a/drivers/clk/rockchip/softrst.c
+++ b/drivers/clk/rockchip/softrst.c
@@ -13,6 +13,7 @@
 
 struct rockchip_softrst {
 	struct reset_controller_dev	rcdev;
+	const int			*lut;
 	void __iomem			*reg_base;
 	int				num_regs;
 	int				num_per_reg;
@@ -26,8 +27,13 @@ static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
 	struct rockchip_softrst *softrst = container_of(rcdev,
 						     struct rockchip_softrst,
 						     rcdev);
-	int bank = id / softrst->num_per_reg;
-	int offset = id % softrst->num_per_reg;
+	int bank, offset;
+
+	if (softrst->lut)
+		id = softrst->lut[id];
+
+	bank = id / softrst->num_per_reg;
+	offset = id % softrst->num_per_reg;
 
 	if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
 		writel(BIT(offset) | (BIT(offset) << 16),
@@ -53,8 +59,13 @@ static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
 	struct rockchip_softrst *softrst = container_of(rcdev,
 						     struct rockchip_softrst,
 						     rcdev);
-	int bank = id / softrst->num_per_reg;
-	int offset = id % softrst->num_per_reg;
+	int bank, offset;
+
+	if (softrst->lut)
+		id = softrst->lut[id];
+
+	bank = id / softrst->num_per_reg;
+	offset = id % softrst->num_per_reg;
 
 	if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
 		writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
@@ -78,9 +89,10 @@ static const struct reset_control_ops rockchip_softrst_ops = {
 	.deassert	= rockchip_softrst_deassert,
 };
 
-void rockchip_register_softrst(struct device_node *np,
-			       unsigned int num_regs,
-			       void __iomem *base, u8 flags)
+void rockchip_register_softrst_lut(struct device_node *np,
+				   const int *lookup_table,
+				   unsigned int num_regs,
+				   void __iomem *base, u8 flags)
 {
 	struct rockchip_softrst *softrst;
 	int ret;
@@ -92,12 +104,16 @@ void rockchip_register_softrst(struct device_node *np,
 	spin_lock_init(&softrst->lock);
 
 	softrst->reg_base = base;
+	softrst->lut = lookup_table;
 	softrst->flags = flags;
 	softrst->num_regs = num_regs;
 	softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
 								      : 32;
 
-	softrst->rcdev.nr_resets =  num_regs * softrst->num_per_reg;
+	if (lookup_table)
+		softrst->rcdev.nr_resets = num_regs;
+	else
+		softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
 	softrst->rcdev.ops = &rockchip_softrst_ops;
 	softrst->rcdev.of_node = np;
 	ret = reset_controller_register(&softrst->rcdev);
@@ -107,4 +123,4 @@ void rockchip_register_softrst(struct device_node *np,
 		kfree(softrst);
 	}
 };
-EXPORT_SYMBOL_GPL(rockchip_register_softrst);
+EXPORT_SYMBOL_GPL(rockchip_register_softrst_lut);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 07/18] pinctrl: rockchip: Move struct definitions to separate header file
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (5 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 06/18] clk: rockchip: Add rk3588 support Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 08/18] pinctrl/gpio: rockchip: separate gpio from pinctrl driver Sascha Hauer
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Linux has a separated header file as well, do the same for better code
sharing.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pinctrl/pinctrl-rockchip.c | 125 +---------------------
 drivers/pinctrl/pinctrl-rockchip.h | 161 +++++++++++++++++++++++++++++
 2 files changed, 162 insertions(+), 124 deletions(-)
 create mode 100644 drivers/pinctrl/pinctrl-rockchip.h

diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index df5f22a7c5..4021f7ff23 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -25,17 +25,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 
-enum rockchip_pinctrl_type {
-	RK2928,
-	RK3066B,
-	RK3188,
-	RK3568,
-};
-
-enum rockchip_pin_bank_type {
-	COMMON_BANK,
-	RK3188_BANK0,
-};
+#include "pinctrl-rockchip.h"
 
 /**
  * Generate a bitmask for setting a value (v) with a write mask bit in hiword
@@ -54,70 +44,6 @@ enum rockchip_pin_bank_type {
 #define IOMUX_WIDTH_3BIT	BIT(4)
 #define IOMUX_WIDTH_2BIT	BIT(5)
 
-/**
- * struct rockchip_iomux
- * @type: iomux variant using IOMUX_* constants
- * @offset: if initialized to -1 it will be autocalculated, by specifying
- *	    an initial offset value the relevant source offset can be reset
- *	    to a new value for autocalculating the following iomux registers.
- */
-struct rockchip_iomux {
-	int				type;
-	int				offset;
-};
-
-/*
- * enum type index corresponding to rockchip_perpin_drv_list arrays index.
- */
-enum rockchip_pin_drv_type {
-	DRV_TYPE_IO_DEFAULT = 0,
-	DRV_TYPE_IO_1V8_OR_3V0,
-	DRV_TYPE_IO_1V8_ONLY,
-	DRV_TYPE_IO_1V8_3V0_AUTO,
-	DRV_TYPE_IO_3V3_ONLY,
-	DRV_TYPE_MAX
-};
-
-/*
- * enum type index corresponding to rockchip_pull_list arrays index.
- */
-enum rockchip_pin_pull_type {
-	PULL_TYPE_IO_DEFAULT = 0,
-	PULL_TYPE_IO_1V8_ONLY,
-	PULL_TYPE_MAX
-};
-
-/**
- * struct rockchip_drv
- * @drv_type: drive strength variant using rockchip_perpin_drv_type
- * @offset: if initialized to -1 it will be autocalculated, by specifying
- *	    an initial offset value the relevant source offset can be reset
- *	    to a new value for autocalculating the following drive strength
- *	    registers. if used chips own cal_drv func instead to calculate
- *	    registers offset, the variant could be ignored.
- */
-struct rockchip_drv {
-	enum rockchip_pin_drv_type	drv_type;
-	int				offset;
-};
-
-struct rockchip_pin_bank {
-	void __iomem			*reg_base;
-	struct clk			*clk;
-	u32				pin_base;
-	u8				nr_pins;
-	char				*name;
-	u8				bank_num;
-	struct rockchip_iomux		iomux[4];
-	struct rockchip_drv		drv[4];
-	enum rockchip_pin_bank_type	bank_type;
-	bool				valid;
-	struct device_node		*of_node;
-	struct rockchip_pinctrl		*drvdata;
-	struct bgpio_chip		bgpio_chip;
-	u32				route_mask;
-};
-
 #define PIN_BANK(id, pins, label)			\
 	{						\
 		.bank_num	= id,			\
@@ -157,55 +83,6 @@ struct rockchip_pin_bank {
 #define RK_MUXROUTE_PMU(ID, PIN, FUNC, REG, VAL)	\
 	PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_PMU)
 
-enum rockchip_mux_route_location {
-	ROCKCHIP_ROUTE_SAME = 0,
-	ROCKCHIP_ROUTE_PMU,
-	ROCKCHIP_ROUTE_GRF,
-};
-
-/**
- * struct rockchip_mux_recalced_data: represent a pin iomux data.
- * @bank_num: bank number.
- * @pin: index at register or used to calc index.
- * @func: the min pin.
- * @route_location: the mux route location (same, pmu, grf).
- * @route_offset: the max pin.
- * @route_val: the register offset.
- */
-struct rockchip_mux_route_data {
-	u8 bank_num;
-	u8 pin;
-	u8 func;
-	enum rockchip_mux_route_location route_location;
-	u32 route_offset;
-	u32 route_val;
-};
-
-struct rockchip_pin_ctrl {
-	struct rockchip_pin_bank	*pin_banks;
-	u32				nr_banks;
-	u32				nr_pins;
-	char				*label;
-	enum rockchip_pinctrl_type	type;
-	int				grf_mux_offset;
-	int				pmu_mux_offset;
-	int				grf_drv_offset;
-	int				pmu_drv_offset;
-	struct rockchip_mux_route_data *iomux_routes;
-	u32				niomux_routes;
-	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num,
-				 void __iomem **reg, u8 *bit);
-	void	(*drv_calc_reg)(struct rockchip_pin_bank *bank,
-				    int pin_num, void __iomem **reg, u8 *bit);
-};
-
-struct rockchip_pinctrl {
-	void __iomem			*reg_base;
-	void __iomem			*reg_pmu;
-	struct pinctrl_device		pctl_dev;
-	struct rockchip_pin_ctrl	*ctrl;
-};
-
 enum {
 	RK_BIAS_DISABLE = 0,
 	RK_BIAS_PULL_UP,
diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
new file mode 100644
index 0000000000..5279c78439
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-rockchip.h
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020-2021 Rockchip Electronics Co. Ltd.
+ *
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * With some ideas taken from pinctrl-samsung:
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ *		https://www.linaro.org
+ *
+ * and pinctrl-at91:
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ */
+
+#ifndef _PINCTRL_ROCKCHIP_H
+#define _PINCTRL_ROCKCHIP_H
+
+enum rockchip_pinctrl_type {
+	RK2928,
+	RK3066B,
+	RK3188,
+	RK3568,
+};
+
+/**
+ * struct rockchip_iomux
+ * @type: iomux variant using IOMUX_* constants
+ * @offset: if initialized to -1 it will be autocalculated, by specifying
+ *	    an initial offset value the relevant source offset can be reset
+ *	    to a new value for autocalculating the following iomux registers.
+ */
+struct rockchip_iomux {
+	int type;
+	int offset;
+};
+
+/*
+ * enum type index corresponding to rockchip_perpin_drv_list arrays index.
+ */
+enum rockchip_pin_drv_type {
+	DRV_TYPE_IO_DEFAULT = 0,
+	DRV_TYPE_IO_1V8_OR_3V0,
+	DRV_TYPE_IO_1V8_ONLY,
+	DRV_TYPE_IO_1V8_3V0_AUTO,
+	DRV_TYPE_IO_3V3_ONLY,
+	DRV_TYPE_MAX
+};
+
+/*
+ * enum type index corresponding to rockchip_pull_list arrays index.
+ */
+enum rockchip_pin_pull_type {
+	PULL_TYPE_IO_DEFAULT = 0,
+	PULL_TYPE_IO_1V8_ONLY,
+	PULL_TYPE_MAX
+};
+
+/**
+ * struct rockchip_drv
+ * @drv_type: drive strength variant using rockchip_perpin_drv_type
+ * @offset: if initialized to -1 it will be autocalculated, by specifying
+ *	    an initial offset value the relevant source offset can be reset
+ *	    to a new value for autocalculating the following drive strength
+ *	    registers. if used chips own cal_drv func instead to calculate
+ *	    registers offset, the variant could be ignored.
+ */
+struct rockchip_drv {
+	enum rockchip_pin_drv_type	drv_type;
+	int				offset;
+};
+
+enum rockchip_pin_bank_type {
+	COMMON_BANK,
+	RK3188_BANK0,
+};
+
+/**
+ * struct rockchip_pin_bank
+ * @reg_base: register base of the gpio bank
+ * @clk: clock of the gpio bank
+ * @pin_base: first pin number
+ * @nr_pins: number of pins in this bank
+ * @name: name of the bank
+ * @bank_num: number of the bank, to account for holes
+ * @iomux: array describing the 4 iomux sources of the bank
+ * @drv: array describing the 4 drive strength sources of the bank
+ * @valid: is all necessary information present
+ * @of_node: dt node of this bank
+ * @drvdata: common pinctrl basedata
+ * @route_mask: bits describing the routing pins of per bank
+ */
+struct rockchip_pin_bank {
+	void __iomem			*reg_base;
+	struct clk			*clk;
+	u32				pin_base;
+	u8				nr_pins;
+	char				*name;
+	u8				bank_num;
+	struct rockchip_iomux		iomux[4];
+	struct rockchip_drv		drv[4];
+	enum rockchip_pin_bank_type	bank_type;
+	bool				valid;
+	struct device_node		*of_node;
+	struct rockchip_pinctrl		*drvdata;
+	struct bgpio_chip		bgpio_chip;
+	u32				route_mask;
+};
+
+enum rockchip_mux_route_location {
+	ROCKCHIP_ROUTE_SAME = 0,
+	ROCKCHIP_ROUTE_PMU,
+	ROCKCHIP_ROUTE_GRF,
+};
+
+/**
+ * struct rockchip_mux_recalced_data: represent a pin iomux data.
+ * @bank_num: bank number.
+ * @pin: index at register or used to calc index.
+ * @func: the min pin.
+ * @route_location: the mux route location (same, pmu, grf).
+ * @route_offset: the max pin.
+ * @route_val: the register offset.
+ */
+struct rockchip_mux_route_data {
+	u8 bank_num;
+	u8 pin;
+	u8 func;
+	enum rockchip_mux_route_location route_location;
+	u32 route_offset;
+	u32 route_val;
+};
+
+struct rockchip_pin_ctrl {
+	struct rockchip_pin_bank	*pin_banks;
+	u32				nr_banks;
+	u32				nr_pins;
+	char				*label;
+	enum rockchip_pinctrl_type	type;
+	int				grf_mux_offset;
+	int				pmu_mux_offset;
+	int				grf_drv_offset;
+	int				pmu_drv_offset;
+	struct rockchip_mux_route_data *iomux_routes;
+	u32				niomux_routes;
+	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num,
+				 void __iomem **reg, u8 *bit);
+	void	(*drv_calc_reg)(struct rockchip_pin_bank *bank,
+				    int pin_num, void __iomem **reg, u8 *bit);
+};
+
+struct rockchip_pinctrl {
+	void __iomem			*reg_base;
+	void __iomem			*reg_pmu;
+	struct pinctrl_device		pctl_dev;
+	struct rockchip_pin_ctrl	*ctrl;
+};
+
+#endif
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 08/18] pinctrl/gpio: rockchip: separate gpio from pinctrl driver
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (6 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 07/18] pinctrl: rockchip: Move struct definitions to separate header file Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 09/18] pinctrl: Update pinctrl-rockchip from kernel Sascha Hauer
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Like done in Linux, for easier code sharing.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/Kconfig                   |   1 +
 drivers/gpio/Kconfig               |   7 ++
 drivers/gpio/Makefile              |   1 +
 drivers/gpio/gpio-rockchip.c       | 196 +++++++++++++++++++++++++++++
 drivers/pinctrl/pinctrl-rockchip.c | 178 --------------------------
 5 files changed, 205 insertions(+), 178 deletions(-)
 create mode 100644 drivers/gpio/gpio-rockchip.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5aef8fcd3b..37fe591000 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -260,6 +260,7 @@ config ARCH_ROCKCHIP
 	select OFTREE
 	select HAVE_PBL_MULTI_IMAGES
 	select HAS_DEBUG_LL
+	imply GPIO_ROCKCHIP
 
 config ARCH_STM32MP
 	bool "STMicroelectronics STM32MP"
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index dd2b56d256..e19f5a5aba 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -155,6 +155,13 @@ config GPIO_RASPBERRYPI_EXP
 	  Turn on GPIO support for the expander on Raspberry Pi 3 boards, using
 	  the firmware mailbox to communicate with VideoCore on BCM283x chips.
 
+config GPIO_ROCKCHIP
+	bool "Rockchip GPIO support"
+	depends on ARCH_ROCKCHIP
+	help
+	  Say yes here to include the driver for the GPIO controller found on
+	  Rockchip SoCs.
+
 config GPIO_STMPE
 	depends on MFD_STMPE
 	bool "STMPE GPIO Expander"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 90ab0a8b28..628e975285 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
+obj-$(CONFIG_GPIO_ROCKCHIP)	+= gpio-rockchip.o
 obj-$(CONFIG_GPIO_TEGRA)	+= gpio-tegra.o
 obj-$(CONFIG_GPIO_DESIGNWARE)	+= gpio-dw.o
 obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
new file mode 100644
index 0000000000..b01a30c18a
--- /dev/null
+++ b/drivers/gpio/gpio-rockchip.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <of.h>
+#include <gpio.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/basic_mmio_gpio.h>
+#include <mach/rockchip/rockchip.h>
+
+struct rockchip_gpiochip {
+	struct device			*dev;
+	void __iomem			*reg_base;
+	struct clk			*clk;
+	struct bgpio_chip		bgpio_chip;
+};
+
+/* GPIO registers */
+enum {
+	RK_GPIO_SWPORT_DR	= 0x00,
+	RK_GPIO_SWPORT_DDR	= 0x04,
+	RK_GPIO_EXT_PORT	= 0x50,
+};
+
+/* GPIO registers */
+enum {
+	RK_GPIOV2_DR_L	= 0x00,
+	RK_GPIOV2_DR_H	= 0x04,
+	RK_GPIOV2_DDR_L	= 0x08,
+	RK_GPIOV2_DDR_H	= 0x0c,
+	RK_GPIOV2_EXT_PORT = 0x70,
+};
+
+static struct rockchip_gpiochip *gc_to_rockchip_pinctrl(struct gpio_chip *gc)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+	return container_of(bgc, struct rockchip_gpiochip, bgpio_chip);
+}
+
+static int rockchip_gpiov2_direction_input(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+	u32 mask;
+
+	mask = 1 << (16 + (gpio % 16));
+
+	if (gpio < 16)
+		writel(mask, rgc->reg_base + RK_GPIOV2_DDR_L);
+	else
+		writel(mask, rgc->reg_base + RK_GPIOV2_DDR_H);
+
+	return 0;
+}
+
+static int rockchip_gpiov2_get_direction(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+	u32 r;
+
+	if (gpio < 16)
+		r = readl(rgc->reg_base + RK_GPIOV2_DDR_L);
+	else
+		r = readl(rgc->reg_base + RK_GPIOV2_DDR_H);
+
+	return r & BIT(gpio % 16) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
+}
+
+static void rockchip_gpiov2_set_value(struct gpio_chip *gc, unsigned int gpio,
+				      int val)
+{
+	struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+	u32 mask, vval = 0;
+
+	mask = 1 << (16 + (gpio % 16));
+	if (val)
+		vval = 1 << (gpio % 16);
+
+	if (gpio < 16)
+		writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_L);
+	else
+		writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_H);
+}
+
+static int rockchip_gpiov2_direction_output(struct gpio_chip *gc,
+					    unsigned int gpio, int val)
+{
+	struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+	u32 mask, out, vval = 0;
+
+	mask = 1 << (16 + (gpio % 16));
+	out = 1 << (gpio % 16);
+	if (val)
+		vval = 1 << (gpio % 16);
+
+	if (gpio < 16) {
+		writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_L);
+		writel(mask | out, rgc->reg_base + RK_GPIOV2_DDR_L);
+	} else {
+		writel(mask | vval, rgc->reg_base + RK_GPIOV2_DR_H);
+		writel(mask | out, rgc->reg_base + RK_GPIOV2_DDR_H);
+	}
+
+	return 0;
+}
+
+static int rockchip_gpiov2_get_value(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct rockchip_gpiochip *rgc = gc_to_rockchip_pinctrl(gc);
+	u32 mask, r;
+
+	mask = 1 << (gpio % 32);
+	r = readl(rgc->reg_base + RK_GPIOV2_EXT_PORT);
+
+	return r & mask ? 1 : 0;
+}
+
+static struct gpio_ops rockchip_gpio_ops = {
+	.direction_input = rockchip_gpiov2_direction_input,
+	.direction_output = rockchip_gpiov2_direction_output,
+	.get = rockchip_gpiov2_get_value,
+	.set = rockchip_gpiov2_set_value,
+	.get_direction = rockchip_gpiov2_get_direction,
+};
+
+static int rockchip_gpio_probe(struct device *dev)
+{
+	struct rockchip_gpiochip *rgc;
+	struct gpio_chip *gpio;
+	struct resource *res;
+	void __iomem *reg_base;
+	int ret;
+
+	rgc = xzalloc(sizeof(*rgc));
+	gpio = &rgc->bgpio_chip.gc;
+
+	res = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(res))
+		return PTR_ERR(res);
+
+	rgc->reg_base = IOMEM(res->start);
+
+	rgc->clk = clk_get(dev, NULL);
+
+	if (IS_ERR(rgc->clk))
+		return PTR_ERR(rgc->clk);
+
+	ret = clk_enable(rgc->clk);
+	if (ret)
+		return ret;
+
+	reg_base = rgc->reg_base;
+
+	if (rockchip_soc() == 3568) {
+		gpio->ngpio = 32;
+		gpio->dev = dev;
+		gpio->ops = &rockchip_gpio_ops;
+		gpio->base = of_alias_get_id(dev->of_node, "gpio");
+		if (gpio->base < 0)
+			return -EINVAL;
+		gpio->base *= 32;
+	} else {
+		ret = bgpio_init(&rgc->bgpio_chip, dev, 4,
+				 reg_base + RK_GPIO_EXT_PORT,
+				 reg_base + RK_GPIO_SWPORT_DR, NULL,
+				 reg_base + RK_GPIO_SWPORT_DDR, NULL, 0);
+		if (ret)
+			return ret;
+	}
+
+	ret = gpiochip_add(&rgc->bgpio_chip.gc);
+	if (ret) {
+		dev_err(dev, "failed to register gpio_chip:: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct of_device_id rockchip_gpio_dt_match[] = {
+	{
+		.compatible = "rockchip,gpio-bank",
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct driver rockchip_gpio_driver = {
+	.name = "rockchip-gpio",
+	.probe = rockchip_gpio_probe,
+	.of_compatible = DRV_OF_COMPAT(rockchip_gpio_dt_match),
+};
+
+core_platform_driver(rockchip_gpio_driver);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 4021f7ff23..6547423261 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -90,167 +90,6 @@ enum {
 	RK_BIAS_BUS_HOLD,
 };
 
-/* GPIO registers */
-enum {
-	RK_GPIO_SWPORT_DR	= 0x00,
-	RK_GPIO_SWPORT_DDR	= 0x04,
-	RK_GPIO_EXT_PORT	= 0x50,
-};
-
-/* GPIO registers */
-enum {
-	RK_GPIOV2_DR_L	= 0x00,
-	RK_GPIOV2_DR_H	= 0x04,
-	RK_GPIOV2_DDR_L	= 0x08,
-	RK_GPIOV2_DDR_H	= 0x0c,
-	RK_GPIOV2_EXT_PORT = 0x70,
-};
-
-static struct rockchip_pin_bank *gc_to_rockchip_pinctrl(struct gpio_chip *gc)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-
-	return container_of(bgc, struct rockchip_pin_bank, bgpio_chip);
-}
-
-static int rockchip_gpiov2_direction_input(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
-	u32 mask;
-
-	mask = 1 << (16 + (gpio % 16));
-
-	if (gpio < 16)
-		writel(mask, bank->reg_base + RK_GPIOV2_DDR_L);
-	else
-		writel(mask, bank->reg_base + RK_GPIOV2_DDR_H);
-
-	return 0;
-}
-
-static int rockchip_gpiov2_get_direction(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
-	u32 r;
-
-	if (gpio < 16)
-		r = readl(bank->reg_base + RK_GPIOV2_DDR_L);
-	else
-		r = readl(bank->reg_base + RK_GPIOV2_DDR_H);
-
-	return r & BIT(gpio % 16) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
-}
-
-static void rockchip_gpiov2_set_value(struct gpio_chip *gc, unsigned int gpio,
-				      int val)
-{
-	struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
-	u32 mask, vval = 0;
-
-	mask = 1 << (16 + (gpio % 16));
-	if (val)
-		vval = 1 << (gpio % 16);
-
-	if (gpio < 16)
-		writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_L);
-	else
-		writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_H);
-}
-
-static int rockchip_gpiov2_direction_output(struct gpio_chip *gc,
-					    unsigned int gpio, int val)
-{
-	struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
-	u32 mask, out, vval = 0;
-
-	mask = 1 << (16 + (gpio % 16));
-	out = 1 << (gpio % 16);
-	if (val)
-		vval = 1 << (gpio % 16);
-
-	if (gpio < 16) {
-		writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_L);
-		writel(mask | out, bank->reg_base + RK_GPIOV2_DDR_L);
-	} else {
-		writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_H);
-		writel(mask | out, bank->reg_base + RK_GPIOV2_DDR_H);
-	}
-
-	return 0;
-}
-
-static int rockchip_gpiov2_get_value(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc);
-	u32 mask, r;
-
-	mask = 1 << (gpio % 32);
-	r = readl(bank->reg_base + RK_GPIOV2_EXT_PORT);
-
-	return r & mask ? 1 : 0;
-}
-
-static struct gpio_ops rockchip_gpio_ops = {
-	.direction_input = rockchip_gpiov2_direction_input,
-	.direction_output = rockchip_gpiov2_direction_output,
-	.get = rockchip_gpiov2_get_value,
-	.set = rockchip_gpiov2_set_value,
-	.get_direction = rockchip_gpiov2_get_direction,
-};
-
-static int rockchip_gpio_probe(struct device *dev)
-{
-	struct rockchip_pinctrl *info = dev->parent->priv;
-	struct rockchip_pin_ctrl *ctrl = info->ctrl;
-	struct rockchip_pin_bank *bank;
-	struct gpio_chip *gpio;
-	void __iomem *reg_base;
-	int ret, bankno;
-
-	bankno = of_alias_get_id(dev->of_node, "gpio");
-	if (bankno >= ctrl->nr_banks)
-		bankno = -EINVAL;
-	if (bankno < 0)
-		return bankno;
-
-	bank = &ctrl->pin_banks[bankno];
-	gpio = &bank->bgpio_chip.gc;
-
-	if (!bank->valid)
-		dev_warn(dev, "bank %s is not valid\n", bank->name);
-
-	reg_base = bank->reg_base;
-
-	if (ctrl->type == RK3568) {
-		gpio->ngpio = 32;
-		gpio->dev = dev;
-		gpio->ops = &rockchip_gpio_ops;
-		gpio->base = bankno;
-		if (gpio->base < 0)
-			return -EINVAL;
-		gpio->base *= 32;
-	} else {
-		ret = bgpio_init(&bank->bgpio_chip, dev, 4,
-				 reg_base + RK_GPIO_EXT_PORT,
-				 reg_base + RK_GPIO_SWPORT_DR, NULL,
-				 reg_base + RK_GPIO_SWPORT_DDR, NULL, 0);
-		if (ret)
-			return ret;
-	}
-
-	bank->bgpio_chip.gc.dev = dev;
-
-	bank->bgpio_chip.gc.ngpio = bank->nr_pins;
-	ret = gpiochip_add(&bank->bgpio_chip.gc);
-	if (ret) {
-		dev_err(dev, "failed to register gpio_chip %s, error code: %d\n",
-			bank->name, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
 static struct rockchip_pinctrl *to_rockchip_pinctrl(struct pinctrl_device *pdev)
 {
 	return container_of(pdev, struct rockchip_pinctrl, pctl_dev);
@@ -1145,20 +984,3 @@ static struct driver rockchip_pinctrl_driver = {
 };
 
 core_platform_driver(rockchip_pinctrl_driver);
-
-static struct of_device_id rockchip_gpio_dt_match[] = {
-	{
-		.compatible = "rockchip,gpio-bank",
-		.data = &rk2928_pin_ctrl,
-	}, {
-		/* sentinel */
-	}
-};
-
-static struct driver rockchip_gpio_driver = {
-	.name = "rockchip-gpio",
-	.probe = rockchip_gpio_probe,
-	.of_compatible = DRV_OF_COMPAT(rockchip_gpio_dt_match),
-};
-
-core_platform_driver(rockchip_gpio_driver);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 09/18] pinctrl: Update pinctrl-rockchip from kernel
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (7 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 08/18] pinctrl/gpio: rockchip: separate gpio from pinctrl driver Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 10/18] phy: rockchip: naneng-combphy: add rk3588 support Sascha Hauer
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Update the pinctrl driver to the state of Linux-6.3-rc7. This also
adds support for all Rockchip SoCs supported by the kernel driver.
Unlike the Kernel driver we have some dead code elimination for
unused SoCs.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pinctrl/pinctrl-rockchip.c | 2935 +++++++++++++++++++++++-----
 drivers/pinctrl/pinctrl-rockchip.h |  321 ++-
 2 files changed, 2767 insertions(+), 489 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 6547423261..57d676fc98 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -27,7 +27,7 @@
 
 #include "pinctrl-rockchip.h"
 
-/**
+/*
  * Generate a bitmask for setting a value (v) with a write mask bit in hiword
  * register 31:16 area.
  */
@@ -43,12 +43,19 @@
 #define IOMUX_UNROUTED		BIT(3)
 #define IOMUX_WIDTH_3BIT	BIT(4)
 #define IOMUX_WIDTH_2BIT	BIT(5)
+#define IOMUX_L_SOURCE_PMU	BIT(6)
 
 #define PIN_BANK(id, pins, label)			\
 	{						\
 		.bank_num	= id,			\
 		.nr_pins	= pins,			\
 		.name		= label,		\
+		.iomux		= {			\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+		},					\
 	}
 
 #define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3)	\
@@ -64,6 +71,134 @@
 		},							\
 	}
 
+#define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+		},							\
+		.drv		= {					\
+			{ .drv_type = type0, .offset = -1 },		\
+			{ .drv_type = type1, .offset = -1 },		\
+			{ .drv_type = type2, .offset = -1 },		\
+			{ .drv_type = type3, .offset = -1 },		\
+		},							\
+	}
+
+#define PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(id, pins, label, iom0, iom1,	\
+					iom2, iom3, pull0, pull1,	\
+					pull2, pull3)			\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
+#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1,	\
+				      drv2, drv3, pull0, pull1,		\
+				      pull2, pull3)			\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = -1 },		\
+			{ .drv_type = drv1, .offset = -1 },		\
+			{ .drv_type = drv2, .offset = -1 },		\
+			{ .drv_type = drv3, .offset = -1 },		\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
+#define PIN_BANK_IOMUX_FLAGS_OFFSET(id, pins, label, iom0, iom1, iom2,	\
+				    iom3, offset0, offset1, offset2,	\
+				    offset3)				\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = offset0 },		\
+			{ .type = iom1, .offset = offset1 },		\
+			{ .type = iom2, .offset = offset2 },		\
+			{ .type = iom3, .offset = offset3 },		\
+		},							\
+	}
+
+#define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,	\
+					iom2, iom3, drv0, drv1, drv2,	\
+					drv3, offset0, offset1,		\
+					offset2, offset3)		\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = offset0 },	\
+			{ .drv_type = drv1, .offset = offset1 },	\
+			{ .drv_type = drv2, .offset = offset2 },	\
+			{ .drv_type = drv3, .offset = offset3 },	\
+		},							\
+	}
+
+#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins,	\
+					      label, iom0, iom1, iom2,  \
+					      iom3, drv0, drv1, drv2,   \
+					      drv3, offset0, offset1,   \
+					      offset2, offset3, pull0,  \
+					      pull1, pull2, pull3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = offset0 },	\
+			{ .drv_type = drv1, .offset = offset1 },	\
+			{ .drv_type = drv2, .offset = offset2 },	\
+			{ .drv_type = drv3, .offset = offset3 },	\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 #define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG)		\
 	{								\
 		.bank_num	= ID,					\
@@ -83,6 +218,9 @@
 #define RK_MUXROUTE_PMU(ID, PIN, FUNC, REG, VAL)	\
 	PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_PMU)
 
+#define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P)			\
+	PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P)
+
 enum {
 	RK_BIAS_DISABLE = 0,
 	RK_BIAS_PULL_UP,
@@ -92,86 +230,1509 @@ enum {
 
 static struct rockchip_pinctrl *to_rockchip_pinctrl(struct pinctrl_device *pdev)
 {
-	return container_of(pdev, struct rockchip_pinctrl, pctl_dev);
+	return container_of(pdev, struct rockchip_pinctrl, pctl_dev);
+}
+
+static int parse_bias_config(struct device_node *np)
+{
+	u32 val;
+ 
+	if (of_property_read_u32(np, "bias-pull-up", &val) != -EINVAL)
+		return RK_BIAS_PULL_UP;
+	else if (of_property_read_u32(np, "bias-pull-down", &val) != -EINVAL)
+		return RK_BIAS_PULL_DOWN;
+	else if (of_property_read_u32(np, "bias-bus-hold", &val) != -EINVAL)
+		return RK_BIAS_BUS_HOLD;
+	else
+		return RK_BIAS_DISABLE;
+}
+
+static struct rockchip_pin_bank *bank_num_to_bank(
+					struct rockchip_pinctrl *info,
+					unsigned num)
+{
+	struct rockchip_pin_bank *b = info->ctrl->pin_banks;
+	int i;
+
+	for (i = 0; i < info->ctrl->nr_banks; i++, b++) {
+		if (b->bank_num == num)
+			return b;
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+/*
+ * Hardware access
+ */
+
+static struct rockchip_mux_recalced_data rv1108_mux_recalced_data[] = {
+	{
+		.num = 1,
+		.pin = 0,
+		.reg = 0x418,
+		.bit = 0,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 1,
+		.reg = 0x418,
+		.bit = 2,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 2,
+		.reg = 0x418,
+		.bit = 4,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 3,
+		.reg = 0x418,
+		.bit = 6,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 4,
+		.reg = 0x418,
+		.bit = 8,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 5,
+		.reg = 0x418,
+		.bit = 10,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 6,
+		.reg = 0x418,
+		.bit = 12,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 7,
+		.reg = 0x418,
+		.bit = 14,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 8,
+		.reg = 0x41c,
+		.bit = 0,
+		.mask = 0x3
+	}, {
+		.num = 1,
+		.pin = 9,
+		.reg = 0x41c,
+		.bit = 2,
+		.mask = 0x3
+	},
+};
+
+static struct rockchip_mux_recalced_data rv1126_mux_recalced_data[] = {
+	{
+		.num = 0,
+		.pin = 20,
+		.reg = 0x10000,
+		.bit = 0,
+		.mask = 0xf
+	},
+	{
+		.num = 0,
+		.pin = 21,
+		.reg = 0x10000,
+		.bit = 4,
+		.mask = 0xf
+	},
+	{
+		.num = 0,
+		.pin = 22,
+		.reg = 0x10000,
+		.bit = 8,
+		.mask = 0xf
+	},
+	{
+		.num = 0,
+		.pin = 23,
+		.reg = 0x10000,
+		.bit = 12,
+		.mask = 0xf
+	},
+};
+
+static  struct rockchip_mux_recalced_data rk3128_mux_recalced_data[] = {
+	{
+		.num = 2,
+		.pin = 20,
+		.reg = 0xe8,
+		.bit = 0,
+		.mask = 0x7
+	}, {
+		.num = 2,
+		.pin = 21,
+		.reg = 0xe8,
+		.bit = 4,
+		.mask = 0x7
+	}, {
+		.num = 2,
+		.pin = 22,
+		.reg = 0xe8,
+		.bit = 8,
+		.mask = 0x7
+	}, {
+		.num = 2,
+		.pin = 23,
+		.reg = 0xe8,
+		.bit = 12,
+		.mask = 0x7
+	}, {
+		.num = 2,
+		.pin = 24,
+		.reg = 0xd4,
+		.bit = 12,
+		.mask = 0x7
+	},
+};
+
+static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = {
+	{
+		/* gpio1b6_sel */
+		.num = 1,
+		.pin = 14,
+		.reg = 0x28,
+		.bit = 12,
+		.mask = 0xf
+	}, {
+		/* gpio1b7_sel */
+		.num = 1,
+		.pin = 15,
+		.reg = 0x2c,
+		.bit = 0,
+		.mask = 0x3
+	}, {
+		/* gpio1c2_sel */
+		.num = 1,
+		.pin = 18,
+		.reg = 0x30,
+		.bit = 4,
+		.mask = 0xf
+	}, {
+		/* gpio1c3_sel */
+		.num = 1,
+		.pin = 19,
+		.reg = 0x30,
+		.bit = 8,
+		.mask = 0xf
+	}, {
+		/* gpio1c4_sel */
+		.num = 1,
+		.pin = 20,
+		.reg = 0x30,
+		.bit = 12,
+		.mask = 0xf
+	}, {
+		/* gpio1c5_sel */
+		.num = 1,
+		.pin = 21,
+		.reg = 0x34,
+		.bit = 0,
+		.mask = 0xf
+	}, {
+		/* gpio1c6_sel */
+		.num = 1,
+		.pin = 22,
+		.reg = 0x34,
+		.bit = 4,
+		.mask = 0xf
+	}, {
+		/* gpio1c7_sel */
+		.num = 1,
+		.pin = 23,
+		.reg = 0x34,
+		.bit = 8,
+		.mask = 0xf
+	}, {
+		/* gpio2a2_sel */
+		.num = 2,
+		.pin = 2,
+		.reg = 0x40,
+		.bit = 4,
+		.mask = 0x3
+	}, {
+		/* gpio2a3_sel */
+		.num = 2,
+		.pin = 3,
+		.reg = 0x40,
+		.bit = 6,
+		.mask = 0x3
+	}, {
+		/* gpio2c0_sel */
+		.num = 2,
+		.pin = 16,
+		.reg = 0x50,
+		.bit = 0,
+		.mask = 0x3
+	}, {
+		/* gpio3b2_sel */
+		.num = 3,
+		.pin = 10,
+		.reg = 0x68,
+		.bit = 4,
+		.mask = 0x3
+	}, {
+		/* gpio3b3_sel */
+		.num = 3,
+		.pin = 11,
+		.reg = 0x68,
+		.bit = 6,
+		.mask = 0x3
+	}, {
+		/* gpio3b4_sel */
+		.num = 3,
+		.pin = 12,
+		.reg = 0x68,
+		.bit = 8,
+		.mask = 0xf
+	}, {
+		/* gpio3b5_sel */
+		.num = 3,
+		.pin = 13,
+		.reg = 0x68,
+		.bit = 12,
+		.mask = 0xf
+	},
+};
+
+static struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = {
+	{
+		.num = 2,
+		.pin = 12,
+		.reg = 0x24,
+		.bit = 8,
+		.mask = 0x3
+	}, {
+		.num = 2,
+		.pin = 15,
+		.reg = 0x28,
+		.bit = 0,
+		.mask = 0x7
+	}, {
+		.num = 2,
+		.pin = 23,
+		.reg = 0x30,
+		.bit = 14,
+		.mask = 0x3
+	},
+};
+
+static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
+				      int *reg, u8 *bit, int *mask)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct rockchip_pin_ctrl *ctrl = info->ctrl;
+	struct rockchip_mux_recalced_data *data = NULL;
+	int i;
+
+	for (i = 0; i < ctrl->niomux_recalced; i++) {
+		data = &ctrl->iomux_recalced[i];
+		if (data->num == bank->bank_num &&
+		    data->pin == pin)
+			break;
+	}
+
+	if (i >= ctrl->niomux_recalced)
+		return;
+
+	*reg = data->reg;
+	*mask = data->mask;
+	*bit = data->bit;
+}
+
+static struct rockchip_mux_route_data px30_mux_route_data[] = {
+	RK_MUXROUTE_SAME(2, RK_PB4, 1, 0x184, BIT(16 + 7)), /* cif-d0m0 */
+	RK_MUXROUTE_SAME(3, RK_PA1, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d0m1 */
+	RK_MUXROUTE_SAME(2, RK_PB6, 1, 0x184, BIT(16 + 7)), /* cif-d1m0 */
+	RK_MUXROUTE_SAME(3, RK_PA2, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d1m1 */
+	RK_MUXROUTE_SAME(2, RK_PA0, 1, 0x184, BIT(16 + 7)), /* cif-d2m0 */
+	RK_MUXROUTE_SAME(3, RK_PA3, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d2m1 */
+	RK_MUXROUTE_SAME(2, RK_PA1, 1, 0x184, BIT(16 + 7)), /* cif-d3m0 */
+	RK_MUXROUTE_SAME(3, RK_PA5, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d3m1 */
+	RK_MUXROUTE_SAME(2, RK_PA2, 1, 0x184, BIT(16 + 7)), /* cif-d4m0 */
+	RK_MUXROUTE_SAME(3, RK_PA7, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d4m1 */
+	RK_MUXROUTE_SAME(2, RK_PA3, 1, 0x184, BIT(16 + 7)), /* cif-d5m0 */
+	RK_MUXROUTE_SAME(3, RK_PB0, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d5m1 */
+	RK_MUXROUTE_SAME(2, RK_PA4, 1, 0x184, BIT(16 + 7)), /* cif-d6m0 */
+	RK_MUXROUTE_SAME(3, RK_PB1, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d6m1 */
+	RK_MUXROUTE_SAME(2, RK_PA5, 1, 0x184, BIT(16 + 7)), /* cif-d7m0 */
+	RK_MUXROUTE_SAME(3, RK_PB4, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d7m1 */
+	RK_MUXROUTE_SAME(2, RK_PA6, 1, 0x184, BIT(16 + 7)), /* cif-d8m0 */
+	RK_MUXROUTE_SAME(3, RK_PB6, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d8m1 */
+	RK_MUXROUTE_SAME(2, RK_PA7, 1, 0x184, BIT(16 + 7)), /* cif-d9m0 */
+	RK_MUXROUTE_SAME(3, RK_PB7, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d9m1 */
+	RK_MUXROUTE_SAME(2, RK_PB7, 1, 0x184, BIT(16 + 7)), /* cif-d10m0 */
+	RK_MUXROUTE_SAME(3, RK_PC6, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d10m1 */
+	RK_MUXROUTE_SAME(2, RK_PC0, 1, 0x184, BIT(16 + 7)), /* cif-d11m0 */
+	RK_MUXROUTE_SAME(3, RK_PC7, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d11m1 */
+	RK_MUXROUTE_SAME(2, RK_PB0, 1, 0x184, BIT(16 + 7)), /* cif-vsyncm0 */
+	RK_MUXROUTE_SAME(3, RK_PD1, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-vsyncm1 */
+	RK_MUXROUTE_SAME(2, RK_PB1, 1, 0x184, BIT(16 + 7)), /* cif-hrefm0 */
+	RK_MUXROUTE_SAME(3, RK_PD2, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-hrefm1 */
+	RK_MUXROUTE_SAME(2, RK_PB2, 1, 0x184, BIT(16 + 7)), /* cif-clkinm0 */
+	RK_MUXROUTE_SAME(3, RK_PD3, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-clkinm1 */
+	RK_MUXROUTE_SAME(2, RK_PB3, 1, 0x184, BIT(16 + 7)), /* cif-clkoutm0 */
+	RK_MUXROUTE_SAME(3, RK_PD0, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-clkoutm1 */
+	RK_MUXROUTE_SAME(3, RK_PC6, 2, 0x184, BIT(16 + 8)), /* pdm-m0 */
+	RK_MUXROUTE_SAME(2, RK_PC6, 1, 0x184, BIT(16 + 8) | BIT(8)), /* pdm-m1 */
+	RK_MUXROUTE_SAME(3, RK_PD3, 2, 0x184, BIT(16 + 8)), /* pdm-sdi0m0 */
+	RK_MUXROUTE_SAME(2, RK_PC5, 2, 0x184, BIT(16 + 8) | BIT(8)), /* pdm-sdi0m1 */
+	RK_MUXROUTE_SAME(1, RK_PD3, 2, 0x184, BIT(16 + 10)), /* uart2-rxm0 */
+	RK_MUXROUTE_SAME(2, RK_PB6, 2, 0x184, BIT(16 + 10) | BIT(10)), /* uart2-rxm1 */
+	RK_MUXROUTE_SAME(1, RK_PD2, 2, 0x184, BIT(16 + 10)), /* uart2-txm0 */
+	RK_MUXROUTE_SAME(2, RK_PB4, 2, 0x184, BIT(16 + 10) | BIT(10)), /* uart2-txm1 */
+	RK_MUXROUTE_SAME(0, RK_PC1, 2, 0x184, BIT(16 + 9)), /* uart3-rxm0 */
+	RK_MUXROUTE_SAME(1, RK_PB7, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-rxm1 */
+	RK_MUXROUTE_SAME(0, RK_PC0, 2, 0x184, BIT(16 + 9)), /* uart3-txm0 */
+	RK_MUXROUTE_SAME(1, RK_PB6, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-txm1 */
+	RK_MUXROUTE_SAME(0, RK_PC2, 2, 0x184, BIT(16 + 9)), /* uart3-ctsm0 */
+	RK_MUXROUTE_SAME(1, RK_PB4, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-ctsm1 */
+	RK_MUXROUTE_SAME(0, RK_PC3, 2, 0x184, BIT(16 + 9)), /* uart3-rtsm0 */
+	RK_MUXROUTE_SAME(1, RK_PB5, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-rtsm1 */
+};
+
+static struct rockchip_mux_route_data rv1126_mux_route_data[] = {
+	RK_MUXROUTE_GRF(3, RK_PD2, 1, 0x10260, WRITE_MASK_VAL(0, 0, 0)), /* I2S0_MCLK_M0 */
+	RK_MUXROUTE_GRF(3, RK_PB0, 3, 0x10260, WRITE_MASK_VAL(0, 0, 1)), /* I2S0_MCLK_M1 */
+
+	RK_MUXROUTE_GRF(0, RK_PD4, 4, 0x10260, WRITE_MASK_VAL(3, 2, 0)), /* I2S1_MCLK_M0 */
+	RK_MUXROUTE_GRF(1, RK_PD5, 2, 0x10260, WRITE_MASK_VAL(3, 2, 1)), /* I2S1_MCLK_M1 */
+	RK_MUXROUTE_GRF(2, RK_PC7, 6, 0x10260, WRITE_MASK_VAL(3, 2, 2)), /* I2S1_MCLK_M2 */
+
+	RK_MUXROUTE_GRF(1, RK_PD0, 1, 0x10260, WRITE_MASK_VAL(4, 4, 0)), /* I2S2_MCLK_M0 */
+	RK_MUXROUTE_GRF(2, RK_PB3, 2, 0x10260, WRITE_MASK_VAL(4, 4, 1)), /* I2S2_MCLK_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PD4, 2, 0x10260, WRITE_MASK_VAL(12, 12, 0)), /* PDM_CLK0_M0 */
+	RK_MUXROUTE_GRF(3, RK_PC0, 3, 0x10260, WRITE_MASK_VAL(12, 12, 1)), /* PDM_CLK0_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PC6, 1, 0x10264, WRITE_MASK_VAL(0, 0, 0)), /* CIF_CLKOUT_M0 */
+	RK_MUXROUTE_GRF(2, RK_PD1, 3, 0x10264, WRITE_MASK_VAL(0, 0, 1)), /* CIF_CLKOUT_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PA4, 5, 0x10264, WRITE_MASK_VAL(5, 4, 0)), /* I2C3_SCL_M0 */
+	RK_MUXROUTE_GRF(2, RK_PD4, 7, 0x10264, WRITE_MASK_VAL(5, 4, 1)), /* I2C3_SCL_M1 */
+	RK_MUXROUTE_GRF(1, RK_PD6, 3, 0x10264, WRITE_MASK_VAL(5, 4, 2)), /* I2C3_SCL_M2 */
+
+	RK_MUXROUTE_GRF(3, RK_PA0, 7, 0x10264, WRITE_MASK_VAL(6, 6, 0)), /* I2C4_SCL_M0 */
+	RK_MUXROUTE_GRF(4, RK_PA0, 4, 0x10264, WRITE_MASK_VAL(6, 6, 1)), /* I2C4_SCL_M1 */
+
+	RK_MUXROUTE_GRF(2, RK_PA5, 7, 0x10264, WRITE_MASK_VAL(9, 8, 0)), /* I2C5_SCL_M0 */
+	RK_MUXROUTE_GRF(3, RK_PB0, 5, 0x10264, WRITE_MASK_VAL(9, 8, 1)), /* I2C5_SCL_M1 */
+	RK_MUXROUTE_GRF(1, RK_PD0, 4, 0x10264, WRITE_MASK_VAL(9, 8, 2)), /* I2C5_SCL_M2 */
+
+	RK_MUXROUTE_GRF(3, RK_PC0, 5, 0x10264, WRITE_MASK_VAL(11, 10, 0)), /* SPI1_CLK_M0 */
+	RK_MUXROUTE_GRF(1, RK_PC6, 3, 0x10264, WRITE_MASK_VAL(11, 10, 1)), /* SPI1_CLK_M1 */
+	RK_MUXROUTE_GRF(2, RK_PD5, 6, 0x10264, WRITE_MASK_VAL(11, 10, 2)), /* SPI1_CLK_M2 */
+
+	RK_MUXROUTE_GRF(3, RK_PC0, 2, 0x10264, WRITE_MASK_VAL(12, 12, 0)), /* RGMII_CLK_M0 */
+	RK_MUXROUTE_GRF(2, RK_PB7, 2, 0x10264, WRITE_MASK_VAL(12, 12, 1)), /* RGMII_CLK_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PA1, 3, 0x10264, WRITE_MASK_VAL(13, 13, 0)), /* CAN_TXD_M0 */
+	RK_MUXROUTE_GRF(3, RK_PA7, 5, 0x10264, WRITE_MASK_VAL(13, 13, 1)), /* CAN_TXD_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PA4, 6, 0x10268, WRITE_MASK_VAL(0, 0, 0)), /* PWM8_M0 */
+	RK_MUXROUTE_GRF(2, RK_PD7, 5, 0x10268, WRITE_MASK_VAL(0, 0, 1)), /* PWM8_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PA5, 6, 0x10268, WRITE_MASK_VAL(2, 2, 0)), /* PWM9_M0 */
+	RK_MUXROUTE_GRF(2, RK_PD6, 5, 0x10268, WRITE_MASK_VAL(2, 2, 1)), /* PWM9_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PA6, 6, 0x10268, WRITE_MASK_VAL(4, 4, 0)), /* PWM10_M0 */
+	RK_MUXROUTE_GRF(2, RK_PD5, 5, 0x10268, WRITE_MASK_VAL(4, 4, 1)), /* PWM10_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PA7, 6, 0x10268, WRITE_MASK_VAL(6, 6, 0)), /* PWM11_IR_M0 */
+	RK_MUXROUTE_GRF(3, RK_PA1, 5, 0x10268, WRITE_MASK_VAL(6, 6, 1)), /* PWM11_IR_M1 */
+
+	RK_MUXROUTE_GRF(1, RK_PA5, 3, 0x10268, WRITE_MASK_VAL(8, 8, 0)), /* UART2_TX_M0 */
+	RK_MUXROUTE_GRF(3, RK_PA2, 1, 0x10268, WRITE_MASK_VAL(8, 8, 1)), /* UART2_TX_M1 */
+
+	RK_MUXROUTE_GRF(3, RK_PC6, 3, 0x10268, WRITE_MASK_VAL(11, 10, 0)), /* UART3_TX_M0 */
+	RK_MUXROUTE_GRF(1, RK_PA7, 2, 0x10268, WRITE_MASK_VAL(11, 10, 1)), /* UART3_TX_M1 */
+	RK_MUXROUTE_GRF(3, RK_PA0, 4, 0x10268, WRITE_MASK_VAL(11, 10, 2)), /* UART3_TX_M2 */
+
+	RK_MUXROUTE_GRF(3, RK_PA4, 4, 0x10268, WRITE_MASK_VAL(13, 12, 0)), /* UART4_TX_M0 */
+	RK_MUXROUTE_GRF(2, RK_PA6, 4, 0x10268, WRITE_MASK_VAL(13, 12, 1)), /* UART4_TX_M1 */
+	RK_MUXROUTE_GRF(1, RK_PD5, 3, 0x10268, WRITE_MASK_VAL(13, 12, 2)), /* UART4_TX_M2 */
+
+	RK_MUXROUTE_GRF(3, RK_PA6, 4, 0x10268, WRITE_MASK_VAL(15, 14, 0)), /* UART5_TX_M0 */
+	RK_MUXROUTE_GRF(2, RK_PB0, 4, 0x10268, WRITE_MASK_VAL(15, 14, 1)), /* UART5_TX_M1 */
+	RK_MUXROUTE_GRF(2, RK_PA0, 3, 0x10268, WRITE_MASK_VAL(15, 14, 2)), /* UART5_TX_M2 */
+
+	RK_MUXROUTE_PMU(0, RK_PB6, 3, 0x0114, WRITE_MASK_VAL(0, 0, 0)), /* PWM0_M0 */
+	RK_MUXROUTE_PMU(2, RK_PB3, 5, 0x0114, WRITE_MASK_VAL(0, 0, 1)), /* PWM0_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PB7, 3, 0x0114, WRITE_MASK_VAL(2, 2, 0)), /* PWM1_M0 */
+	RK_MUXROUTE_PMU(2, RK_PB2, 5, 0x0114, WRITE_MASK_VAL(2, 2, 1)), /* PWM1_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PC0, 3, 0x0114, WRITE_MASK_VAL(4, 4, 0)), /* PWM2_M0 */
+	RK_MUXROUTE_PMU(2, RK_PB1, 5, 0x0114, WRITE_MASK_VAL(4, 4, 1)), /* PWM2_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PC1, 3, 0x0114, WRITE_MASK_VAL(6, 6, 0)), /* PWM3_IR_M0 */
+	RK_MUXROUTE_PMU(2, RK_PB0, 5, 0x0114, WRITE_MASK_VAL(6, 6, 1)), /* PWM3_IR_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PC2, 3, 0x0114, WRITE_MASK_VAL(8, 8, 0)), /* PWM4_M0 */
+	RK_MUXROUTE_PMU(2, RK_PA7, 5, 0x0114, WRITE_MASK_VAL(8, 8, 1)), /* PWM4_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PC3, 3, 0x0114, WRITE_MASK_VAL(10, 10, 0)), /* PWM5_M0 */
+	RK_MUXROUTE_PMU(2, RK_PA6, 5, 0x0114, WRITE_MASK_VAL(10, 10, 1)), /* PWM5_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PB2, 3, 0x0114, WRITE_MASK_VAL(12, 12, 0)), /* PWM6_M0 */
+	RK_MUXROUTE_PMU(2, RK_PD4, 5, 0x0114, WRITE_MASK_VAL(12, 12, 1)), /* PWM6_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PB1, 3, 0x0114, WRITE_MASK_VAL(14, 14, 0)), /* PWM7_IR_M0 */
+	RK_MUXROUTE_PMU(3, RK_PA0, 5, 0x0114, WRITE_MASK_VAL(14, 14, 1)), /* PWM7_IR_M1 */
+
+	RK_MUXROUTE_PMU(0, RK_PB0, 1, 0x0118, WRITE_MASK_VAL(1, 0, 0)), /* SPI0_CLK_M0 */
+	RK_MUXROUTE_PMU(2, RK_PA1, 1, 0x0118, WRITE_MASK_VAL(1, 0, 1)), /* SPI0_CLK_M1 */
+	RK_MUXROUTE_PMU(2, RK_PB2, 6, 0x0118, WRITE_MASK_VAL(1, 0, 2)), /* SPI0_CLK_M2 */
+
+	RK_MUXROUTE_PMU(0, RK_PB6, 2, 0x0118, WRITE_MASK_VAL(2, 2, 0)), /* UART1_TX_M0 */
+	RK_MUXROUTE_PMU(1, RK_PD0, 5, 0x0118, WRITE_MASK_VAL(2, 2, 1)), /* UART1_TX_M1 */
+};
+
+static struct rockchip_mux_route_data rk3128_mux_route_data[] = {
+	RK_MUXROUTE_SAME(1, RK_PB2, 1, 0x144, BIT(16 + 3) | BIT(16 + 4)), /* spi-0 */
+	RK_MUXROUTE_SAME(1, RK_PD3, 3, 0x144, BIT(16 + 3) | BIT(16 + 4) | BIT(3)), /* spi-1 */
+	RK_MUXROUTE_SAME(0, RK_PB5, 2, 0x144, BIT(16 + 3) | BIT(16 + 4) | BIT(4)), /* spi-2 */
+	RK_MUXROUTE_SAME(1, RK_PA5, 1, 0x144, BIT(16 + 5)), /* i2s-0 */
+	RK_MUXROUTE_SAME(0, RK_PB6, 1, 0x144, BIT(16 + 5) | BIT(5)), /* i2s-1 */
+	RK_MUXROUTE_SAME(1, RK_PC6, 2, 0x144, BIT(16 + 6)), /* emmc-0 */
+	RK_MUXROUTE_SAME(2, RK_PA4, 2, 0x144, BIT(16 + 6) | BIT(6)), /* emmc-1 */
+};
+
+static struct rockchip_mux_route_data rk3188_mux_route_data[] = {
+	RK_MUXROUTE_SAME(0, RK_PD0, 1, 0xa0, BIT(16 + 11)), /* non-iomuxed emmc/flash pins on flash-dqs */
+	RK_MUXROUTE_SAME(0, RK_PD0, 2, 0xa0, BIT(16 + 11) | BIT(11)), /* non-iomuxed emmc/flash pins on emmc-clk */
+};
+
+static struct rockchip_mux_route_data rk3228_mux_route_data[] = {
+	RK_MUXROUTE_SAME(0, RK_PD2, 1, 0x50, BIT(16)), /* pwm0-0 */
+	RK_MUXROUTE_SAME(3, RK_PC5, 1, 0x50, BIT(16) | BIT(0)), /* pwm0-1 */
+	RK_MUXROUTE_SAME(0, RK_PD3, 1, 0x50, BIT(16 + 1)), /* pwm1-0 */
+	RK_MUXROUTE_SAME(0, RK_PD6, 2, 0x50, BIT(16 + 1) | BIT(1)), /* pwm1-1 */
+	RK_MUXROUTE_SAME(0, RK_PD4, 1, 0x50, BIT(16 + 2)), /* pwm2-0 */
+	RK_MUXROUTE_SAME(1, RK_PB4, 2, 0x50, BIT(16 + 2) | BIT(2)), /* pwm2-1 */
+	RK_MUXROUTE_SAME(3, RK_PD2, 1, 0x50, BIT(16 + 3)), /* pwm3-0 */
+	RK_MUXROUTE_SAME(1, RK_PB3, 2, 0x50, BIT(16 + 3) | BIT(3)), /* pwm3-1 */
+	RK_MUXROUTE_SAME(1, RK_PA1, 1, 0x50, BIT(16 + 4)), /* sdio-0_d0 */
+	RK_MUXROUTE_SAME(3, RK_PA2, 1, 0x50, BIT(16 + 4) | BIT(4)), /* sdio-1_d0 */
+	RK_MUXROUTE_SAME(0, RK_PB5, 2, 0x50, BIT(16 + 5)), /* spi-0_rx */
+	RK_MUXROUTE_SAME(2, RK_PA0, 2, 0x50, BIT(16 + 5) | BIT(5)), /* spi-1_rx */
+	RK_MUXROUTE_SAME(1, RK_PC6, 2, 0x50, BIT(16 + 7)), /* emmc-0_cmd */
+	RK_MUXROUTE_SAME(2, RK_PA4, 2, 0x50, BIT(16 + 7) | BIT(7)), /* emmc-1_cmd */
+	RK_MUXROUTE_SAME(1, RK_PC3, 2, 0x50, BIT(16 + 8)), /* uart2-0_rx */
+	RK_MUXROUTE_SAME(1, RK_PB2, 2, 0x50, BIT(16 + 8) | BIT(8)), /* uart2-1_rx */
+	RK_MUXROUTE_SAME(1, RK_PB2, 1, 0x50, BIT(16 + 11)), /* uart1-0_rx */
+	RK_MUXROUTE_SAME(3, RK_PB5, 1, 0x50, BIT(16 + 11) | BIT(11)), /* uart1-1_rx */
+};
+
+static struct rockchip_mux_route_data rk3288_mux_route_data[] = {
+	RK_MUXROUTE_SAME(7, RK_PC0, 2, 0x264, BIT(16 + 12) | BIT(12)), /* edphdmi_cecinoutt1 */
+	RK_MUXROUTE_SAME(7, RK_PC7, 4, 0x264, BIT(16 + 12)), /* edphdmi_cecinout */
+};
+
+static struct rockchip_mux_route_data rk3308_mux_route_data[] = {
+	RK_MUXROUTE_SAME(0, RK_PC3, 1, 0x314, BIT(16 + 0) | BIT(0)), /* rtc_clk */
+	RK_MUXROUTE_SAME(1, RK_PC6, 2, 0x314, BIT(16 + 2) | BIT(16 + 3)), /* uart2_rxm0 */
+	RK_MUXROUTE_SAME(4, RK_PD2, 2, 0x314, BIT(16 + 2) | BIT(16 + 3) | BIT(2)), /* uart2_rxm1 */
+	RK_MUXROUTE_SAME(0, RK_PB7, 2, 0x608, BIT(16 + 8) | BIT(16 + 9)), /* i2c3_sdam0 */
+	RK_MUXROUTE_SAME(3, RK_PB4, 2, 0x608, BIT(16 + 8) | BIT(16 + 9) | BIT(8)), /* i2c3_sdam1 */
+	RK_MUXROUTE_SAME(2, RK_PA0, 3, 0x608, BIT(16 + 8) | BIT(16 + 9) | BIT(9)), /* i2c3_sdam2 */
+	RK_MUXROUTE_SAME(1, RK_PA3, 2, 0x308, BIT(16 + 3)), /* i2s-8ch-1-sclktxm0 */
+	RK_MUXROUTE_SAME(1, RK_PA4, 2, 0x308, BIT(16 + 3)), /* i2s-8ch-1-sclkrxm0 */
+	RK_MUXROUTE_SAME(1, RK_PB5, 2, 0x308, BIT(16 + 3) | BIT(3)), /* i2s-8ch-1-sclktxm1 */
+	RK_MUXROUTE_SAME(1, RK_PB6, 2, 0x308, BIT(16 + 3) | BIT(3)), /* i2s-8ch-1-sclkrxm1 */
+	RK_MUXROUTE_SAME(1, RK_PA4, 3, 0x308, BIT(16 + 12) | BIT(16 + 13)), /* pdm-clkm0 */
+	RK_MUXROUTE_SAME(1, RK_PB6, 4, 0x308, BIT(16 + 12) | BIT(16 + 13) | BIT(12)), /* pdm-clkm1 */
+	RK_MUXROUTE_SAME(2, RK_PA6, 2, 0x308, BIT(16 + 12) | BIT(16 + 13) | BIT(13)), /* pdm-clkm2 */
+	RK_MUXROUTE_SAME(2, RK_PA4, 3, 0x600, BIT(16 + 2) | BIT(2)), /* pdm-clkm-m2 */
+	RK_MUXROUTE_SAME(3, RK_PB2, 3, 0x314, BIT(16 + 9)), /* spi1_miso */
+	RK_MUXROUTE_SAME(2, RK_PA4, 2, 0x314, BIT(16 + 9) | BIT(9)), /* spi1_miso_m1 */
+	RK_MUXROUTE_SAME(0, RK_PB3, 3, 0x314, BIT(16 + 10) | BIT(16 + 11)), /* owire_m0 */
+	RK_MUXROUTE_SAME(1, RK_PC6, 7, 0x314, BIT(16 + 10) | BIT(16 + 11) | BIT(10)), /* owire_m1 */
+	RK_MUXROUTE_SAME(2, RK_PA2, 5, 0x314, BIT(16 + 10) | BIT(16 + 11) | BIT(11)), /* owire_m2 */
+	RK_MUXROUTE_SAME(0, RK_PB3, 2, 0x314, BIT(16 + 12) | BIT(16 + 13)), /* can_rxd_m0 */
+	RK_MUXROUTE_SAME(1, RK_PC6, 5, 0x314, BIT(16 + 12) | BIT(16 + 13) | BIT(12)), /* can_rxd_m1 */
+	RK_MUXROUTE_SAME(2, RK_PA2, 4, 0x314, BIT(16 + 12) | BIT(16 + 13) | BIT(13)), /* can_rxd_m2 */
+	RK_MUXROUTE_SAME(1, RK_PC4, 3, 0x314, BIT(16 + 14)), /* mac_rxd0_m0 */
+	RK_MUXROUTE_SAME(4, RK_PA2, 2, 0x314, BIT(16 + 14) | BIT(14)), /* mac_rxd0_m1 */
+	RK_MUXROUTE_SAME(3, RK_PB4, 4, 0x314, BIT(16 + 15)), /* uart3_rx */
+	RK_MUXROUTE_SAME(0, RK_PC1, 3, 0x314, BIT(16 + 15) | BIT(15)), /* uart3_rx_m1 */
+};
+
+static struct rockchip_mux_route_data rk3328_mux_route_data[] = {
+	RK_MUXROUTE_SAME(1, RK_PA1, 2, 0x50, BIT(16) | BIT(16 + 1)), /* uart2dbg_rxm0 */
+	RK_MUXROUTE_SAME(2, RK_PA1, 1, 0x50, BIT(16) | BIT(16 + 1) | BIT(0)), /* uart2dbg_rxm1 */
+	RK_MUXROUTE_SAME(1, RK_PB3, 2, 0x50, BIT(16 + 2) | BIT(2)), /* gmac-m1_rxd0 */
+	RK_MUXROUTE_SAME(1, RK_PB6, 2, 0x50, BIT(16 + 10) | BIT(10)), /* gmac-m1-optimized_rxd3 */
+	RK_MUXROUTE_SAME(2, RK_PC3, 2, 0x50, BIT(16 + 3)), /* pdm_sdi0m0 */
+	RK_MUXROUTE_SAME(1, RK_PC7, 3, 0x50, BIT(16 + 3) | BIT(3)), /* pdm_sdi0m1 */
+	RK_MUXROUTE_SAME(3, RK_PA2, 4, 0x50, BIT(16 + 4) | BIT(16 + 5) | BIT(5)), /* spi_rxdm2 */
+	RK_MUXROUTE_SAME(1, RK_PD0, 1, 0x50, BIT(16 + 6)), /* i2s2_sdim0 */
+	RK_MUXROUTE_SAME(3, RK_PA2, 6, 0x50, BIT(16 + 6) | BIT(6)), /* i2s2_sdim1 */
+	RK_MUXROUTE_SAME(2, RK_PC6, 3, 0x50, BIT(16 + 7) | BIT(7)), /* card_iom1 */
+	RK_MUXROUTE_SAME(2, RK_PC0, 3, 0x50, BIT(16 + 8) | BIT(8)), /* tsp_d5m1 */
+	RK_MUXROUTE_SAME(2, RK_PC0, 4, 0x50, BIT(16 + 9) | BIT(9)), /* cif_data5m1 */
+};
+
+static struct rockchip_mux_route_data rk3399_mux_route_data[] = {
+	RK_MUXROUTE_SAME(4, RK_PB0, 2, 0xe21c, BIT(16 + 10) | BIT(16 + 11)), /* uart2dbga_rx */
+	RK_MUXROUTE_SAME(4, RK_PC0, 2, 0xe21c, BIT(16 + 10) | BIT(16 + 11) | BIT(10)), /* uart2dbgb_rx */
+	RK_MUXROUTE_SAME(4, RK_PC3, 1, 0xe21c, BIT(16 + 10) | BIT(16 + 11) | BIT(11)), /* uart2dbgc_rx */
+	RK_MUXROUTE_SAME(2, RK_PD2, 2, 0xe21c, BIT(16 + 14)), /* pcie_clkreqn */
+	RK_MUXROUTE_SAME(4, RK_PD0, 1, 0xe21c, BIT(16 + 14) | BIT(14)), /* pcie_clkreqnb */
+};
+
+static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
+	RK_MUXROUTE_PMU(0, RK_PB7, 1, 0x0110, WRITE_MASK_VAL(1, 0, 0)), /* PWM0 IO mux M0 */
+	RK_MUXROUTE_PMU(0, RK_PC7, 2, 0x0110, WRITE_MASK_VAL(1, 0, 1)), /* PWM0 IO mux M1 */
+	RK_MUXROUTE_PMU(0, RK_PC0, 1, 0x0110, WRITE_MASK_VAL(3, 2, 0)), /* PWM1 IO mux M0 */
+	RK_MUXROUTE_PMU(0, RK_PB5, 4, 0x0110, WRITE_MASK_VAL(3, 2, 1)), /* PWM1 IO mux M1 */
+	RK_MUXROUTE_PMU(0, RK_PC1, 1, 0x0110, WRITE_MASK_VAL(5, 4, 0)), /* PWM2 IO mux M0 */
+	RK_MUXROUTE_PMU(0, RK_PB6, 4, 0x0110, WRITE_MASK_VAL(5, 4, 1)), /* PWM2 IO mux M1 */
+	RK_MUXROUTE_GRF(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PA1, 4, 0x0300, WRITE_MASK_VAL(0, 0, 1)), /* CAN0 IO mux M1 */
+	RK_MUXROUTE_GRF(1, RK_PA1, 3, 0x0300, WRITE_MASK_VAL(2, 2, 0)), /* CAN1 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC3, 3, 0x0300, WRITE_MASK_VAL(2, 2, 1)), /* CAN1 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PB5, 3, 0x0300, WRITE_MASK_VAL(4, 4, 0)), /* CAN2 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PB2, 4, 0x0300, WRITE_MASK_VAL(4, 4, 1)), /* CAN2 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PC4, 1, 0x0300, WRITE_MASK_VAL(6, 6, 0)), /* HPDIN IO mux M0 */
+	RK_MUXROUTE_GRF(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PB1, 3, 0x0300, WRITE_MASK_VAL(8, 8, 0)), /* GMAC1 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PA7, 3, 0x0300, WRITE_MASK_VAL(8, 8, 1)), /* GMAC1 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PD1, 1, 0x0300, WRITE_MASK_VAL(10, 10, 0)), /* HDMITX IO mux M0 */
+	RK_MUXROUTE_GRF(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */
+	RK_MUXROUTE_GRF(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PB4, 1, 0x0300, WRITE_MASK_VAL(14, 14, 1)), /* I2C2 IO mux M1 */
+	RK_MUXROUTE_GRF(1, RK_PA0, 1, 0x0304, WRITE_MASK_VAL(0, 0, 0)), /* I2C3 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PB6, 4, 0x0304, WRITE_MASK_VAL(0, 0, 1)), /* I2C3 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PB2, 1, 0x0304, WRITE_MASK_VAL(2, 2, 0)), /* I2C4 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PB1, 2, 0x0304, WRITE_MASK_VAL(2, 2, 1)), /* I2C4 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PB4, 4, 0x0304, WRITE_MASK_VAL(4, 4, 0)), /* I2C5 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PD0, 2, 0x0304, WRITE_MASK_VAL(4, 4, 1)), /* I2C5 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PB1, 5, 0x0304, WRITE_MASK_VAL(14, 14, 0)), /* PWM8 IO mux M0 */
+	RK_MUXROUTE_GRF(1, RK_PD5, 4, 0x0304, WRITE_MASK_VAL(14, 14, 1)), /* PWM8 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PB2, 5, 0x0308, WRITE_MASK_VAL(0, 0, 0)), /* PWM9 IO mux M0 */
+	RK_MUXROUTE_GRF(1, RK_PD6, 4, 0x0308, WRITE_MASK_VAL(0, 0, 1)), /* PWM9 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PB5, 5, 0x0308, WRITE_MASK_VAL(2, 2, 0)), /* PWM10 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PA1, 2, 0x0308, WRITE_MASK_VAL(2, 2, 1)), /* PWM10 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PB6, 5, 0x0308, WRITE_MASK_VAL(4, 4, 0)), /* PWM11 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC0, 3, 0x0308, WRITE_MASK_VAL(4, 4, 1)), /* PWM11 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PB7, 2, 0x0308, WRITE_MASK_VAL(6, 6, 0)), /* PWM12 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC5, 1, 0x0308, WRITE_MASK_VAL(6, 6, 1)), /* PWM12 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PC0, 2, 0x0308, WRITE_MASK_VAL(8, 8, 0)), /* PWM13 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC6, 1, 0x0308, WRITE_MASK_VAL(8, 8, 1)), /* PWM13 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PC4, 1, 0x0308, WRITE_MASK_VAL(10, 10, 0)), /* PWM14 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC2, 1, 0x0308, WRITE_MASK_VAL(10, 10, 1)), /* PWM14 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PC5, 1, 0x0308, WRITE_MASK_VAL(12, 12, 0)), /* PWM15 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC3, 1, 0x0308, WRITE_MASK_VAL(12, 12, 1)), /* PWM15 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PD2, 3, 0x0308, WRITE_MASK_VAL(14, 14, 0)), /* SDMMC2 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PA5, 5, 0x0308, WRITE_MASK_VAL(14, 14, 1)), /* SDMMC2 IO mux M1 */
+	RK_MUXROUTE_GRF(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PD3, 3, 0x030c, WRITE_MASK_VAL(0, 0, 1)), /* SPI0 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PB5, 3, 0x030c, WRITE_MASK_VAL(2, 2, 0)), /* SPI1 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PC3, 3, 0x030c, WRITE_MASK_VAL(2, 2, 1)), /* SPI1 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PC1, 4, 0x030c, WRITE_MASK_VAL(4, 4, 0)), /* SPI2 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PA0, 3, 0x030c, WRITE_MASK_VAL(4, 4, 1)), /* SPI2 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PB3, 4, 0x030c, WRITE_MASK_VAL(6, 6, 0)), /* SPI3 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC2, 2, 0x030c, WRITE_MASK_VAL(6, 6, 1)), /* SPI3 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PB4, 2, 0x030c, WRITE_MASK_VAL(8, 8, 0)), /* UART1 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PD6, 4, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */
+	RK_MUXROUTE_GRF(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */
+	RK_MUXROUTE_GRF(1, RK_PD5, 2, 0x030c, WRITE_MASK_VAL(10, 10, 1)), /* UART2 IO mux M1 */
+	RK_MUXROUTE_GRF(1, RK_PA1, 2, 0x030c, WRITE_MASK_VAL(12, 12, 0)), /* UART3 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PB7, 4, 0x030c, WRITE_MASK_VAL(12, 12, 1)), /* UART3 IO mux M1 */
+	RK_MUXROUTE_GRF(1, RK_PA6, 2, 0x030c, WRITE_MASK_VAL(14, 14, 0)), /* UART4 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PB2, 4, 0x030c, WRITE_MASK_VAL(14, 14, 1)), /* UART4 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PA2, 3, 0x0310, WRITE_MASK_VAL(0, 0, 0)), /* UART5 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PC2, 4, 0x0310, WRITE_MASK_VAL(0, 0, 1)), /* UART5 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PA4, 3, 0x0310, WRITE_MASK_VAL(2, 2, 0)), /* UART6 IO mux M0 */
+	RK_MUXROUTE_GRF(1, RK_PD5, 3, 0x0310, WRITE_MASK_VAL(2, 2, 1)), /* UART6 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PA6, 3, 0x0310, WRITE_MASK_VAL(5, 4, 0)), /* UART7 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PC4, 4, 0x0310, WRITE_MASK_VAL(5, 4, 1)), /* UART7 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PA2, 4, 0x0310, WRITE_MASK_VAL(5, 4, 2)), /* UART7 IO mux M2 */
+	RK_MUXROUTE_GRF(2, RK_PC5, 3, 0x0310, WRITE_MASK_VAL(6, 6, 0)), /* UART8 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PD7, 4, 0x0310, WRITE_MASK_VAL(6, 6, 1)), /* UART8 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PB0, 3, 0x0310, WRITE_MASK_VAL(9, 8, 0)), /* UART9 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC5, 4, 0x0310, WRITE_MASK_VAL(9, 8, 1)), /* UART9 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PA4, 4, 0x0310, WRITE_MASK_VAL(9, 8, 2)), /* UART9 IO mux M2 */
+	RK_MUXROUTE_GRF(1, RK_PA2, 1, 0x0310, WRITE_MASK_VAL(11, 10, 0)), /* I2S1 IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PC6, 4, 0x0310, WRITE_MASK_VAL(11, 10, 1)), /* I2S1 IO mux M1 */
+	RK_MUXROUTE_GRF(2, RK_PD0, 5, 0x0310, WRITE_MASK_VAL(11, 10, 2)), /* I2S1 IO mux M2 */
+	RK_MUXROUTE_GRF(2, RK_PC1, 1, 0x0310, WRITE_MASK_VAL(12, 12, 0)), /* I2S2 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PB6, 5, 0x0310, WRITE_MASK_VAL(12, 12, 1)), /* I2S2 IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PA2, 4, 0x0310, WRITE_MASK_VAL(14, 14, 0)), /* I2S3 IO mux M0 */
+	RK_MUXROUTE_GRF(4, RK_PC2, 5, 0x0310, WRITE_MASK_VAL(14, 14, 1)), /* I2S3 IO mux M1 */
+	RK_MUXROUTE_GRF(1, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(1, 0, 0)), /* PDM IO mux M0 */
+	RK_MUXROUTE_GRF(1, RK_PA6, 3, 0x0314, WRITE_MASK_VAL(1, 0, 0)), /* PDM IO mux M0 */
+	RK_MUXROUTE_GRF(3, RK_PD6, 5, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PA0, 4, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
+	RK_MUXROUTE_GRF(3, RK_PC4, 5, 0x0314, WRITE_MASK_VAL(1, 0, 2)), /* PDM IO mux M2 */
+	RK_MUXROUTE_GRF(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PD0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 1)), /* PCIE20 IO mux M1 */
+	RK_MUXROUTE_GRF(1, RK_PB0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 2)), /* PCIE20 IO mux M2 */
+	RK_MUXROUTE_GRF(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PD2, 4, 0x0314, WRITE_MASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux M1 */
+	RK_MUXROUTE_GRF(1, RK_PA5, 4, 0x0314, WRITE_MASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux M2 */
+	RK_MUXROUTE_GRF(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */
+	RK_MUXROUTE_GRF(2, RK_PD4, 4, 0x0314, WRITE_MASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux M1 */
+	RK_MUXROUTE_GRF(4, RK_PC2, 4, 0x0314, WRITE_MASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux M2 */
+};
+
+static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
+				   int mux, u32 *loc, u32 *reg, u32 *value)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct rockchip_pin_ctrl *ctrl = info->ctrl;
+	struct rockchip_mux_route_data *data = NULL;
+	int i;
+
+	for (i = 0; i < ctrl->niomux_routes; i++) {
+		data = &ctrl->iomux_routes[i];
+		if ((data->bank_num == bank->bank_num) &&
+		    (data->pin == pin) && (data->func == mux))
+			break;
+	}
+
+	if (i >= ctrl->niomux_routes)
+		return false;
+
+	*loc = data->route_location;
+	*reg = data->route_offset;
+	*value = data->route_val;
+
+	return true;
+}
+
+static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
+			       int pin, int mux)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct device *dev = info->dev;
+	int iomux_num = (pin / 8);
+
+	if (iomux_num > 3)
+		return -EINVAL;
+
+	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
+		dev_err(dev, "pin %d is unrouted\n", pin);
+		return -EINVAL;
+	}
+
+	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
+		if (mux != RK_FUNC_GPIO) {
+			dev_err(dev, "pin %d only supports a gpio mux\n", pin);
+			return -ENOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Set a new mux function for a pin.
+ *
+ * The register is divided into the upper and lower 16 bit. When changing
+ * a value, the previous register value is not read and changed. Instead
+ * it seems the changed bits are marked in the upper 16 bit, while the
+ * changed value gets set in the same offset in the lower 16 bit.
+ * All pin settings seem to be 2 bit wide in both the upper and lower
+ * parts.
+ * @bank: pin bank to change
+ * @pin: pin to change
+ * @mux: new mux function to set
+ */
+static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct rockchip_pin_ctrl *ctrl = info->ctrl;
+	struct device *dev = info->dev;
+	int iomux_num = (pin / 8);
+	struct regmap *regmap;
+	int reg, ret, mask, mux_type;
+	u8 bit;
+	u32 data, rmask, route_location, route_reg, route_val;
+
+	ret = rockchip_verify_mux(bank, pin, mux);
+	if (ret < 0)
+		return ret;
+
+	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
+		return 0;
+
+	dev_dbg(dev, "setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
+
+	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+		regmap = info->regmap_pmu;
+	else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
+		regmap = (pin % 8 < 4) ? info->regmap_pmu : info->regmap_base;
+	else
+		regmap = info->regmap_base;
+
+	/* get basic quadrupel of mux registers and the correct reg inside */
+	mux_type = bank->iomux[iomux_num].type;
+	reg = bank->iomux[iomux_num].offset;
+	if (mux_type & IOMUX_WIDTH_4BIT) {
+		if ((pin % 8) >= 4)
+			reg += 0x4;
+		bit = (pin % 4) * 4;
+		mask = 0xf;
+	} else if (mux_type & IOMUX_WIDTH_3BIT) {
+		if ((pin % 8) >= 5)
+			reg += 0x4;
+		bit = (pin % 8 % 5) * 3;
+		mask = 0x7;
+	} else {
+		bit = (pin % 8) * 2;
+		mask = 0x3;
+	}
+
+	if (bank->recalced_mask & BIT(pin))
+		rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
+
+	if (ctrl->type == RK3588) {
+		if (bank->bank_num == 0) {
+			if ((pin >= RK_PB4) && (pin <= RK_PD7)) {
+				if (mux < 8) {
+					reg += 0x4000 - 0xC; /* PMU2_IOC_BASE */
+					data = (mask << (bit + 16));
+					rmask = data | (data >> 16);
+					data |= (mux & mask) << bit;
+					ret = regmap_update_bits(regmap, reg, rmask, data);
+				} else {
+					u32 reg0 = 0;
+
+					reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */
+					data = (mask << (bit + 16));
+					rmask = data | (data >> 16);
+					data |= 8 << bit;
+					ret = regmap_update_bits(regmap, reg0, rmask, data);
+
+					reg0 = reg + 0x8000; /* BUS_IOC_BASE */
+					data = (mask << (bit + 16));
+					rmask = data | (data >> 16);
+					data |= mux << bit;
+					regmap = info->regmap_base;
+					ret |= regmap_update_bits(regmap, reg0, rmask, data);
+				}
+			} else {
+				data = (mask << (bit + 16));
+				rmask = data | (data >> 16);
+				data |= (mux & mask) << bit;
+				ret = regmap_update_bits(regmap, reg, rmask, data);
+			}
+			return ret;
+		} else if (bank->bank_num > 0) {
+			reg += 0x8000; /* BUS_IOC_BASE */
+		}
+	}
+
+	if (mux > mask)
+		return -EINVAL;
+
+	if (bank->route_mask & BIT(pin)) {
+		if (rockchip_get_mux_route(bank, pin, mux, &route_location,
+					   &route_reg, &route_val)) {
+			struct regmap *route_regmap = regmap;
+
+			/* handle special locations */
+			switch (route_location) {
+			case ROCKCHIP_ROUTE_PMU:
+				route_regmap = info->regmap_pmu;
+				break;
+			case ROCKCHIP_ROUTE_GRF:
+				route_regmap = info->regmap_base;
+				break;
+			}
+
+			ret = regmap_write(route_regmap, route_reg, route_val);
+			if (ret)
+				return ret;
+		}
+	}
+
+	data = (mask << (bit + 16));
+	rmask = data | (data >> 16);
+	data |= (mux & mask) << bit;
+	ret = regmap_update_bits(regmap, reg, rmask, data);
+
+	return ret;
+}
+
+#define PX30_PULL_PMU_OFFSET		0x10
+#define PX30_PULL_GRF_OFFSET		0x60
+#define PX30_PULL_BITS_PER_PIN		2
+#define PX30_PULL_PINS_PER_REG		8
+#define PX30_PULL_BANK_STRIDE		16
+
+static int px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+				      int pin_num, struct regmap **regmap,
+				      int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = PX30_PULL_PMU_OFFSET;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = PX30_PULL_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * PX30_PULL_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / PX30_PULL_PINS_PER_REG) * 4);
+	*bit = (pin_num % PX30_PULL_PINS_PER_REG);
+	*bit *= PX30_PULL_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define PX30_DRV_PMU_OFFSET		0x20
+#define PX30_DRV_GRF_OFFSET		0xf0
+#define PX30_DRV_BITS_PER_PIN		2
+#define PX30_DRV_PINS_PER_REG		8
+#define PX30_DRV_BANK_STRIDE		16
+
+static int px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				     int pin_num, struct regmap **regmap,
+				     int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = PX30_DRV_PMU_OFFSET;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = PX30_DRV_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * PX30_DRV_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / PX30_DRV_PINS_PER_REG) * 4);
+	*bit = (pin_num % PX30_DRV_PINS_PER_REG);
+	*bit *= PX30_DRV_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define PX30_SCHMITT_PMU_OFFSET			0x38
+#define PX30_SCHMITT_GRF_OFFSET			0xc0
+#define PX30_SCHMITT_PINS_PER_PMU_REG		16
+#define PX30_SCHMITT_BANK_STRIDE		16
+#define PX30_SCHMITT_PINS_PER_GRF_REG		8
+
+static int px30_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					 int pin_num,
+					 struct regmap **regmap,
+					 int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	int pins_per_reg;
+
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = PX30_SCHMITT_PMU_OFFSET;
+		pins_per_reg = PX30_SCHMITT_PINS_PER_PMU_REG;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = PX30_SCHMITT_GRF_OFFSET;
+		pins_per_reg = PX30_SCHMITT_PINS_PER_GRF_REG;
+		*reg += (bank->bank_num  - 1) * PX30_SCHMITT_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / pins_per_reg) * 4);
+	*bit = pin_num % pins_per_reg;
+
+	return 0;
+}
+
+#define RV1108_PULL_PMU_OFFSET		0x10
+#define RV1108_PULL_OFFSET		0x110
+#define RV1108_PULL_PINS_PER_REG	8
+#define RV1108_PULL_BITS_PER_PIN	2
+#define RV1108_PULL_BANK_STRIDE		16
+
+static int rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RV1108_PULL_PMU_OFFSET;
+	} else {
+		*reg = RV1108_PULL_OFFSET;
+		*regmap = info->regmap_base;
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RV1108_PULL_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / RV1108_PULL_PINS_PER_REG) * 4);
+	*bit = (pin_num % RV1108_PULL_PINS_PER_REG);
+	*bit *= RV1108_PULL_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RV1108_DRV_PMU_OFFSET		0x20
+#define RV1108_DRV_GRF_OFFSET		0x210
+#define RV1108_DRV_BITS_PER_PIN		2
+#define RV1108_DRV_PINS_PER_REG		8
+#define RV1108_DRV_BANK_STRIDE		16
+
+static int rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RV1108_DRV_PMU_OFFSET;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RV1108_DRV_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RV1108_DRV_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / RV1108_DRV_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1108_DRV_PINS_PER_REG;
+	*bit *= RV1108_DRV_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RV1108_SCHMITT_PMU_OFFSET		0x30
+#define RV1108_SCHMITT_GRF_OFFSET		0x388
+#define RV1108_SCHMITT_BANK_STRIDE		8
+#define RV1108_SCHMITT_PINS_PER_GRF_REG		16
+#define RV1108_SCHMITT_PINS_PER_PMU_REG		8
+
+static int rv1108_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num,
+					   struct regmap **regmap,
+					   int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	int pins_per_reg;
+
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RV1108_SCHMITT_PMU_OFFSET;
+		pins_per_reg = RV1108_SCHMITT_PINS_PER_PMU_REG;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RV1108_SCHMITT_GRF_OFFSET;
+		pins_per_reg = RV1108_SCHMITT_PINS_PER_GRF_REG;
+		*reg += (bank->bank_num  - 1) * RV1108_SCHMITT_BANK_STRIDE;
+	}
+	*reg += ((pin_num / pins_per_reg) * 4);
+	*bit = pin_num % pins_per_reg;
+
+	return 0;
+}
+
+#define RV1126_PULL_PMU_OFFSET		0x40
+#define RV1126_PULL_GRF_GPIO1A0_OFFSET	0x10108
+#define RV1126_PULL_PINS_PER_REG	8
+#define RV1126_PULL_BITS_PER_PIN	2
+#define RV1126_PULL_BANK_STRIDE		16
+#define RV1126_GPIO_C4_D7(p)		(p >= 20 && p <= 31) /* GPIO0_C4 ~ GPIO0_D7 */
+
+static int rv1126_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		if (RV1126_GPIO_C4_D7(pin_num)) {
+			*regmap = info->regmap_base;
+			*reg = RV1126_PULL_GRF_GPIO1A0_OFFSET;
+			*reg -= (((31 - pin_num) / RV1126_PULL_PINS_PER_REG + 1) * 4);
+			*bit = pin_num % RV1126_PULL_PINS_PER_REG;
+			*bit *= RV1126_PULL_BITS_PER_PIN;
+			return 0;
+		}
+		*regmap = info->regmap_pmu;
+		*reg = RV1126_PULL_PMU_OFFSET;
+	} else {
+		*reg = RV1126_PULL_GRF_GPIO1A0_OFFSET;
+		*regmap = info->regmap_base;
+		*reg += (bank->bank_num - 1) * RV1126_PULL_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / RV1126_PULL_PINS_PER_REG) * 4);
+	*bit = (pin_num % RV1126_PULL_PINS_PER_REG);
+	*bit *= RV1126_PULL_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RV1126_DRV_PMU_OFFSET		0x20
+#define RV1126_DRV_GRF_GPIO1A0_OFFSET	0x10090
+#define RV1126_DRV_BITS_PER_PIN		4
+#define RV1126_DRV_PINS_PER_REG		4
+#define RV1126_DRV_BANK_STRIDE		32
+
+static int rv1126_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		if (RV1126_GPIO_C4_D7(pin_num)) {
+			*regmap = info->regmap_base;
+			*reg = RV1126_DRV_GRF_GPIO1A0_OFFSET;
+			*reg -= (((31 - pin_num) / RV1126_DRV_PINS_PER_REG + 1) * 4);
+			*reg -= 0x4;
+			*bit = pin_num % RV1126_DRV_PINS_PER_REG;
+			*bit *= RV1126_DRV_BITS_PER_PIN;
+			return 0;
+		}
+		*regmap = info->regmap_pmu;
+		*reg = RV1126_DRV_PMU_OFFSET;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RV1126_DRV_GRF_GPIO1A0_OFFSET;
+		*reg += (bank->bank_num - 1) * RV1126_DRV_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / RV1126_DRV_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1126_DRV_PINS_PER_REG;
+	*bit *= RV1126_DRV_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RV1126_SCHMITT_PMU_OFFSET		0x60
+#define RV1126_SCHMITT_GRF_GPIO1A0_OFFSET	0x10188
+#define RV1126_SCHMITT_BANK_STRIDE		16
+#define RV1126_SCHMITT_PINS_PER_GRF_REG		8
+#define RV1126_SCHMITT_PINS_PER_PMU_REG		8
+
+static int rv1126_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num,
+					   struct regmap **regmap,
+					   int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	int pins_per_reg;
+
+	if (bank->bank_num == 0) {
+		if (RV1126_GPIO_C4_D7(pin_num)) {
+			*regmap = info->regmap_base;
+			*reg = RV1126_SCHMITT_GRF_GPIO1A0_OFFSET;
+			*reg -= (((31 - pin_num) / RV1126_SCHMITT_PINS_PER_GRF_REG + 1) * 4);
+			*bit = pin_num % RV1126_SCHMITT_PINS_PER_GRF_REG;
+			return 0;
+		}
+		*regmap = info->regmap_pmu;
+		*reg = RV1126_SCHMITT_PMU_OFFSET;
+		pins_per_reg = RV1126_SCHMITT_PINS_PER_PMU_REG;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RV1126_SCHMITT_GRF_GPIO1A0_OFFSET;
+		pins_per_reg = RV1126_SCHMITT_PINS_PER_GRF_REG;
+		*reg += (bank->bank_num - 1) * RV1126_SCHMITT_BANK_STRIDE;
+	}
+	*reg += ((pin_num / pins_per_reg) * 4);
+	*bit = pin_num % pins_per_reg;
+
+	return 0;
+}
+
+#define RK3308_SCHMITT_PINS_PER_REG		8
+#define RK3308_SCHMITT_BANK_STRIDE		16
+#define RK3308_SCHMITT_GRF_OFFSET		0x1a0
+
+static int rk3308_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	*regmap = info->regmap_base;
+	*reg = RK3308_SCHMITT_GRF_OFFSET;
+
+	*reg += bank->bank_num * RK3308_SCHMITT_BANK_STRIDE;
+	*reg += ((pin_num / RK3308_SCHMITT_PINS_PER_REG) * 4);
+	*bit = pin_num % RK3308_SCHMITT_PINS_PER_REG;
+
+	return 0;
+}
+
+#define RK2928_PULL_OFFSET		0x118
+#define RK2928_PULL_PINS_PER_REG	16
+#define RK2928_PULL_BANK_STRIDE		8
+
+static int rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	*regmap = info->regmap_base;
+	*reg = RK2928_PULL_OFFSET;
+	*reg += bank->bank_num * RK2928_PULL_BANK_STRIDE;
+	*reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4;
+
+	*bit = pin_num % RK2928_PULL_PINS_PER_REG;
+
+	return 0;
+};
+
+#define RK3128_PULL_OFFSET	0x118
+
+static int rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	*regmap = info->regmap_base;
+	*reg = RK3128_PULL_OFFSET;
+	*reg += bank->bank_num * RK2928_PULL_BANK_STRIDE;
+	*reg += ((pin_num / RK2928_PULL_PINS_PER_REG) * 4);
+
+	*bit = pin_num % RK2928_PULL_PINS_PER_REG;
+
+	return 0;
+}
+
+#define RK3188_PULL_OFFSET		0x164
+#define RK3188_PULL_BITS_PER_PIN	2
+#define RK3188_PULL_PINS_PER_REG	8
+#define RK3188_PULL_BANK_STRIDE		16
+#define RK3188_PULL_PMU_OFFSET		0x64
+
+static int rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 12 pins of the first bank are located elsewhere */
+	if (bank->bank_num == 0 && pin_num < 12) {
+		*regmap = info->regmap_pmu ? info->regmap_pmu
+					   : bank->regmap_pull;
+		*reg = info->regmap_pmu ? RK3188_PULL_PMU_OFFSET : 0;
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_pull ? info->regmap_pull
+					    : info->regmap_base;
+		*reg = info->regmap_pull ? 0 : RK3188_PULL_OFFSET;
+
+		/* correct the offset, as it is the 2nd pull register */
+		*reg -= 4;
+		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+		/*
+		 * The bits in these registers have an inverse ordering
+		 * with the lowest pin being in bits 15:14 and the highest
+		 * pin in bits 1:0
+		 */
+		*bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG);
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	}
+
+	return 0;
+}
+
+#define RK3288_PULL_OFFSET		0x140
+static int rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3188_PULL_PMU_OFFSET;
+
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3288_PULL_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	}
+
+	return 0;
+}
+
+#define RK3288_DRV_PMU_OFFSET		0x70
+#define RK3288_DRV_GRF_OFFSET		0x1c0
+#define RK3288_DRV_BITS_PER_PIN		2
+#define RK3288_DRV_PINS_PER_REG		8
+#define RK3288_DRV_BANK_STRIDE		16
+
+static int rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3288_DRV_PMU_OFFSET;
+
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3288_DRV_PINS_PER_REG;
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3288_DRV_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	}
+
+	return 0;
+}
+
+#define RK3228_PULL_OFFSET		0x100
+
+static int rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	*regmap = info->regmap_base;
+	*reg = RK3228_PULL_OFFSET;
+	*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+	*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+	*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+	*bit *= RK3188_PULL_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RK3228_DRV_GRF_OFFSET		0x200
+
+static int rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	*regmap = info->regmap_base;
+	*reg = RK3228_DRV_GRF_OFFSET;
+	*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+	*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+	*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+	*bit *= RK3288_DRV_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RK3308_PULL_OFFSET		0xa0
+
+static int rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	*regmap = info->regmap_base;
+	*reg = RK3308_PULL_OFFSET;
+	*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+	*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+	*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+	*bit *= RK3188_PULL_BITS_PER_PIN;
+
+	return 0;
 }
 
-static struct rockchip_pin_bank *bank_num_to_bank(struct rockchip_pinctrl *info,
-						  unsigned num)
+#define RK3308_DRV_GRF_OFFSET		0x100
+
+static int rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
 {
-	struct rockchip_pin_bank *b = info->ctrl->pin_banks;
-	int i;
+	struct rockchip_pinctrl *info = bank->drvdata;
 
-	for (i = 0; i < info->ctrl->nr_banks; i++, b++) {
-		if (b->bank_num == num)
-			return b;
-	}
+	*regmap = info->regmap_base;
+	*reg = RK3308_DRV_GRF_OFFSET;
+	*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+	*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
 
-	return ERR_PTR(-EINVAL);
+	*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+	*bit *= RK3288_DRV_BITS_PER_PIN;
+
+	return 0;
 }
 
-static int parse_bias_config(struct device_node *np)
+#define RK3368_PULL_GRF_OFFSET		0x100
+#define RK3368_PULL_PMU_OFFSET		0x10
+
+static int rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
 {
-	u32 val;
+	struct rockchip_pinctrl *info = bank->drvdata;
 
-	if (of_property_read_u32(np, "bias-pull-up", &val) != -EINVAL)
-		return RK_BIAS_PULL_UP;
-	else if (of_property_read_u32(np, "bias-pull-down", &val) != -EINVAL)
-		return RK_BIAS_PULL_DOWN;
-	else if (of_property_read_u32(np, "bias-bus-hold", &val) != -EINVAL)
-		return RK_BIAS_BUS_HOLD;
-	else
-		return RK_BIAS_DISABLE;
-}
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3368_PULL_PMU_OFFSET;
 
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3368_PULL_GRF_OFFSET;
 
-#define RK2928_PULL_OFFSET		0x118
-#define RK2928_PULL_PINS_PER_REG	16
-#define RK2928_PULL_BANK_STRIDE		8
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	}
+
+	return 0;
+}
+
+#define RK3368_DRV_PMU_OFFSET		0x20
+#define RK3368_DRV_GRF_OFFSET		0x200
 
-static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
-					 int pin_num, void __iomem **reg,
-					 u8 *bit)
+static int rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 
-	*reg = info->reg_base + RK2928_PULL_OFFSET;
-	*reg += bank->bank_num * RK2928_PULL_BANK_STRIDE;
-	*reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4;
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3368_DRV_PMU_OFFSET;
 
-	*bit = pin_num % RK2928_PULL_PINS_PER_REG;
-};
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3288_DRV_PINS_PER_REG;
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3368_DRV_GRF_OFFSET;
 
-#define RK3188_PULL_OFFSET		0x164
-#define RK3188_PULL_BITS_PER_PIN	2
-#define RK3188_PULL_PINS_PER_REG	8
-#define RK3188_PULL_BANK_STRIDE		16
-#define RK3188_PULL_PMU_OFFSET		0x64
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	}
+
+	return 0;
+}
+
+#define RK3399_PULL_GRF_OFFSET		0xe040
+#define RK3399_PULL_PMU_OFFSET		0x40
+#define RK3399_DRV_3BITS_PER_PIN	3
 
-static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
-					 int pin_num, void __iomem **reg,
-					 u8 *bit)
+static int rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 
-	/* The first 12 pins of the first bank are located elsewhere */
-	if (bank->bank_type == RK3188_BANK0 && pin_num < 12) {
-		*reg = info->reg_pmu + RK3188_PULL_PMU_OFFSET +
-				((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+	/* The bank0:16 and bank1:32 pins are located in PMU */
+	if ((bank->bank_num == 0) || (bank->bank_num == 1)) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3399_PULL_PMU_OFFSET;
+
+		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
 		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
 		*bit *= RK3188_PULL_BITS_PER_PIN;
 	} else {
-		*reg = info->reg_base + RK3188_PULL_OFFSET - 4;
+		*regmap = info->regmap_base;
+		*reg = RK3399_PULL_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 3rd bank */
+		*reg -= 0x20;
 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
 
-		/*
-		 * The bits in these registers have an inverse ordering
-		 * with the lowest pin being in bits 15:14 and the highest
-		 * pin in bits 1:0
-		 */
-		*bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG);
+		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
 		*bit *= RK3188_PULL_BITS_PER_PIN;
 	}
+
+	return 0;
+}
+
+static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	int drv_num = (pin_num / 8);
+
+	/*  The bank0:16 and bank1:32 pins are located in PMU */
+	if ((bank->bank_num == 0) || (bank->bank_num == 1))
+		*regmap = info->regmap_pmu;
+	else
+		*regmap = info->regmap_base;
+
+	*reg = bank->drv[drv_num].offset;
+	if ((bank->drv[drv_num].drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
+	    (bank->drv[drv_num].drv_type == DRV_TYPE_IO_3V3_ONLY))
+		*bit = (pin_num % 8) * 3;
+	else
+		*bit = (pin_num % 8) * 2;
+
+	return 0;
 }
 
 #define RK3568_PULL_PMU_OFFSET		0x20
@@ -180,27 +1741,31 @@ static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
 #define RK3568_PULL_PINS_PER_REG	8
 #define RK3568_PULL_BANK_STRIDE		0x10
 
-static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
-					 int pin_num, void __iomem **reg,
-					 u8 *bit)
+static int rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 
 	if (bank->bank_num == 0) {
-		*reg = info->reg_pmu + RK3568_PULL_PMU_OFFSET;
+		*regmap = info->regmap_pmu;
+		*reg = RK3568_PULL_PMU_OFFSET;
 		*reg += bank->bank_num * RK3568_PULL_BANK_STRIDE;
 		*reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
 
 		*bit = pin_num % RK3568_PULL_PINS_PER_REG;
 		*bit *= RK3568_PULL_BITS_PER_PIN;
 	} else {
-		*reg = info->reg_base + RK3568_PULL_GRF_OFFSET;
+		*regmap = info->regmap_base;
+		*reg = RK3568_PULL_GRF_OFFSET;
 		*reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE;
 		*reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
 
 		*bit = (pin_num % RK3568_PULL_PINS_PER_REG);
 		*bit *= RK3568_PULL_BITS_PER_PIN;
 	}
+
+	return 0;
 }
 
 #define RK3568_DRV_PMU_OFFSET		0x70
@@ -209,168 +1774,212 @@ static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
 #define RK3568_DRV_PINS_PER_REG		2
 #define RK3568_DRV_BANK_STRIDE		0x40
 
-static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
-					int pin_num, void __iomem **reg, u8 *bit)
+static int rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 
 	/* The first 32 pins of the first bank are located in PMU */
 	if (bank->bank_num == 0) {
-		*reg = info->reg_pmu + RK3568_DRV_PMU_OFFSET;
+		*regmap = info->regmap_pmu;
+		*reg = RK3568_DRV_PMU_OFFSET;
 		*reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
 
 		*bit = pin_num % RK3568_DRV_PINS_PER_REG;
 		*bit *= RK3568_DRV_BITS_PER_PIN;
 	} else {
-		*reg = info->reg_base + RK3568_DRV_GRF_OFFSET;
+		*regmap = info->regmap_base;
+		*reg = RK3568_DRV_GRF_OFFSET;
 		*reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE;
 		*reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
 
 		*bit = (pin_num % RK3568_DRV_PINS_PER_REG);
 		*bit *= RK3568_DRV_BITS_PER_PIN;
 	}
+
+	return 0;
 }
 
-static struct rockchip_mux_route_data rk3188_mux_route_data[] = {
-	RK_MUXROUTE_SAME(0, RK_PD0, 1, 0xa0, BIT(16 + 11)), /* non-iomuxed emmc/flash pins on flash-dqs */
-	RK_MUXROUTE_SAME(0, RK_PD0, 2, 0xa0, BIT(16 + 11) | BIT(11)), /* non-iomuxed emmc/flash pins on emmc-clk */
+#define RK3588_PMU1_IOC_REG		(0x0000)
+#define RK3588_PMU2_IOC_REG		(0x4000)
+#define RK3588_BUS_IOC_REG		(0x8000)
+#define RK3588_VCCIO1_4_IOC_REG		(0x9000)
+#define RK3588_VCCIO3_5_IOC_REG		(0xA000)
+#define RK3588_VCCIO2_IOC_REG		(0xB000)
+#define RK3588_VCCIO6_IOC_REG		(0xC000)
+#define RK3588_EMMC_IOC_REG		(0xD000)
+
+static const u32 rk3588_ds_regs[][2] = {
+	{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0010},
+	{RK_GPIO0_A4, RK3588_PMU1_IOC_REG + 0x0014},
+	{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0018},
+	{RK_GPIO0_B4, RK3588_PMU2_IOC_REG + 0x0014},
+	{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0018},
+	{RK_GPIO0_C4, RK3588_PMU2_IOC_REG + 0x001C},
+	{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0020},
+	{RK_GPIO0_D4, RK3588_PMU2_IOC_REG + 0x0024},
+	{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0020},
+	{RK_GPIO1_A4, RK3588_VCCIO1_4_IOC_REG + 0x0024},
+	{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0028},
+	{RK_GPIO1_B4, RK3588_VCCIO1_4_IOC_REG + 0x002C},
+	{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0030},
+	{RK_GPIO1_C4, RK3588_VCCIO1_4_IOC_REG + 0x0034},
+	{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x0038},
+	{RK_GPIO1_D4, RK3588_VCCIO1_4_IOC_REG + 0x003C},
+	{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0040},
+	{RK_GPIO2_A4, RK3588_VCCIO3_5_IOC_REG + 0x0044},
+	{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0048},
+	{RK_GPIO2_B4, RK3588_VCCIO3_5_IOC_REG + 0x004C},
+	{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0050},
+	{RK_GPIO2_C4, RK3588_VCCIO3_5_IOC_REG + 0x0054},
+	{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x0058},
+	{RK_GPIO2_D4, RK3588_EMMC_IOC_REG + 0x005C},
+	{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0060},
+	{RK_GPIO3_A4, RK3588_VCCIO3_5_IOC_REG + 0x0064},
+	{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0068},
+	{RK_GPIO3_B4, RK3588_VCCIO3_5_IOC_REG + 0x006C},
+	{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0070},
+	{RK_GPIO3_C4, RK3588_VCCIO3_5_IOC_REG + 0x0074},
+	{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x0078},
+	{RK_GPIO3_D4, RK3588_VCCIO3_5_IOC_REG + 0x007C},
+	{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0080},
+	{RK_GPIO4_A4, RK3588_VCCIO6_IOC_REG + 0x0084},
+	{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0088},
+	{RK_GPIO4_B4, RK3588_VCCIO6_IOC_REG + 0x008C},
+	{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0090},
+	{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0090},
+	{RK_GPIO4_C4, RK3588_VCCIO3_5_IOC_REG + 0x0094},
+	{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x0098},
+	{RK_GPIO4_D4, RK3588_VCCIO2_IOC_REG + 0x009C},
 };
 
-static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
-				   int mux, u32 *loc, u32 *reg, u32 *value)
+static const u32 rk3588_p_regs[][2] = {
+	{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0020},
+	{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0024},
+	{RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0028},
+	{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x002C},
+	{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0030},
+	{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0110},
+	{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0114},
+	{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0118},
+	{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x011C},
+	{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0120},
+	{RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0120},
+	{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0124},
+	{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0128},
+	{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x012C},
+	{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0130},
+	{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0134},
+	{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0138},
+	{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x013C},
+	{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0140},
+	{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0144},
+	{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0148},
+	{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0148},
+	{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x014C},
+};
+
+static const u32 rk3588_smt_regs[][2] = {
+	{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0030},
+	{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0034},
+	{RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0040},
+	{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0044},
+	{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0048},
+	{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0210},
+	{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0214},
+	{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0218},
+	{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x021C},
+	{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0220},
+	{RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0220},
+	{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0224},
+	{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0228},
+	{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x022C},
+	{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0230},
+	{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0234},
+	{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0238},
+	{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x023C},
+	{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0240},
+	{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0244},
+	{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0248},
+	{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0248},
+	{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x024C},
+};
+
+#define RK3588_PULL_BITS_PER_PIN		2
+#define RK3588_PULL_PINS_PER_REG		8
+
+static int rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
-	struct rockchip_pin_ctrl *ctrl = info->ctrl;
-	struct rockchip_mux_route_data *data = NULL;
+	u8 bank_num = bank->bank_num;
+	u32 pin = bank_num * 32 + pin_num;
 	int i;
 
-	for (i = 0; i < ctrl->niomux_routes; i++) {
-		data = &ctrl->iomux_routes[i];
-		if ((data->bank_num == bank->bank_num) &&
-		    (data->pin == pin) && (data->func == mux))
-			break;
+	for (i = ARRAY_SIZE(rk3588_p_regs) - 1; i >= 0; i--) {
+		if (pin >= rk3588_p_regs[i][0]) {
+			*reg = rk3588_p_regs[i][1];
+			*regmap = info->regmap_base;
+			*bit = pin_num % RK3588_PULL_PINS_PER_REG;
+			*bit *= RK3588_PULL_BITS_PER_PIN;
+			return 0;
+		}
 	}
 
-	if (i >= ctrl->niomux_routes)
-		return false;
-
-	*loc = data->route_location;
-	*reg = data->route_offset;
-	*value = data->route_val;
-
-	return true;
+	return -EINVAL;
 }
 
-static int rockchip_pinctrl_set_func(struct rockchip_pin_bank *bank, int pin,
-				     int mux)
+#define RK3588_DRV_BITS_PER_PIN		4
+#define RK3588_DRV_PINS_PER_REG		4
+
+static int rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
-	void __iomem *base, *reg;
-	u8 bit;
-	u32 data, route_location, route_reg, route_val;
-	int iomux_num = (pin / 8);
-	int mux_type;
-	int mask;
-
-	base = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
-				? info->reg_pmu : info->reg_base;
-
-	/* get basic quadrupel of mux registers and the correct reg inside */
-	mux_type = bank->iomux[iomux_num].type;
-	reg = base + bank->iomux[iomux_num].offset;
-
-	dev_dbg(info->pctl_dev.dev, "setting func of GPIO%d-%d to %d\n",
-		 bank->bank_num, pin, mux);
-
-	if (mux_type & IOMUX_WIDTH_4BIT) {
-		if ((pin % 8) >= 4)
-			reg += 0x4;
-		bit = (pin % 4) * 4;
-		mask = 0xf;
-	} else if (mux_type & IOMUX_WIDTH_3BIT) {
-		if ((pin % 8) >= 5)
-			reg += 0x4;
-		bit = (pin % 8 % 5) * 3;
-		mask = 0x7;
-	} else {
-		bit = (pin % 8) * 2;
-		mask = 0x3;
-	}
-
-	if (bank->route_mask & BIT(pin)) {
-		if (rockchip_get_mux_route(bank, pin, mux, &route_location,
-					   &route_reg, &route_val)) {
-			void __iomem  *route = base;
-
-			/* handle special locations */
-			switch (route_location) {
-			case ROCKCHIP_ROUTE_PMU:
-				route = info->reg_pmu;
-				break;
-			case ROCKCHIP_ROUTE_GRF:
-				route = info->reg_base;
-				break;
-			}
+	u8 bank_num = bank->bank_num;
+	u32 pin = bank_num * 32 + pin_num;
+	int i;
 
-			writel(route_val, route + route_reg);
+	for (i = ARRAY_SIZE(rk3588_ds_regs) - 1; i >= 0; i--) {
+		if (pin >= rk3588_ds_regs[i][0]) {
+			*reg = rk3588_ds_regs[i][1];
+			*regmap = info->regmap_base;
+			*bit = pin_num % RK3588_DRV_PINS_PER_REG;
+			*bit *= RK3588_DRV_BITS_PER_PIN;
+			return 0;
 		}
 	}
 
-	data = 3 << (bit + 16);
-	data |= (mux & 3) << bit;
-	writel(data, reg);
-
-	return 0;
+	return -EINVAL;
 }
 
-static int rockchip_pinctrl_set_pull(struct rockchip_pin_bank *bank,
-				     int pin_num, int pull)
+#define RK3588_SMT_BITS_PER_PIN		1
+#define RK3588_SMT_PINS_PER_REG		8
+
+static int rk3588_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num,
+					   struct regmap **regmap,
+					   int *reg, u8 *bit)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
-	struct rockchip_pin_ctrl *ctrl = info->ctrl;
-	void __iomem *reg;
-	u8 bit;
-	u32 data;
-
-	dev_dbg(info->pctl_dev.dev, "setting pull of GPIO%d-%d to %d\n",
-		 bank->bank_num, pin_num, pull);
-
-	/* rk3066b doesn't support any pulls */
-	if (ctrl->type == RK3066B)
-		return pull ? -EINVAL : 0;
-
-	ctrl->pull_calc_reg(bank, pin_num, &reg, &bit);
-
-	switch (ctrl->type) {
-	case RK2928:
-		data = BIT(bit + 16);
-		if (pull == RK_BIAS_DISABLE)
-			data |= BIT(bit);
-		writel(data, reg);
-		break;
-	case RK3188:
-	case RK3568:
-		/*
-		 * In the TRM, pull-up being 1 for everything except the GPIO0_D0-D6,
-		 * where that pull up value becomes 3.
-		 */
-		if (ctrl->type == RK3568 &&
-		    bank->bank_num == 0 &&
-		    pin_num >= 27 &&
-		    pin_num <= 30 &&
-		    pull == RK_BIAS_PULL_UP)
-			pull = 3;
+	u8 bank_num = bank->bank_num;
+	u32 pin = bank_num * 32 + pin_num;
+	int i;
 
-		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
-		data |= pull << bit;
-		writel(data, reg);
-		break;
-	default:
-		dev_err(info->pctl_dev.dev, "unsupported pinctrl type\n");
-		return -EINVAL;
+	for (i = ARRAY_SIZE(rk3588_smt_regs) - 1; i >= 0; i--) {
+		if (pin >= rk3588_smt_regs[i][0]) {
+			*reg = rk3588_smt_regs[i][1];
+			*regmap = info->regmap_base;
+			*bit = pin_num % RK3588_SMT_PINS_PER_REG;
+			*bit *= RK3588_SMT_BITS_PER_PIN;
+			return 0;
+		}
 	}
 
-	return 0;
+	return -EINVAL;
 }
 
 static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = {
@@ -381,33 +1990,40 @@ static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = {
 	{ 4, 7, 10, 13, 16, 19, 22, 26 }
 };
 
-#define RK3288_DRV_BITS_PER_PIN		2
-#define RK3399_DRV_3BITS_PER_PIN	3
-
 static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 				     int pin_num, int strength)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
-	int ret, i;
-	void __iomem *reg;
-	u32 data, rmask, rmask_bits, temp, val;
+	struct device *dev = info->dev;
+	struct regmap *regmap;
+	int reg, ret, i;
+	u32 data, rmask, rmask_bits, temp;
 	u8 bit;
 	int drv_type = bank->drv[pin_num / 8].drv_type;
 
-	if (!ctrl->drv_calc_reg)
-		return -ENOTSUPP;
-
-	dev_dbg(info->pctl_dev.dev, "setting drive of GPIO%d-%d to %d\n",
+	dev_dbg(dev, "setting drive of GPIO%d-%d to %d\n",
 		bank->bank_num, pin_num, strength);
 
-	ctrl->drv_calc_reg(bank, pin_num, &reg, &bit);
-	if (ctrl->type == RK3568) {
+	ret = ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
+	if (ret)
+		return ret;
+	if (ctrl->type == RK3588) {
+		rmask_bits = RK3588_DRV_BITS_PER_PIN;
+		ret = strength;
+		goto config;
+	} else if (ctrl->type == RK3568) {
 		rmask_bits = RK3568_DRV_BITS_PER_PIN;
 		ret = (1 << (strength + 1)) - 1;
 		goto config;
 	}
 
+	if (ctrl->type == RV1126) {
+		rmask_bits = RV1126_DRV_BITS_PER_PIN;
+		ret = strength;
+		goto config;
+	}
+
 	ret = -EINVAL;
 	for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[drv_type]); i++) {
 		if (rockchip_perpin_drv_list[drv_type][i] == strength) {
@@ -420,8 +2036,7 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 	}
 
 	if (ret < 0) {
-		dev_err(info->pctl_dev.dev, "unsupported driver strength %d\n",
-			strength);
+		dev_err(dev, "unsupported driver strength %d\n", strength);
 		return ret;
 	}
 
@@ -444,20 +2059,14 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 
 			rmask = BIT(15) | BIT(31);
 			data |= BIT(31);
-
-			val = readl(reg);
-			val &= ~rmask;
-			val |= data & rmask;
-			writel(val, reg);
+			ret = regmap_update_bits(regmap, reg, rmask, data);
+			if (ret)
+				return ret;
 
 			rmask = 0x3 | (0x3 << 16);
 			temp |= (0x3 << 16);
 			reg += 0x4;
-
-			val = readl(reg);
-			val &= ~rmask;
-			val |= temp & rmask;
-			writel(val, reg);
+			ret = regmap_update_bits(regmap, reg, rmask, temp);
 
 			return ret;
 		case 18 ... 21:
@@ -466,7 +2075,7 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 			bit -= 16;
 			break;
 		default:
-			dev_err(info->pctl_dev.dev, "unsupported bit: %d for pinctrl drive type: %d\n",
+			dev_err(dev, "unsupported bit: %d for pinctrl drive type: %d\n",
 				bit, drv_type);
 			return -EINVAL;
 		}
@@ -477,8 +2086,7 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 		rmask_bits = RK3288_DRV_BITS_PER_PIN;
 		break;
 	default:
-		dev_err(info->pctl_dev.dev, "unsupported pinctrl drive type: %d\n",
-			drv_type);
+		dev_err(dev, "unsupported pinctrl drive type: %d\n", drv_type);
 		return -EINVAL;
 	}
 
@@ -488,136 +2096,145 @@ config:
 	rmask = data | (data >> 16);
 	data |= (ret << bit);
 
-	val = readl(reg);
-	val &= ~rmask;
-	val |= data & rmask;
-	writel(val, reg);
+	ret = regmap_update_bits(regmap, reg, rmask, data);
 
 	return ret;
 }
 
-static int rockchip_pinctrl_set_state(struct pinctrl_device *pdev,
-				      struct device_node *np)
+static int rockchip_set_pull(struct rockchip_pin_bank *bank,
+					int pin_num, int pull)
 {
-	struct rockchip_pinctrl *info = to_rockchip_pinctrl(pdev);
-	const __be32 *list;
-	int i, size, ret;
-	int bank_num, pin_num, func;
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct rockchip_pin_ctrl *ctrl = info->ctrl;
+	struct device *dev = info->dev;
+	struct regmap *regmap;
+	int reg, ret;
+	u8 bit;
+	u32 data, rmask;
 
-	/*
-	 * the binding format is rockchip,pins = <bank pin mux CONFIG>,
-	 * do sanity check and calculate pins number
-	 */
-	list = of_get_property(np, "rockchip,pins", &size);
-	size /= sizeof(*list);
+	dev_dbg(dev, "setting pull of GPIO%d-%d to %d\n", bank->bank_num, pin_num, pull);
 
-	if (!size || size % 4) {
-		dev_err(pdev->dev, "wrong pins number or pins and configs should be by 4\n");
+	/* rk3066b does support any pulls */
+	if (ctrl->type == RK3066B)
+		return pull ? -EINVAL : 0;
+
+	ret = ctrl->pull_calc_reg(bank, pin_num, &regmap, &reg, &bit);
+	if (ret)
+		return ret;
+
+	switch (ctrl->type) {
+	case RK2928:
+	case RK3128:
+		data = BIT(bit + 16);
+		if (pull == RK_BIAS_DISABLE)
+			data |= BIT(bit);
+		ret = regmap_write(regmap, reg, data);
+		break;
+	case PX30:
+	case RV1108:
+	case RV1126:
+	case RK3188:
+	case RK3288:
+	case RK3308:
+	case RK3368:
+	case RK3399:
+	case RK3568:
+	case RK3588:
+		/*
+		 * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
+		 * where that pull up value becomes 3.
+		 */
+		if (ctrl->type == RK3568 && bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
+			if (pull == RK_BIAS_PULL_UP)
+				pull = 3;
+		}
+
+		/* enable the write to the equivalent lower bits */
+		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+		rmask = data | (data >> 16);
+		data |= (pull << bit);
+
+		ret = regmap_update_bits(regmap, reg, rmask, data);
+		break;
+	default:
+		dev_err(dev, "unsupported pinctrl type\n");
 		return -EINVAL;
 	}
 
-	for (i = 0; i < size; i += 4) {
-		const __be32 *phandle;
-		struct device_node *np_config;
-		struct rockchip_pin_bank *bank;
-		u32 drive_strength;
-
-		bank_num = be32_to_cpu(*list++);
-		pin_num = be32_to_cpu(*list++);
-		func = be32_to_cpu(*list++);
-		phandle = list++;
+	return ret;
+}
 
-		if (!phandle)
-			return -EINVAL;
+#define RK3328_SCHMITT_BITS_PER_PIN		1
+#define RK3328_SCHMITT_PINS_PER_REG		16
+#define RK3328_SCHMITT_BANK_STRIDE		8
+#define RK3328_SCHMITT_GRF_OFFSET		0x380
 
-		np_config = of_find_node_by_phandle(be32_to_cpup(phandle));
-		bank = bank_num_to_bank(info, bank_num);
-		rockchip_pinctrl_set_func(bank, pin_num, func);
-		rockchip_pinctrl_set_pull(bank, pin_num,
-					  parse_bias_config(np_config));
+static int rk3328_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num,
+					   struct regmap **regmap,
+					   int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
 
-		ret = of_property_read_u32(np_config, "drive-strength", &drive_strength);
-		if (!ret)
-			rockchip_set_drive_perpin(bank, pin_num, drive_strength);
-	}
+	*regmap = info->regmap_base;
+	*reg = RK3328_SCHMITT_GRF_OFFSET;
+
+	*reg += bank->bank_num * RK3328_SCHMITT_BANK_STRIDE;
+	*reg += ((pin_num / RK3328_SCHMITT_PINS_PER_REG) * 4);
+	*bit = pin_num % RK3328_SCHMITT_PINS_PER_REG;
 
 	return 0;
 }
 
-static struct pinctrl_ops rockchip_pinctrl_ops = {
-	.set_state = rockchip_pinctrl_set_state,
-};
+#define RK3568_SCHMITT_BITS_PER_PIN		2
+#define RK3568_SCHMITT_PINS_PER_REG		8
+#define RK3568_SCHMITT_BANK_STRIDE		0x10
+#define RK3568_SCHMITT_GRF_OFFSET		0xc0
+#define RK3568_SCHMITT_PMUGRF_OFFSET		0x30
 
-static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
-				  struct device *dev)
+static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num,
+					   struct regmap **regmap,
+					   int *reg, u8 *bit)
 {
-	struct resource node_res, *res;
-
-	if (of_address_to_resource(bank->of_node, 0, &node_res)) {
-		dev_err(dev, "cannot find IO resource for bank\n");
-		return -ENOENT;
-	}
+	struct rockchip_pinctrl *info = bank->drvdata;
 
-	res = request_iomem_region(dev_name(dev), node_res.start, node_res.end);
-	if (IS_ERR(res)) {
-		dev_err(dev, "cannot request iomem region %pa\n",
-			&node_res.start);
-		return PTR_ERR(res);
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3568_SCHMITT_PMUGRF_OFFSET;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3568_SCHMITT_GRF_OFFSET;
+		*reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE;
 	}
 
-	bank->reg_base = (void __iomem *)res->start;
-
-	if (of_device_is_compatible(bank->of_node,
-				    "rockchip,rk3188-gpio-bank0"))
-		bank->bank_type = RK3188_BANK0;
-	else
-		bank->bank_type = COMMON_BANK;
-
-	bank->clk = of_clk_get(bank->of_node, 0);
-	if (IS_ERR(bank->clk))
-		return PTR_ERR(bank->clk);
+	*reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4);
+	*bit = pin_num % RK3568_SCHMITT_PINS_PER_REG;
+	*bit *= RK3568_SCHMITT_BITS_PER_PIN;
 
-	return clk_enable(bank->clk);
+	return 0;
 }
 
-static struct of_device_id rockchip_pinctrl_dt_match[];
+/*
+ * Pinconf_ops handling
+ */
+
+static const struct of_device_id rockchip_pinctrl_dt_match[];
 
+/* retrieve the soc specific data */
 static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
-	struct rockchip_pinctrl *d, struct device *dev)
+						struct rockchip_pinctrl *d,
+						struct device *dev)
 {
-	const struct of_device_id *match;
 	struct device_node *node = dev->of_node;
-	struct device_node *np;
+	const struct of_device_id *match;
 	struct rockchip_pin_ctrl *ctrl;
 	struct rockchip_pin_bank *bank;
 	int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j;
-	int gpio = 0;
 
 	match = of_match_node(rockchip_pinctrl_dt_match, node);
 	ctrl = (struct rockchip_pin_ctrl *)match->data;
 
-	for_each_child_of_node(node, np) {
-		int id;
-
-		if (!of_find_property(np, "gpio-controller", NULL))
-			continue;
-
-		id = of_alias_get_id(np, "gpio");
-		if (id < 0)
-			id = gpio++;
-
-		bank = ctrl->pin_banks;
-		for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
-			if (bank->bank_num == id) {
-				bank->of_node = np;
-				if (!rockchip_get_bank_data(bank, dev))
-					bank->valid = true;
-
-				break;
-			}
-		}
-	}
-
 	grf_offs = ctrl->grf_mux_offset;
 	pmu_offs = ctrl->pmu_mux_offset;
 	drv_pmu_offs = ctrl->pmu_drv_offset;
@@ -641,12 +2258,14 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
 
 			/* preset iomux offset value, set new start value */
 			if (iom->offset >= 0) {
-				if (iom->type & IOMUX_SOURCE_PMU)
+				if ((iom->type & IOMUX_SOURCE_PMU) ||
+				    (iom->type & IOMUX_L_SOURCE_PMU))
 					pmu_offs = iom->offset;
 				else
 					grf_offs = iom->offset;
 			} else { /* set current iomux offset */
-				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
+				iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
+					       (iom->type & IOMUX_L_SOURCE_PMU)) ?
 							pmu_offs : grf_offs;
 			}
 
@@ -671,7 +2290,7 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
 			inc = (iom->type & (IOMUX_WIDTH_4BIT |
 					    IOMUX_WIDTH_3BIT |
 					    IOMUX_WIDTH_2BIT)) ? 8 : 4;
-			if (iom->type & IOMUX_SOURCE_PMU)
+			if ((iom->type & IOMUX_SOURCE_PMU) || (iom->type & IOMUX_L_SOURCE_PMU))
 				pmu_offs += inc;
 			else
 				grf_offs += inc;
@@ -694,6 +2313,16 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
 			bank_pins += 8;
 		}
 
+		/* calculate the per-bank recalced_mask */
+		for (j = 0; j < ctrl->niomux_recalced; j++) {
+			int pin = 0;
+
+			if (ctrl->iomux_recalced[j].num == bank->bank_num) {
+				pin = ctrl->iomux_recalced[j].pin;
+				bank->recalced_mask |= BIT(pin);
+			}
+		}
+
 		/* calculate the per-bank route_mask */
 		for (j = 0; j < ctrl->niomux_routes; j++) {
 			int pin = 0;
@@ -708,44 +2337,104 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
 	return ctrl;
 }
 
+static int rockchip_pinctrl_set_state(struct pinctrl_device *pdev,
+				      struct device_node *np)
+{
+	struct rockchip_pinctrl *info = to_rockchip_pinctrl(pdev);
+	const __be32 *list;
+	int i, size, ret;
+	int bank_num, pin_num, func;
+
+	/*
+	 * the binding format is rockchip,pins = <bank pin mux CONFIG>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "rockchip,pins", &size);
+	size /= sizeof(*list);
+
+	if (!size || size % 4) {
+		dev_err(pdev->dev, "wrong pins number or pins and configs should be by 4\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < size; i += 4) {
+		const __be32 *phandle;
+		struct device_node *np_config;
+		struct rockchip_pin_bank *bank;
+		u32 drive_strength;
+
+		bank_num = be32_to_cpu(*list++);
+		pin_num = be32_to_cpu(*list++);
+		func = be32_to_cpu(*list++);
+		phandle = list++;
+
+		if (!phandle)
+			return -EINVAL;
+
+		np_config = of_find_node_by_phandle(be32_to_cpup(phandle));
+		bank = bank_num_to_bank(info, bank_num);
+		rockchip_set_mux(bank, pin_num, func);
+		rockchip_set_pull(bank, pin_num, parse_bias_config(np_config));
+
+		ret = of_property_read_u32(np_config, "drive-strength", &drive_strength);
+		if (!ret)
+			rockchip_set_drive_perpin(bank, pin_num, drive_strength);
+	}
+
+	return 0;
+}
+
+static struct pinctrl_ops rockchip_pinctrl_ops = {
+	.set_state = rockchip_pinctrl_set_state,
+};
+
 static int rockchip_pinctrl_probe(struct device *dev)
 {
 	struct rockchip_pinctrl *info;
+	struct device_node *np = dev->of_node, *node;
 	struct rockchip_pin_ctrl *ctrl;
 	int ret;
 
-	info = xzalloc(sizeof(struct rockchip_pinctrl));
+	if (!dev->of_node)
+		return dev_err_probe(dev, -ENODEV, "device tree node not found\n");
+
+	info = xzalloc(sizeof(*info));
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
 
 	ctrl = rockchip_pinctrl_get_soc_data(info, dev);
-	if (!ctrl) {
-		dev_err(dev, "driver data not available\n");
-		return -EINVAL;
-	}
+	if (!ctrl)
+		return dev_err_probe(dev, -EINVAL, "driver data not available\n");
 	info->ctrl = ctrl;
 
-	info->reg_base = syscon_base_lookup_by_phandle(dev->of_node,
-						       "rockchip,grf");
-	if (IS_ERR(info->reg_base)) {
-		dev_err(dev, "Could not get grf syscon address\n");
-		return -ENODEV;
-	}
+	node = of_parse_phandle(np, "rockchip,grf", 0);
+	if (!node)
+		return -EINVAL;
 
-	info->reg_pmu = syscon_base_lookup_by_phandle(dev->of_node,
-						      "rockchip,pmu");
-	if (IS_ERR(info->reg_pmu)) {
-		dev_err(dev, "Could not get pmu syscon address\n");
-		return -ENODEV;
+	info->regmap_base = syscon_node_to_regmap(node);
+	of_node_put(node);
+	if (IS_ERR(info->regmap_base))
+		return PTR_ERR(info->regmap_base);
+
+	/* try to find the optional reference to the pmu syscon */
+	node = of_parse_phandle(np, "rockchip,pmu", 0);
+	if (node) {
+		info->regmap_pmu = syscon_node_to_regmap(node);
+		of_node_put(node);
+		if (IS_ERR(info->regmap_pmu))
+			return PTR_ERR(info->regmap_pmu);
 	}
 
-	info->pctl_dev.dev = dev;
-	info->pctl_dev.ops = &rockchip_pinctrl_ops;
-
 	dev->priv = info;
 
-	of_platform_populate(dev->of_node, NULL, dev);
+	ret = of_platform_populate(np, NULL, dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to register gpio device\n");
 
-	if (!IS_ENABLED(CONFIG_PINCTRL))
-		return 0;
+	info->pctl_dev.dev = dev;
+	info->pctl_dev.ops = &rockchip_pinctrl_ops;
 
 	ret = pinctrl_register(&info->pctl_dev);
 	if (ret)
@@ -754,22 +2443,125 @@ static int rockchip_pinctrl_probe(struct device *dev)
 	return 0;
 }
 
-static struct rockchip_pin_bank rk2928_pin_banks[] = {
+static __maybe_unused struct rockchip_pin_bank px30_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU
+			    ),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT
+			    ),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT
+			    ),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT
+			    ),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl px30_pin_ctrl = {
+		.pin_banks		= px30_pin_banks,
+		.nr_banks		= ARRAY_SIZE(px30_pin_banks),
+		.label			= "PX30-GPIO",
+		.type			= PX30,
+		.grf_mux_offset		= 0x0,
+		.pmu_mux_offset		= 0x0,
+		.iomux_routes		= px30_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(px30_mux_route_data),
+		.pull_calc_reg		= px30_calc_pull_reg_and_bit,
+		.drv_calc_reg		= px30_calc_drv_reg_and_bit,
+		.schmitt_calc_reg	= px30_calc_schmitt_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rv1108_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rv1108_pin_ctrl = {
+	.pin_banks		= rv1108_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rv1108_pin_banks),
+	.label			= "RV1108-GPIO",
+	.type			= RV1108,
+	.grf_mux_offset		= 0x10,
+	.pmu_mux_offset		= 0x0,
+	.iomux_recalced		= rv1108_mux_recalced_data,
+	.niomux_recalced	= ARRAY_SIZE(rv1108_mux_recalced_data),
+	.pull_calc_reg		= rv1108_calc_pull_reg_and_bit,
+	.drv_calc_reg		= rv1108_calc_drv_reg_and_bit,
+	.schmitt_calc_reg	= rv1108_calc_schmitt_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rv1126_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0",
+			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+			     IOMUX_WIDTH_4BIT | IOMUX_L_SOURCE_PMU,
+			     IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x10010, 0x10018, 0x10020, 0x10028),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2",
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(4, 2, "gpio4",
+			     IOMUX_WIDTH_4BIT, 0, 0, 0),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rv1126_pin_ctrl = {
+	.pin_banks		= rv1126_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rv1126_pin_banks),
+	.label			= "RV1126-GPIO",
+	.type			= RV1126,
+	.grf_mux_offset		= 0x10004, /* mux offset from GPIO0_D0 */
+	.pmu_mux_offset		= 0x0,
+	.iomux_routes		= rv1126_mux_route_data,
+	.niomux_routes		= ARRAY_SIZE(rv1126_mux_route_data),
+	.iomux_recalced		= rv1126_mux_recalced_data,
+	.niomux_recalced	= ARRAY_SIZE(rv1126_mux_recalced_data),
+	.pull_calc_reg		= rv1126_calc_pull_reg_and_bit,
+	.drv_calc_reg		= rv1126_calc_drv_reg_and_bit,
+	.schmitt_calc_reg	= rv1126_calc_schmitt_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rk3036_pin_banks[] = {
 	PIN_BANK(0, 32, "gpio0"),
 	PIN_BANK(1, 32, "gpio1"),
 	PIN_BANK(2, 32, "gpio2"),
-	PIN_BANK(3, 32, "gpio3"),
 };
 
-static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
-	.pin_banks	= rk2928_pin_banks,
-	.nr_banks	= ARRAY_SIZE(rk2928_pin_banks),
-	.type		= RK2928,
-	.grf_mux_offset	= 0xa8,
-	.pull_calc_reg	= rk2928_calc_pull_reg_and_bit,
+static __maybe_unused struct rockchip_pin_ctrl rk3036_pin_ctrl = {
+		.pin_banks		= rk3036_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3036_pin_banks),
+		.label			= "RK3036-GPIO",
+		.type			= RK2928,
+		.grf_mux_offset		= 0xa8,
+		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
 };
 
-static struct rockchip_pin_bank rk3066a_pin_banks[] = {
+static __maybe_unused struct rockchip_pin_bank rk3066a_pin_banks[] = {
 	PIN_BANK(0, 32, "gpio0"),
 	PIN_BANK(1, 32, "gpio1"),
 	PIN_BANK(2, 32, "gpio2"),
@@ -778,142 +2570,275 @@ static struct rockchip_pin_bank rk3066a_pin_banks[] = {
 	PIN_BANK(6, 16, "gpio6"),
 };
 
-static struct rockchip_pin_ctrl rk3066a_pin_ctrl = {
-	.pin_banks	= rk3066a_pin_banks,
-	.nr_banks	= ARRAY_SIZE(rk3066a_pin_banks),
-	.type		= RK2928,
-	.grf_mux_offset	= 0xa8,
-	.pull_calc_reg	= rk2928_calc_pull_reg_and_bit,
+static __maybe_unused struct rockchip_pin_ctrl rk3066a_pin_ctrl = {
+		.pin_banks		= rk3066a_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3066a_pin_banks),
+		.label			= "RK3066a-GPIO",
+		.type			= RK2928,
+		.grf_mux_offset		= 0xa8,
+		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
 };
 
-static struct rockchip_pin_bank rk3066b_pin_banks[] = {
+static __maybe_unused struct rockchip_pin_bank rk3128_pin_banks[] = {
 	PIN_BANK(0, 32, "gpio0"),
 	PIN_BANK(1, 32, "gpio1"),
 	PIN_BANK(2, 32, "gpio2"),
 	PIN_BANK(3, 32, "gpio3"),
 };
 
-static struct rockchip_pin_ctrl rk3066b_pin_ctrl = {
-	.pin_banks	= rk3066b_pin_banks,
-	.nr_banks	= ARRAY_SIZE(rk3066b_pin_banks),
-	.type		= RK3066B,
-	.grf_mux_offset	= 0x60,
+static __maybe_unused struct rockchip_pin_ctrl rk3128_pin_ctrl = {
+		.pin_banks		= rk3128_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3128_pin_banks),
+		.label			= "RK3128-GPIO",
+		.type			= RK3128,
+		.grf_mux_offset		= 0xa8,
+		.iomux_recalced		= rk3128_mux_recalced_data,
+		.niomux_recalced	= ARRAY_SIZE(rk3128_mux_recalced_data),
+		.iomux_routes		= rk3128_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(rk3128_mux_route_data),
+		.pull_calc_reg		= rk3128_calc_pull_reg_and_bit,
 };
 
-static struct rockchip_pin_bank rk3188_pin_banks[] = {
+static __maybe_unused struct rockchip_pin_bank rk3188_pin_banks[] = {
 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0),
 	PIN_BANK(1, 32, "gpio1"),
 	PIN_BANK(2, 32, "gpio2"),
 	PIN_BANK(3, 32, "gpio3"),
 };
 
-static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
-	.pin_banks	= rk3188_pin_banks,
-	.nr_banks	= ARRAY_SIZE(rk3188_pin_banks),
-	.type		= RK3188,
-	.grf_mux_offset	= 0x60,
-	.iomux_routes	= rk3188_mux_route_data,
-	.niomux_routes	= ARRAY_SIZE(rk3188_mux_route_data),
-	.pull_calc_reg	= rk3188_calc_pull_reg_and_bit,
+static __maybe_unused struct rockchip_pin_ctrl rk3188_pin_ctrl = {
+		.pin_banks		= rk3188_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3188_pin_banks),
+		.label			= "RK3188-GPIO",
+		.type			= RK3188,
+		.grf_mux_offset		= 0x60,
+		.iomux_routes		= rk3188_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(rk3188_mux_route_data),
+		.pull_calc_reg		= rk3188_calc_pull_reg_and_bit,
 };
 
-static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
-	RK_MUXROUTE_PMU(0, RK_PB7, 1, 0x0110, WRITE_MASK_VAL(1, 0, 0)), /* PWM0 IO mux M0 */
-	RK_MUXROUTE_PMU(0, RK_PC7, 2, 0x0110, WRITE_MASK_VAL(1, 0, 1)), /* PWM0 IO mux M1 */
-	RK_MUXROUTE_PMU(0, RK_PC0, 1, 0x0110, WRITE_MASK_VAL(3, 2, 0)), /* PWM1 IO mux M0 */
-	RK_MUXROUTE_PMU(0, RK_PB5, 4, 0x0110, WRITE_MASK_VAL(3, 2, 1)), /* PWM1 IO mux M1 */
-	RK_MUXROUTE_PMU(0, RK_PC1, 1, 0x0110, WRITE_MASK_VAL(5, 4, 0)), /* PWM2 IO mux M0 */
-	RK_MUXROUTE_PMU(0, RK_PB6, 4, 0x0110, WRITE_MASK_VAL(5, 4, 1)), /* PWM2 IO mux M1 */
-	RK_MUXROUTE_PMU(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PA1, 4, 0x0300, WRITE_MASK_VAL(0, 0, 1)), /* CAN0 IO mux M1 */
-	RK_MUXROUTE_GRF(1, RK_PA1, 3, 0x0300, WRITE_MASK_VAL(2, 2, 0)), /* CAN1 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC3, 3, 0x0300, WRITE_MASK_VAL(2, 2, 1)), /* CAN1 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PB5, 3, 0x0300, WRITE_MASK_VAL(4, 4, 0)), /* CAN2 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PB2, 4, 0x0300, WRITE_MASK_VAL(4, 4, 1)), /* CAN2 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PC4, 1, 0x0300, WRITE_MASK_VAL(6, 6, 0)), /* HPDIN IO mux M0 */
-	RK_MUXROUTE_PMU(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PB1, 3, 0x0300, WRITE_MASK_VAL(8, 8, 0)), /* GMAC1 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PA7, 3, 0x0300, WRITE_MASK_VAL(8, 8, 1)), /* GMAC1 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PD1, 1, 0x0300, WRITE_MASK_VAL(10, 10, 0)), /* HDMITX IO mux M0 */
-	RK_MUXROUTE_PMU(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */
-	RK_MUXROUTE_PMU(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PB4, 1, 0x0300, WRITE_MASK_VAL(14, 14, 1)), /* I2C2 IO mux M1 */
-	RK_MUXROUTE_GRF(1, RK_PA0, 1, 0x0304, WRITE_MASK_VAL(0, 0, 0)), /* I2C3 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PB6, 4, 0x0304, WRITE_MASK_VAL(0, 0, 1)), /* I2C3 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PB2, 1, 0x0304, WRITE_MASK_VAL(2, 2, 0)), /* I2C4 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PB1, 2, 0x0304, WRITE_MASK_VAL(2, 2, 1)), /* I2C4 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PB4, 4, 0x0304, WRITE_MASK_VAL(4, 4, 0)), /* I2C5 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PD0, 2, 0x0304, WRITE_MASK_VAL(4, 4, 1)), /* I2C5 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PB1, 5, 0x0304, WRITE_MASK_VAL(14, 14, 0)), /* PWM8 IO mux M0 */
-	RK_MUXROUTE_GRF(1, RK_PD5, 4, 0x0304, WRITE_MASK_VAL(14, 14, 1)), /* PWM8 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PB2, 5, 0x0308, WRITE_MASK_VAL(0, 0, 0)), /* PWM9 IO mux M0 */
-	RK_MUXROUTE_GRF(1, RK_PD6, 4, 0x0308, WRITE_MASK_VAL(0, 0, 1)), /* PWM9 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PB5, 5, 0x0308, WRITE_MASK_VAL(2, 2, 0)), /* PWM10 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PA1, 2, 0x0308, WRITE_MASK_VAL(2, 2, 1)), /* PWM10 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PB6, 5, 0x0308, WRITE_MASK_VAL(4, 4, 0)), /* PWM11 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC0, 3, 0x0308, WRITE_MASK_VAL(4, 4, 1)), /* PWM11 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PB7, 2, 0x0308, WRITE_MASK_VAL(6, 6, 0)), /* PWM12 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC5, 1, 0x0308, WRITE_MASK_VAL(6, 6, 1)), /* PWM12 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PC0, 2, 0x0308, WRITE_MASK_VAL(8, 8, 0)), /* PWM13 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC6, 1, 0x0308, WRITE_MASK_VAL(8, 8, 1)), /* PWM13 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PC4, 1, 0x0308, WRITE_MASK_VAL(10, 10, 0)), /* PWM14 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC2, 1, 0x0308, WRITE_MASK_VAL(10, 10, 1)), /* PWM14 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PC5, 1, 0x0308, WRITE_MASK_VAL(12, 12, 0)), /* PWM15 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC3, 1, 0x0308, WRITE_MASK_VAL(12, 12, 1)), /* PWM15 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PD2, 3, 0x0308, WRITE_MASK_VAL(14, 14, 0)), /* SDMMC2 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PA5, 5, 0x0308, WRITE_MASK_VAL(14, 14, 1)), /* SDMMC2 IO mux M1 */
-	RK_MUXROUTE_PMU(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PD3, 3, 0x030c, WRITE_MASK_VAL(0, 0, 1)), /* SPI0 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PB5, 3, 0x030c, WRITE_MASK_VAL(2, 2, 0)), /* SPI1 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PC3, 3, 0x030c, WRITE_MASK_VAL(2, 2, 1)), /* SPI1 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PC1, 4, 0x030c, WRITE_MASK_VAL(4, 4, 0)), /* SPI2 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PA0, 3, 0x030c, WRITE_MASK_VAL(4, 4, 1)), /* SPI2 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PB3, 4, 0x030c, WRITE_MASK_VAL(6, 6, 0)), /* SPI3 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC2, 2, 0x030c, WRITE_MASK_VAL(6, 6, 1)), /* SPI3 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PB4, 2, 0x030c, WRITE_MASK_VAL(8, 8, 0)), /* UART1 IO mux M0 */
-	RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */
-	RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */
-	RK_MUXROUTE_GRF(1, RK_PD5, 2, 0x030c, WRITE_MASK_VAL(10, 10, 1)), /* UART2 IO mux M1 */
-	RK_MUXROUTE_GRF(1, RK_PA1, 2, 0x030c, WRITE_MASK_VAL(12, 12, 0)), /* UART3 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PB7, 4, 0x030c, WRITE_MASK_VAL(12, 12, 1)), /* UART3 IO mux M1 */
-	RK_MUXROUTE_GRF(1, RK_PA6, 2, 0x030c, WRITE_MASK_VAL(14, 14, 0)), /* UART4 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PB2, 4, 0x030c, WRITE_MASK_VAL(14, 14, 1)), /* UART4 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PA2, 3, 0x0310, WRITE_MASK_VAL(0, 0, 0)), /* UART5 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PC2, 4, 0x0310, WRITE_MASK_VAL(0, 0, 1)), /* UART5 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PA4, 3, 0x0310, WRITE_MASK_VAL(2, 2, 0)), /* UART6 IO mux M0 */
-	RK_MUXROUTE_GRF(1, RK_PD5, 3, 0x0310, WRITE_MASK_VAL(2, 2, 1)), /* UART6 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PA6, 3, 0x0310, WRITE_MASK_VAL(5, 4, 0)), /* UART7 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PC4, 4, 0x0310, WRITE_MASK_VAL(5, 4, 1)), /* UART7 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PA2, 4, 0x0310, WRITE_MASK_VAL(5, 4, 2)), /* UART7 IO mux M2 */
-	RK_MUXROUTE_GRF(2, RK_PC5, 3, 0x0310, WRITE_MASK_VAL(6, 6, 0)), /* UART8 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PD7, 4, 0x0310, WRITE_MASK_VAL(6, 6, 1)), /* UART8 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PB0, 3, 0x0310, WRITE_MASK_VAL(9, 8, 0)), /* UART9 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC5, 4, 0x0310, WRITE_MASK_VAL(9, 8, 1)), /* UART9 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PA4, 4, 0x0310, WRITE_MASK_VAL(9, 8, 2)), /* UART9 IO mux M2 */
-	RK_MUXROUTE_GRF(1, RK_PA2, 1, 0x0310, WRITE_MASK_VAL(11, 10, 0)), /* I2S1 IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PC6, 4, 0x0310, WRITE_MASK_VAL(11, 10, 1)), /* I2S1 IO mux M1 */
-	RK_MUXROUTE_GRF(2, RK_PD0, 5, 0x0310, WRITE_MASK_VAL(11, 10, 2)), /* I2S1 IO mux M2 */
-	RK_MUXROUTE_GRF(2, RK_PC1, 1, 0x0310, WRITE_MASK_VAL(12, 12, 0)), /* I2S2 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PB6, 5, 0x0310, WRITE_MASK_VAL(12, 12, 1)), /* I2S2 IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PA2, 4, 0x0310, WRITE_MASK_VAL(14, 14, 0)), /* I2S3 IO mux M0 */
-	RK_MUXROUTE_GRF(4, RK_PC2, 5, 0x0310, WRITE_MASK_VAL(14, 14, 1)), /* I2S3 IO mux M1 */
-	RK_MUXROUTE_GRF(1, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(1, 0, 0)), /* PDM IO mux M0 */
-	RK_MUXROUTE_GRF(1, RK_PA6, 3, 0x0314, WRITE_MASK_VAL(1, 0, 0)), /* PDM IO mux M0 */
-	RK_MUXROUTE_GRF(3, RK_PD6, 5, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PA0, 4, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
-	RK_MUXROUTE_GRF(3, RK_PC4, 5, 0x0314, WRITE_MASK_VAL(1, 0, 2)), /* PDM IO mux M2 */
-	RK_MUXROUTE_PMU(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PD0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 1)), /* PCIE20 IO mux M1 */
-	RK_MUXROUTE_GRF(1, RK_PB0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 2)), /* PCIE20 IO mux M2 */
-	RK_MUXROUTE_PMU(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PD2, 4, 0x0314, WRITE_MASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux M1 */
-	RK_MUXROUTE_GRF(1, RK_PA5, 4, 0x0314, WRITE_MASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux M2 */
-	RK_MUXROUTE_PMU(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */
-	RK_MUXROUTE_GRF(2, RK_PD4, 4, 0x0314, WRITE_MASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux M1 */
-	RK_MUXROUTE_GRF(4, RK_PC2, 4, 0x0314, WRITE_MASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux M2 */
+static __maybe_unused struct rockchip_pin_bank rk3228_pin_banks[] = {
+	PIN_BANK(0, 32, "gpio0"),
+	PIN_BANK(1, 32, "gpio1"),
+	PIN_BANK(2, 32, "gpio2"),
+	PIN_BANK(3, 32, "gpio3"),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rk3228_pin_ctrl = {
+		.pin_banks		= rk3228_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3228_pin_banks),
+		.label			= "RK3228-GPIO",
+		.type			= RK3288,
+		.grf_mux_offset		= 0x0,
+		.iomux_routes		= rk3228_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(rk3228_mux_route_data),
+		.pull_calc_reg		= rk3228_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3228_calc_drv_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rk3288_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_UNROUTED
+			    ),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED,
+					     IOMUX_UNROUTED,
+					     IOMUX_UNROUTED,
+					     0
+			    ),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     0,
+					     0
+			    ),
+	PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED,
+					     0,
+					     0,
+					     IOMUX_UNROUTED
+			    ),
+	PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED),
+	PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0,
+					     0,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_UNROUTED
+			    ),
+	PIN_BANK(8, 16, "gpio8"),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rk3288_pin_ctrl = {
+		.pin_banks		= rk3288_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3288_pin_banks),
+		.label			= "RK3288-GPIO",
+		.type			= RK3288,
+		.grf_mux_offset		= 0x0,
+		.pmu_mux_offset		= 0x84,
+		.iomux_routes		= rk3288_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(rk3288_mux_route_data),
+		.pull_calc_reg		= rk3288_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3288_calc_drv_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rk3308_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT),
+	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT,
+					     IOMUX_WIDTH_2BIT),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rk3308_pin_ctrl = {
+		.pin_banks		= rk3308_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3308_pin_banks),
+		.label			= "RK3308-GPIO",
+		.type			= RK3308,
+		.grf_mux_offset		= 0x0,
+		.iomux_recalced		= rk3308_mux_recalced_data,
+		.niomux_recalced	= ARRAY_SIZE(rk3308_mux_recalced_data),
+		.iomux_routes		= rk3308_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(rk3308_mux_route_data),
+		.pull_calc_reg		= rk3308_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3308_calc_drv_reg_and_bit,
+		.schmitt_calc_reg	= rk3308_calc_schmitt_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rk3328_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0,
+			     IOMUX_WIDTH_3BIT,
+			     IOMUX_WIDTH_3BIT,
+			     0),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
+			     IOMUX_WIDTH_3BIT,
+			     IOMUX_WIDTH_3BIT,
+			     0,
+			     0),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rk3328_pin_ctrl = {
+		.pin_banks		= rk3328_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3328_pin_banks),
+		.label			= "RK3328-GPIO",
+		.type			= RK3288,
+		.grf_mux_offset		= 0x0,
+		.iomux_recalced		= rk3328_mux_recalced_data,
+		.niomux_recalced	= ARRAY_SIZE(rk3328_mux_recalced_data),
+		.iomux_routes		= rk3328_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(rk3328_mux_route_data),
+		.pull_calc_reg		= rk3228_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3228_calc_drv_reg_and_bit,
+		.schmitt_calc_reg	= rk3328_calc_schmitt_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rk3368_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU
+			    ),
+	PIN_BANK(1, 32, "gpio1"),
+	PIN_BANK(2, 32, "gpio2"),
+	PIN_BANK(3, 32, "gpio3"),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rk3368_pin_ctrl = {
+		.pin_banks		= rk3368_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3368_pin_banks),
+		.label			= "RK3368-GPIO",
+		.type			= RK3368,
+		.grf_mux_offset		= 0x0,
+		.pmu_mux_offset		= 0x0,
+		.pull_calc_reg		= rk3368_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3368_calc_drv_reg_and_bit,
+};
+
+static __maybe_unused struct rockchip_pin_bank rk3399_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0",
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_DEFAULT,
+							 DRV_TYPE_IO_DEFAULT,
+							 0x80,
+							 0x88,
+							 -1,
+							 -1,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_DEFAULT,
+							 PULL_TYPE_IO_DEFAULT
+							),
+	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
+					IOMUX_SOURCE_PMU,
+					IOMUX_SOURCE_PMU,
+					IOMUX_SOURCE_PMU,
+					DRV_TYPE_IO_1V8_OR_3V0,
+					DRV_TYPE_IO_1V8_OR_3V0,
+					DRV_TYPE_IO_1V8_OR_3V0,
+					DRV_TYPE_IO_1V8_OR_3V0,
+					0xa0,
+					0xa8,
+					0xb0,
+					0xb8
+					),
+	PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_1V8_ONLY
+				      ),
+	PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
+			   DRV_TYPE_IO_3V3_ONLY,
+			   DRV_TYPE_IO_3V3_ONLY,
+			   DRV_TYPE_IO_1V8_OR_3V0
+			   ),
+	PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0,
+			   DRV_TYPE_IO_1V8_3V0_AUTO,
+			   DRV_TYPE_IO_1V8_OR_3V0,
+			   DRV_TYPE_IO_1V8_OR_3V0
+			   ),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rk3399_pin_ctrl = {
+		.pin_banks		= rk3399_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3399_pin_banks),
+		.label			= "RK3399-GPIO",
+		.type			= RK3399,
+		.grf_mux_offset		= 0xe000,
+		.pmu_mux_offset		= 0x0,
+		.grf_drv_offset		= 0xe100,
+		.pmu_drv_offset		= 0x80,
+		.iomux_routes		= rk3399_mux_route_data,
+		.niomux_routes		= ARRAY_SIZE(rk3399_mux_route_data),
+		.pull_calc_reg		= rk3399_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3399_calc_drv_reg_and_bit,
 };
 
-static struct rockchip_pin_bank rk3568_pin_banks[] = {
+static __maybe_unused struct rockchip_pin_bank rk3568_pin_banks[] = {
 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
 					     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
 					     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
@@ -936,7 +2861,7 @@ static struct rockchip_pin_bank rk3568_pin_banks[] = {
 					     IOMUX_WIDTH_4BIT),
 };
 
-static struct rockchip_pin_ctrl rk3568_pin_ctrl = {
+static __maybe_unused struct rockchip_pin_ctrl rk3568_pin_ctrl = {
 	.pin_banks		= rk3568_pin_banks,
 	.nr_banks		= ARRAY_SIZE(rk3568_pin_banks),
 	.label			= "RK3568-GPIO",
@@ -949,32 +2874,94 @@ static struct rockchip_pin_ctrl rk3568_pin_ctrl = {
 	.niomux_routes		= ARRAY_SIZE(rk3568_mux_route_data),
 	.pull_calc_reg		= rk3568_calc_pull_reg_and_bit,
 	.drv_calc_reg		= rk3568_calc_drv_reg_and_bit,
+	.schmitt_calc_reg	= rk3568_calc_schmitt_reg_and_bit,
 };
 
-static struct of_device_id rockchip_pinctrl_dt_match[] = {
-	{
-		.compatible = "rockchip,rk2928-pinctrl",
-		.data = &rk2928_pin_ctrl,
-	},
-	{
-		.compatible = "rockchip,rk3066a-pinctrl",
-		.data = &rk3066a_pin_ctrl,
-	},
-	{
-		.compatible = "rockchip,rk3066b-pinctrl",
-		.data = &rk3066b_pin_ctrl,
-	},
-	{
-		.compatible = "rockchip,rk3188-pinctrl",
-		.data = &rk3188_pin_ctrl,
-	},
-	{
-		.compatible = "rockchip,rk3568-pinctrl",
-		.data = &rk3568_pin_ctrl
-	},
-	{
-		/* sentinel */
-	}
+static __maybe_unused struct rockchip_pin_bank rk3588_pin_banks[] = {
+	RK3588_PIN_BANK_FLAGS(0, 32, "gpio0",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(1, 32, "gpio1",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(2, 32, "gpio2",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(3, 32, "gpio3",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(4, 32, "gpio4",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+};
+
+static __maybe_unused struct rockchip_pin_ctrl rk3588_pin_ctrl = {
+	.pin_banks		= rk3588_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rk3588_pin_banks),
+	.label			= "RK3588-GPIO",
+	.type			= RK3588,
+	.pull_calc_reg		= rk3588_calc_pull_reg_and_bit,
+	.drv_calc_reg		= rk3588_calc_drv_reg_and_bit,
+	.schmitt_calc_reg	= rk3588_calc_schmitt_reg_and_bit,
+};
+
+static const struct of_device_id rockchip_pinctrl_dt_match[] = {
+#ifdef CONFIG_ARCH_PX30
+	{ .compatible = "rockchip,px30-pinctrl",
+		.data = &px30_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RV1108
+	{ .compatible = "rockchip,rv1108-pinctrl",
+		.data = &rv1108_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RV1126
+	{ .compatible = "rockchip,rv1126-pinctrl",
+		.data = &rv1126_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3036
+	{ .compatible = "rockchip,rk3036-pinctrl",
+		.data = &rk3036_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3066A
+	{ .compatible = "rockchip,rk3066a-pinctrl",
+		.data = &rk3066a_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3128
+	{ .compatible = "rockchip,rk3128-pinctrl",
+		.data = (void *)&rk3128_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3188
+	{ .compatible = "rockchip,rk3188-pinctrl",
+		.data = &rk3188_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3228
+	{ .compatible = "rockchip,rk3228-pinctrl",
+		.data = &rk3228_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3288
+	{ .compatible = "rockchip,rk3288-pinctrl",
+		.data = &rk3288_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3308
+	{ .compatible = "rockchip,rk3308-pinctrl",
+		.data = &rk3308_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3328
+	{ .compatible = "rockchip,rk3328-pinctrl",
+		.data = &rk3328_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3368
+	{ .compatible = "rockchip,rk3368-pinctrl",
+		.data = &rk3368_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3399
+	{ .compatible = "rockchip,rk3399-pinctrl",
+		.data = &rk3399_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3568
+	{ .compatible = "rockchip,rk3568-pinctrl",
+		.data = &rk3568_pin_ctrl },
+#endif
+#ifdef CONFIG_ARCH_RK3588
+	{ .compatible = "rockchip,rk3588-pinctrl",
+		.data = &rk3588_pin_ctrl },
+#endif
+	{},
 };
 
 static struct driver rockchip_pinctrl_driver = {
diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
index 5279c78439..498f4615e1 100644
--- a/drivers/pinctrl/pinctrl-rockchip.h
+++ b/drivers/pinctrl/pinctrl-rockchip.h
@@ -18,11 +18,221 @@
 #ifndef _PINCTRL_ROCKCHIP_H
 #define _PINCTRL_ROCKCHIP_H
 
+#define RK_GPIO0_A0	0
+#define RK_GPIO0_A1	1
+#define RK_GPIO0_A2	2
+#define RK_GPIO0_A3	3
+#define RK_GPIO0_A4	4
+#define RK_GPIO0_A5	5
+#define RK_GPIO0_A6	6
+#define RK_GPIO0_A7	7
+#define RK_GPIO0_B0	8
+#define RK_GPIO0_B1	9
+#define RK_GPIO0_B2	10
+#define RK_GPIO0_B3	11
+#define RK_GPIO0_B4	12
+#define RK_GPIO0_B5	13
+#define RK_GPIO0_B6	14
+#define RK_GPIO0_B7	15
+#define RK_GPIO0_C0	16
+#define RK_GPIO0_C1	17
+#define RK_GPIO0_C2	18
+#define RK_GPIO0_C3	19
+#define RK_GPIO0_C4	20
+#define RK_GPIO0_C5	21
+#define RK_GPIO0_C6	22
+#define RK_GPIO0_C7	23
+#define RK_GPIO0_D0	24
+#define RK_GPIO0_D1	25
+#define RK_GPIO0_D2	26
+#define RK_GPIO0_D3	27
+#define RK_GPIO0_D4	28
+#define RK_GPIO0_D5	29
+#define RK_GPIO0_D6	30
+#define RK_GPIO0_D7	31
+
+#define RK_GPIO1_A0	32
+#define RK_GPIO1_A1	33
+#define RK_GPIO1_A2	34
+#define RK_GPIO1_A3	35
+#define RK_GPIO1_A4	36
+#define RK_GPIO1_A5	37
+#define RK_GPIO1_A6	38
+#define RK_GPIO1_A7	39
+#define RK_GPIO1_B0	40
+#define RK_GPIO1_B1	41
+#define RK_GPIO1_B2	42
+#define RK_GPIO1_B3	43
+#define RK_GPIO1_B4	44
+#define RK_GPIO1_B5	45
+#define RK_GPIO1_B6	46
+#define RK_GPIO1_B7	47
+#define RK_GPIO1_C0	48
+#define RK_GPIO1_C1	49
+#define RK_GPIO1_C2	50
+#define RK_GPIO1_C3	51
+#define RK_GPIO1_C4	52
+#define RK_GPIO1_C5	53
+#define RK_GPIO1_C6	54
+#define RK_GPIO1_C7	55
+#define RK_GPIO1_D0	56
+#define RK_GPIO1_D1	57
+#define RK_GPIO1_D2	58
+#define RK_GPIO1_D3	59
+#define RK_GPIO1_D4	60
+#define RK_GPIO1_D5	61
+#define RK_GPIO1_D6	62
+#define RK_GPIO1_D7	63
+
+#define RK_GPIO2_A0	64
+#define RK_GPIO2_A1	65
+#define RK_GPIO2_A2	66
+#define RK_GPIO2_A3	67
+#define RK_GPIO2_A4	68
+#define RK_GPIO2_A5	69
+#define RK_GPIO2_A6	70
+#define RK_GPIO2_A7	71
+#define RK_GPIO2_B0	72
+#define RK_GPIO2_B1	73
+#define RK_GPIO2_B2	74
+#define RK_GPIO2_B3	75
+#define RK_GPIO2_B4	76
+#define RK_GPIO2_B5	77
+#define RK_GPIO2_B6	78
+#define RK_GPIO2_B7	79
+#define RK_GPIO2_C0	80
+#define RK_GPIO2_C1	81
+#define RK_GPIO2_C2	82
+#define RK_GPIO2_C3	83
+#define RK_GPIO2_C4	84
+#define RK_GPIO2_C5	85
+#define RK_GPIO2_C6	86
+#define RK_GPIO2_C7	87
+#define RK_GPIO2_D0	88
+#define RK_GPIO2_D1	89
+#define RK_GPIO2_D2	90
+#define RK_GPIO2_D3	91
+#define RK_GPIO2_D4	92
+#define RK_GPIO2_D5	93
+#define RK_GPIO2_D6	94
+#define RK_GPIO2_D7	95
+
+#define RK_GPIO3_A0	96
+#define RK_GPIO3_A1	97
+#define RK_GPIO3_A2	98
+#define RK_GPIO3_A3	99
+#define RK_GPIO3_A4	100
+#define RK_GPIO3_A5	101
+#define RK_GPIO3_A6	102
+#define RK_GPIO3_A7	103
+#define RK_GPIO3_B0	104
+#define RK_GPIO3_B1	105
+#define RK_GPIO3_B2	106
+#define RK_GPIO3_B3	107
+#define RK_GPIO3_B4	108
+#define RK_GPIO3_B5	109
+#define RK_GPIO3_B6	110
+#define RK_GPIO3_B7	111
+#define RK_GPIO3_C0	112
+#define RK_GPIO3_C1	113
+#define RK_GPIO3_C2	114
+#define RK_GPIO3_C3	115
+#define RK_GPIO3_C4	116
+#define RK_GPIO3_C5	117
+#define RK_GPIO3_C6	118
+#define RK_GPIO3_C7	119
+#define RK_GPIO3_D0	120
+#define RK_GPIO3_D1	121
+#define RK_GPIO3_D2	122
+#define RK_GPIO3_D3	123
+#define RK_GPIO3_D4	124
+#define RK_GPIO3_D5	125
+#define RK_GPIO3_D6	126
+#define RK_GPIO3_D7	127
+
+#define RK_GPIO4_A0	128
+#define RK_GPIO4_A1	129
+#define RK_GPIO4_A2	130
+#define RK_GPIO4_A3	131
+#define RK_GPIO4_A4	132
+#define RK_GPIO4_A5	133
+#define RK_GPIO4_A6	134
+#define RK_GPIO4_A7	135
+#define RK_GPIO4_B0	136
+#define RK_GPIO4_B1	137
+#define RK_GPIO4_B2	138
+#define RK_GPIO4_B3	139
+#define RK_GPIO4_B4	140
+#define RK_GPIO4_B5	141
+#define RK_GPIO4_B6	142
+#define RK_GPIO4_B7	143
+#define RK_GPIO4_C0	144
+#define RK_GPIO4_C1	145
+#define RK_GPIO4_C2	146
+#define RK_GPIO4_C3	147
+#define RK_GPIO4_C4	148
+#define RK_GPIO4_C5	149
+#define RK_GPIO4_C6	150
+#define RK_GPIO4_C7	151
+#define RK_GPIO4_D0	152
+#define RK_GPIO4_D1	153
+#define RK_GPIO4_D2	154
+#define RK_GPIO4_D3	155
+#define RK_GPIO4_D4	156
+#define RK_GPIO4_D5	157
+#define RK_GPIO4_D6	158
+#define RK_GPIO4_D7	159
+
 enum rockchip_pinctrl_type {
+	PX30,
+	RV1108,
+	RV1126,
 	RK2928,
 	RK3066B,
+	RK3128,
 	RK3188,
+	RK3288,
+	RK3308,
+	RK3368,
+	RK3399,
 	RK3568,
+	RK3588,
+};
+
+/**
+ * struct rockchip_gpio_regs
+ * @port_dr: data register
+ * @port_ddr: data direction register
+ * @int_en: interrupt enable
+ * @int_mask: interrupt mask
+ * @int_type: interrupt trigger type, such as high, low, edge trriger type.
+ * @int_polarity: interrupt polarity enable register
+ * @int_bothedge: interrupt bothedge enable register
+ * @int_status: interrupt status register
+ * @int_rawstatus: int_status = int_rawstatus & int_mask
+ * @debounce: enable debounce for interrupt signal
+ * @dbclk_div_en: enable divider for debounce clock
+ * @dbclk_div_con: setting for divider of debounce clock
+ * @port_eoi: end of interrupt of the port
+ * @ext_port: port data from external
+ * @version_id: controller version register
+ */
+struct rockchip_gpio_regs {
+	u32 port_dr;
+	u32 port_ddr;
+	u32 int_en;
+	u32 int_mask;
+	u32 int_type;
+	u32 int_polarity;
+	u32 int_bothedge;
+	u32 int_status;
+	u32 int_rawstatus;
+	u32 debounce;
+	u32 dbclk_div_en;
+	u32 dbclk_div_con;
+	u32 port_eoi;
+	u32 ext_port;
+	u32 version_id;
 };
 
 /**
@@ -72,41 +282,73 @@ struct rockchip_drv {
 	int				offset;
 };
 
-enum rockchip_pin_bank_type {
-	COMMON_BANK,
-	RK3188_BANK0,
-};
-
 /**
  * struct rockchip_pin_bank
- * @reg_base: register base of the gpio bank
+ * @dev: the pinctrl device bind to the bank
+ * @regmap_pull: optional separate register for additional pull settings
  * @clk: clock of the gpio bank
+ * @db_clk: clock of the gpio debounce
+ * @irq: interrupt of the gpio bank
+ * @saved_masks: Saved content of GPIO_INTEN at suspend time.
  * @pin_base: first pin number
  * @nr_pins: number of pins in this bank
  * @name: name of the bank
  * @bank_num: number of the bank, to account for holes
  * @iomux: array describing the 4 iomux sources of the bank
  * @drv: array describing the 4 drive strength sources of the bank
+ * @pull_type: array describing the 4 pull type sources of the bank
  * @valid: is all necessary information present
  * @of_node: dt node of this bank
  * @drvdata: common pinctrl basedata
+ * @domain: irqdomain of the gpio bank
+ * @gpio_chip: gpiolib chip
+ * @grange: gpio range
+ * @slock: spinlock for the gpio bank
+ * @toggle_edge_mode: bit mask to toggle (falling/rising) edge mode
+ * @recalced_mask: bit mask to indicate a need to recalulate the mask
  * @route_mask: bits describing the routing pins of per bank
+ * @deferred_output: gpio output settings to be done after gpio bank probed
+ * @deferred_lock: mutex for the deferred_output shared btw gpio and pinctrl
  */
 struct rockchip_pin_bank {
-	void __iomem			*reg_base;
+	struct device			*dev;
+	struct regmap			*regmap_pull;
 	struct clk			*clk;
+	struct clk			*db_clk;
+	int				irq;
+	u32				saved_masks;
 	u32				pin_base;
 	u8				nr_pins;
 	char				*name;
 	u8				bank_num;
 	struct rockchip_iomux		iomux[4];
 	struct rockchip_drv		drv[4];
-	enum rockchip_pin_bank_type	bank_type;
+	enum rockchip_pin_pull_type	pull_type[4];
 	bool				valid;
 	struct device_node		*of_node;
 	struct rockchip_pinctrl		*drvdata;
 	struct bgpio_chip		bgpio_chip;
+	u32				gpio_type;
+	u32				toggle_edge_mode;
+	u32				recalced_mask;
 	u32				route_mask;
+	struct list_head		deferred_pins;
+};
+
+/**
+ * struct rockchip_mux_recalced_data: represent a pin iomux data.
+ * @num: bank number.
+ * @pin: pin number.
+ * @bit: index at register.
+ * @reg: register offset.
+ * @mask: mask bit
+ */
+struct rockchip_mux_recalced_data {
+	u8 num;
+	u8 pin;
+	u32 reg;
+	u8 bit;
+	u8 mask;
 };
 
 enum rockchip_mux_route_location {
@@ -143,19 +385,68 @@ struct rockchip_pin_ctrl {
 	int				pmu_mux_offset;
 	int				grf_drv_offset;
 	int				pmu_drv_offset;
+	struct rockchip_mux_recalced_data *iomux_recalced;
+	u32				niomux_recalced;
 	struct rockchip_mux_route_data *iomux_routes;
 	u32				niomux_routes;
-	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num,
-				 void __iomem **reg, u8 *bit);
-	void	(*drv_calc_reg)(struct rockchip_pin_bank *bank,
-				    int pin_num, void __iomem **reg, u8 *bit);
+
+	int	(*pull_calc_reg)(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit);
+	int	(*drv_calc_reg)(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit);
+	int	(*schmitt_calc_reg)(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit);
+};
+
+struct rockchip_pin_config {
+	unsigned int		func;
+	unsigned long		*configs;
+	unsigned int		nconfigs;
+};
+
+struct rockchip_pin_deferred {
+	struct list_head head;
+	unsigned int pin;
+	u32 arg;
+};
+
+/**
+ * struct rockchip_pin_group: represent group of pins of a pinmux function.
+ * @name: name of the pin group, used to lookup the group.
+ * @pins: the pins included in this group.
+ * @npins: number of pins included in this group.
+ * @data: local pin configuration
+ */
+struct rockchip_pin_group {
+	const char			*name;
+	unsigned int			npins;
+	unsigned int			*pins;
+	struct rockchip_pin_config	*data;
+};
+
+/**
+ * struct rockchip_pmx_func: represent a pin function.
+ * @name: name of the pin function, used to lookup the function.
+ * @groups: one or more names of pin groups that provide this function.
+ * @ngroups: number of groups included in @groups.
+ */
+struct rockchip_pmx_func {
+	const char		*name;
+	const char		**groups;
+	u8			ngroups;
 };
 
 struct rockchip_pinctrl {
-	void __iomem			*reg_base;
-	void __iomem			*reg_pmu;
-	struct pinctrl_device		pctl_dev;
+	struct regmap			*regmap_base;
+	int				reg_size;
+	struct regmap			*regmap_pull;
+	struct regmap			*regmap_pmu;
+	struct device			*dev;
 	struct rockchip_pin_ctrl	*ctrl;
+	struct pinctrl_device		pctl_dev;
 };
 
 #endif
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 10/18] phy: rockchip: naneng-combphy: add rk3588 support
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (8 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 09/18] pinctrl: Update pinctrl-rockchip from kernel Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 11/18] reset: Implement reset array support Sascha Hauer
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../rockchip/phy-rockchip-naneng-combphy.c    | 278 ++++++++++++++++++
 1 file changed, 278 insertions(+)

diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
index bd5dff954e..2c0e629bab 100644
--- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
@@ -41,6 +41,7 @@ struct rockchip_combphy_grfcfg {
 	struct combphy_reg pipe_rxterm_set;
 	struct combphy_reg pipe_txelec_set;
 	struct combphy_reg pipe_txcomp_set;
+	struct combphy_reg pipe_clk_24m;
 	struct combphy_reg pipe_clk_25m;
 	struct combphy_reg pipe_clk_100m;
 	struct combphy_reg pipe_phymode_sel;
@@ -61,6 +62,7 @@ struct rockchip_combphy_grfcfg {
 	struct combphy_reg con2_for_sata;
 	struct combphy_reg con3_for_sata;
 	struct combphy_reg pipe_con0_for_sata;
+	struct combphy_reg pipe_con1_for_sata;
 	struct combphy_reg pipe_sgmii_mac_sel;
 	struct combphy_reg pipe_xpcs_phy_ready;
 	struct combphy_reg u3otg0_port_en;
@@ -71,6 +73,7 @@ struct rockchip_combphy_cfg {
 	const int num_clks;
 	const struct clk_bulk_data *clks;
 	const struct rockchip_combphy_grfcfg *grfcfg;
+	bool force_det_out; /* Tx detect Rx errata */
 	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
 };
 
@@ -580,10 +583,285 @@ static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
 	.combphy_cfg	= rk3568_combphy_cfg,
 };
 
+static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
+{
+	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
+	struct clk *refclk = NULL;
+	unsigned long rate;
+	int i;
+	u32 val;
+
+	/* Configure PHY reference clock frequency */
+	for (i = 0; i < priv->num_clks; i++) {
+		if (!strncmp(priv->clks[i].id, "refclk", 6)) {
+			refclk = priv->clks[i].clk;
+			break;
+		}
+	}
+
+	if (!refclk) {
+		dev_err(priv->dev, "No refclk found\n");
+		return -EINVAL;
+	}
+
+	switch (priv->mode) {
+	case PHY_TYPE_PCIE:
+		/* Set SSC downward spread spectrum */
+		val = readl(priv->mmio + (0x1f << 2));
+		val &= ~GENMASK(5, 4);
+		val |= 0x01 << 4;
+		writel(val, priv->mmio + 0x7c);
+
+		param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
+		param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
+		param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
+		param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
+		break;
+	case PHY_TYPE_USB3:
+		/* Set SSC downward spread spectrum */
+		val = readl(priv->mmio + (0x1f << 2));
+		val &= ~GENMASK(5, 4);
+		val |= 0x01 << 4;
+		writel(val, priv->mmio + 0x7c);
+
+		/* Enable adaptive CTLE for USB3.0 Rx */
+		val = readl(priv->mmio + (0x0e << 2));
+		val &= ~GENMASK(0, 0);
+		val |= 0x01;
+		writel(val, priv->mmio + (0x0e << 2));
+
+		/* Set PLL KVCO fine tuning signals */
+		val = readl(priv->mmio + (0x20 << 2));
+		val &= ~(0x7 << 2);
+		val |= 0x2 << 2;
+		writel(val, priv->mmio + (0x20 << 2));
+
+		/* Set PLL LPF R1 to su_trim[10:7]=1001 */
+		writel(0x4, priv->mmio + (0xb << 2));
+
+		/* Set PLL input clock divider 1/2 */
+		val = readl(priv->mmio + (0x5 << 2));
+		val &= ~(0x3 << 6);
+		val |= 0x1 << 6;
+		writel(val, priv->mmio + (0x5 << 2));
+
+		/* Set PLL loop divider */
+		writel(0x32, priv->mmio + (0x11 << 2));
+
+		/* Set PLL KVCO to min and set PLL charge pump current to max */
+		writel(0xf0, priv->mmio + (0xa << 2));
+
+		/* Set Rx squelch input filler bandwidth */
+		writel(0x0d, priv->mmio + (0x14 << 2));
+
+		param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
+		param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
+		param_write(priv->phy_grf, &cfg->usb_mode_set, true);
+		break;
+	case PHY_TYPE_SATA:
+		/* Enable adaptive CTLE for SATA Rx */
+		val = readl(priv->mmio + (0x0e << 2));
+		val &= ~GENMASK(0, 0);
+		val |= 0x01;
+		writel(val, priv->mmio + (0x0e << 2));
+		/* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */
+		writel(0x8F, priv->mmio + (0x06 << 2));
+
+		param_write(priv->phy_grf, &cfg->con0_for_sata, true);
+		param_write(priv->phy_grf, &cfg->con1_for_sata, true);
+		param_write(priv->phy_grf, &cfg->con2_for_sata, true);
+		param_write(priv->phy_grf, &cfg->con3_for_sata, true);
+		param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
+		param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
+		break;
+	case PHY_TYPE_SGMII:
+	case PHY_TYPE_QSGMII:
+	default:
+		dev_err(priv->dev, "incompatible PHY type\n");
+		return -EINVAL;
+	}
+
+	rate = clk_get_rate(refclk);
+
+	switch (rate) {
+	case 24000000:
+		param_write(priv->phy_grf, &cfg->pipe_clk_24m, true);
+		if (priv->mode == PHY_TYPE_USB3 || priv->mode == PHY_TYPE_SATA) {
+			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz */
+			val = readl(priv->mmio + (0x0e << 2));
+			val &= ~GENMASK(7, 6);
+			val |= 0x01 << 6;
+			writel(val, priv->mmio + (0x0e << 2));
+
+			val = readl(priv->mmio + (0x0f << 2));
+			val &= ~GENMASK(7, 0);
+			val |= 0x5f;
+			writel(val, priv->mmio + (0x0f << 2));
+		} else if (priv->mode == PHY_TYPE_PCIE) {
+			/* PLL KVCO tuning fine */
+			val = readl(priv->mmio + (0x20 << 2));
+			val &= ~GENMASK(4, 2);
+			val |= 0x4 << 2;
+			writel(val, priv->mmio + (0x20 << 2));
+
+			/* Set up rx_trim */
+			val = 0x0;
+			writel(val, priv->mmio + (0x1b << 2));
+
+			/* Set up su_trim: T0_1 */
+			val = 0x90;
+			writel(val, priv->mmio + (0xa << 2));
+			val = 0x02;
+			writel(val, priv->mmio + (0xb << 2));
+			val = 0x57;
+			writel(val, priv->mmio + (0xd << 2));
+
+			val = 0x5f;
+			writel(val, priv->mmio + (0xf << 2));
+		}
+		break;
+	case 25000000:
+		param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
+		break;
+	case 100000000:
+		param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
+		if (priv->mode == PHY_TYPE_PCIE) {
+			/* gate_tx_pck_sel length select work for L1SS */
+			val = 0xc0;
+			writel(val, priv->mmio + 0x74);
+
+			/* PLL KVCO tuning fine */
+			val = readl(priv->mmio + (0x20 << 2));
+			val &= ~GENMASK(4, 2);
+			val |= 0x4 << 2;
+			writel(val, priv->mmio + (0x20 << 2));
+
+			/* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
+			val = 0x4c;
+			writel(val, priv->mmio + (0x1b << 2));
+
+			/* Set up su_trim: T3_P1 650mv */
+			val = 0x90;
+			writel(val, priv->mmio + (0xa << 2));
+			val = 0x43;
+			writel(val, priv->mmio + (0xb << 2));
+			val = 0x88;
+			writel(val, priv->mmio + (0xc << 2));
+			val = 0x56;
+			writel(val, priv->mmio + (0xd << 2));
+		} else if (priv->mode == PHY_TYPE_SATA) {
+			/* downward spread spectrum +500ppm */
+			val = readl(priv->mmio + (0x1f << 2));
+			val &= ~GENMASK(7, 4);
+			val |= 0x50;
+			writel(val, priv->mmio + (0x1f << 2));
+
+			/* ssc ppm adjust to 3500ppm */
+			val = readl(priv->mmio + (0x9 << 2));
+			val &= ~GENMASK(3, 0);
+			val |= 0x7;
+			writel(val, priv->mmio + (0x9 << 2));
+		}
+		break;
+	default:
+		dev_err(priv->dev, "Unsupported rate: %lu\n", rate);
+		return -EINVAL;
+	}
+
+	if (of_property_read_bool(priv->dev->of_node, "rockchip,ext-refclk")) {
+		param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
+		if (priv->mode == PHY_TYPE_PCIE && rate == 100000000) {
+			val = 0x10;
+			writel(val, priv->mmio + (0x20 << 2));
+
+			val = 0x0c;
+			writel(val, priv->mmio + (0x1b << 2));
+
+			/* Set up su_trim: T3_P1 650mv */
+			val = 0x90;
+			writel(val, priv->mmio + (0xa << 2));
+			val = 0x43;
+			writel(val, priv->mmio + (0xb << 2));
+			val = 0x88;
+			writel(val, priv->mmio + (0xc << 2));
+			val = 0x56;
+			writel(val, priv->mmio + (0xd << 2));
+		}
+	}
+
+	if (of_property_read_bool(priv->dev->of_node, "rockchip,enable-ssc")) {
+		val = readl(priv->mmio + (0x7 << 2));
+		val |= BIT(4);
+		writel(val, priv->mmio + (0x7 << 2));
+
+		if (priv->mode == PHY_TYPE_PCIE && rate == 24000000) {
+			/* Xin24M T0_1 650mV */
+			writel(0x00, priv->mmio + (0x10 << 2));
+			writel(0x32, priv->mmio + (0x11 << 2));
+			writel(0x00, priv->mmio + (0x1b << 2));
+			writel(0x90, priv->mmio + (0x0a << 2));
+			writel(0x02, priv->mmio + (0x0b << 2));
+			writel(0x08, priv->mmio + (0x0c << 2));
+			writel(0x57, priv->mmio + (0x0d << 2));
+			writel(0x40, priv->mmio + (0x0e << 2));
+			writel(0x5f, priv->mmio + (0x0f << 2));
+			writel(0x10, priv->mmio + (0x20 << 2));
+		}
+	}
+
+	return 0;
+}
+
+static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
+	/* pipe-phy-grf */
+	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
+	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
+	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
+	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
+	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
+	.pipe_clk_24m		= { 0x0004, 14, 13, 0x00, 0x00 },
+	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
+	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
+	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
+	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
+	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
+	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
+	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
+	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
+	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
+	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
+	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
+	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0129 },
+	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0000 },
+	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c1 },
+	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x0407 },
+	/* pipe-grf */
+	.pipe_con0_for_sata	= { 0x0000, 11, 5, 0x00, 0x22 },
+	.pipe_con1_for_sata	= { 0x0004, 2, 0, 0x00, 0x2 },
+};
+
+
+static const struct clk_bulk_data rk3588_clks[] = {
+	{ .id = "refclk" },
+	{ .id = "apbclk" },
+	{ .id = "phpclk" },
+};
+
+static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
+	.num_clks	= ARRAY_SIZE(rk3588_clks),
+	.clks		= rk3588_clks,
+	.grfcfg		= &rk3588_combphy_grfcfgs,
+	.combphy_cfg	= rk3588_combphy_cfg,
+	.force_det_out	= true,
+};
+
 static const struct of_device_id rockchip_combphy_of_match[] = {
 	{
 		.compatible = "rockchip,rk3568-naneng-combphy",
 		.data = &rk3568_combphy_cfgs,
+	}, {
+		.compatible = "rockchip,rk3588-naneng-combphy",
+		.data = &rk3588_combphy_cfgs,
 	},
 	{ },
 };
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 11/18] reset: Implement reset array support
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (9 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 10/18] phy: rockchip: naneng-combphy: add rk3588 support Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 12/18] pci: designware: add rockchip support Sascha Hauer
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Add support for reset arrays, needed by the Rockchip PCIe driver.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/reset/core.c  | 127 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/reset.h |   7 +++
 2 files changed, 134 insertions(+)

diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 5ab21ac95e..94bfad2067 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -31,6 +31,19 @@ struct reset_control {
 
 	struct device *dev;
 	unsigned int id;
+	bool array;
+};
+
+/**
+ * struct reset_control_array - an array of reset controls
+ * @base: reset control for compatibility with reset control API functions
+ * @num_rstcs: number of reset controls
+ * @rstc: array of reset controls
+ */
+struct reset_control_array {
+	struct reset_control base;
+	unsigned int num_rstcs;
+	struct reset_control *rstc[];
 };
 
 /**
@@ -102,6 +115,65 @@ int reset_control_status(struct reset_control *rstc)
 }
 EXPORT_SYMBOL_GPL(reset_control_status);
 
+static inline struct reset_control_array *
+rstc_to_array(struct reset_control *rstc) {
+	return container_of(rstc, struct reset_control_array, base);
+}
+
+static int reset_control_array_reset(struct reset_control_array *resets)
+{
+	int ret, i;
+
+	for (i = 0; i < resets->num_rstcs; i++) {
+		ret = reset_control_reset(resets->rstc[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int reset_control_array_assert(struct reset_control_array *resets)
+{
+	int ret, i;
+
+	for (i = 0; i < resets->num_rstcs; i++) {
+		ret = reset_control_assert(resets->rstc[i]);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	while (i--)
+		reset_control_deassert(resets->rstc[i]);
+	return ret;
+}
+
+static int reset_control_array_deassert(struct reset_control_array *resets)
+{
+	int ret, i;
+
+	for (i = 0; i < resets->num_rstcs; i++) {
+		ret = reset_control_deassert(resets->rstc[i]);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	while (i--)
+		reset_control_assert(resets->rstc[i]);
+	return ret;
+}
+
+static inline bool reset_control_is_array(struct reset_control *rstc)
+{
+	return rstc->array;
+}
+
 /**
  * reset_control_reset - reset the controlled device
  * @rstc: reset controller
@@ -111,6 +183,9 @@ int reset_control_reset(struct reset_control *rstc)
 	if (!rstc)
 		return 0;
 
+	if (reset_control_is_array(rstc))
+		return reset_control_array_reset(rstc_to_array(rstc));
+
 	if (rstc->rcdev->ops->reset)
 		return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
 
@@ -127,6 +202,9 @@ int reset_control_assert(struct reset_control *rstc)
 	if (!rstc)
 		return 0;
 
+	if (reset_control_is_array(rstc))
+		return reset_control_array_assert(rstc_to_array(rstc));
+
 	if (rstc->gpio >= 0)
 		return gpio_direction_output(rstc->gpio, rstc->gpio_active_high);
 
@@ -146,6 +224,9 @@ int reset_control_deassert(struct reset_control *rstc)
 	if (!rstc)
 		return 0;
 
+	if (reset_control_is_array(rstc))
+		return reset_control_array_deassert(rstc_to_array(rstc));
+
 	if (rstc->gpio >= 0)
 		return gpio_direction_output(rstc->gpio, !rstc->gpio_active_high);
 
@@ -352,6 +433,52 @@ int device_reset(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_reset);
 
+/*
+ * APIs to manage an array of reset controls.
+ */
+
+/**
+ * reset_control_array_get - Get a list of reset controls
+ *
+ * @dev: device that requests the reset controls array
+ *
+ * Returns pointer to allocated reset_control on success or error on failure
+ */
+struct reset_control *reset_control_array_get(struct device *dev)
+{
+	struct reset_control_array *resets;
+	struct reset_control *rstc;
+	struct device_node *np = dev->of_node;
+	int num, i;
+
+	num = reset_control_get_count(dev);
+	if (num < 0)
+		return ERR_PTR(num);
+
+	resets = kzalloc(struct_size(resets, rstc, num), GFP_KERNEL);
+	if (!resets)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < num; i++) {
+		rstc = of_reset_control_get_by_index(np, i);
+		if (IS_ERR(rstc))
+			goto err_rst;
+		resets->rstc[i] = rstc;
+	}
+	resets->num_rstcs = num;
+	resets->base.array = true;
+
+	return &resets->base;
+
+err_rst:
+	while (--i >= 0)
+		reset_control_put(resets->rstc[i]);
+
+	kfree(resets);
+
+	return rstc;
+}
+
 int device_reset_all(struct device *dev)
 {
 	struct reset_control *rstc;
diff --git a/include/linux/reset.h b/include/linux/reset.h
index 7a08b8f945..7db3d3162a 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -26,6 +26,8 @@ int __must_check device_reset_all(struct device *dev);
 
 int reset_control_get_count(struct device *dev);
 
+struct reset_control *reset_control_array_get(struct device *dev);
+
 #else
 
 static inline int reset_control_status(struct reset_control *rstc)
@@ -84,6 +86,11 @@ static inline int reset_control_get_count(struct device *dev)
 	return 0;
 }
 
+static inline struct reset_control *reset_control_array_get(struct device *dev)
+{
+	return NULL;
+}
+
 #endif /* CONFIG_RESET_CONTROLLER */
 
 static inline struct reset_control *reset_control_get_optional(struct device *dev,
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 12/18] pci: designware: add rockchip support
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (10 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 11/18] reset: Implement reset array support Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 13/18] phy: realtek: Add RTL8125 internal phy support Sascha Hauer
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Add support for the PCIe controller found on Rockchip RK3568 and RK3588
SoCs. Based on Linux-6.3-rc7.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-rockchip/Kconfig |   1 +
 drivers/pci/Kconfig            |   7 +
 drivers/pci/Makefile           |   1 +
 drivers/pci/pcie-dw-rockchip.c | 299 +++++++++++++++++++++++++++++++++
 4 files changed, 308 insertions(+)
 create mode 100644 drivers/pci/pcie-dw-rockchip.c

diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 0bce83ecee..6f32a440a1 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -45,6 +45,7 @@ config ARCH_RK3399PRO
 config ARCH_RK3568
 	bool
 	select ARCH_ROCKCHIP_V8
+	select HW_HAS_PCI
 
 comment "select Rockchip boards:"
 
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index e7ce6a8c45..32a9e831b9 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -55,6 +55,13 @@ config PCI_LAYERSCAPE
 	select OF_PCI
 	select PCI
 
+config PCI_ROCKCHIP
+	bool "Rockchip PCIe controller"
+	depends on ARCH_ROCKCHIP
+	select PCIE_DW
+	select OF_PCI
+	select PCI
+
 config PCI_EFI
 	bool "EFI PCI protocol"
 	depends on EFI_BOOTUP
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index deed79601d..9249bffecb 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
 obj-$(CONFIG_PCI_EFI) += pci-efi.o
 obj-$(CONFIG_PCI_ECAM_GENERIC) += pci-ecam-generic.o
+obj-$(CONFIG_PCI_ROCKCHIP) += pcie-dw-rockchip.o
diff --git a/drivers/pci/pcie-dw-rockchip.c b/drivers/pci/pcie-dw-rockchip.c
new file mode 100644
index 0000000000..e82047b388
--- /dev/null
+++ b/drivers/pci/pcie-dw-rockchip.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Rockchip SoCs.
+ *
+ * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
+ *		http://www.rock-chips.com
+ *
+ * Author: Simon Xue <xxm@rock-chips.com>
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <abort.h>
+#include <malloc.h>
+#include <io.h>
+#include <init.h>
+#include <gpio.h>
+#include <asm/mmu.h>
+#include <of_gpio.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <of_address.h>
+#include <of_pci.h>
+#include <gpiod.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/reset.h>
+#include <linux/sizes.h>
+#include <linux/bitfield.h>
+
+#include "pcie-designware.h"
+
+/*
+ * The upper 16 bits of PCIE_CLIENT_CONFIG are a write
+ * mask for the lower 16 bits.
+ */
+#define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val))
+#define HIWORD_UPDATE_BIT(val)	HIWORD_UPDATE(val, val)
+#define HIWORD_DISABLE_BIT(val)	HIWORD_UPDATE(val, ~val)
+
+#define PCIE_CLIENT_RC_MODE		HIWORD_UPDATE_BIT(0x40)
+#define PCIE_CLIENT_ENABLE_LTSSM	HIWORD_UPDATE_BIT(0xc)
+#define PCIE_SMLH_LINKUP		BIT(16)
+#define PCIE_RDLH_LINKUP		BIT(17)
+#define PCIE_LINKUP			(PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP)
+#define PCIE_L0S_ENTRY			0x11
+#define PCIE_CLIENT_GENERAL_CONTROL	0x0
+#define PCIE_CLIENT_INTR_STATUS_LEGACY	0x8
+#define PCIE_CLIENT_INTR_MASK_LEGACY	0x1c
+#define PCIE_CLIENT_GENERAL_DEBUG	0x104
+#define PCIE_CLIENT_HOT_RESET_CTRL	0x180
+#define PCIE_CLIENT_LTSSM_STATUS	0x300
+#define PCIE_LTSSM_ENABLE_ENHANCE	BIT(4)
+#define PCIE_LTSSM_STATUS_MASK		GENMASK(5, 0)
+
+struct rockchip_pcie {
+	struct dw_pcie			pci;
+	void __iomem			*apb_base;
+	struct phy			*phy;
+	struct clk_bulk_data		*clks;
+	unsigned int			clk_cnt;
+	struct reset_control		*rst;
+	int				rst_gpio;
+	struct regulator                *vpcie3v3;
+	struct irq_domain		*irq_domain;
+};
+
+static inline struct rockchip_pcie *to_rockchip_pcie(struct dw_pcie *dw)
+{
+	return container_of(dw, struct rockchip_pcie, pci);
+}
+
+static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip,
+					     u32 reg)
+{
+	return readl_relaxed(rockchip->apb_base + reg);
+}
+
+static void rockchip_pcie_writel_apb(struct rockchip_pcie *rockchip,
+						u32 val, u32 reg)
+{
+	writel_relaxed(val, rockchip->apb_base + reg);
+}
+
+static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)
+{
+	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM,
+				 PCIE_CLIENT_GENERAL_CONTROL);
+}
+
+static int rockchip_pcie_link_up(struct dw_pcie *pci)
+{
+	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+	u32 val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS);
+
+	if ((val & PCIE_LINKUP) == PCIE_LINKUP &&
+	    (val & PCIE_LTSSM_STATUS_MASK) == PCIE_L0S_ENTRY)
+		return 1;
+
+	return 0;
+}
+
+static int rockchip_pcie_start_link(struct dw_pcie *pci)
+{
+	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+
+	/* Reset device */
+	gpio_set_value(rockchip->rst_gpio, 0);
+
+	rockchip_pcie_enable_ltssm(rockchip);
+
+	/*
+	 * PCIe requires the refclk to be stable for 100µs prior to releasing
+	 * PERST. See table 2-4 in section 2.6.2 AC Specifications of the PCI
+	 * Express Card Electromechanical Specification, 1.1. However, we don't
+	 * know if the refclk is coming from RC's PHY or external OSC. If it's
+	 * from RC, so enabling LTSSM is the just right place to release #PERST.
+	 * We need more extra time as before, rather than setting just
+	 * 100us as we don't know how long should the device need to reset.
+	 */
+	mdelay(100);
+	gpio_set_value(rockchip->rst_gpio, 1);
+
+	return 0;
+}
+
+static int rockchip_pcie_host_init(struct pcie_port *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+	u32 val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE);
+
+	/* LTSSM enable control mode */
+	rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
+
+	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE,
+				 PCIE_CLIENT_GENERAL_CONTROL);
+
+	dw_pcie_setup_rc(pp);
+	rockchip_pcie_start_link(pci);
+
+	return 0;
+}
+
+static const struct dw_pcie_host_ops rockchip_pcie_host_ops = {
+	.host_init = rockchip_pcie_host_init,
+};
+
+static int rockchip_pcie_clk_init(struct rockchip_pcie *rockchip)
+{
+	struct device *dev = rockchip->pci.dev;
+	int ret;
+
+	ret = clk_bulk_get_all(dev, &rockchip->clks);
+	if (ret < 0)
+		return ret;
+
+	rockchip->clk_cnt = ret;
+
+	return clk_bulk_enable(rockchip->clk_cnt, rockchip->clks);
+}
+
+static int rockchip_pcie_resource_get(struct device *dev,
+				      struct rockchip_pcie *rockchip)
+{
+	struct resource *r;
+
+	r = dev_request_mem_resource_by_name(dev, "apb");
+	if (IS_ERR(r))
+		return PTR_ERR(r);
+	rockchip->apb_base = IOMEM(r->start);
+
+
+	r = dev_request_mem_resource_by_name(dev, "dbi");
+	if (IS_ERR(r))
+		return PTR_ERR(r);
+	rockchip->pci.dbi_base = IOMEM(r->start);
+
+	rockchip->rst_gpio = gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (rockchip->rst_gpio < 0 && rockchip->rst_gpio != -ENOENT)
+		return rockchip->rst_gpio;
+
+	rockchip->rst = reset_control_array_get(dev);
+	if (IS_ERR(rockchip->rst))
+		return dev_err_probe(dev, PTR_ERR(rockchip->rst),
+				     "failed to get reset lines\n");
+
+	return 0;
+}
+
+static int rockchip_pcie_phy_init(struct rockchip_pcie *rockchip)
+{
+	struct device *dev = rockchip->pci.dev;
+	int ret;
+
+	rockchip->phy = phy_get(dev, "pcie-phy");
+	if (IS_ERR(rockchip->phy))
+		return dev_err_probe(dev, PTR_ERR(rockchip->phy),
+				     "missing PHY\n");
+
+	ret = phy_init(rockchip->phy);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_power_on(rockchip->phy);
+	if (ret)
+		phy_exit(rockchip->phy);
+
+	return ret;
+}
+
+static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)
+{
+	phy_exit(rockchip->phy);
+	phy_power_off(rockchip->phy);
+}
+
+static const struct dw_pcie_ops dw_pcie_ops = {
+	.link_up = rockchip_pcie_link_up,
+};
+
+static int rockchip_pcie_probe(struct device *dev)
+{
+	struct rockchip_pcie *rockchip;
+	struct pcie_port *pp;
+	int ret;
+
+	rockchip = xzalloc(sizeof(*rockchip));
+	if (!rockchip)
+		return -ENOMEM;
+
+	rockchip->pci.dev = dev;
+	rockchip->pci.ops = &dw_pcie_ops;
+
+	pp = &rockchip->pci.pp;
+	pp->ops = &rockchip_pcie_host_ops;
+
+	ret = rockchip_pcie_resource_get(dev, rockchip);
+	if (ret)
+		return ret;
+
+	ret = reset_control_assert(rockchip->rst);
+	if (ret)
+		return ret;
+
+	/* DON'T MOVE ME: must be enable before PHY init */
+	rockchip->vpcie3v3 = regulator_get(dev, "vpcie3v3");
+	if (IS_ERR(rockchip->vpcie3v3)) {
+		if (PTR_ERR(rockchip->vpcie3v3) != -ENODEV)
+			return dev_err_probe(dev, PTR_ERR(rockchip->vpcie3v3),
+					"failed to get vpcie3v3 regulator\n");
+		rockchip->vpcie3v3 = NULL;
+	} else {
+		ret = regulator_enable(rockchip->vpcie3v3);
+		if (ret) {
+			dev_err(dev, "failed to enable vpcie3v3 regulator\n");
+			return ret;
+		}
+	}
+
+	ret = rockchip_pcie_phy_init(rockchip);
+	if (ret)
+		goto disable_regulator;
+
+	ret = reset_control_deassert(rockchip->rst);
+	if (ret)
+		goto deinit_phy;
+
+	ret = rockchip_pcie_clk_init(rockchip);
+	if (ret)
+		goto deinit_phy;
+
+	ret = dw_pcie_host_init(pp);
+	if (!ret)
+		return 0;
+
+	clk_bulk_disable(rockchip->clk_cnt, rockchip->clks);
+deinit_phy:
+	rockchip_pcie_phy_deinit(rockchip);
+disable_regulator:
+	if (rockchip->vpcie3v3)
+		regulator_disable(rockchip->vpcie3v3);
+
+	return ret;
+}
+
+static const struct of_device_id rockchip_pcie_of_match[] = {
+	{ .compatible = "rockchip,rk3568-pcie", },
+	{ .compatible = "rockchip,rk3588-pcie", },
+	{},
+};
+
+static struct driver rockchip_pcie_driver = {
+        .name = "rockchip-dw-pcie",
+        .of_compatible = DRV_OF_COMPAT(rockchip_pcie_of_match),
+        .probe = rockchip_pcie_probe,
+};
+device_platform_driver(rockchip_pcie_driver);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 13/18] phy: realtek: Add RTL8125 internal phy support
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (11 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 12/18] pci: designware: add rockchip support Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 14/18] net: Update Realtek r8169 driver Sascha Hauer
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/net/phy/realtek.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 6e064c8f49..c23947b7cb 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -154,6 +154,12 @@ static struct phy_driver realtek_drvs[] = {
 		.features	= PHY_BASIC_FEATURES,
 		.read_page	= rtl821x_read_page,
 		.write_page	= rtl821x_write_page,
+	}, {
+		PHY_ID_MATCH_EXACT(0x001cc840),
+		.drv.name	= "RTL8226B_RTL8221B 2.5Gbps PHY",
+		.features	= PHY_GBIT_FEATURES,
+		.read_page	= rtl821x_read_page,
+		.write_page	= rtl821x_write_page,
 	}, {
 		PHY_ID_MATCH_EXACT(0x001cc910),
 		.drv.name	= "RTL8211 Gigabit Ethernet",
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 14/18] net: Update Realtek r8169 driver
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (12 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 13/18] phy: realtek: Add RTL8125 internal phy support Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 15/18] ARM: rockchip: Add rk3588 support Sascha Hauer
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

This updates the r8169 driver from Linux-6.3-rc7. The driver code itself
is mostly taken from the old driver, but all the initialization code and
file structure has been taken from Linux. Tested on a RTL8125 chip.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/net/Kconfig            |    1 +
 drivers/net/Makefile           |    2 +-
 drivers/net/r8169.h            |   79 +
 drivers/net/r8169_firmware.c   |  237 +++
 drivers/net/r8169_firmware.h   |   36 +
 drivers/net/r8169_main.c       | 3214 ++++++++++++++++++++++++++++++++
 drivers/net/r8169_phy_config.c | 1156 ++++++++++++
 drivers/net/rtl8169.c          |  562 ------
 8 files changed, 4724 insertions(+), 563 deletions(-)
 create mode 100644 drivers/net/r8169.h
 create mode 100644 drivers/net/r8169_firmware.c
 create mode 100644 drivers/net/r8169_firmware.h
 create mode 100644 drivers/net/r8169_main.c
 create mode 100644 drivers/net/r8169_phy_config.c
 delete mode 100644 drivers/net/rtl8169.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 25b46ccb11..1c89cf9e41 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -251,6 +251,7 @@ config DRIVER_NET_RTL8169
 	depends on PCI
 	depends on HAS_DMA
 	select PHYLIB
+	select REALTEK_PHY
 	help
 	  This is a driver for the Fast Ethernet PCI network cards based on
 	  the RTL 8169 chips.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 84d998338a..1a272d9158 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -36,7 +36,7 @@ obj-$(CONFIG_DRIVER_NET_MPC5200)	+= fec_mpc5200.o
 obj-$(CONFIG_DRIVER_NET_MVNETA)		+= mvneta.o
 obj-$(CONFIG_DRIVER_NET_ORION)		+= orion-gbe.o
 obj-$(CONFIG_DRIVER_NET_RTL8139)	+= rtl8139.o
-obj-$(CONFIG_DRIVER_NET_RTL8169)	+= rtl8169.o
+obj-$(CONFIG_DRIVER_NET_RTL8169)	+= r8169_main.o r8169_firmware.o r8169_phy_config.o
 obj-$(CONFIG_DRIVER_NET_SJA1105)	+= sja1105.o
 obj-$(CONFIG_DRIVER_NET_SMC911X)	+= smc911x.o
 obj-$(CONFIG_DRIVER_NET_SMC91111)	+= smc91111.o
diff --git a/drivers/net/r8169.h b/drivers/net/r8169.h
new file mode 100644
index 0000000000..55ef8251fe
--- /dev/null
+++ b/drivers/net/r8169.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* r8169.h: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
+ */
+
+#include <linux/types.h>
+#include <linux/phy.h>
+
+enum mac_version {
+	/* support for ancient RTL_GIGA_MAC_VER_01 has been removed */
+	RTL_GIGA_MAC_VER_02,
+	RTL_GIGA_MAC_VER_03,
+	RTL_GIGA_MAC_VER_04,
+	RTL_GIGA_MAC_VER_05,
+	RTL_GIGA_MAC_VER_06,
+	RTL_GIGA_MAC_VER_07,
+	RTL_GIGA_MAC_VER_08,
+	RTL_GIGA_MAC_VER_09,
+	RTL_GIGA_MAC_VER_10,
+	RTL_GIGA_MAC_VER_11,
+	/* RTL_GIGA_MAC_VER_12 was handled the same as VER_17 */
+	/* RTL_GIGA_MAC_VER_13 was merged with VER_10 */
+	RTL_GIGA_MAC_VER_14,
+	/* RTL_GIGA_MAC_VER_16 was merged with VER_10 */
+	RTL_GIGA_MAC_VER_17,
+	RTL_GIGA_MAC_VER_18,
+	RTL_GIGA_MAC_VER_19,
+	RTL_GIGA_MAC_VER_20,
+	RTL_GIGA_MAC_VER_21,
+	RTL_GIGA_MAC_VER_22,
+	RTL_GIGA_MAC_VER_23,
+	RTL_GIGA_MAC_VER_24,
+	RTL_GIGA_MAC_VER_25,
+	RTL_GIGA_MAC_VER_26,
+	/* support for RTL_GIGA_MAC_VER_27 has been removed */
+	RTL_GIGA_MAC_VER_28,
+	RTL_GIGA_MAC_VER_29,
+	RTL_GIGA_MAC_VER_30,
+	RTL_GIGA_MAC_VER_31,
+	RTL_GIGA_MAC_VER_32,
+	RTL_GIGA_MAC_VER_33,
+	RTL_GIGA_MAC_VER_34,
+	RTL_GIGA_MAC_VER_35,
+	RTL_GIGA_MAC_VER_36,
+	RTL_GIGA_MAC_VER_37,
+	RTL_GIGA_MAC_VER_38,
+	RTL_GIGA_MAC_VER_39,
+	RTL_GIGA_MAC_VER_40,
+	/* support for RTL_GIGA_MAC_VER_41 has been removed */
+	RTL_GIGA_MAC_VER_42,
+	RTL_GIGA_MAC_VER_43,
+	RTL_GIGA_MAC_VER_44,
+	/* support for RTL_GIGA_MAC_VER_45 has been removed */
+	RTL_GIGA_MAC_VER_46,
+	/* support for RTL_GIGA_MAC_VER_47 has been removed */
+	RTL_GIGA_MAC_VER_48,
+	/* support for RTL_GIGA_MAC_VER_49 has been removed */
+	/* support for RTL_GIGA_MAC_VER_50 has been removed */
+	RTL_GIGA_MAC_VER_51,
+	RTL_GIGA_MAC_VER_52,
+	RTL_GIGA_MAC_VER_53,
+	/* support for RTL_GIGA_MAC_VER_60 has been removed */
+	RTL_GIGA_MAC_VER_61,
+	RTL_GIGA_MAC_VER_63,
+	RTL_GIGA_MAC_NONE
+};
+
+struct rtl8169_private;
+
+void r8169_apply_firmware(struct rtl8169_private *tp);
+u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp);
+u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr);
+void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
+			 enum mac_version ver);
diff --git a/drivers/net/r8169_firmware.c b/drivers/net/r8169_firmware.c
new file mode 100644
index 0000000000..29c6be50a7
--- /dev/null
+++ b/drivers/net/r8169_firmware.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
+ */
+
+#include <common.h>
+#include <firmware.h>
+
+#include "r8169_firmware.h"
+
+enum rtl_fw_opcode {
+	PHY_READ		= 0x0,
+	PHY_DATA_OR		= 0x1,
+	PHY_DATA_AND		= 0x2,
+	PHY_BJMPN		= 0x3,
+	PHY_MDIO_CHG		= 0x4,
+	PHY_CLEAR_READCOUNT	= 0x7,
+	PHY_WRITE		= 0x8,
+	PHY_READCOUNT_EQ_SKIP	= 0x9,
+	PHY_COMP_EQ_SKIPN	= 0xa,
+	PHY_COMP_NEQ_SKIPN	= 0xb,
+	PHY_WRITE_PREVIOUS	= 0xc,
+	PHY_SKIPN		= 0xd,
+	PHY_DELAY_MS		= 0xe,
+};
+
+struct fw_info {
+	u32	magic;
+	char	version[RTL_VER_SIZE];
+	__le32	fw_start;
+	__le32	fw_len;
+	u8	chksum;
+} __packed;
+
+#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])
+
+static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
+{
+	const struct firmware *fw = rtl_fw->fw;
+	struct fw_info *fw_info = (struct fw_info *)fw->data;
+	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+
+	if (fw->size < FW_OPCODE_SIZE)
+		return false;
+
+	if (!fw_info->magic) {
+		size_t i, size, start;
+		u8 checksum = 0;
+
+		if (fw->size < sizeof(*fw_info))
+			return false;
+
+		for (i = 0; i < fw->size; i++)
+			checksum += fw->data[i];
+		if (checksum != 0)
+			return false;
+
+		start = le32_to_cpu(fw_info->fw_start);
+		if (start > fw->size)
+			return false;
+
+		size = le32_to_cpu(fw_info->fw_len);
+		if (size > (fw->size - start) / FW_OPCODE_SIZE)
+			return false;
+
+		strlcpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE);
+
+		pa->code = (__le32 *)(fw->data + start);
+		pa->size = size;
+	} else {
+		if (fw->size % FW_OPCODE_SIZE)
+			return false;
+
+		strlcpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE);
+
+		pa->code = (__le32 *)fw->data;
+		pa->size = fw->size / FW_OPCODE_SIZE;
+	}
+
+	return true;
+}
+
+static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw)
+{
+	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+	size_t index;
+
+	for (index = 0; index < pa->size; index++) {
+		u32 action = le32_to_cpu(pa->code[index]);
+		u32 val = action & 0x0000ffff;
+		u32 regno = (action & 0x0fff0000) >> 16;
+
+		switch (action >> 28) {
+		case PHY_READ:
+		case PHY_DATA_OR:
+		case PHY_DATA_AND:
+		case PHY_CLEAR_READCOUNT:
+		case PHY_WRITE:
+		case PHY_WRITE_PREVIOUS:
+		case PHY_DELAY_MS:
+			break;
+
+		case PHY_MDIO_CHG:
+			if (val > 1)
+				goto out;
+			break;
+
+		case PHY_BJMPN:
+			if (regno > index)
+				goto out;
+			break;
+		case PHY_READCOUNT_EQ_SKIP:
+			if (index + 2 >= pa->size)
+				goto out;
+			break;
+		case PHY_COMP_EQ_SKIPN:
+		case PHY_COMP_NEQ_SKIPN:
+		case PHY_SKIPN:
+			if (index + 1 + regno >= pa->size)
+				goto out;
+			break;
+
+		default:
+			dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
+			return false;
+		}
+	}
+
+	return true;
+out:
+	dev_err(rtl_fw->dev, "Out of range of firmware\n");
+	return false;
+}
+
+void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
+{
+	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+	rtl_fw_write_t fw_write = rtl_fw->phy_write;
+	rtl_fw_read_t fw_read = rtl_fw->phy_read;
+	int predata = 0, count = 0;
+	size_t index;
+
+	for (index = 0; index < pa->size; index++) {
+		u32 action = le32_to_cpu(pa->code[index]);
+		u32 data = action & 0x0000ffff;
+		u32 regno = (action & 0x0fff0000) >> 16;
+		enum rtl_fw_opcode opcode = action >> 28;
+
+		if (!action)
+			break;
+
+		switch (opcode) {
+		case PHY_READ:
+			predata = fw_read(tp, regno);
+			count++;
+			break;
+		case PHY_DATA_OR:
+			predata |= data;
+			break;
+		case PHY_DATA_AND:
+			predata &= data;
+			break;
+		case PHY_BJMPN:
+			index -= (regno + 1);
+			break;
+		case PHY_MDIO_CHG:
+			if (data) {
+				fw_write = rtl_fw->mac_mcu_write;
+				fw_read = rtl_fw->mac_mcu_read;
+			} else {
+				fw_write = rtl_fw->phy_write;
+				fw_read = rtl_fw->phy_read;
+			}
+
+			break;
+		case PHY_CLEAR_READCOUNT:
+			count = 0;
+			break;
+		case PHY_WRITE:
+			fw_write(tp, regno, data);
+			break;
+		case PHY_READCOUNT_EQ_SKIP:
+			if (count == data)
+				index++;
+			break;
+		case PHY_COMP_EQ_SKIPN:
+			if (predata == data)
+				index += regno;
+			break;
+		case PHY_COMP_NEQ_SKIPN:
+			if (predata != data)
+				index += regno;
+			break;
+		case PHY_WRITE_PREVIOUS:
+			fw_write(tp, regno, predata);
+			break;
+		case PHY_SKIPN:
+			index += regno;
+			break;
+		case PHY_DELAY_MS:
+			mdelay(data);
+			break;
+		}
+	}
+}
+
+void rtl_fw_release_firmware(struct rtl_fw *rtl_fw)
+{
+	release_firmware(rtl_fw->fw);
+}
+
+int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
+{
+	int rc;
+
+	rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
+	if (rc < 0)
+		goto out;
+
+	if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) {
+		release_firmware(rtl_fw->fw);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	return 0;
+out:
+	/* At least some NiCs work without firmware, even if there is one */
+	dev_dbg(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
+		rtl_fw->fw_name, rc);
+	return rc;
+}
diff --git a/drivers/net/r8169_firmware.h b/drivers/net/r8169_firmware.h
new file mode 100644
index 0000000000..8d3b037225
--- /dev/null
+++ b/drivers/net/r8169_firmware.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* r8169_firmware.h: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
+ */
+
+struct rtl8169_private;
+typedef void (*rtl_fw_write_t)(struct rtl8169_private *tp, int reg, int val);
+typedef int (*rtl_fw_read_t)(struct rtl8169_private *tp, int reg);
+
+#define RTL_VER_SIZE		32
+
+struct rtl_fw {
+	rtl_fw_write_t phy_write;
+	rtl_fw_read_t phy_read;
+	rtl_fw_write_t mac_mcu_write;
+	rtl_fw_read_t mac_mcu_read;
+	const struct firmware *fw;
+	const char *fw_name;
+	struct device *dev;
+
+	char version[RTL_VER_SIZE];
+
+	struct rtl_fw_phy_action {
+		__le32 *code;
+		size_t size;
+	} phy_action;
+};
+
+int rtl_fw_request_firmware(struct rtl_fw *rtl_fw);
+void rtl_fw_release_firmware(struct rtl_fw *rtl_fw);
+void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw);
diff --git a/drivers/net/r8169_main.c b/drivers/net/r8169_main.c
new file mode 100644
index 0000000000..5b448fa029
--- /dev/null
+++ b/drivers/net/r8169_main.c
@@ -0,0 +1,3214 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * r8169.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
+ */
+
+#include <common.h>
+#include <dma.h>
+#include <init.h>
+#include <net.h>
+#include <malloc.h>
+#include <linux/pci.h>
+#include <linux/sizes.h>
+#include <asm/unaligned.h>
+#include <asm/system.h>
+
+#include "r8169.h"
+#include "r8169_firmware.h"
+
+#define FIRMWARE_8168D_1	"rtl_nic/rtl8168d-1.fw"
+#define FIRMWARE_8168D_2	"rtl_nic/rtl8168d-2.fw"
+#define FIRMWARE_8168E_1	"rtl_nic/rtl8168e-1.fw"
+#define FIRMWARE_8168E_2	"rtl_nic/rtl8168e-2.fw"
+#define FIRMWARE_8168E_3	"rtl_nic/rtl8168e-3.fw"
+#define FIRMWARE_8168F_1	"rtl_nic/rtl8168f-1.fw"
+#define FIRMWARE_8168F_2	"rtl_nic/rtl8168f-2.fw"
+#define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
+#define FIRMWARE_8402_1		"rtl_nic/rtl8402-1.fw"
+#define FIRMWARE_8411_1		"rtl_nic/rtl8411-1.fw"
+#define FIRMWARE_8411_2		"rtl_nic/rtl8411-2.fw"
+#define FIRMWARE_8106E_1	"rtl_nic/rtl8106e-1.fw"
+#define FIRMWARE_8106E_2	"rtl_nic/rtl8106e-2.fw"
+#define FIRMWARE_8168G_2	"rtl_nic/rtl8168g-2.fw"
+#define FIRMWARE_8168G_3	"rtl_nic/rtl8168g-3.fw"
+#define FIRMWARE_8168H_2	"rtl_nic/rtl8168h-2.fw"
+#define FIRMWARE_8168FP_3	"rtl_nic/rtl8168fp-3.fw"
+#define FIRMWARE_8107E_2	"rtl_nic/rtl8107e-2.fw"
+#define FIRMWARE_8125A_3	"rtl_nic/rtl8125a-3.fw"
+#define FIRMWARE_8125B_2	"rtl_nic/rtl8125b-2.fw"
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+   The RTL chips use a 64 element hash table based on the Ethernet CRC. */
+#define	MC_FILTER_LIMIT	32
+
+#define TX_DMA_BURST	7	/* Maximum PCI burst, '7' is unlimited */
+#define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
+
+#define R8169_REGS_SIZE		256
+#define R8169_RX_BUF_SIZE	(SZ_16K - 1)
+#define NUM_TX_DESC	256	/* Number of Tx descriptor registers */
+#define NUM_RX_DESC	256	/* Number of Rx descriptor registers */
+#define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
+#define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
+
+#define OCP_STD_PHY_BASE	0xa400
+
+#define RTL_CFG_NO_GBIT	1
+
+/* write/read MMIO register */
+#define RTL_W8(tp, reg, val8)	writeb((val8), tp->mmio_addr + (reg))
+#define RTL_W16(tp, reg, val16)	writew((val16), tp->mmio_addr + (reg))
+#define RTL_W32(tp, reg, val32)	writel((val32), tp->mmio_addr + (reg))
+#define RTL_R8(tp, reg)		readb(tp->mmio_addr + (reg))
+#define RTL_R16(tp, reg)		readw(tp->mmio_addr + (reg))
+#define RTL_R32(tp, reg)		readl(tp->mmio_addr + (reg))
+
+#define JUMBO_4K	(4 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
+#define JUMBO_6K	(6 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
+#define JUMBO_7K	(7 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
+#define JUMBO_9K	(9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
+
+static const struct {
+	const char *name;
+	const char *fw_name;
+} rtl_chip_infos[] = {
+	/* PCI devices. */
+	[RTL_GIGA_MAC_VER_02] = {"RTL8169s"				},
+	[RTL_GIGA_MAC_VER_03] = {"RTL8110s"				},
+	[RTL_GIGA_MAC_VER_04] = {"RTL8169sb/8110sb"			},
+	[RTL_GIGA_MAC_VER_05] = {"RTL8169sc/8110sc"			},
+	[RTL_GIGA_MAC_VER_06] = {"RTL8169sc/8110sc"			},
+	/* PCI-E devices. */
+	[RTL_GIGA_MAC_VER_07] = {"RTL8102e"				},
+	[RTL_GIGA_MAC_VER_08] = {"RTL8102e"				},
+	[RTL_GIGA_MAC_VER_09] = {"RTL8102e/RTL8103e"			},
+	[RTL_GIGA_MAC_VER_10] = {"RTL8101e/RTL8100e"			},
+	[RTL_GIGA_MAC_VER_11] = {"RTL8168b/8111b"			},
+	[RTL_GIGA_MAC_VER_14] = {"RTL8401"				},
+	[RTL_GIGA_MAC_VER_17] = {"RTL8168b/8111b"			},
+	[RTL_GIGA_MAC_VER_18] = {"RTL8168cp/8111cp"			},
+	[RTL_GIGA_MAC_VER_19] = {"RTL8168c/8111c"			},
+	[RTL_GIGA_MAC_VER_20] = {"RTL8168c/8111c"			},
+	[RTL_GIGA_MAC_VER_21] = {"RTL8168c/8111c"			},
+	[RTL_GIGA_MAC_VER_22] = {"RTL8168c/8111c"			},
+	[RTL_GIGA_MAC_VER_23] = {"RTL8168cp/8111cp"			},
+	[RTL_GIGA_MAC_VER_24] = {"RTL8168cp/8111cp"			},
+	[RTL_GIGA_MAC_VER_25] = {"RTL8168d/8111d",	FIRMWARE_8168D_1},
+	[RTL_GIGA_MAC_VER_26] = {"RTL8168d/8111d",	FIRMWARE_8168D_2},
+	[RTL_GIGA_MAC_VER_28] = {"RTL8168dp/8111dp"			},
+	[RTL_GIGA_MAC_VER_29] = {"RTL8105e",		FIRMWARE_8105E_1},
+	[RTL_GIGA_MAC_VER_30] = {"RTL8105e",		FIRMWARE_8105E_1},
+	[RTL_GIGA_MAC_VER_31] = {"RTL8168dp/8111dp"			},
+	[RTL_GIGA_MAC_VER_32] = {"RTL8168e/8111e",	FIRMWARE_8168E_1},
+	[RTL_GIGA_MAC_VER_33] = {"RTL8168e/8111e",	FIRMWARE_8168E_2},
+	[RTL_GIGA_MAC_VER_34] = {"RTL8168evl/8111evl",	FIRMWARE_8168E_3},
+	[RTL_GIGA_MAC_VER_35] = {"RTL8168f/8111f",	FIRMWARE_8168F_1},
+	[RTL_GIGA_MAC_VER_36] = {"RTL8168f/8111f",	FIRMWARE_8168F_2},
+	[RTL_GIGA_MAC_VER_37] = {"RTL8402",		FIRMWARE_8402_1 },
+	[RTL_GIGA_MAC_VER_38] = {"RTL8411",		FIRMWARE_8411_1 },
+	[RTL_GIGA_MAC_VER_39] = {"RTL8106e",		FIRMWARE_8106E_1},
+	[RTL_GIGA_MAC_VER_40] = {"RTL8168g/8111g",	FIRMWARE_8168G_2},
+	[RTL_GIGA_MAC_VER_42] = {"RTL8168gu/8111gu",	FIRMWARE_8168G_3},
+	[RTL_GIGA_MAC_VER_43] = {"RTL8106eus",		FIRMWARE_8106E_2},
+	[RTL_GIGA_MAC_VER_44] = {"RTL8411b",		FIRMWARE_8411_2 },
+	[RTL_GIGA_MAC_VER_46] = {"RTL8168h/8111h",	FIRMWARE_8168H_2},
+	[RTL_GIGA_MAC_VER_48] = {"RTL8107e",		FIRMWARE_8107E_2},
+	[RTL_GIGA_MAC_VER_51] = {"RTL8168ep/8111ep"			},
+	[RTL_GIGA_MAC_VER_52] = {"RTL8168fp/RTL8117",  FIRMWARE_8168FP_3},
+	[RTL_GIGA_MAC_VER_53] = {"RTL8168fp/RTL8117",			},
+	[RTL_GIGA_MAC_VER_61] = {"RTL8125A",		FIRMWARE_8125A_3},
+	/* reserve 62 for CFG_METHOD_4 in the vendor driver */
+	[RTL_GIGA_MAC_VER_63] = {"RTL8125B",		FIRMWARE_8125B_2},
+};
+
+static const struct pci_device_id rtl8169_pci_tbl[] = {
+	{ PCI_VDEVICE(REALTEK,	0x2502) },
+	{ PCI_VDEVICE(REALTEK,	0x2600) },
+	{ PCI_VDEVICE(REALTEK,	0x8129) },
+	{ PCI_VDEVICE(REALTEK,	0x8136), RTL_CFG_NO_GBIT },
+	{ PCI_VDEVICE(REALTEK,	0x8161) },
+	{ PCI_VDEVICE(REALTEK,	0x8162) },
+	{ PCI_VDEVICE(REALTEK,	0x8167) },
+	{ PCI_VDEVICE(REALTEK,	0x8168) },
+	{ PCI_VDEVICE(NCUBE,	0x8168) },
+	{ PCI_VDEVICE(REALTEK,	0x8169) },
+	{ PCI_VENDOR_ID_DLINK,	0x4300,
+		PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0 },
+	{ PCI_VDEVICE(DLINK,	0x4300) },
+	{ PCI_VDEVICE(DLINK,	0x4302) },
+	{ PCI_VDEVICE(AT,	0xc107) },
+	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024 },
+	{ 0x0001, 0x8168, PCI_ANY_ID, 0x2410 },
+	{ PCI_VDEVICE(REALTEK,	0x8125) },
+	{ PCI_VDEVICE(REALTEK,	0x3000) },
+	{}
+};
+
+MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
+
+enum rtl_registers {
+	MAC0		= 0,	/* Ethernet hardware address. */
+	MAC4		= 4,
+	MAR0		= 8,	/* Multicast filter. */
+	CounterAddrLow		= 0x10,
+	CounterAddrHigh		= 0x14,
+	TxDescStartAddrLow	= 0x20,
+	TxDescStartAddrHigh	= 0x24,
+	TxHDescStartAddrLow	= 0x28,
+	TxHDescStartAddrHigh	= 0x2c,
+	FLASH		= 0x30,
+	ERSR		= 0x36,
+	ChipCmd		= 0x37,
+	TxPoll		= 0x38,
+	IntrMask	= 0x3c,
+	IntrStatus	= 0x3e,
+
+	TxConfig	= 0x40,
+#define	TXCFG_AUTO_FIFO			(1 << 7)	/* 8111e-vl */
+#define	TXCFG_EMPTY			(1 << 11)	/* 8111e-vl */
+
+	RxConfig	= 0x44,
+#define	RX128_INT_EN			(1 << 15)	/* 8111c and later */
+#define	RX_MULTI_EN			(1 << 14)	/* 8111c only */
+#define	RXCFG_FIFO_SHIFT		13
+					/* No threshold before first PCI xfer */
+#define	RX_FIFO_THRESH			(7 << RXCFG_FIFO_SHIFT)
+#define	RX_EARLY_OFF			(1 << 11)
+#define	RXCFG_DMA_SHIFT			8
+					/* Unlimited maximum PCI burst. */
+#define	RX_DMA_BURST			(7 << RXCFG_DMA_SHIFT)
+	RxMissed	= 0x4c,
+	Cfg9346		= 0x50,
+	Config0		= 0x51,
+	Config1		= 0x52,
+	Config2		= 0x53,
+#define PME_SIGNAL			(1 << 5)	/* 8168c and later */
+
+	Config3		= 0x54,
+	Config4		= 0x55,
+	Config5		= 0x56,
+	PHYAR		= 0x60,
+	PHYstatus	= 0x6c,
+	RxMaxSize	= 0xda,
+	CPlusCmd	= 0xe0,
+	IntrMitigate	= 0xe2,
+
+#define RTL_COALESCE_TX_USECS	GENMASK(15, 12)
+#define RTL_COALESCE_TX_FRAMES	GENMASK(11, 8)
+#define RTL_COALESCE_RX_USECS	GENMASK(7, 4)
+#define RTL_COALESCE_RX_FRAMES	GENMASK(3, 0)
+
+#define RTL_COALESCE_T_MAX	0x0fU
+#define RTL_COALESCE_FRAME_MAX	(RTL_COALESCE_T_MAX * 4)
+
+	RxDescAddrLow	= 0xe4,
+	RxDescAddrHigh	= 0xe8,
+	EarlyTxThres	= 0xec,	/* 8169. Unit of 32 bytes. */
+
+#define NoEarlyTx	0x3f	/* Max value : no early transmit. */
+
+	MaxTxPacketSize	= 0xec,	/* 8101/8168. Unit of 128 bytes. */
+
+#define TxPacketMax	(8064 >> 7)
+#define EarlySize	0x27
+
+	FuncEvent	= 0xf0,
+	FuncEventMask	= 0xf4,
+	FuncPresetState	= 0xf8,
+	IBCR0           = 0xf8,
+	IBCR2           = 0xf9,
+	IBIMR0          = 0xfa,
+	IBISR0          = 0xfb,
+	FuncForceEvent	= 0xfc,
+};
+
+enum rtl8168_8101_registers {
+	CSIDR			= 0x64,
+	CSIAR			= 0x68,
+#define	CSIAR_FLAG			0x80000000
+#define	CSIAR_WRITE_CMD			0x80000000
+#define	CSIAR_BYTE_ENABLE		0x0000f000
+#define	CSIAR_ADDR_MASK			0x00000fff
+	PMCH			= 0x6f,
+#define D3COLD_NO_PLL_DOWN		BIT(7)
+#define D3HOT_NO_PLL_DOWN		BIT(6)
+#define D3_NO_PLL_DOWN			(BIT(7) | BIT(6))
+	EPHYAR			= 0x80,
+#define	EPHYAR_FLAG			0x80000000
+#define	EPHYAR_WRITE_CMD		0x80000000
+#define	EPHYAR_REG_MASK			0x1f
+#define	EPHYAR_REG_SHIFT		16
+#define	EPHYAR_DATA_MASK		0xffff
+	DLLPR			= 0xd0,
+#define	PFM_EN				(1 << 6)
+#define	TX_10M_PS_EN			(1 << 7)
+	DBG_REG			= 0xd1,
+#define	FIX_NAK_1			(1 << 4)
+#define	FIX_NAK_2			(1 << 3)
+	TWSI			= 0xd2,
+	MCU			= 0xd3,
+#define	NOW_IS_OOB			(1 << 7)
+#define	TX_EMPTY			(1 << 5)
+#define	RX_EMPTY			(1 << 4)
+#define	RXTX_EMPTY			(TX_EMPTY | RX_EMPTY)
+#define	EN_NDP				(1 << 3)
+#define	EN_OOB_RESET			(1 << 2)
+#define	LINK_LIST_RDY			(1 << 1)
+	EFUSEAR			= 0xdc,
+#define	EFUSEAR_FLAG			0x80000000
+#define	EFUSEAR_WRITE_CMD		0x80000000
+#define	EFUSEAR_READ_CMD		0x00000000
+#define	EFUSEAR_REG_MASK		0x03ff
+#define	EFUSEAR_REG_SHIFT		8
+#define	EFUSEAR_DATA_MASK		0xff
+	MISC_1			= 0xf2,
+#define	PFM_D3COLD_EN			(1 << 6)
+};
+
+enum rtl8168_registers {
+	LED_FREQ		= 0x1a,
+	EEE_LED			= 0x1b,
+	ERIDR			= 0x70,
+	ERIAR			= 0x74,
+#define ERIAR_FLAG			0x80000000
+#define ERIAR_WRITE_CMD			0x80000000
+#define ERIAR_READ_CMD			0x00000000
+#define ERIAR_ADDR_BYTE_ALIGN		4
+#define ERIAR_TYPE_SHIFT		16
+#define ERIAR_EXGMAC			(0x00 << ERIAR_TYPE_SHIFT)
+#define ERIAR_MSIX			(0x01 << ERIAR_TYPE_SHIFT)
+#define ERIAR_ASF			(0x02 << ERIAR_TYPE_SHIFT)
+#define ERIAR_OOB			(0x02 << ERIAR_TYPE_SHIFT)
+#define ERIAR_MASK_SHIFT		12
+#define ERIAR_MASK_0001			(0x1 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_0011			(0x3 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_0100			(0x4 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_0101			(0x5 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_1111			(0xf << ERIAR_MASK_SHIFT)
+	EPHY_RXER_NUM		= 0x7c,
+	OCPDR			= 0xb0,	/* OCP GPHY access */
+#define OCPDR_WRITE_CMD			0x80000000
+#define OCPDR_READ_CMD			0x00000000
+#define OCPDR_REG_MASK			0x7f
+#define OCPDR_GPHY_REG_SHIFT		16
+#define OCPDR_DATA_MASK			0xffff
+	OCPAR			= 0xb4,
+#define OCPAR_FLAG			0x80000000
+#define OCPAR_GPHY_WRITE_CMD		0x8000f060
+#define OCPAR_GPHY_READ_CMD		0x0000f060
+	GPHY_OCP		= 0xb8,
+	RDSAR1			= 0xd0,	/* 8168c only. Undocumented on 8168dp */
+	MISC			= 0xf0,	/* 8168e only. */
+#define TXPLA_RST			(1 << 29)
+#define DISABLE_LAN_EN			(1 << 23) /* Enable GPIO pin */
+#define PWM_EN				(1 << 22)
+#define RXDV_GATED_EN			(1 << 19)
+#define EARLY_TALLY_EN			(1 << 16)
+};
+
+enum rtl8125_registers {
+	IntrMask_8125		= 0x38,
+	IntrStatus_8125		= 0x3c,
+	TxPoll_8125		= 0x90,
+	MAC0_BKP		= 0x19e0,
+	EEE_TXIDLE_TIMER_8125	= 0x6048,
+};
+
+#define RX_VLAN_INNER_8125	BIT(22)
+#define RX_VLAN_OUTER_8125	BIT(23)
+#define RX_VLAN_8125		(RX_VLAN_INNER_8125 | RX_VLAN_OUTER_8125)
+
+#define RX_FETCH_DFLT_8125	(8 << 27)
+
+enum rtl_register_content {
+	/* InterruptStatusBits */
+	SYSErr		= 0x8000,
+	PCSTimeout	= 0x4000,
+	SWInt		= 0x0100,
+	TxDescUnavail	= 0x0080,
+	RxFIFOOver	= 0x0040,
+	LinkChg		= 0x0020,
+	RxOverflow	= 0x0010,
+	TxErr		= 0x0008,
+	TxOK		= 0x0004,
+	RxErr		= 0x0002,
+	RxOK		= 0x0001,
+
+	/* RxStatusDesc */
+	RxRWT	= (1 << 22),
+	RxRES	= (1 << 21),
+	RxRUNT	= (1 << 20),
+	RxCRC	= (1 << 19),
+
+	/* ChipCmdBits */
+	StopReq		= 0x80,
+	CmdReset	= 0x10,
+	CmdRxEnb	= 0x08,
+	CmdTxEnb	= 0x04,
+	RxBufEmpty	= 0x01,
+
+	/* TXPoll register p.5 */
+	HPQ		= 0x80,		/* Poll cmd on the high prio queue */
+	NPQ		= 0x40,		/* Poll cmd on the low prio queue */
+	FSWInt		= 0x01,		/* Forced software interrupt */
+
+	/* Cfg9346Bits */
+	Cfg9346_Lock	= 0x00,
+	Cfg9346_Unlock	= 0xc0,
+
+	/* rx_mode_bits */
+	AcceptErr	= 0x20,
+	AcceptRunt	= 0x10,
+#define RX_CONFIG_ACCEPT_ERR_MASK	0x30
+	AcceptBroadcast	= 0x08,
+	AcceptMulticast	= 0x04,
+	AcceptMyPhys	= 0x02,
+	AcceptAllPhys	= 0x01,
+#define RX_CONFIG_ACCEPT_OK_MASK	0x0f
+#define RX_CONFIG_ACCEPT_MASK		0x3f
+
+	/* TxConfigBits */
+	TxInterFrameGapShift = 24,
+	TxDMAShift = 8,	/* DMA burst value (0-7) is shift this many bits */
+
+	/* Config1 register p.24 */
+	LEDS1		= (1 << 7),
+	LEDS0		= (1 << 6),
+	Speed_down	= (1 << 4),
+	MEMMAP		= (1 << 3),
+	IOMAP		= (1 << 2),
+	VPD		= (1 << 1),
+	PMEnable	= (1 << 0),	/* Power Management Enable */
+
+	/* Config2 register p. 25 */
+	ClkReqEn	= (1 << 7),	/* Clock Request Enable */
+	MSIEnable	= (1 << 5),	/* 8169 only. Reserved in the 8168. */
+	PCI_Clock_66MHz = 0x01,
+	PCI_Clock_33MHz = 0x00,
+
+	/* Config3 register p.25 */
+	MagicPacket	= (1 << 5),	/* Wake up when receives a Magic Packet */
+	LinkUp		= (1 << 4),	/* Wake up when the cable connection is re-established */
+	Jumbo_En0	= (1 << 2),	/* 8168 only. Reserved in the 8168b */
+	Rdy_to_L23	= (1 << 1),	/* L23 Enable */
+	Beacon_en	= (1 << 0),	/* 8168 only. Reserved in the 8168b */
+
+	/* Config4 register */
+	Jumbo_En1	= (1 << 1),	/* 8168 only. Reserved in the 8168b */
+
+	/* Config5 register p.27 */
+	BWF		= (1 << 6),	/* Accept Broadcast wakeup frame */
+	MWF		= (1 << 5),	/* Accept Multicast wakeup frame */
+	UWF		= (1 << 4),	/* Accept Unicast wakeup frame */
+	Spi_en		= (1 << 3),
+	LanWake		= (1 << 1),	/* LanWake enable/disable */
+	PMEStatus	= (1 << 0),	/* PME status can be reset by PCI RST# */
+	ASPM_en		= (1 << 0),	/* ASPM enable */
+
+	/* CPlusCmd p.31 */
+	EnableBist	= (1 << 15),	// 8168 8101
+	Mac_dbgo_oe	= (1 << 14),	// 8168 8101
+	EnAnaPLL	= (1 << 14),	// 8169
+	Normal_mode	= (1 << 13),	// unused
+	Force_half_dup	= (1 << 12),	// 8168 8101
+	Force_rxflow_en	= (1 << 11),	// 8168 8101
+	Force_txflow_en	= (1 << 10),	// 8168 8101
+	Cxpl_dbg_sel	= (1 << 9),	// 8168 8101
+	ASF		= (1 << 8),	// 8168 8101
+	PktCntrDisable	= (1 << 7),	// 8168 8101
+	Mac_dbgo_sel	= 0x001c,	// 8168
+	RxVlan		= (1 << 6),
+	RxChkSum	= (1 << 5),
+	PCIDAC		= (1 << 4),
+	PCIMulRW	= (1 << 3),
+#define INTT_MASK	GENMASK(1, 0)
+#define CPCMD_MASK	(Normal_mode | RxVlan | RxChkSum | INTT_MASK)
+
+	/* rtl8169_PHYstatus */
+	TBI_Enable	= 0x80,
+	TxFlowCtrl	= 0x40,
+	RxFlowCtrl	= 0x20,
+	_1000bpsF	= 0x10,
+	_100bps		= 0x08,
+	_10bps		= 0x04,
+	LinkStatus	= 0x02,
+	FullDup		= 0x01,
+
+	/* ResetCounterCommand */
+	CounterReset	= 0x1,
+
+	/* DumpCounterCommand */
+	CounterDump	= 0x8,
+
+	/* magic enable v2 */
+	MagicPacket_v2	= (1 << 16),	/* Wake up when receives a Magic Packet */
+};
+
+enum rtl_desc_bit {
+	/* First doubleword. */
+	DescOwn		= (1 << 31), /* Descriptor is owned by NIC */
+	RingEnd		= (1 << 30), /* End of descriptor ring */
+	FirstFrag	= (1 << 29), /* First segment of a packet */
+	LastFrag	= (1 << 28), /* Final segment of a packet */
+};
+
+/* Generic case. */
+enum rtl_tx_desc_bit {
+	/* First doubleword. */
+	TD_LSO		= (1 << 27),		/* Large Send Offload */
+#define TD_MSS_MAX			0x07ffu	/* MSS value */
+
+	/* Second doubleword. */
+	TxVlanTag	= (1 << 17),		/* Add VLAN tag */
+};
+
+/* 8169, 8168b and 810x except 8102e. */
+enum rtl_tx_desc_bit_0 {
+	/* First doubleword. */
+#define TD0_MSS_SHIFT			16	/* MSS position (11 bits) */
+	TD0_TCP_CS	= (1 << 16),		/* Calculate TCP/IP checksum */
+	TD0_UDP_CS	= (1 << 17),		/* Calculate UDP/IP checksum */
+	TD0_IP_CS	= (1 << 18),		/* Calculate IP checksum */
+};
+
+/* 8102e, 8168c and beyond. */
+enum rtl_tx_desc_bit_1 {
+	/* First doubleword. */
+	TD1_GTSENV4	= (1 << 26),		/* Giant Send for IPv4 */
+	TD1_GTSENV6	= (1 << 25),		/* Giant Send for IPv6 */
+#define GTTCPHO_SHIFT			18
+#define GTTCPHO_MAX			0x7f
+
+	/* Second doubleword. */
+#define TCPHO_SHIFT			18
+#define TCPHO_MAX			0x3ff
+#define TD1_MSS_SHIFT			18	/* MSS position (11 bits) */
+	TD1_IPv6_CS	= (1 << 28),		/* Calculate IPv6 checksum */
+	TD1_IPv4_CS	= (1 << 29),		/* Calculate IPv4 checksum */
+	TD1_TCP_CS	= (1 << 30),		/* Calculate TCP/IP checksum */
+	TD1_UDP_CS	= (1 << 31),		/* Calculate UDP/IP checksum */
+};
+
+enum rtl_rx_desc_bit {
+	/* Rx private */
+	PID1		= (1 << 18), /* Protocol ID bit 1/2 */
+	PID0		= (1 << 17), /* Protocol ID bit 0/2 */
+
+#define RxProtoUDP	(PID1)
+#define RxProtoTCP	(PID0)
+#define RxProtoIP	(PID1 | PID0)
+#define RxProtoMask	RxProtoIP
+
+	IPFail		= (1 << 16), /* IP checksum failed */
+	UDPFail		= (1 << 15), /* UDP/IP checksum failed */
+	TCPFail		= (1 << 14), /* TCP/IP checksum failed */
+
+#define RxCSFailMask	(IPFail | UDPFail | TCPFail)
+
+	RxVlanTag	= (1 << 16), /* VLAN tag available */
+};
+
+#define RTL_GSO_MAX_SIZE_V1	32000
+#define RTL_GSO_MAX_SEGS_V1	24
+#define RTL_GSO_MAX_SIZE_V2	64000
+#define RTL_GSO_MAX_SEGS_V2	64
+
+struct TxDesc {
+	__le32 opts1;
+	__le32 opts2;
+	__le64 addr;
+};
+
+struct RxDesc {
+	__le32 opts1;
+	__le32 opts2;
+	__le64 addr;
+};
+
+struct ring_info {
+	struct sk_buff	*skb;
+	u32		len;
+};
+
+struct rtl8169_counters {
+	__le64	tx_packets;
+	__le64	rx_packets;
+	__le64	tx_errors;
+	__le32	rx_errors;
+	__le16	rx_missed;
+	__le16	align_errors;
+	__le32	tx_one_collision;
+	__le32	tx_multi_collision;
+	__le64	rx_unicast;
+	__le64	rx_broadcast;
+	__le32	rx_multicast;
+	__le16	tx_aborted;
+	__le16	tx_underun;
+};
+
+struct rtl8169_tc_offsets {
+	bool	inited;
+	__le64	tx_errors;
+	__le32	tx_multi_collision;
+	__le16	tx_aborted;
+	__le16	rx_missed;
+};
+
+enum rtl_flag {
+	RTL_FLAG_TASK_ENABLED = 0,
+	RTL_FLAG_TASK_RESET_PENDING,
+	RTL_FLAG_TASK_TX_TIMEOUT,
+	RTL_FLAG_MAX
+};
+
+enum rtl_dash_type {
+	RTL_DASH_NONE,
+	RTL_DASH_DP,
+	RTL_DASH_EP,
+};
+
+struct rtl8169_private {
+	void __iomem *mmio_addr;	/* memory map physical address */
+	struct pci_dev *pci_dev;
+	struct device *dev;
+	struct eth_device edev;
+	struct phy_device *phydev;
+	enum mac_version mac_version;
+	enum rtl_dash_type dash_type;
+	u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
+	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
+	u32 dirty_tx;
+	struct TxDesc *TxDescArray;	/* 256-aligned Tx descriptor ring */
+	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */
+	dma_addr_t TxPhyAddr;
+	dma_addr_t RxPhyAddr;
+	u16 cp_cmd;
+	void			*tx_buf;
+	dma_addr_t		tx_buf_phys;
+	void			*rx_buf;
+	dma_addr_t		rx_buf_phys;
+
+	unsigned supports_gmii:1;
+	unsigned aspm_manageable:1;
+
+	const char *fw_name;
+	struct rtl_fw *rtl_fw;
+
+	u32 ocp_base;
+
+	struct mii_bus miibus;
+};
+
+typedef void (*rtl_generic_fct)(struct rtl8169_private *tp);
+
+static inline struct device *tp_to_dev(struct rtl8169_private *tp)
+{
+	return &tp->pci_dev->dev;
+}
+
+static void rtl_lock_config_regs(struct rtl8169_private *tp)
+{
+	RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+}
+
+static void rtl_unlock_config_regs(struct rtl8169_private *tp)
+{
+	RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+}
+
+static void rtl_pci_commit(struct rtl8169_private *tp)
+{
+	/* Read an arbitrary register to commit a preceding PCI write */
+	RTL_R8(tp, ChipCmd);
+}
+
+static bool rtl_is_8125(struct rtl8169_private *tp)
+{
+	return tp->mac_version >= RTL_GIGA_MAC_VER_61;
+}
+
+static bool rtl_is_8168evl_up(struct rtl8169_private *tp)
+{
+	return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
+	       tp->mac_version != RTL_GIGA_MAC_VER_39 &&
+	       tp->mac_version <= RTL_GIGA_MAC_VER_53;
+}
+
+static void rtl_read_mac_from_reg(struct rtl8169_private *tp, u8 *mac, int reg)
+{
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		mac[i] = RTL_R8(tp, reg + i);
+}
+
+struct rtl_cond {
+	bool (*check)(struct rtl8169_private *);
+	const char *msg;
+};
+
+static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
+			  unsigned long usecs, int n, bool high)
+{
+	int i;
+
+	for (i = 0; i < n; i++) {
+		if (c->check(tp) == high)
+			return true;
+		udelay(usecs);
+	}
+
+	dev_err(tp->dev, "%s == %d (loop: %d, delay: %lu).\n",
+		   c->msg, !high, n, usecs);
+	return false;
+}
+
+static bool rtl_loop_wait_high(struct rtl8169_private *tp,
+			       const struct rtl_cond *c,
+			       unsigned long d, int n)
+{
+	return rtl_loop_wait(tp, c, d, n, true);
+}
+
+static bool rtl_loop_wait_low(struct rtl8169_private *tp,
+			      const struct rtl_cond *c,
+			      unsigned long d, int n)
+{
+	return rtl_loop_wait(tp, c, d, n, false);
+}
+
+#define DECLARE_RTL_COND(name)				\
+static bool name ## _check(struct rtl8169_private *);	\
+							\
+static const struct rtl_cond name = {			\
+	.check	= name ## _check,			\
+	.msg	= #name					\
+};							\
+							\
+static bool name ## _check(struct rtl8169_private *tp)
+
+static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type)
+{
+	/* based on RTL8168FP_OOBMAC_BASE in vendor driver */
+	if (type == ERIAR_OOB &&
+	    (tp->mac_version == RTL_GIGA_MAC_VER_52 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_53))
+		*cmd |= 0xf70 << 18;
+}
+
+DECLARE_RTL_COND(rtl_eriar_cond)
+{
+	return RTL_R32(tp, ERIAR) & ERIAR_FLAG;
+}
+
+static void _rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
+			   u32 val, int type)
+{
+	u32 cmd = ERIAR_WRITE_CMD | type | mask | addr;
+
+	if (WARN(addr & 3 || !mask, "addr: 0x%x, mask: 0x%08x\n", addr, mask))
+		return;
+
+	RTL_W32(tp, ERIDR, val);
+	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
+	RTL_W32(tp, ERIAR, cmd);
+
+	rtl_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
+}
+
+static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
+			  u32 val)
+{
+	_rtl_eri_write(tp, addr, mask, val, ERIAR_EXGMAC);
+}
+
+static u32 _rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
+{
+	u32 cmd = ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr;
+
+	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
+	RTL_W32(tp, ERIAR, cmd);
+
+	return rtl_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
+		RTL_R32(tp, ERIDR) : ~0;
+}
+
+static u32 rtl_eri_read(struct rtl8169_private *tp, int addr)
+{
+	return _rtl_eri_read(tp, addr, ERIAR_EXGMAC);
+}
+
+static void rtl_w0w1_eri(struct rtl8169_private *tp, int addr, u32 p, u32 m)
+{
+	u32 val = rtl_eri_read(tp, addr);
+
+	rtl_eri_write(tp, addr, ERIAR_MASK_1111, (val & ~m) | p);
+}
+
+static void rtl_eri_set_bits(struct rtl8169_private *tp, int addr, u32 p)
+{
+	rtl_w0w1_eri(tp, addr, p, 0);
+}
+
+static void rtl_eri_clear_bits(struct rtl8169_private *tp, int addr, u32 m)
+{
+	rtl_w0w1_eri(tp, addr, 0, m);
+}
+
+static bool rtl_ocp_reg_failure(u32 reg)
+{
+	return WARN_ONCE(reg & 0xffff0001, "Invalid ocp reg %x!\n", reg);
+}
+
+DECLARE_RTL_COND(rtl_ocp_gphy_cond)
+{
+	return RTL_R32(tp, GPHY_OCP) & OCPAR_FLAG;
+}
+
+static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
+{
+	if (rtl_ocp_reg_failure(reg))
+		return;
+
+	RTL_W32(tp, GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
+
+	rtl_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
+}
+
+static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
+{
+	if (rtl_ocp_reg_failure(reg))
+		return 0;
+
+	RTL_W32(tp, GPHY_OCP, reg << 15);
+
+	return rtl_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
+		(RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;
+}
+
+static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
+{
+	if (rtl_ocp_reg_failure(reg))
+		return;
+
+	RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
+}
+
+static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
+{
+	if (rtl_ocp_reg_failure(reg))
+		return 0;
+
+	RTL_W32(tp, OCPDR, reg << 15);
+
+	return RTL_R32(tp, OCPDR);
+}
+
+static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
+				 u16 set)
+{
+	u16 data = r8168_mac_ocp_read(tp, reg);
+
+	r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
+}
+
+/* Work around a hw issue with RTL8168g PHY, the quirk disables
+ * PHY MCU interrupts before PHY power-down.
+ */
+static void rtl8168g_phy_suspend_quirk(struct rtl8169_private *tp, int value)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_40:
+		if (value & BMCR_RESET || !(value & BMCR_PDOWN))
+			rtl_eri_set_bits(tp, 0x1a8, 0xfc000000);
+		else
+			rtl_eri_clear_bits(tp, 0x1a8, 0xfc000000);
+		break;
+	default:
+		break;
+	}
+};
+
+static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
+{
+	if (reg == 0x1f) {
+		tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
+		return;
+	}
+
+	if (tp->ocp_base != OCP_STD_PHY_BASE)
+		reg -= 0x10;
+
+	if (tp->ocp_base == OCP_STD_PHY_BASE && reg == MII_BMCR)
+		rtl8168g_phy_suspend_quirk(tp, value);
+
+	r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
+}
+
+static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
+{
+	if (reg == 0x1f)
+		return tp->ocp_base == OCP_STD_PHY_BASE ? 0 : tp->ocp_base >> 4;
+
+	if (tp->ocp_base != OCP_STD_PHY_BASE)
+		reg -= 0x10;
+
+	return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
+}
+
+static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)
+{
+	if (reg == 0x1f) {
+		tp->ocp_base = value << 4;
+		return;
+	}
+
+	r8168_mac_ocp_write(tp, tp->ocp_base + reg, value);
+}
+
+static int mac_mcu_read(struct rtl8169_private *tp, int reg)
+{
+	return r8168_mac_ocp_read(tp, tp->ocp_base + reg);
+}
+
+DECLARE_RTL_COND(rtl_phyar_cond)
+{
+	return RTL_R32(tp, PHYAR) & 0x80000000;
+}
+
+static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
+{
+	RTL_W32(tp, PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
+
+	rtl_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
+	/*
+	 * According to hardware specs a 20us delay is required after write
+	 * complete indication, but before sending next command.
+	 */
+	udelay(20);
+}
+
+static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
+{
+	int value;
+
+	RTL_W32(tp, PHYAR, 0x0 | (reg & 0x1f) << 16);
+
+	value = rtl_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
+		RTL_R32(tp, PHYAR) & 0xffff : -ETIMEDOUT;
+
+	/*
+	 * According to hardware specs a 20us delay is required after read
+	 * complete indication, but before sending next command.
+	 */
+	udelay(20);
+
+	return value;
+}
+
+DECLARE_RTL_COND(rtl_ocpar_cond)
+{
+	return RTL_R32(tp, OCPAR) & OCPAR_FLAG;
+}
+
+#define R8168DP_1_MDIO_ACCESS_BIT	0x00020000
+
+static void r8168dp_2_mdio_start(struct rtl8169_private *tp)
+{
+	RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
+}
+
+static void r8168dp_2_mdio_stop(struct rtl8169_private *tp)
+{
+	RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
+}
+
+static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
+{
+	r8168dp_2_mdio_start(tp);
+
+	r8169_mdio_write(tp, reg, value);
+
+	r8168dp_2_mdio_stop(tp);
+}
+
+static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
+{
+	int value;
+
+	/* Work around issue with chip reporting wrong PHY ID */
+	if (reg == MII_PHYSID2)
+		return 0xc912;
+
+	r8168dp_2_mdio_start(tp);
+
+	value = r8169_mdio_read(tp, reg);
+
+	r8168dp_2_mdio_stop(tp);
+
+	return value;
+}
+
+static void rtl_writephy(struct rtl8169_private *tp, int location, int val)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		r8168dp_2_mdio_write(tp, location, val);
+		break;
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
+		r8168g_mdio_write(tp, location, val);
+		break;
+	default:
+		r8169_mdio_write(tp, location, val);
+		break;
+	}
+}
+
+static int rtl_readphy(struct rtl8169_private *tp, int location)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		return r8168dp_2_mdio_read(tp, location);
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
+		return r8168g_mdio_read(tp, location);
+	default:
+		return r8169_mdio_read(tp, location);
+	}
+}
+
+DECLARE_RTL_COND(rtl_ephyar_cond)
+{
+	return RTL_R32(tp, EPHYAR) & EPHYAR_FLAG;
+}
+
+static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
+{
+	RTL_W32(tp, EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
+		(reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+	rtl_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
+
+	udelay(10);
+}
+
+static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
+{
+	RTL_W32(tp, EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+	return rtl_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
+		RTL_R32(tp, EPHYAR) & EPHYAR_DATA_MASK : ~0;
+}
+
+static u32 r8168dp_ocp_read(struct rtl8169_private *tp, u16 reg)
+{
+	RTL_W32(tp, OCPAR, 0x0fu << 12 | (reg & 0x0fff));
+	return rtl_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
+		RTL_R32(tp, OCPDR) : ~0;
+}
+
+static u32 r8168ep_ocp_read(struct rtl8169_private *tp, u16 reg)
+{
+	return _rtl_eri_read(tp, reg, ERIAR_OOB);
+}
+
+static void r8168dp_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
+			      u32 data)
+{
+	RTL_W32(tp, OCPDR, data);
+	RTL_W32(tp, OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
+	rtl_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
+}
+
+static void r8168ep_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
+			      u32 data)
+{
+	_rtl_eri_write(tp, reg, ((u32)mask & 0x0f) << ERIAR_MASK_SHIFT,
+		       data, ERIAR_OOB);
+}
+
+static void r8168dp_oob_notify(struct rtl8169_private *tp, u8 cmd)
+{
+	rtl_eri_write(tp, 0xe8, ERIAR_MASK_0001, cmd);
+
+	r8168dp_ocp_write(tp, 0x1, 0x30, 0x00000001);
+}
+
+#define OOB_CMD_RESET		0x00
+#define OOB_CMD_DRIVER_START	0x05
+#define OOB_CMD_DRIVER_STOP	0x06
+
+static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
+{
+	return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
+}
+
+DECLARE_RTL_COND(rtl_dp_ocp_read_cond)
+{
+	u16 reg;
+
+	reg = rtl8168_get_ocp_reg(tp);
+
+	return r8168dp_ocp_read(tp, reg) & 0x00000800;
+}
+
+DECLARE_RTL_COND(rtl_ep_ocp_read_cond)
+{
+	return r8168ep_ocp_read(tp, 0x124) & 0x00000001;
+}
+
+DECLARE_RTL_COND(rtl_ocp_tx_cond)
+{
+	return RTL_R8(tp, IBISR0) & 0x20;
+}
+
+static void rtl8168ep_stop_cmac(struct rtl8169_private *tp)
+{
+	RTL_W8(tp, IBCR2, RTL_R8(tp, IBCR2) & ~0x01);
+	rtl_loop_wait_high(tp, &rtl_ocp_tx_cond, 50000, 2000);
+	RTL_W8(tp, IBISR0, RTL_R8(tp, IBISR0) | 0x20);
+	RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01);
+}
+
+static void rtl8168dp_driver_start(struct rtl8169_private *tp)
+{
+	r8168dp_oob_notify(tp, OOB_CMD_DRIVER_START);
+	rtl_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
+}
+
+static void rtl8168ep_driver_start(struct rtl8169_private *tp)
+{
+	r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
+	r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
+	rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 10);
+}
+
+static void rtl8168_driver_start(struct rtl8169_private *tp)
+{
+	if (tp->dash_type == RTL_DASH_DP)
+		rtl8168dp_driver_start(tp);
+	else
+		rtl8168ep_driver_start(tp);
+}
+
+static bool r8168dp_check_dash(struct rtl8169_private *tp)
+{
+	u16 reg = rtl8168_get_ocp_reg(tp);
+
+	return r8168dp_ocp_read(tp, reg) & BIT(15);
+}
+
+static bool r8168ep_check_dash(struct rtl8169_private *tp)
+{
+	return r8168ep_ocp_read(tp, 0x128) & BIT(0);
+}
+
+static enum rtl_dash_type rtl_check_dash(struct rtl8169_private *tp)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		return r8168dp_check_dash(tp) ? RTL_DASH_DP : RTL_DASH_NONE;
+	case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
+		return r8168ep_check_dash(tp) ? RTL_DASH_EP : RTL_DASH_NONE;
+	default:
+		return RTL_DASH_NONE;
+	}
+}
+
+static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
+	case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_37:
+	case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
+		if (enable)
+			RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~D3_NO_PLL_DOWN);
+		else
+			RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | D3_NO_PLL_DOWN);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rtl_reset_packet_filter(struct rtl8169_private *tp)
+{
+	rtl_eri_clear_bits(tp, 0xdc, BIT(0));
+	rtl_eri_set_bits(tp, 0xdc, BIT(0));
+}
+
+DECLARE_RTL_COND(rtl_efusear_cond)
+{
+	return RTL_R32(tp, EFUSEAR) & EFUSEAR_FLAG;
+}
+
+u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
+{
+	RTL_W32(tp, EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
+
+	return rtl_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
+		RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
+}
+
+static void rtl_link_chg_patch(struct rtl8169_private *tp)
+{
+	struct phy_device *phydev = tp->phydev;
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_38) {
+		if (phydev->speed == SPEED_1000) {
+			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
+			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
+		} else if (phydev->speed == SPEED_100) {
+			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
+			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
+		} else {
+			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
+			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
+		}
+		rtl_reset_packet_filter(tp);
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_36) {
+		if (phydev->speed == SPEED_1000) {
+			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
+			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
+		} else {
+			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
+			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
+		}
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
+		if (phydev->speed == SPEED_10) {
+			rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02);
+			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060a);
+		} else {
+			rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
+		}
+	}
+}
+
+static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
+{
+	/*
+	 * The driver currently handles the 8168Bf and the 8168Be identically
+	 * but they can be identified more specifically through the test below
+	 * if needed:
+	 *
+	 * (RTL_R32(tp, TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
+	 *
+	 * Same thing for the 8101Eb and the 8101Ec:
+	 *
+	 * (RTL_R32(tp, TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
+	 */
+	static const struct rtl_mac_info {
+		u16 mask;
+		u16 val;
+		enum mac_version ver;
+	} mac_info[] = {
+		/* 8125B family. */
+		{ 0x7cf, 0x641,	RTL_GIGA_MAC_VER_63 },
+
+		/* 8125A family. */
+		{ 0x7cf, 0x609,	RTL_GIGA_MAC_VER_61 },
+		/* It seems only XID 609 made it to the mass market.
+		 * { 0x7cf, 0x608,	RTL_GIGA_MAC_VER_60 },
+		 * { 0x7c8, 0x608,	RTL_GIGA_MAC_VER_61 },
+		 */
+
+		/* RTL8117 */
+		{ 0x7cf, 0x54b,	RTL_GIGA_MAC_VER_53 },
+		{ 0x7cf, 0x54a,	RTL_GIGA_MAC_VER_52 },
+
+		/* 8168EP family. */
+		{ 0x7cf, 0x502,	RTL_GIGA_MAC_VER_51 },
+		/* It seems this chip version never made it to
+		 * the wild. Let's disable detection.
+		 * { 0x7cf, 0x501,      RTL_GIGA_MAC_VER_50 },
+		 * { 0x7cf, 0x500,      RTL_GIGA_MAC_VER_49 },
+		 */
+
+		/* 8168H family. */
+		{ 0x7cf, 0x541,	RTL_GIGA_MAC_VER_46 },
+		/* It seems this chip version never made it to
+		 * the wild. Let's disable detection.
+		 * { 0x7cf, 0x540,	RTL_GIGA_MAC_VER_45 },
+		 */
+
+		/* 8168G family. */
+		{ 0x7cf, 0x5c8,	RTL_GIGA_MAC_VER_44 },
+		{ 0x7cf, 0x509,	RTL_GIGA_MAC_VER_42 },
+		/* It seems this chip version never made it to
+		 * the wild. Let's disable detection.
+		 * { 0x7cf, 0x4c1,	RTL_GIGA_MAC_VER_41 },
+		 */
+		{ 0x7cf, 0x4c0,	RTL_GIGA_MAC_VER_40 },
+
+		/* 8168F family. */
+		{ 0x7c8, 0x488,	RTL_GIGA_MAC_VER_38 },
+		{ 0x7cf, 0x481,	RTL_GIGA_MAC_VER_36 },
+		{ 0x7cf, 0x480,	RTL_GIGA_MAC_VER_35 },
+
+		/* 8168E family. */
+		{ 0x7c8, 0x2c8,	RTL_GIGA_MAC_VER_34 },
+		{ 0x7cf, 0x2c1,	RTL_GIGA_MAC_VER_32 },
+		{ 0x7c8, 0x2c0,	RTL_GIGA_MAC_VER_33 },
+
+		/* 8168D family. */
+		{ 0x7cf, 0x281,	RTL_GIGA_MAC_VER_25 },
+		{ 0x7c8, 0x280,	RTL_GIGA_MAC_VER_26 },
+
+		/* 8168DP family. */
+		/* It seems this early RTL8168dp version never made it to
+		 * the wild. Support has been removed.
+		 * { 0x7cf, 0x288,      RTL_GIGA_MAC_VER_27 },
+		 */
+		{ 0x7cf, 0x28a,	RTL_GIGA_MAC_VER_28 },
+		{ 0x7cf, 0x28b,	RTL_GIGA_MAC_VER_31 },
+
+		/* 8168C family. */
+		{ 0x7cf, 0x3c9,	RTL_GIGA_MAC_VER_23 },
+		{ 0x7cf, 0x3c8,	RTL_GIGA_MAC_VER_18 },
+		{ 0x7c8, 0x3c8,	RTL_GIGA_MAC_VER_24 },
+		{ 0x7cf, 0x3c0,	RTL_GIGA_MAC_VER_19 },
+		{ 0x7cf, 0x3c2,	RTL_GIGA_MAC_VER_20 },
+		{ 0x7cf, 0x3c3,	RTL_GIGA_MAC_VER_21 },
+		{ 0x7c8, 0x3c0,	RTL_GIGA_MAC_VER_22 },
+
+		/* 8168B family. */
+		{ 0x7c8, 0x380,	RTL_GIGA_MAC_VER_17 },
+		{ 0x7c8, 0x300,	RTL_GIGA_MAC_VER_11 },
+
+		/* 8101 family. */
+		{ 0x7c8, 0x448,	RTL_GIGA_MAC_VER_39 },
+		{ 0x7c8, 0x440,	RTL_GIGA_MAC_VER_37 },
+		{ 0x7cf, 0x409,	RTL_GIGA_MAC_VER_29 },
+		{ 0x7c8, 0x408,	RTL_GIGA_MAC_VER_30 },
+		{ 0x7cf, 0x349,	RTL_GIGA_MAC_VER_08 },
+		{ 0x7cf, 0x249,	RTL_GIGA_MAC_VER_08 },
+		{ 0x7cf, 0x348,	RTL_GIGA_MAC_VER_07 },
+		{ 0x7cf, 0x248,	RTL_GIGA_MAC_VER_07 },
+		{ 0x7cf, 0x240,	RTL_GIGA_MAC_VER_14 },
+		{ 0x7c8, 0x348,	RTL_GIGA_MAC_VER_09 },
+		{ 0x7c8, 0x248,	RTL_GIGA_MAC_VER_09 },
+		{ 0x7c8, 0x340,	RTL_GIGA_MAC_VER_10 },
+
+		/* 8110 family. */
+		{ 0xfc8, 0x980,	RTL_GIGA_MAC_VER_06 },
+		{ 0xfc8, 0x180,	RTL_GIGA_MAC_VER_05 },
+		{ 0xfc8, 0x100,	RTL_GIGA_MAC_VER_04 },
+		{ 0xfc8, 0x040,	RTL_GIGA_MAC_VER_03 },
+		{ 0xfc8, 0x008,	RTL_GIGA_MAC_VER_02 },
+
+		/* Catch-all */
+		{ 0x000, 0x000,	RTL_GIGA_MAC_NONE   }
+	};
+	const struct rtl_mac_info *p = mac_info;
+	enum mac_version ver;
+
+	while ((xid & p->mask) != p->val)
+		p++;
+	ver = p->ver;
+
+	if (ver != RTL_GIGA_MAC_NONE && !gmii) {
+		if (ver == RTL_GIGA_MAC_VER_42)
+			ver = RTL_GIGA_MAC_VER_43;
+		else if (ver == RTL_GIGA_MAC_VER_46)
+			ver = RTL_GIGA_MAC_VER_48;
+	}
+
+	return ver;
+}
+
+void r8169_apply_firmware(struct rtl8169_private *tp)
+{
+	int val;
+	u64 start;
+
+	/* TODO: release firmware if rtl_fw_write_firmware signals failure. */
+	if (tp->rtl_fw) {
+		rtl_fw_write_firmware(tp, tp->rtl_fw);
+		/* At least one firmware doesn't reset tp->ocp_base. */
+		tp->ocp_base = OCP_STD_PHY_BASE;
+
+		/* PHY soft reset may still be in progress */
+		start = get_time_ns();
+		while (is_timeout(start, SECOND)) {
+			val = phy_read(tp->phydev, MII_BMCR);
+			if (!(val & BMCR_RESET))
+				return;
+		}
+	}
+}
+
+static void rtl_rar_exgmac_set(struct rtl8169_private *tp, const u8 *addr)
+{
+	rtl_eri_write(tp, 0xe0, ERIAR_MASK_1111, get_unaligned_le32(addr));
+	rtl_eri_write(tp, 0xe4, ERIAR_MASK_1111, get_unaligned_le16(addr + 4));
+	rtl_eri_write(tp, 0xf0, ERIAR_MASK_1111, get_unaligned_le16(addr) << 16);
+	rtl_eri_write(tp, 0xf4, ERIAR_MASK_1111, get_unaligned_le32(addr + 2));
+}
+
+u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp)
+{
+	u16 data1, data2, ioffset;
+
+	r8168_mac_ocp_write(tp, 0xdd02, 0x807d);
+	data1 = r8168_mac_ocp_read(tp, 0xdd02);
+	data2 = r8168_mac_ocp_read(tp, 0xdd00);
+
+	ioffset = (data2 >> 1) & 0x7ff8;
+	ioffset |= data2 & 0x0007;
+	if (data1 & BIT(7))
+		ioffset |= BIT(15);
+
+	return ioffset;
+}
+
+static void rtl8169_init_phy(struct rtl8169_private *tp)
+{
+	r8169_hw_phy_config(tp, tp->phydev, tp->mac_version);
+
+	if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+		pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
+		pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
+		/* set undocumented MAC Reg C+CR Offset 0x82h */
+		RTL_W8(tp, 0x82, 0x01);
+	}
+}
+
+static void rtl_rar_set(struct rtl8169_private *tp, const u8 *addr)
+{
+	rtl_unlock_config_regs(tp);
+
+	RTL_W32(tp, MAC4, get_unaligned_le16(addr + 4));
+	rtl_pci_commit(tp);
+
+	RTL_W32(tp, MAC0, get_unaligned_le32(addr));
+	rtl_pci_commit(tp);
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_34)
+		rtl_rar_exgmac_set(tp, addr);
+
+	rtl_lock_config_regs(tp);
+}
+
+static void rtl_init_rxcfg(struct rtl8169_private *tp)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
+	case RTL_GIGA_MAC_VER_10 ... RTL_GIGA_MAC_VER_17:
+		RTL_W32(tp, RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
+		break;
+	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24:
+	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_36:
+	case RTL_GIGA_MAC_VER_38:
+		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
+		break;
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53:
+		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
+		break;
+	case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
+		RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
+		break;
+	default:
+		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_DMA_BURST);
+		break;
+	}
+}
+
+DECLARE_RTL_COND(rtl_chipcmd_cond)
+{
+	return RTL_R8(tp, ChipCmd) & CmdReset;
+}
+
+static void rtl_hw_reset(struct rtl8169_private *tp)
+{
+	RTL_W8(tp, ChipCmd, CmdReset);
+
+	rtl_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
+}
+
+static void rtl_request_firmware(struct rtl8169_private *tp)
+{
+	struct rtl_fw *rtl_fw;
+
+	/* firmware loaded already or no firmware available */
+	if (tp->rtl_fw || !tp->fw_name)
+		return;
+
+	rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
+	if (!rtl_fw)
+		return;
+
+	rtl_fw->phy_write = rtl_writephy;
+	rtl_fw->phy_read = rtl_readphy;
+	rtl_fw->mac_mcu_write = mac_mcu_write;
+	rtl_fw->mac_mcu_read = mac_mcu_read;
+	rtl_fw->fw_name = tp->fw_name;
+	rtl_fw->dev = tp_to_dev(tp);
+
+	if (rtl_fw_request_firmware(rtl_fw))
+		kfree(rtl_fw);
+	else
+		tp->rtl_fw = rtl_fw;
+}
+
+static void rtl_rx_close(struct rtl8169_private *tp)
+{
+	RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
+}
+
+DECLARE_RTL_COND(rtl_npq_cond)
+{
+	return RTL_R8(tp, TxPoll) & NPQ;
+}
+
+DECLARE_RTL_COND(rtl_txcfg_empty_cond)
+{
+	return RTL_R32(tp, TxConfig) & TXCFG_EMPTY;
+}
+
+DECLARE_RTL_COND(rtl_rxtx_empty_cond)
+{
+	return (RTL_R8(tp, MCU) & RXTX_EMPTY) == RXTX_EMPTY;
+}
+
+DECLARE_RTL_COND(rtl_rxtx_empty_cond_2)
+{
+	/* IntrMitigate has new functionality on RTL8125 */
+	return (RTL_R16(tp, IntrMitigate) & 0x0103) == 0x0103;
+}
+
+static void rtl_wait_txrx_fifo_empty(struct rtl8169_private *tp)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53:
+		rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42);
+		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
+		break;
+	case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61:
+		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
+		break;
+	case RTL_GIGA_MAC_VER_63:
+		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
+		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
+		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rtl_disable_rxdvgate(struct rtl8169_private *tp)
+{
+	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
+}
+
+static void rtl_enable_rxdvgate(struct rtl8169_private *tp)
+{
+	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | RXDV_GATED_EN);
+	udelay(2000);
+	rtl_wait_txrx_fifo_empty(tp);
+}
+
+static void rtl_set_tx_config_registers(struct rtl8169_private *tp)
+{
+	u32 val = TX_DMA_BURST << TxDMAShift |
+		  InterFrameGap << TxInterFrameGapShift;
+
+	if (rtl_is_8168evl_up(tp))
+		val |= TXCFG_AUTO_FIFO;
+
+	RTL_W32(tp, TxConfig, val);
+}
+
+static void rtl_set_rx_max_size(struct rtl8169_private *tp)
+{
+	/* Low hurts. Let's disable the filtering. */
+	RTL_W16(tp, RxMaxSize, R8169_RX_BUF_SIZE + 1);
+}
+
+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp)
+{
+	/*
+	 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
+	 * register to be written before TxDescAddrLow to work.
+	 * Switching from MMIO to I/O access fixes the issue as well.
+	 */
+	RTL_W32(tp, TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
+	RTL_W32(tp, TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
+	RTL_W32(tp, RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
+	RTL_W32(tp, RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
+}
+
+static void rtl8169_set_magic_reg(struct rtl8169_private *tp)
+{
+	u32 val;
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
+		val = 0x000fff00;
+	else if (tp->mac_version == RTL_GIGA_MAC_VER_06)
+		val = 0x00ffff00;
+	else
+		return;
+
+	if (RTL_R8(tp, Config2) & PCI_Clock_66MHz)
+		val |= 0xff;
+
+	RTL_W32(tp, 0x7c, val);
+}
+
+static void rtl_set_rx_mode(struct  rtl8169_private *tp)
+{
+	u32 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
+	/* Multicast hash filter */
+	u32 mc_filter[2] = { 0xffffffff, 0xffffffff };
+	u32 tmp;
+
+	RTL_W32(tp, MAR0 + 4, mc_filter[1]);
+	RTL_W32(tp, MAR0 + 0, mc_filter[0]);
+
+	tmp = RTL_R32(tp, RxConfig);
+	RTL_W32(tp, RxConfig, (tmp & ~RX_CONFIG_ACCEPT_OK_MASK) | rx_mode);
+}
+
+DECLARE_RTL_COND(rtl_csiar_cond)
+{
+	return RTL_R32(tp, CSIAR) & CSIAR_FLAG;
+}
+
+static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
+{
+	u32 func = PCI_FUNC(tp->pci_dev->devfn);
+
+	RTL_W32(tp, CSIDR, value);
+	RTL_W32(tp, CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
+		CSIAR_BYTE_ENABLE | func << 16);
+
+	rtl_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
+}
+
+static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
+{
+	u32 func = PCI_FUNC(tp->pci_dev->devfn);
+
+	RTL_W32(tp, CSIAR, (addr & CSIAR_ADDR_MASK) | func << 16 |
+		CSIAR_BYTE_ENABLE);
+
+	return rtl_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
+		RTL_R32(tp, CSIDR) : ~0;
+}
+
+static void rtl_set_aspm_entry_latency(struct rtl8169_private *tp, u8 val)
+{
+	struct pci_dev *pdev = tp->pci_dev;
+	u32 csi;
+
+	/* According to Realtek the value at config space address 0x070f
+	 * controls the L0s/L1 entrance latency. We try standard ECAM access
+	 * first and if it fails fall back to CSI.
+	 * bit 0..2: L0: 0 = 1us, 1 = 2us .. 6 = 7us, 7 = 7us (no typo)
+	 * bit 3..5: L1: 0 = 1us, 1 = 2us .. 6 = 64us, 7 = 64us
+	 */
+	if (pci_write_config_byte(pdev, 0x070f, val) == PCIBIOS_SUCCESSFUL)
+		return;
+
+	dev_dbg(tp->dev,
+		"No native access to PCI extended config space, falling back to CSI\n");
+	csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
+	rtl_csi_write(tp, 0x070c, csi | val << 24);
+}
+
+static void rtl_set_def_aspm_entry_latency(struct rtl8169_private *tp)
+{
+	/* L0 7us, L1 16us */
+	rtl_set_aspm_entry_latency(tp, 0x27);
+}
+
+struct ephy_info {
+	unsigned int offset;
+	u16 mask;
+	u16 bits;
+};
+
+static void __rtl_ephy_init(struct rtl8169_private *tp,
+			    const struct ephy_info *e, int len)
+{
+	u16 w;
+
+	while (len-- > 0) {
+		w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
+		rtl_ephy_write(tp, e->offset, w);
+		e++;
+	}
+}
+
+#define rtl_ephy_init(tp, a) __rtl_ephy_init(tp, a, ARRAY_SIZE(a))
+
+static void rtl_disable_clock_request(struct rtl8169_private *tp)
+{
+	/* Not yet implemented */
+}
+
+static void rtl_enable_clock_request(struct rtl8169_private *tp)
+{
+	/* Not yet implemented */
+}
+
+static void rtl_pcie_state_l2l3_disable(struct rtl8169_private *tp)
+{
+	/* work around an issue when PCI reset occurs during L2/L3 state */
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Rdy_to_L23);
+}
+
+static void rtl_enable_exit_l1(struct rtl8169_private *tp)
+{
+	/* Bits control which events trigger ASPM L1 exit:
+	 * Bit 12: rxdv
+	 * Bit 11: ltr_msg
+	 * Bit 10: txdma_poll
+	 * Bit  9: xadm
+	 * Bit  8: pktavi
+	 * Bit  7: txpla
+	 */
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_36:
+		rtl_eri_set_bits(tp, 0xd4, 0x1f00);
+		break;
+	case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38:
+		rtl_eri_set_bits(tp, 0xd4, 0x0c00);
+		break;
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
+		r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rtl_disable_exit_l1(struct rtl8169_private *tp)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
+		rtl_eri_clear_bits(tp, 0xd4, 0x1f00);
+		break;
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
+		r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
+{
+	/* Don't enable ASPM in the chip if OS can't control ASPM */
+	if (enable && tp->aspm_manageable) {
+		RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
+		RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
+
+		switch (tp->mac_version) {
+		case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+		case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
+			/* reset ephy tx/rx disable timer */
+			r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);
+			/* chip can trigger L1.2 */
+			r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, BIT(2));
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (tp->mac_version) {
+		case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+		case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
+			r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);
+			break;
+		default:
+			break;
+		}
+
+		RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
+		RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+	}
+
+	udelay(10);
+}
+
+static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
+			      u16 tx_stat, u16 rx_dyn, u16 tx_dyn)
+{
+	/* Usage of dynamic vs. static FIFO is controlled by bit
+	 * TXCFG_AUTO_FIFO. Exact meaning of FIFO values isn't known.
+	 */
+	rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, (rx_stat << 16) | rx_dyn);
+	rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, (tx_stat << 16) | tx_dyn);
+}
+
+static void rtl8168g_set_pause_thresholds(struct rtl8169_private *tp,
+					  u8 low, u8 high)
+{
+	/* FIFO thresholds for pause flow control */
+	rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, low);
+	rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, high);
+}
+
+static void rtl_hw_start_8168b(struct rtl8169_private *tp)
+{
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
+}
+
+static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
+{
+	RTL_W8(tp, Config1, RTL_R8(tp, Config1) | Speed_down);
+
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
+
+	rtl_disable_clock_request(tp);
+}
+
+static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168cp[] = {
+		{ 0x01, 0,	0x0001 },
+		{ 0x02, 0x0800,	0x1000 },
+		{ 0x03, 0,	0x0042 },
+		{ 0x06, 0x0080,	0x0000 },
+		{ 0x07, 0,	0x2000 }
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_ephy_init(tp, e_info_8168cp);
+
+	__rtl_hw_start_8168cp(tp);
+}
+
+static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
+{
+	rtl_set_def_aspm_entry_latency(tp);
+
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
+}
+
+static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
+{
+	rtl_set_def_aspm_entry_latency(tp);
+
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
+
+	/* Magic. */
+	RTL_W8(tp, DBG_REG, 0x20);
+}
+
+static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168c_1[] = {
+		{ 0x02, 0x0800,	0x1000 },
+		{ 0x03, 0,	0x0002 },
+		{ 0x06, 0x0080,	0x0000 }
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	RTL_W8(tp, DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
+
+	rtl_ephy_init(tp, e_info_8168c_1);
+
+	__rtl_hw_start_8168cp(tp);
+}
+
+static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168c_2[] = {
+		{ 0x01, 0,	0x0001 },
+		{ 0x03, 0x0400,	0x0020 }
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_ephy_init(tp, e_info_8168c_2);
+
+	__rtl_hw_start_8168cp(tp);
+}
+
+static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
+{
+	rtl_set_def_aspm_entry_latency(tp);
+
+	__rtl_hw_start_8168cp(tp);
+}
+
+static void rtl_hw_start_8168d(struct rtl8169_private *tp)
+{
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_disable_clock_request(tp);
+}
+
+static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168d_4[] = {
+		{ 0x0b, 0x0000,	0x0048 },
+		{ 0x19, 0x0020,	0x0050 },
+		{ 0x0c, 0x0100,	0x0020 },
+		{ 0x10, 0x0004,	0x0000 },
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_ephy_init(tp, e_info_8168d_4);
+
+	rtl_enable_clock_request(tp);
+}
+
+static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168e_1[] = {
+		{ 0x00, 0x0200,	0x0100 },
+		{ 0x00, 0x0000,	0x0004 },
+		{ 0x06, 0x0002,	0x0001 },
+		{ 0x06, 0x0000,	0x0030 },
+		{ 0x07, 0x0000,	0x2000 },
+		{ 0x00, 0x0000,	0x0020 },
+		{ 0x03, 0x5800,	0x2000 },
+		{ 0x03, 0x0000,	0x0001 },
+		{ 0x01, 0x0800,	0x1000 },
+		{ 0x07, 0x0000,	0x4000 },
+		{ 0x1e, 0x0000,	0x2000 },
+		{ 0x19, 0xffff,	0xfe6c },
+		{ 0x0a, 0x0000,	0x0040 }
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_ephy_init(tp, e_info_8168e_1);
+
+	rtl_disable_clock_request(tp);
+
+	/* Reset tx FIFO pointer */
+	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | TXPLA_RST);
+	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~TXPLA_RST);
+
+	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
+}
+
+static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168e_2[] = {
+		{ 0x09, 0x0000,	0x0080 },
+		{ 0x19, 0x0000,	0x0224 },
+		{ 0x00, 0x0000,	0x0004 },
+		{ 0x0c, 0x3df0,	0x0200 },
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_ephy_init(tp, e_info_8168e_2);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_1111, 0x0000);
+	rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06);
+	rtl_eri_set_bits(tp, 0x1d0, BIT(1));
+	rtl_reset_packet_filter(tp);
+	rtl_eri_set_bits(tp, 0x1b0, BIT(4));
+	rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050);
+	rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060);
+
+	rtl_disable_clock_request(tp);
+
+	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
+	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
+	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
+
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_start_8168f(struct rtl8169_private *tp)
+{
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_1111, 0x0000);
+	rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06);
+	rtl_reset_packet_filter(tp);
+	rtl_eri_set_bits(tp, 0x1b0, BIT(4));
+	rtl_eri_set_bits(tp, 0x1d0, BIT(4) | BIT(1));
+	rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050);
+	rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060);
+
+	rtl_disable_clock_request(tp);
+
+	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
+	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
+	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
+}
+
+static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168f_1[] = {
+		{ 0x06, 0x00c0,	0x0020 },
+		{ 0x08, 0x0001,	0x0002 },
+		{ 0x09, 0x0000,	0x0080 },
+		{ 0x19, 0x0000,	0x0224 },
+		{ 0x00, 0x0000,	0x0008 },
+		{ 0x0c, 0x3df0,	0x0200 },
+	};
+
+	rtl_hw_start_8168f(tp);
+
+	rtl_ephy_init(tp, e_info_8168f_1);
+}
+
+static void rtl_hw_start_8411(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168f_1[] = {
+		{ 0x06, 0x00c0,	0x0020 },
+		{ 0x0f, 0xffff,	0x5200 },
+		{ 0x19, 0x0000,	0x0224 },
+		{ 0x00, 0x0000,	0x0008 },
+		{ 0x0c, 0x3df0,	0x0200 },
+	};
+
+	rtl_hw_start_8168f(tp);
+	rtl_pcie_state_l2l3_disable(tp);
+
+	rtl_ephy_init(tp, e_info_8168f_1);
+}
+
+static void rtl_hw_start_8168g(struct rtl8169_private *tp)
+{
+	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
+	rtl8168g_set_pause_thresholds(tp, 0x38, 0x48);
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_reset_packet_filter(tp);
+	rtl_eri_write(tp, 0x2f8, ERIAR_MASK_0011, 0x1d8f);
+
+	rtl_disable_rxdvgate(tp);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
+
+	rtl_w0w1_eri(tp, 0x2fc, 0x01, 0x06);
+	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
+
+	rtl_pcie_state_l2l3_disable(tp);
+}
+
+static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168g_1[] = {
+		{ 0x00, 0x0008,	0x0000 },
+		{ 0x0c, 0x3ff0,	0x0820 },
+		{ 0x1e, 0x0000,	0x0001 },
+		{ 0x19, 0x8000,	0x0000 }
+	};
+
+	rtl_hw_start_8168g(tp);
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8168g_1);
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168g_2[] = {
+		{ 0x00, 0x0008,	0x0000 },
+		{ 0x0c, 0x3ff0,	0x0820 },
+		{ 0x19, 0xffff,	0x7c00 },
+		{ 0x1e, 0xffff,	0x20eb },
+		{ 0x0d, 0xffff,	0x1666 },
+		{ 0x00, 0xffff,	0x10a3 },
+		{ 0x06, 0xffff,	0xf050 },
+		{ 0x04, 0x0000,	0x0010 },
+		{ 0x1d, 0x4000,	0x0000 },
+	};
+
+	rtl_hw_start_8168g(tp);
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8168g_2);
+}
+
+static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8411_2[] = {
+		{ 0x00, 0x0008,	0x0000 },
+		{ 0x0c, 0x37d0,	0x0820 },
+		{ 0x1e, 0x0000,	0x0001 },
+		{ 0x19, 0x8021,	0x0000 },
+		{ 0x1e, 0x0000,	0x2000 },
+		{ 0x0d, 0x0100,	0x0200 },
+		{ 0x00, 0x0000,	0x0080 },
+		{ 0x06, 0x0000,	0x0010 },
+		{ 0x04, 0x0000,	0x0010 },
+		{ 0x1d, 0x0000,	0x4000 },
+	};
+
+	rtl_hw_start_8168g(tp);
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8411_2);
+
+	/* The following Realtek-provided magic fixes an issue with the RX unit
+	 * getting confused after the PHY having been powered-down.
+	 */
+	r8168_mac_ocp_write(tp, 0xFC28, 0x0000);
+	r8168_mac_ocp_write(tp, 0xFC2A, 0x0000);
+	r8168_mac_ocp_write(tp, 0xFC2C, 0x0000);
+	r8168_mac_ocp_write(tp, 0xFC2E, 0x0000);
+	r8168_mac_ocp_write(tp, 0xFC30, 0x0000);
+	r8168_mac_ocp_write(tp, 0xFC32, 0x0000);
+	r8168_mac_ocp_write(tp, 0xFC34, 0x0000);
+	r8168_mac_ocp_write(tp, 0xFC36, 0x0000);
+	mdelay(3);
+	r8168_mac_ocp_write(tp, 0xFC26, 0x0000);
+
+	r8168_mac_ocp_write(tp, 0xF800, 0xE008);
+	r8168_mac_ocp_write(tp, 0xF802, 0xE00A);
+	r8168_mac_ocp_write(tp, 0xF804, 0xE00C);
+	r8168_mac_ocp_write(tp, 0xF806, 0xE00E);
+	r8168_mac_ocp_write(tp, 0xF808, 0xE027);
+	r8168_mac_ocp_write(tp, 0xF80A, 0xE04F);
+	r8168_mac_ocp_write(tp, 0xF80C, 0xE05E);
+	r8168_mac_ocp_write(tp, 0xF80E, 0xE065);
+	r8168_mac_ocp_write(tp, 0xF810, 0xC602);
+	r8168_mac_ocp_write(tp, 0xF812, 0xBE00);
+	r8168_mac_ocp_write(tp, 0xF814, 0x0000);
+	r8168_mac_ocp_write(tp, 0xF816, 0xC502);
+	r8168_mac_ocp_write(tp, 0xF818, 0xBD00);
+	r8168_mac_ocp_write(tp, 0xF81A, 0x074C);
+	r8168_mac_ocp_write(tp, 0xF81C, 0xC302);
+	r8168_mac_ocp_write(tp, 0xF81E, 0xBB00);
+	r8168_mac_ocp_write(tp, 0xF820, 0x080A);
+	r8168_mac_ocp_write(tp, 0xF822, 0x6420);
+	r8168_mac_ocp_write(tp, 0xF824, 0x48C2);
+	r8168_mac_ocp_write(tp, 0xF826, 0x8C20);
+	r8168_mac_ocp_write(tp, 0xF828, 0xC516);
+	r8168_mac_ocp_write(tp, 0xF82A, 0x64A4);
+	r8168_mac_ocp_write(tp, 0xF82C, 0x49C0);
+	r8168_mac_ocp_write(tp, 0xF82E, 0xF009);
+	r8168_mac_ocp_write(tp, 0xF830, 0x74A2);
+	r8168_mac_ocp_write(tp, 0xF832, 0x8CA5);
+	r8168_mac_ocp_write(tp, 0xF834, 0x74A0);
+	r8168_mac_ocp_write(tp, 0xF836, 0xC50E);
+	r8168_mac_ocp_write(tp, 0xF838, 0x9CA2);
+	r8168_mac_ocp_write(tp, 0xF83A, 0x1C11);
+	r8168_mac_ocp_write(tp, 0xF83C, 0x9CA0);
+	r8168_mac_ocp_write(tp, 0xF83E, 0xE006);
+	r8168_mac_ocp_write(tp, 0xF840, 0x74F8);
+	r8168_mac_ocp_write(tp, 0xF842, 0x48C4);
+	r8168_mac_ocp_write(tp, 0xF844, 0x8CF8);
+	r8168_mac_ocp_write(tp, 0xF846, 0xC404);
+	r8168_mac_ocp_write(tp, 0xF848, 0xBC00);
+	r8168_mac_ocp_write(tp, 0xF84A, 0xC403);
+	r8168_mac_ocp_write(tp, 0xF84C, 0xBC00);
+	r8168_mac_ocp_write(tp, 0xF84E, 0x0BF2);
+	r8168_mac_ocp_write(tp, 0xF850, 0x0C0A);
+	r8168_mac_ocp_write(tp, 0xF852, 0xE434);
+	r8168_mac_ocp_write(tp, 0xF854, 0xD3C0);
+	r8168_mac_ocp_write(tp, 0xF856, 0x49D9);
+	r8168_mac_ocp_write(tp, 0xF858, 0xF01F);
+	r8168_mac_ocp_write(tp, 0xF85A, 0xC526);
+	r8168_mac_ocp_write(tp, 0xF85C, 0x64A5);
+	r8168_mac_ocp_write(tp, 0xF85E, 0x1400);
+	r8168_mac_ocp_write(tp, 0xF860, 0xF007);
+	r8168_mac_ocp_write(tp, 0xF862, 0x0C01);
+	r8168_mac_ocp_write(tp, 0xF864, 0x8CA5);
+	r8168_mac_ocp_write(tp, 0xF866, 0x1C15);
+	r8168_mac_ocp_write(tp, 0xF868, 0xC51B);
+	r8168_mac_ocp_write(tp, 0xF86A, 0x9CA0);
+	r8168_mac_ocp_write(tp, 0xF86C, 0xE013);
+	r8168_mac_ocp_write(tp, 0xF86E, 0xC519);
+	r8168_mac_ocp_write(tp, 0xF870, 0x74A0);
+	r8168_mac_ocp_write(tp, 0xF872, 0x48C4);
+	r8168_mac_ocp_write(tp, 0xF874, 0x8CA0);
+	r8168_mac_ocp_write(tp, 0xF876, 0xC516);
+	r8168_mac_ocp_write(tp, 0xF878, 0x74A4);
+	r8168_mac_ocp_write(tp, 0xF87A, 0x48C8);
+	r8168_mac_ocp_write(tp, 0xF87C, 0x48CA);
+	r8168_mac_ocp_write(tp, 0xF87E, 0x9CA4);
+	r8168_mac_ocp_write(tp, 0xF880, 0xC512);
+	r8168_mac_ocp_write(tp, 0xF882, 0x1B00);
+	r8168_mac_ocp_write(tp, 0xF884, 0x9BA0);
+	r8168_mac_ocp_write(tp, 0xF886, 0x1B1C);
+	r8168_mac_ocp_write(tp, 0xF888, 0x483F);
+	r8168_mac_ocp_write(tp, 0xF88A, 0x9BA2);
+	r8168_mac_ocp_write(tp, 0xF88C, 0x1B04);
+	r8168_mac_ocp_write(tp, 0xF88E, 0xC508);
+	r8168_mac_ocp_write(tp, 0xF890, 0x9BA0);
+	r8168_mac_ocp_write(tp, 0xF892, 0xC505);
+	r8168_mac_ocp_write(tp, 0xF894, 0xBD00);
+	r8168_mac_ocp_write(tp, 0xF896, 0xC502);
+	r8168_mac_ocp_write(tp, 0xF898, 0xBD00);
+	r8168_mac_ocp_write(tp, 0xF89A, 0x0300);
+	r8168_mac_ocp_write(tp, 0xF89C, 0x051E);
+	r8168_mac_ocp_write(tp, 0xF89E, 0xE434);
+	r8168_mac_ocp_write(tp, 0xF8A0, 0xE018);
+	r8168_mac_ocp_write(tp, 0xF8A2, 0xE092);
+	r8168_mac_ocp_write(tp, 0xF8A4, 0xDE20);
+	r8168_mac_ocp_write(tp, 0xF8A6, 0xD3C0);
+	r8168_mac_ocp_write(tp, 0xF8A8, 0xC50F);
+	r8168_mac_ocp_write(tp, 0xF8AA, 0x76A4);
+	r8168_mac_ocp_write(tp, 0xF8AC, 0x49E3);
+	r8168_mac_ocp_write(tp, 0xF8AE, 0xF007);
+	r8168_mac_ocp_write(tp, 0xF8B0, 0x49C0);
+	r8168_mac_ocp_write(tp, 0xF8B2, 0xF103);
+	r8168_mac_ocp_write(tp, 0xF8B4, 0xC607);
+	r8168_mac_ocp_write(tp, 0xF8B6, 0xBE00);
+	r8168_mac_ocp_write(tp, 0xF8B8, 0xC606);
+	r8168_mac_ocp_write(tp, 0xF8BA, 0xBE00);
+	r8168_mac_ocp_write(tp, 0xF8BC, 0xC602);
+	r8168_mac_ocp_write(tp, 0xF8BE, 0xBE00);
+	r8168_mac_ocp_write(tp, 0xF8C0, 0x0C4C);
+	r8168_mac_ocp_write(tp, 0xF8C2, 0x0C28);
+	r8168_mac_ocp_write(tp, 0xF8C4, 0x0C2C);
+	r8168_mac_ocp_write(tp, 0xF8C6, 0xDC00);
+	r8168_mac_ocp_write(tp, 0xF8C8, 0xC707);
+	r8168_mac_ocp_write(tp, 0xF8CA, 0x1D00);
+	r8168_mac_ocp_write(tp, 0xF8CC, 0x8DE2);
+	r8168_mac_ocp_write(tp, 0xF8CE, 0x48C1);
+	r8168_mac_ocp_write(tp, 0xF8D0, 0xC502);
+	r8168_mac_ocp_write(tp, 0xF8D2, 0xBD00);
+	r8168_mac_ocp_write(tp, 0xF8D4, 0x00AA);
+	r8168_mac_ocp_write(tp, 0xF8D6, 0xE0C0);
+	r8168_mac_ocp_write(tp, 0xF8D8, 0xC502);
+	r8168_mac_ocp_write(tp, 0xF8DA, 0xBD00);
+	r8168_mac_ocp_write(tp, 0xF8DC, 0x0132);
+
+	r8168_mac_ocp_write(tp, 0xFC26, 0x8000);
+
+	r8168_mac_ocp_write(tp, 0xFC2A, 0x0743);
+	r8168_mac_ocp_write(tp, 0xFC2C, 0x0801);
+	r8168_mac_ocp_write(tp, 0xFC2E, 0x0BE9);
+	r8168_mac_ocp_write(tp, 0xFC30, 0x02FD);
+	r8168_mac_ocp_write(tp, 0xFC32, 0x0C25);
+	r8168_mac_ocp_write(tp, 0xFC34, 0x00A9);
+	r8168_mac_ocp_write(tp, 0xFC36, 0x012D);
+
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168h_1[] = {
+		{ 0x1e, 0x0800,	0x0001 },
+		{ 0x1d, 0x0000,	0x0800 },
+		{ 0x05, 0xffff,	0x2089 },
+		{ 0x06, 0xffff,	0x5881 },
+		{ 0x04, 0xffff,	0x854a },
+		{ 0x01, 0xffff,	0x068b }
+	};
+	int rg_saw_cnt;
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8168h_1);
+
+	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
+	rtl8168g_set_pause_thresholds(tp, 0x38, 0x48);
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_reset_packet_filter(tp);
+
+	rtl_eri_set_bits(tp, 0xdc, 0x001c);
+
+	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
+
+	rtl_disable_rxdvgate(tp);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
+	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
+
+	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
+
+	rtl_pcie_state_l2l3_disable(tp);
+
+	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
+	if (rg_saw_cnt > 0) {
+		u16 sw_cnt_1ms_ini;
+
+		sw_cnt_1ms_ini = 16000000/rg_saw_cnt;
+		sw_cnt_1ms_ini &= 0x0fff;
+		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
+	}
+
+	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070);
+	r8168_mac_ocp_modify(tp, 0xe052, 0x6000, 0x8008);
+	r8168_mac_ocp_modify(tp, 0xe0d6, 0x01ff, 0x017f);
+	r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
+
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
+
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
+{
+	rtl8168ep_stop_cmac(tp);
+
+	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
+	rtl8168g_set_pause_thresholds(tp, 0x2f, 0x5f);
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_reset_packet_filter(tp);
+
+	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
+
+	rtl_disable_rxdvgate(tp);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
+
+	rtl_w0w1_eri(tp, 0x2fc, 0x01, 0x06);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
+
+	rtl_pcie_state_l2l3_disable(tp);
+}
+
+static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8168ep_3[] = {
+		{ 0x00, 0x0000,	0x0080 },
+		{ 0x0d, 0x0100,	0x0200 },
+		{ 0x19, 0x8021,	0x0000 },
+		{ 0x1e, 0x0000,	0x2000 },
+	};
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8168ep_3);
+
+	rtl_hw_start_8168ep(tp);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
+	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
+
+	r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x0271);
+	r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);
+	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
+
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_start_8117(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8117[] = {
+		{ 0x19, 0x0040,	0x1100 },
+		{ 0x59, 0x0040,	0x1100 },
+	};
+	int rg_saw_cnt;
+
+	rtl8168ep_stop_cmac(tp);
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8117);
+
+	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
+	rtl8168g_set_pause_thresholds(tp, 0x2f, 0x5f);
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_reset_packet_filter(tp);
+
+	rtl_eri_set_bits(tp, 0xd4, 0x0010);
+
+	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
+
+	rtl_disable_rxdvgate(tp);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
+	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
+
+	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
+
+	rtl_pcie_state_l2l3_disable(tp);
+
+	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
+	if (rg_saw_cnt > 0) {
+		u16 sw_cnt_1ms_ini;
+
+		sw_cnt_1ms_ini = (16000000 / rg_saw_cnt) & 0x0fff;
+		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
+	}
+
+	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070);
+	r8168_mac_ocp_write(tp, 0xea80, 0x0003);
+	r8168_mac_ocp_modify(tp, 0xe052, 0x0000, 0x0009);
+	r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
+
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
+
+	/* firmware is for MAC only */
+	r8169_apply_firmware(tp);
+
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8102e_1[] = {
+		{ 0x01,	0, 0x6e65 },
+		{ 0x02,	0, 0x091f },
+		{ 0x03,	0, 0xc2f9 },
+		{ 0x06,	0, 0xafb5 },
+		{ 0x07,	0, 0x0e00 },
+		{ 0x19,	0, 0xec80 },
+		{ 0x01,	0, 0x2e65 },
+		{ 0x01,	0, 0x6e65 }
+	};
+	u8 cfg1;
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	RTL_W8(tp, DBG_REG, FIX_NAK_1);
+
+	RTL_W8(tp, Config1,
+	       LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
+
+	cfg1 = RTL_R8(tp, Config1);
+	if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
+		RTL_W8(tp, Config1, cfg1 & ~LEDS0);
+
+	rtl_ephy_init(tp, e_info_8102e_1);
+}
+
+static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
+{
+	rtl_set_def_aspm_entry_latency(tp);
+
+	RTL_W8(tp, Config1, MEMMAP | IOMAP | VPD | PMEnable);
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
+}
+
+static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
+{
+	rtl_hw_start_8102e_2(tp);
+
+	rtl_ephy_write(tp, 0x03, 0xc2f9);
+}
+
+static void rtl_hw_start_8401(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8401[] = {
+		{ 0x01,	0xffff, 0x6fe5 },
+		{ 0x03,	0xffff, 0x0599 },
+		{ 0x06,	0xffff, 0xaf25 },
+		{ 0x07,	0xffff, 0x8e68 },
+	};
+
+	rtl_ephy_init(tp, e_info_8401);
+	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
+}
+
+static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8105e_1[] = {
+		{ 0x07,	0, 0x4000 },
+		{ 0x19,	0, 0x0200 },
+		{ 0x19,	0, 0x0020 },
+		{ 0x1e,	0, 0x2000 },
+		{ 0x03,	0, 0x0001 },
+		{ 0x19,	0, 0x0100 },
+		{ 0x19,	0, 0x0004 },
+		{ 0x0a,	0, 0x0020 }
+	};
+
+	/* Force LAN exit from ASPM if Rx/Tx are not idle */
+	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
+
+	/* Disable Early Tally Counter */
+	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) & ~0x010000);
+
+	RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
+
+	rtl_ephy_init(tp, e_info_8105e_1);
+
+	rtl_pcie_state_l2l3_disable(tp);
+}
+
+static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
+{
+	rtl_hw_start_8105e_1(tp);
+	rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
+}
+
+static void rtl_hw_start_8402(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8402[] = {
+		{ 0x19,	0xffff, 0xff64 },
+		{ 0x1e,	0, 0x4000 }
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	/* Force LAN exit from ASPM if Rx/Tx are not idle */
+	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
+
+	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
+
+	rtl_ephy_init(tp, e_info_8402);
+
+	rtl_set_fifo_size(tp, 0x00, 0x00, 0x02, 0x06);
+	rtl_reset_packet_filter(tp);
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
+	rtl_w0w1_eri(tp, 0x0d4, 0x0e00, 0xff00);
+
+	/* disable EEE */
+	rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
+
+	rtl_pcie_state_l2l3_disable(tp);
+}
+
+static void rtl_hw_start_8106(struct rtl8169_private *tp)
+{
+	rtl_hw_aspm_clkreq_enable(tp, false);
+
+	/* Force LAN exit from ASPM if Rx/Tx are not idle */
+	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
+
+	RTL_W32(tp, MISC, (RTL_R32(tp, MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
+	RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
+
+	/* L0 7us, L1 32us - needed to avoid issues with link-up detection */
+	rtl_set_aspm_entry_latency(tp, 0x2f);
+
+	rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
+
+	/* disable EEE */
+	rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
+
+	rtl_pcie_state_l2l3_disable(tp);
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
+{
+	return r8168_mac_ocp_read(tp, 0xe00e) & BIT(13);
+}
+
+static void rtl_hw_start_8125_common(struct rtl8169_private *tp)
+{
+	rtl_pcie_state_l2l3_disable(tp);
+
+	RTL_W16(tp, 0x382, 0x221b);
+	RTL_W8(tp, 0x4500, 0);
+	RTL_W16(tp, 0x4800, 0);
+
+	/* disable UPS */
+	r8168_mac_ocp_modify(tp, 0xd40a, 0x0010, 0x0000);
+
+	RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10);
+
+	r8168_mac_ocp_write(tp, 0xc140, 0xffff);
+	r8168_mac_ocp_write(tp, 0xc142, 0xffff);
+
+	r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x03a9);
+	r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);
+	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
+
+	/* disable new tx descriptor format */
+	r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000);
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
+		r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200);
+	else
+		r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
+		r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0000);
+	else
+		r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0020);
+
+	r8168_mac_ocp_modify(tp, 0xc0b4, 0x0000, 0x000c);
+	r8168_mac_ocp_modify(tp, 0xeb6a, 0x00ff, 0x0033);
+	r8168_mac_ocp_modify(tp, 0xeb50, 0x03e0, 0x0040);
+	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0030);
+	r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000);
+	r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001);
+	r8168_mac_ocp_modify(tp, 0xe0c0, 0x4f0f, 0x4403);
+	r8168_mac_ocp_modify(tp, 0xe052, 0x0080, 0x0068);
+	r8168_mac_ocp_modify(tp, 0xd430, 0x0fff, 0x047f);
+
+	r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000);
+	r8168_mac_ocp_modify(tp, 0xeb54, 0x0000, 0x0001);
+	udelay(1);
+	r8168_mac_ocp_modify(tp, 0xeb54, 0x0001, 0x0000);
+	RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~0x0030);
+
+	r8168_mac_ocp_write(tp, 0xe098, 0xc302);
+
+	rtl_loop_wait_low(tp, &rtl_mac_ocp_e00e_cond, 1000, 10);
+
+	rtl_disable_rxdvgate(tp);
+}
+
+static void rtl_hw_start_8125a_2(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8125a_2[] = {
+		{ 0x04, 0xffff, 0xd000 },
+		{ 0x0a, 0xffff, 0x8653 },
+		{ 0x23, 0xffff, 0xab66 },
+		{ 0x20, 0xffff, 0x9455 },
+		{ 0x21, 0xffff, 0x99ff },
+		{ 0x29, 0xffff, 0xfe04 },
+
+		{ 0x44, 0xffff, 0xd000 },
+		{ 0x4a, 0xffff, 0x8653 },
+		{ 0x63, 0xffff, 0xab66 },
+		{ 0x60, 0xffff, 0x9455 },
+		{ 0x61, 0xffff, 0x99ff },
+		{ 0x69, 0xffff, 0xfe04 },
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8125a_2);
+
+	rtl_hw_start_8125_common(tp);
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_start_8125b(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8125b[] = {
+		{ 0x0b, 0xffff, 0xa908 },
+		{ 0x1e, 0xffff, 0x20eb },
+		{ 0x4b, 0xffff, 0xa908 },
+		{ 0x5e, 0xffff, 0x20eb },
+		{ 0x22, 0x0030, 0x0020 },
+		{ 0x62, 0x0030, 0x0020 },
+	};
+
+	rtl_set_def_aspm_entry_latency(tp);
+	rtl_hw_aspm_clkreq_enable(tp, false);
+
+	rtl_ephy_init(tp, e_info_8125b);
+	rtl_hw_start_8125_common(tp);
+
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
+static void rtl_hw_config(struct rtl8169_private *tp)
+{
+	static const rtl_generic_fct hw_configs[] = {
+		[RTL_GIGA_MAC_VER_07] = rtl_hw_start_8102e_1,
+		[RTL_GIGA_MAC_VER_08] = rtl_hw_start_8102e_3,
+		[RTL_GIGA_MAC_VER_09] = rtl_hw_start_8102e_2,
+		[RTL_GIGA_MAC_VER_10] = NULL,
+		[RTL_GIGA_MAC_VER_11] = rtl_hw_start_8168b,
+		[RTL_GIGA_MAC_VER_14] = rtl_hw_start_8401,
+		[RTL_GIGA_MAC_VER_17] = rtl_hw_start_8168b,
+		[RTL_GIGA_MAC_VER_18] = rtl_hw_start_8168cp_1,
+		[RTL_GIGA_MAC_VER_19] = rtl_hw_start_8168c_1,
+		[RTL_GIGA_MAC_VER_20] = rtl_hw_start_8168c_2,
+		[RTL_GIGA_MAC_VER_21] = rtl_hw_start_8168c_2,
+		[RTL_GIGA_MAC_VER_22] = rtl_hw_start_8168c_4,
+		[RTL_GIGA_MAC_VER_23] = rtl_hw_start_8168cp_2,
+		[RTL_GIGA_MAC_VER_24] = rtl_hw_start_8168cp_3,
+		[RTL_GIGA_MAC_VER_25] = rtl_hw_start_8168d,
+		[RTL_GIGA_MAC_VER_26] = rtl_hw_start_8168d,
+		[RTL_GIGA_MAC_VER_28] = rtl_hw_start_8168d_4,
+		[RTL_GIGA_MAC_VER_29] = rtl_hw_start_8105e_1,
+		[RTL_GIGA_MAC_VER_30] = rtl_hw_start_8105e_2,
+		[RTL_GIGA_MAC_VER_31] = rtl_hw_start_8168d,
+		[RTL_GIGA_MAC_VER_32] = rtl_hw_start_8168e_1,
+		[RTL_GIGA_MAC_VER_33] = rtl_hw_start_8168e_1,
+		[RTL_GIGA_MAC_VER_34] = rtl_hw_start_8168e_2,
+		[RTL_GIGA_MAC_VER_35] = rtl_hw_start_8168f_1,
+		[RTL_GIGA_MAC_VER_36] = rtl_hw_start_8168f_1,
+		[RTL_GIGA_MAC_VER_37] = rtl_hw_start_8402,
+		[RTL_GIGA_MAC_VER_38] = rtl_hw_start_8411,
+		[RTL_GIGA_MAC_VER_39] = rtl_hw_start_8106,
+		[RTL_GIGA_MAC_VER_40] = rtl_hw_start_8168g_1,
+		[RTL_GIGA_MAC_VER_42] = rtl_hw_start_8168g_2,
+		[RTL_GIGA_MAC_VER_43] = rtl_hw_start_8168g_2,
+		[RTL_GIGA_MAC_VER_44] = rtl_hw_start_8411_2,
+		[RTL_GIGA_MAC_VER_46] = rtl_hw_start_8168h_1,
+		[RTL_GIGA_MAC_VER_48] = rtl_hw_start_8168h_1,
+		[RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3,
+		[RTL_GIGA_MAC_VER_52] = rtl_hw_start_8117,
+		[RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117,
+		[RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
+		[RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
+	};
+
+	if (hw_configs[tp->mac_version])
+		hw_configs[tp->mac_version](tp);
+}
+
+static void rtl_hw_start_8125(struct rtl8169_private *tp)
+{
+	int i;
+
+	/* disable interrupt coalescing */
+	for (i = 0xa00; i < 0xb00; i += 4)
+		RTL_W32(tp, i, 0);
+
+	rtl_hw_config(tp);
+}
+
+static void rtl_hw_start_8168(struct rtl8169_private *tp)
+{
+	if (rtl_is_8168evl_up(tp))
+		RTL_W8(tp, MaxTxPacketSize, EarlySize);
+	else
+		RTL_W8(tp, MaxTxPacketSize, TxPacketMax);
+
+	rtl_hw_config(tp);
+
+	/* disable interrupt coalescing */
+	RTL_W16(tp, IntrMitigate, 0x0000);
+}
+
+static void rtl_hw_start_8169(struct rtl8169_private *tp)
+{
+	RTL_W8(tp, EarlyTxThres, NoEarlyTx);
+
+	tp->cp_cmd |= PCIMulRW;
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_03)
+		tp->cp_cmd |= EnAnaPLL;
+
+	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
+
+	rtl8169_set_magic_reg(tp);
+
+	/* disable interrupt coalescing */
+	RTL_W16(tp, IntrMitigate, 0x0000);
+}
+
+static void rtl_hw_start(struct  rtl8169_private *tp)
+{
+	rtl_unlock_config_regs(tp);
+
+	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
+
+	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+		rtl_hw_start_8169(tp);
+	else if (rtl_is_8125(tp))
+		rtl_hw_start_8125(tp);
+	else
+		rtl_hw_start_8168(tp);
+
+	rtl_enable_exit_l1(tp);
+	rtl_set_rx_max_size(tp);
+	rtl_set_rx_tx_desc_registers(tp);
+	rtl_lock_config_regs(tp);
+
+	/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
+	rtl_pci_commit(tp);
+
+	RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb);
+	rtl_init_rxcfg(tp);
+	rtl_set_tx_config_registers(tp);
+	rtl_set_rx_mode(tp);
+}
+
+static void rtl8169_cleanup(struct rtl8169_private *tp)
+{
+	rtl_rx_close(tp);
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		rtl_loop_wait_low(tp, &rtl_npq_cond, 20, 2000);
+		break;
+	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
+		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
+		rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
+		break;
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
+		rtl_enable_rxdvgate(tp);
+		udelay(2000);
+		break;
+	default:
+		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
+		udelay(100);
+		break;
+	}
+
+	rtl_hw_reset(tp);
+}
+
+static void rtl_read_mac_address(struct rtl8169_private *tp,
+				 u8 mac_addr[ETH_ALEN])
+{
+	/* Get MAC address */
+	if (rtl_is_8168evl_up(tp) && tp->mac_version != RTL_GIGA_MAC_VER_34) {
+		u32 value;
+
+		value = rtl_eri_read(tp, 0xe0);
+		put_unaligned_le32(value, mac_addr);
+		value = rtl_eri_read(tp, 0xe4);
+		put_unaligned_le16(value, mac_addr + 4);
+	} else if (rtl_is_8125(tp)) {
+		rtl_read_mac_from_reg(tp, mac_addr, MAC0_BKP);
+	}
+}
+
+DECLARE_RTL_COND(rtl_link_list_ready_cond)
+{
+	return RTL_R8(tp, MCU) & LINK_LIST_RDY;
+}
+
+static void r8168g_wait_ll_share_fifo_ready(struct rtl8169_private *tp)
+{
+	rtl_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42);
+}
+
+static void rtl_hw_init_8168g(struct rtl8169_private *tp)
+{
+	rtl_enable_rxdvgate(tp);
+
+	RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
+	mdelay(1);
+	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
+
+	r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0);
+	r8168g_wait_ll_share_fifo_ready(tp);
+
+	r8168_mac_ocp_modify(tp, 0xe8de, 0, BIT(15));
+	r8168g_wait_ll_share_fifo_ready(tp);
+}
+
+static void rtl_hw_init_8125(struct rtl8169_private *tp)
+{
+	rtl_enable_rxdvgate(tp);
+
+	RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
+	mdelay(1);
+	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
+
+	r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0);
+	r8168g_wait_ll_share_fifo_ready(tp);
+
+	r8168_mac_ocp_write(tp, 0xc0aa, 0x07d0);
+	r8168_mac_ocp_write(tp, 0xc0a6, 0x0150);
+	r8168_mac_ocp_write(tp, 0xc01e, 0x5555);
+	r8168g_wait_ll_share_fifo_ready(tp);
+}
+
+static void rtl_hw_initialize(struct rtl8169_private *tp)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
+		rtl8168ep_stop_cmac(tp);
+		fallthrough;
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
+		rtl_hw_init_8168g(tp);
+		break;
+	case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
+		rtl_hw_init_8125(tp);
+		break;
+	default:
+		break;
+	}
+}
+
+static int rtl8169_init_dev(struct eth_device *edev)
+{
+	struct rtl8169_private *tp = edev->priv;
+	int ret;
+
+	rtl_request_firmware(tp);
+
+	pci_set_master(tp->pci_dev);
+
+	tp->phydev = get_phy_device(&tp->miibus, 0);
+	if (IS_ERR(tp->phydev))
+		return PTR_ERR(tp->phydev);
+
+	ret = phy_register_device(tp->phydev);
+	if (ret)
+		return ret;
+
+	rtl8169_init_phy(tp);
+
+	return 0;
+}
+
+#define ETH_ZLEN        60              /* Min. octets in frame sans FCS */
+#define PKT_BUF_SIZE   1536
+
+static void rtl8169_init_ring(struct rtl8169_private *tp)
+{
+	struct eth_device *edev = &tp->edev;
+	int i;
+
+	tp->cur_rx = tp->cur_tx = 0;
+
+	tp->TxDescArray = dma_alloc_coherent(NUM_TX_DESC * sizeof(struct TxDesc),
+					   &tp->TxPhyAddr);
+	tp->tx_buf = dma_alloc(NUM_TX_DESC * PKT_BUF_SIZE);
+	tp->tx_buf_phys = dma_map_single(edev->parent, tp->tx_buf,
+					   NUM_TX_DESC * PKT_BUF_SIZE, DMA_TO_DEVICE);
+
+	tp->RxDescArray = dma_alloc_coherent(NUM_RX_DESC * sizeof(struct RxDesc),
+					   &tp->RxPhyAddr);
+	tp->rx_buf = dma_alloc(NUM_RX_DESC * PKT_BUF_SIZE);
+	tp->rx_buf_phys = dma_map_single(edev->parent, tp->rx_buf,
+					   NUM_RX_DESC * PKT_BUF_SIZE, DMA_FROM_DEVICE);
+
+	for (i = 0; i < NUM_RX_DESC; i++) {
+		if (i == (NUM_RX_DESC - 1))
+			tp->RxDescArray[i].opts1 =
+				cpu_to_le32(DescOwn | RingEnd | PKT_BUF_SIZE);
+		else
+			tp->RxDescArray[i].opts1 =
+				cpu_to_le32(DescOwn | PKT_BUF_SIZE);
+
+		tp->RxDescArray[i].addr =
+				cpu_to_le64(tp->rx_buf_phys + i * PKT_BUF_SIZE);
+	}
+}
+
+static void r8169_phylink_handler(struct eth_device *edev)
+{
+	struct rtl8169_private *tp = edev->priv;
+
+	rtl_link_chg_patch(tp);
+}
+
+static int rtl8169_eth_open(struct eth_device *edev)
+{
+	struct rtl8169_private *tp = edev->priv;
+	int ret;
+
+	pci_set_master(tp->pci_dev);
+
+	rtl8169_init_ring(tp);
+	rtl_hw_start(tp);
+
+	ret = phy_device_connect(edev, &tp->miibus, 0, r8169_phylink_handler, 0,
+				 PHY_INTERFACE_MODE_NA);
+
+	return ret;
+}
+
+static int rtl8169_phy_write(struct mii_bus *bus, int phyaddr, int phyreg, u16 val)
+{
+	struct rtl8169_private *tp = bus->priv;
+
+	if (phyaddr > 0)
+		return -ENODEV;
+
+	rtl_writephy(tp, phyreg, val);
+
+	return 0;
+}
+
+static int rtl8169_phy_read(struct mii_bus *bus, int phyaddr, int phyreg)
+{
+	struct rtl8169_private *tp = bus->priv;
+
+	if (phyaddr > 0)
+		return -ENODEV;
+
+	return rtl_readphy(tp, phyreg);
+}
+
+static void rtl8169_doorbell(struct rtl8169_private *tp)
+{
+	if (rtl_is_8125(tp))
+		RTL_W16(tp, TxPoll_8125, BIT(0));
+	else
+		RTL_W8(tp, TxPoll, NPQ);
+}
+
+static int rtl8169_eth_send(struct eth_device *edev, void *packet,
+				int packet_length)
+{
+	struct rtl8169_private *tp = edev->priv;
+	unsigned int entry;
+	u64 start;
+	int ret = 0;
+
+	entry = tp->cur_tx % NUM_TX_DESC;
+
+	if (packet_length < ETH_ZLEN)
+		memset(tp->tx_buf + entry * PKT_BUF_SIZE, 0, ETH_ZLEN);
+	memcpy(tp->tx_buf + entry * PKT_BUF_SIZE, packet, packet_length);
+	dma_sync_single_for_device(tp->tx_buf_phys + entry *
+				   PKT_BUF_SIZE, PKT_BUF_SIZE, DMA_TO_DEVICE);
+
+	tp->TxDescArray[entry].addr = cpu_to_le64(tp->tx_buf_phys + entry * PKT_BUF_SIZE);
+
+	if (entry != (NUM_TX_DESC - 1)) {
+		tp->TxDescArray[entry].opts1 =
+			cpu_to_le32(DescOwn | FirstFrag | LastFrag |
+			((packet_length > ETH_ZLEN) ? packet_length : ETH_ZLEN));
+	} else {
+		tp->TxDescArray[entry].opts1 =
+			cpu_to_le32(DescOwn | RingEnd | FirstFrag | LastFrag |
+			((packet_length > ETH_ZLEN) ? packet_length : ETH_ZLEN));
+	}
+
+	rtl8169_doorbell(tp);
+
+	start = get_time_ns();
+
+	while (le32_to_cpu(tp->TxDescArray[entry].opts1) & DescOwn) {
+		if (is_timeout(start, 100 * MSECOND)) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+	}
+
+	dma_sync_single_for_cpu(tp->tx_buf_phys + entry * PKT_BUF_SIZE,
+				PKT_BUF_SIZE, DMA_TO_DEVICE);
+
+	tp->cur_tx++;
+
+	return ret;
+}
+
+static int rtl8169_eth_rx(struct eth_device *edev)
+{
+	struct rtl8169_private *tp = edev->priv;
+	unsigned int entry, pkt_size = 0;
+	u8 status;
+
+	entry = tp->cur_rx % NUM_RX_DESC;
+
+	if ((le32_to_cpu(tp->RxDescArray[entry].opts1) & DescOwn) == 0) {
+		if (!(le32_to_cpu(tp->RxDescArray[entry].opts1) & RxRES)) {
+			pkt_size = (le32_to_cpu(tp->RxDescArray[entry].opts1) & 0x1fff) - 4;
+
+			dma_sync_single_for_cpu(tp->rx_buf_phys + entry * PKT_BUF_SIZE,
+						pkt_size, DMA_FROM_DEVICE);
+
+			net_receive(edev, tp->rx_buf + entry * PKT_BUF_SIZE,
+			            pkt_size);
+
+			dma_sync_single_for_device(tp->rx_buf_phys + entry * PKT_BUF_SIZE,
+						   pkt_size, DMA_FROM_DEVICE);
+
+			if (entry == NUM_RX_DESC - 1)
+				tp->RxDescArray[entry].opts1 = cpu_to_le32(DescOwn |
+					RingEnd | PKT_BUF_SIZE);
+			else
+				tp->RxDescArray[entry].opts1 =
+					cpu_to_le32(DescOwn | PKT_BUF_SIZE);
+			tp->RxDescArray[entry].addr = cpu_to_le64(tp->rx_buf_phys +
+					    entry * PKT_BUF_SIZE);
+		} else {
+			dev_err(&edev->dev, "rx error\n");
+		}
+
+		tp->cur_rx++;
+
+		return pkt_size;
+
+	} else {
+		status = RTL_R8(tp, IntrStatus);
+		RTL_W8(tp, IntrStatus, status & ~(TxErr | RxErr | SYSErr));
+		udelay(100);	/* wait */
+	}
+
+	return 0;
+}
+
+static int rtl8169_get_ethaddr(struct eth_device *edev, unsigned char *mac_addr)
+{
+	struct rtl8169_private *tp = edev->priv;
+
+	rtl_read_mac_address(tp, mac_addr);
+	if (is_valid_ether_addr(mac_addr))
+		return 0;
+
+	rtl_read_mac_address(tp, mac_addr);
+	if (is_valid_ether_addr(mac_addr))
+		return 0;
+
+	rtl_read_mac_from_reg(tp, mac_addr, MAC0);
+	if (is_valid_ether_addr(mac_addr))
+		return 0;
+
+	return 0;
+}
+
+static int rtl8169_set_ethaddr(struct eth_device *edev, const unsigned char *mac_addr)
+{
+	struct rtl8169_private *tp = edev->priv;
+
+	rtl_rar_set(tp, mac_addr);
+
+	return 0;
+}
+
+static void rtl8169_eth_halt(struct eth_device *edev)
+{
+	struct rtl8169_private *tp = edev->priv;
+
+	/* Stop the chip's Tx and Rx DMA processes. */
+	RTL_W8(tp, ChipCmd, 0x00);
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	RTL_W16(tp, IntrMask, 0x0000);
+	RTL_W32(tp, RxMissed, 0);
+
+	pci_clear_master(tp->pci_dev);
+	rtl_pci_commit(tp);
+
+	rtl8169_cleanup(tp);
+	rtl_disable_exit_l1(tp);
+
+	dma_unmap_single(edev->parent, tp->tx_buf_phys, NUM_TX_DESC * PKT_BUF_SIZE,
+			 DMA_TO_DEVICE);
+	free(tp->tx_buf);
+	dma_free_coherent((void *)tp->TxDescArray, tp->TxPhyAddr,
+			  NUM_TX_DESC * sizeof(struct TxDesc));
+
+	dma_unmap_single(edev->parent, tp->rx_buf_phys, NUM_RX_DESC * PKT_BUF_SIZE,
+			 DMA_FROM_DEVICE);
+	free(tp->rx_buf);
+	dma_free_coherent((void *)tp->RxDescArray, tp->RxPhyAddr,
+			  NUM_RX_DESC * sizeof(struct RxDesc));
+}
+
+static int rtl8169_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct device *dev = &pdev->dev;
+	struct eth_device *edev;
+	struct rtl8169_private *tp;
+	int region, ret;
+	u16 xid;
+	enum mac_version chipset;
+
+	/* enable pci device */
+	pci_enable_device(pdev);
+
+	tp = xzalloc(sizeof(*tp));
+
+	edev = &tp->edev;
+	dev->type_data = edev;
+	edev->priv = tp;
+
+	tp->pci_dev = pdev;
+	tp->dev = &pdev->dev;
+
+	tp->miibus.read = rtl8169_phy_read;
+	tp->miibus.write = rtl8169_phy_write;
+	tp->miibus.priv = tp;
+	tp->miibus.parent = dev;
+
+	/* use first MMIO region */
+	region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1;
+	if (region < 0) {
+		dev_err(&pdev->dev, "no MMIO resource found\n");
+		return -ENODEV;
+	}
+
+	tp->mmio_addr = pci_iomap(pdev, region);
+
+	rtl_hw_reset(tp);
+
+	xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf;
+
+	/* Identify chip attached to board */
+	chipset = rtl8169_get_mac_version(xid, 1);
+	if (chipset == RTL_GIGA_MAC_NONE) {
+		dev_err(&pdev->dev, "unknown chip XID %03x\n", xid);
+		return -ENODEV;
+	}
+
+	dev_info(dev, "found %s (base=0x%p)\n",
+		 rtl_chip_infos[chipset].name, tp->mmio_addr);
+
+	tp->mac_version = chipset;
+
+	tp->dash_type = rtl_check_dash(tp);
+
+	tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
+
+	rtl_init_rxcfg(tp);
+
+	rtl_hw_initialize(tp);
+
+	tp->fw_name = rtl_chip_infos[chipset].fw_name;
+
+	if (tp->dash_type != RTL_DASH_NONE)
+		rtl8168_driver_start(tp);
+
+	rtl_set_d3_pll_down(tp, tp->dash_type == RTL_DASH_NONE);
+
+	edev->init = rtl8169_init_dev;
+	edev->open = rtl8169_eth_open;
+	edev->send = rtl8169_eth_send;
+	edev->recv = rtl8169_eth_rx;
+	edev->get_ethaddr = rtl8169_get_ethaddr;
+	edev->set_ethaddr = rtl8169_set_ethaddr;
+	edev->halt = rtl8169_eth_halt;
+	edev->parent = dev;
+	tp->ocp_base = OCP_STD_PHY_BASE;
+
+	ret = mdiobus_register(&tp->miibus);
+	if (ret)
+		goto mdio_err;
+
+	ret = eth_register(edev);
+	if (ret)
+		goto eth_err;
+
+	return 0;
+
+mdio_err:
+	eth_unregister(edev);
+
+eth_err:
+	free(tp);
+
+	return ret;
+}
+
+static struct pci_driver rtl8169_eth_driver = {
+	.name = "rtl8169_eth",
+	.id_table = rtl8169_pci_tbl,
+	.probe = rtl8169_probe,
+};
+device_pci_driver(rtl8169_eth_driver);
diff --git a/drivers/net/r8169_phy_config.c b/drivers/net/r8169_phy_config.c
new file mode 100644
index 0000000000..0c34a58b05
--- /dev/null
+++ b/drivers/net/r8169_phy_config.c
@@ -0,0 +1,1156 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * r8169_phy_config.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
+ */
+
+#include <common.h>
+#include <linux/phy.h>
+#include <linux/mdio.h>
+
+#include "r8169.h"
+
+typedef void (*rtl_phy_cfg_fct)(struct rtl8169_private *tp,
+				struct phy_device *phydev);
+
+static void r8168d_modify_extpage(struct phy_device *phydev, int extpage,
+				  int reg, u16 mask, u16 val)
+{
+	int oldpage = phy_select_page(phydev, 0x0007);
+
+	phy_write(phydev, 0x1e, extpage);
+	phy_modify(phydev, reg, mask, val);
+
+	phy_restore_page(phydev, oldpage, 0);
+}
+
+static void r8168d_phy_param(struct phy_device *phydev, u16 parm,
+			     u16 mask, u16 val)
+{
+	int oldpage = phy_select_page(phydev, 0x0005);
+
+	phy_write(phydev, 0x05, parm);
+	phy_modify(phydev, 0x06, mask, val);
+
+	phy_restore_page(phydev, oldpage, 0);
+}
+
+static void r8168g_phy_param(struct phy_device *phydev, u16 parm,
+			     u16 mask, u16 val)
+{
+	int oldpage = phy_select_page(phydev, 0x0a43);
+
+	phy_write(phydev, 0x13, parm);
+	phy_modify(phydev, 0x14, mask, val);
+
+	phy_restore_page(phydev, oldpage, 0);
+}
+
+struct phy_reg {
+	u16 reg;
+	u16 val;
+};
+
+static void __rtl_writephy_batch(struct phy_device *phydev,
+				 const struct phy_reg *regs, int len)
+{
+	while (len-- > 0) {
+		phy_write(phydev, regs->reg, regs->val);
+		regs++;
+	}
+}
+
+#define rtl_writephy_batch(p, a) __rtl_writephy_batch(p, a, ARRAY_SIZE(a))
+
+static void rtl8168f_config_eee_phy(struct phy_device *phydev)
+{
+	r8168d_modify_extpage(phydev, 0x0020, 0x15, 0, BIT(8));
+	r8168d_phy_param(phydev, 0x8b85, 0, BIT(13));
+}
+
+static void rtl8168g_config_eee_phy(struct phy_device *phydev)
+{
+	phy_modify_paged(phydev, 0x0a43, 0x11, 0, BIT(4));
+}
+
+static void rtl8168h_config_eee_phy(struct phy_device *phydev)
+{
+	rtl8168g_config_eee_phy(phydev);
+
+	phy_modify_paged(phydev, 0xa4a, 0x11, 0x0000, 0x0200);
+	phy_modify_paged(phydev, 0xa42, 0x14, 0x0000, 0x0080);
+}
+
+static void rtl8125a_config_eee_phy(struct phy_device *phydev)
+{
+	rtl8168h_config_eee_phy(phydev);
+
+	phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000);
+	phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000);
+}
+
+static void rtl8125b_config_eee_phy(struct phy_device *phydev)
+{
+	phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000);
+	phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000);
+	phy_modify_paged(phydev, 0xa42, 0x14, 0x0080, 0x0000);
+	phy_modify_paged(phydev, 0xa4a, 0x11, 0x0200, 0x0000);
+}
+
+static void rtl8169s_hw_phy_config(struct rtl8169_private *tp,
+				   struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x06, 0x006e },
+		{ 0x08, 0x0708 },
+		{ 0x15, 0x4000 },
+		{ 0x18, 0x65c7 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x03, 0x00a1 },
+		{ 0x02, 0x0008 },
+		{ 0x01, 0x0120 },
+		{ 0x00, 0x1000 },
+		{ 0x04, 0x0800 },
+		{ 0x04, 0x0000 },
+
+		{ 0x03, 0xff41 },
+		{ 0x02, 0xdf60 },
+		{ 0x01, 0x0140 },
+		{ 0x00, 0x0077 },
+		{ 0x04, 0x7800 },
+		{ 0x04, 0x7000 },
+
+		{ 0x03, 0x802f },
+		{ 0x02, 0x4f02 },
+		{ 0x01, 0x0409 },
+		{ 0x00, 0xf0f9 },
+		{ 0x04, 0x9800 },
+		{ 0x04, 0x9000 },
+
+		{ 0x03, 0xdf01 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0xff95 },
+		{ 0x00, 0xba00 },
+		{ 0x04, 0xa800 },
+		{ 0x04, 0xa000 },
+
+		{ 0x03, 0xff41 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0x0140 },
+		{ 0x00, 0x00bb },
+		{ 0x04, 0xb800 },
+		{ 0x04, 0xb000 },
+
+		{ 0x03, 0xdf41 },
+		{ 0x02, 0xdc60 },
+		{ 0x01, 0x6340 },
+		{ 0x00, 0x007d },
+		{ 0x04, 0xd800 },
+		{ 0x04, 0xd000 },
+
+		{ 0x03, 0xdf01 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0x100a },
+		{ 0x00, 0xa0ff },
+		{ 0x04, 0xf800 },
+		{ 0x04, 0xf000 },
+
+		{ 0x1f, 0x0000 },
+		{ 0x0b, 0x0000 },
+		{ 0x00, 0x9200 }
+	};
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+}
+
+static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp,
+				    struct phy_device *phydev)
+{
+	phy_write_paged(phydev, 0x0002, 0x01, 0x90d0);
+}
+
+static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x04, 0x0000 },
+		{ 0x03, 0x00a1 },
+		{ 0x02, 0x0008 },
+		{ 0x01, 0x0120 },
+		{ 0x00, 0x1000 },
+		{ 0x04, 0x0800 },
+		{ 0x04, 0x9000 },
+		{ 0x03, 0x802f },
+		{ 0x02, 0x4f02 },
+		{ 0x01, 0x0409 },
+		{ 0x00, 0xf099 },
+		{ 0x04, 0x9800 },
+		{ 0x04, 0xa000 },
+		{ 0x03, 0xdf01 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0xff95 },
+		{ 0x00, 0xba00 },
+		{ 0x04, 0xa800 },
+		{ 0x04, 0xf000 },
+		{ 0x03, 0xdf01 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0x101a },
+		{ 0x00, 0xa0ff },
+		{ 0x04, 0xf800 },
+		{ 0x04, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x10, 0xf41b },
+		{ 0x14, 0xfb54 },
+		{ 0x18, 0xf5c7 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+}
+
+static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x04, 0x0000 },
+		{ 0x03, 0x00a1 },
+		{ 0x02, 0x0008 },
+		{ 0x01, 0x0120 },
+		{ 0x00, 0x1000 },
+		{ 0x04, 0x0800 },
+		{ 0x04, 0x9000 },
+		{ 0x03, 0x802f },
+		{ 0x02, 0x4f02 },
+		{ 0x01, 0x0409 },
+		{ 0x00, 0xf099 },
+		{ 0x04, 0x9800 },
+		{ 0x04, 0xa000 },
+		{ 0x03, 0xdf01 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0xff95 },
+		{ 0x00, 0xba00 },
+		{ 0x04, 0xa800 },
+		{ 0x04, 0xf000 },
+		{ 0x03, 0xdf01 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0x101a },
+		{ 0x00, 0xa0ff },
+		{ 0x04, 0xf800 },
+		{ 0x04, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x0b, 0x8480 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x18, 0x67c7 },
+		{ 0x04, 0x2000 },
+		{ 0x03, 0x002f },
+		{ 0x02, 0x4360 },
+		{ 0x01, 0x0109 },
+		{ 0x00, 0x3022 },
+		{ 0x04, 0x2800 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+}
+
+static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp,
+				    struct phy_device *phydev)
+{
+	phy_write(phydev, 0x1f, 0x0001);
+	phy_set_bits(phydev, 0x16, BIT(0));
+	phy_write(phydev, 0x10, 0xf41b);
+	phy_write(phydev, 0x1f, 0x0000);
+}
+
+static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	phy_write_paged(phydev, 0x0001, 0x10, 0xf41b);
+}
+
+static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp,
+				      struct phy_device *phydev)
+{
+	phy_write(phydev, 0x1d, 0x0f00);
+	phy_write_paged(phydev, 0x0002, 0x0c, 0x1ec8);
+}
+
+static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp,
+				      struct phy_device *phydev)
+{
+	phy_set_bits(phydev, 0x14, BIT(5));
+	phy_set_bits(phydev, 0x0d, BIT(5));
+	phy_write_paged(phydev, 0x0001, 0x1d, 0x3d98);
+}
+
+static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x12, 0x2300 },
+		{ 0x1f, 0x0002 },
+		{ 0x00, 0x88d4 },
+		{ 0x01, 0x82b1 },
+		{ 0x03, 0x7002 },
+		{ 0x08, 0x9e30 },
+		{ 0x09, 0x01f0 },
+		{ 0x0a, 0x5500 },
+		{ 0x0c, 0x00c8 },
+		{ 0x1f, 0x0003 },
+		{ 0x12, 0xc096 },
+		{ 0x16, 0x000a },
+		{ 0x1f, 0x0000 },
+		{ 0x1f, 0x0000 },
+		{ 0x09, 0x2000 },
+		{ 0x09, 0x0000 }
+	};
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+
+	phy_set_bits(phydev, 0x14, BIT(5));
+	phy_set_bits(phydev, 0x0d, BIT(5));
+}
+
+static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x12, 0x2300 },
+		{ 0x03, 0x802f },
+		{ 0x02, 0x4f02 },
+		{ 0x01, 0x0409 },
+		{ 0x00, 0xf099 },
+		{ 0x04, 0x9800 },
+		{ 0x04, 0x9000 },
+		{ 0x1d, 0x3d98 },
+		{ 0x1f, 0x0002 },
+		{ 0x0c, 0x7eb8 },
+		{ 0x06, 0x0761 },
+		{ 0x1f, 0x0003 },
+		{ 0x16, 0x0f0a },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+
+	phy_set_bits(phydev, 0x16, BIT(0));
+	phy_set_bits(phydev, 0x14, BIT(5));
+	phy_set_bits(phydev, 0x0d, BIT(5));
+}
+
+static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x12, 0x2300 },
+		{ 0x1d, 0x3d98 },
+		{ 0x1f, 0x0002 },
+		{ 0x0c, 0x7eb8 },
+		{ 0x06, 0x5461 },
+		{ 0x1f, 0x0003 },
+		{ 0x16, 0x0f0a },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+
+	phy_set_bits(phydev, 0x16, BIT(0));
+	phy_set_bits(phydev, 0x14, BIT(5));
+	phy_set_bits(phydev, 0x0d, BIT(5));
+}
+
+static const struct phy_reg rtl8168d_1_phy_reg_init_0[] = {
+	/* Channel Estimation */
+	{ 0x1f, 0x0001 },
+	{ 0x06, 0x4064 },
+	{ 0x07, 0x2863 },
+	{ 0x08, 0x059c },
+	{ 0x09, 0x26b4 },
+	{ 0x0a, 0x6a19 },
+	{ 0x0b, 0xdcc8 },
+	{ 0x10, 0xf06d },
+	{ 0x14, 0x7f68 },
+	{ 0x18, 0x7fd9 },
+	{ 0x1c, 0xf0ff },
+	{ 0x1d, 0x3d9c },
+	{ 0x1f, 0x0003 },
+	{ 0x12, 0xf49f },
+	{ 0x13, 0x070b },
+	{ 0x1a, 0x05ad },
+	{ 0x14, 0x94c0 },
+
+	/*
+	 * Tx Error Issue
+	 * Enhance line driver power
+	 */
+	{ 0x1f, 0x0002 },
+	{ 0x06, 0x5561 },
+	{ 0x1f, 0x0005 },
+	{ 0x05, 0x8332 },
+	{ 0x06, 0x5561 },
+
+	/*
+	 * Can not link to 1Gbps with bad cable
+	 * Decrease SNR threshold form 21.07dB to 19.04dB
+	 */
+	{ 0x1f, 0x0001 },
+	{ 0x17, 0x0cc0 },
+
+	{ 0x1f, 0x0000 },
+	{ 0x0d, 0xf880 }
+};
+
+static void rtl8168d_apply_firmware_cond(struct rtl8169_private *tp,
+					 struct phy_device *phydev,
+					 u16 val)
+{
+	u16 reg_val;
+
+	phy_write(phydev, 0x1f, 0x0005);
+	phy_write(phydev, 0x05, 0x001b);
+	reg_val = phy_read(phydev, 0x06);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	if (reg_val != val)
+		dev_warn(&phydev->dev, "chipset not ready for firmware\n");
+	else
+		r8169_apply_firmware(tp);
+}
+
+static void rtl8168d_1_common(struct phy_device *phydev)
+{
+	u16 val;
+
+	phy_write_paged(phydev, 0x0002, 0x05, 0x669a);
+	r8168d_phy_param(phydev, 0x8330, 0xffff, 0x669a);
+	phy_write(phydev, 0x1f, 0x0002);
+
+	val = phy_read(phydev, 0x0d);
+
+	if ((val & 0x00ff) != 0x006c) {
+		static const u16 set[] = {
+			0x0065, 0x0066, 0x0067, 0x0068,
+			0x0069, 0x006a, 0x006b, 0x006c
+		};
+		int i;
+
+		val &= 0xff00;
+		for (i = 0; i < ARRAY_SIZE(set); i++)
+			phy_write(phydev, 0x0d, val | set[i]);
+	}
+}
+
+static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	rtl_writephy_batch(phydev, rtl8168d_1_phy_reg_init_0);
+
+	/*
+	 * Rx Error Issue
+	 * Fine Tune Switching regulator parameter
+	 */
+	phy_write(phydev, 0x1f, 0x0002);
+	phy_modify(phydev, 0x0b, 0x00ef, 0x0010);
+	phy_modify(phydev, 0x0c, 0x5d00, 0xa200);
+
+	if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
+		rtl8168d_1_common(phydev);
+	} else {
+		phy_write_paged(phydev, 0x0002, 0x05, 0x6662);
+		r8168d_phy_param(phydev, 0x8330, 0xffff, 0x6662);
+	}
+
+	/* RSET couple improve */
+	phy_write(phydev, 0x1f, 0x0002);
+	phy_set_bits(phydev, 0x0d, 0x0300);
+	phy_set_bits(phydev, 0x0f, 0x0010);
+
+	/* Fine tune PLL performance */
+	phy_write(phydev, 0x1f, 0x0002);
+	phy_modify(phydev, 0x02, 0x0600, 0x0100);
+	phy_clear_bits(phydev, 0x03, 0xe000);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	rtl8168d_apply_firmware_cond(tp, phydev, 0xbf00);
+}
+
+static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	rtl_writephy_batch(phydev, rtl8168d_1_phy_reg_init_0);
+
+	if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
+		rtl8168d_1_common(phydev);
+	} else {
+		phy_write_paged(phydev, 0x0002, 0x05, 0x2642);
+		r8168d_phy_param(phydev, 0x8330, 0xffff, 0x2642);
+	}
+
+	/* Fine tune PLL performance */
+	phy_write(phydev, 0x1f, 0x0002);
+	phy_modify(phydev, 0x02, 0x0600, 0x0100);
+	phy_clear_bits(phydev, 0x03, 0xe000);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	/* Switching regulator Slew rate */
+	phy_modify_paged(phydev, 0x0002, 0x0f, 0x0000, 0x0017);
+
+	rtl8168d_apply_firmware_cond(tp, phydev, 0xb300);
+}
+
+static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	phy_write_paged(phydev, 0x0001, 0x17, 0x0cc0);
+	r8168d_modify_extpage(phydev, 0x002d, 0x18, 0xffff, 0x0040);
+	phy_set_bits(phydev, 0x0d, BIT(5));
+}
+
+static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		/* Channel estimation fine tune */
+		{ 0x1f, 0x0001 },
+		{ 0x0b, 0x6c20 },
+		{ 0x07, 0x2872 },
+		{ 0x1c, 0xefff },
+		{ 0x1f, 0x0003 },
+		{ 0x14, 0x6420 },
+		{ 0x1f, 0x0000 },
+	};
+
+	r8169_apply_firmware(tp);
+
+	/* Enable Delay cap */
+	r8168d_phy_param(phydev, 0x8b80, 0xffff, 0xc896);
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+
+	/* Update PFM & 10M TX idle timer */
+	r8168d_modify_extpage(phydev, 0x002f, 0x15, 0xffff, 0x1919);
+
+	r8168d_modify_extpage(phydev, 0x00ac, 0x18, 0xffff, 0x0006);
+
+	/* DCO enable for 10M IDLE Power */
+	r8168d_modify_extpage(phydev, 0x0023, 0x17, 0x0000, 0x0006);
+
+	/* For impedance matching */
+	phy_modify_paged(phydev, 0x0002, 0x08, 0x7f00, 0x8000);
+
+	/* PHY auto speed down */
+	r8168d_modify_extpage(phydev, 0x002d, 0x18, 0x0000, 0x0050);
+	phy_set_bits(phydev, 0x14, BIT(15));
+
+	r8168d_phy_param(phydev, 0x8b86, 0x0000, 0x0001);
+	r8168d_phy_param(phydev, 0x8b85, 0x2000, 0x0000);
+
+	r8168d_modify_extpage(phydev, 0x0020, 0x15, 0x1100, 0x0000);
+	phy_write_paged(phydev, 0x0006, 0x00, 0x5a00);
+
+	phy_write_mmd_indirect(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0000);
+}
+
+static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	r8169_apply_firmware(tp);
+
+	/* Enable Delay cap */
+	r8168d_modify_extpage(phydev, 0x00ac, 0x18, 0xffff, 0x0006);
+
+	/* Channel estimation fine tune */
+	phy_write_paged(phydev, 0x0003, 0x09, 0xa20f);
+
+	/* Green Setting */
+	r8168d_phy_param(phydev, 0x8b5b, 0xffff, 0x9222);
+	r8168d_phy_param(phydev, 0x8b6d, 0xffff, 0x8000);
+	r8168d_phy_param(phydev, 0x8b76, 0xffff, 0x8000);
+
+	/* For 4-corner performance improve */
+	phy_write(phydev, 0x1f, 0x0005);
+	phy_write(phydev, 0x05, 0x8b80);
+	phy_set_bits(phydev, 0x17, 0x0006);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	/* PHY auto speed down */
+	r8168d_modify_extpage(phydev, 0x002d, 0x18, 0x0000, 0x0010);
+	phy_set_bits(phydev, 0x14, BIT(15));
+
+	/* improve 10M EEE waveform */
+	r8168d_phy_param(phydev, 0x8b86, 0x0000, 0x0001);
+
+	/* Improve 2-pair detection performance */
+	r8168d_phy_param(phydev, 0x8b85, 0x0000, 0x4000);
+
+	rtl8168f_config_eee_phy(phydev);
+
+	/* Green feature */
+	phy_write(phydev, 0x1f, 0x0003);
+	phy_set_bits(phydev, 0x19, BIT(0));
+	phy_set_bits(phydev, 0x10, BIT(10));
+	phy_write(phydev, 0x1f, 0x0000);
+	phy_modify_paged(phydev, 0x0005, 0x01, 0, BIT(8));
+}
+
+static void rtl8168f_hw_phy_config(struct rtl8169_private *tp,
+				   struct phy_device *phydev)
+{
+	/* For 4-corner performance improve */
+	r8168d_phy_param(phydev, 0x8b80, 0x0000, 0x0006);
+
+	/* PHY auto speed down */
+	r8168d_modify_extpage(phydev, 0x002d, 0x18, 0x0000, 0x0010);
+	phy_set_bits(phydev, 0x14, BIT(15));
+
+	/* Improve 10M EEE waveform */
+	r8168d_phy_param(phydev, 0x8b86, 0x0000, 0x0001);
+
+	rtl8168f_config_eee_phy(phydev);
+}
+
+static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	r8169_apply_firmware(tp);
+
+	/* Channel estimation fine tune */
+	phy_write_paged(phydev, 0x0003, 0x09, 0xa20f);
+
+	/* Modify green table for giga & fnet */
+	r8168d_phy_param(phydev, 0x8b55, 0xffff, 0x0000);
+	r8168d_phy_param(phydev, 0x8b5e, 0xffff, 0x0000);
+	r8168d_phy_param(phydev, 0x8b67, 0xffff, 0x0000);
+	r8168d_phy_param(phydev, 0x8b70, 0xffff, 0x0000);
+	r8168d_modify_extpage(phydev, 0x0078, 0x17, 0xffff, 0x0000);
+	r8168d_modify_extpage(phydev, 0x0078, 0x19, 0xffff, 0x00fb);
+
+	/* Modify green table for 10M */
+	r8168d_phy_param(phydev, 0x8b79, 0xffff, 0xaa00);
+
+	/* Disable hiimpedance detection (RTCT) */
+	phy_write_paged(phydev, 0x0003, 0x01, 0x328a);
+
+	rtl8168f_hw_phy_config(tp, phydev);
+
+	/* Improve 2-pair detection performance */
+	r8168d_phy_param(phydev, 0x8b85, 0x0000, 0x4000);
+}
+
+static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	r8169_apply_firmware(tp);
+
+	rtl8168f_hw_phy_config(tp, phydev);
+}
+
+static void rtl8411_hw_phy_config(struct rtl8169_private *tp,
+				  struct phy_device *phydev)
+{
+	r8169_apply_firmware(tp);
+
+	rtl8168f_hw_phy_config(tp, phydev);
+
+	/* Improve 2-pair detection performance */
+	r8168d_phy_param(phydev, 0x8b85, 0x0000, 0x4000);
+
+	/* Channel estimation fine tune */
+	phy_write_paged(phydev, 0x0003, 0x09, 0xa20f);
+
+	/* Modify green table for giga & fnet */
+	r8168d_phy_param(phydev, 0x8b55, 0xffff, 0x0000);
+	r8168d_phy_param(phydev, 0x8b5e, 0xffff, 0x0000);
+	r8168d_phy_param(phydev, 0x8b67, 0xffff, 0x0000);
+	r8168d_phy_param(phydev, 0x8b70, 0xffff, 0x0000);
+	r8168d_modify_extpage(phydev, 0x0078, 0x17, 0xffff, 0x0000);
+	r8168d_modify_extpage(phydev, 0x0078, 0x19, 0xffff, 0x00aa);
+
+	/* Modify green table for 10M */
+	r8168d_phy_param(phydev, 0x8b79, 0xffff, 0xaa00);
+
+	/* Disable hiimpedance detection (RTCT) */
+	phy_write_paged(phydev, 0x0003, 0x01, 0x328a);
+
+	/* Modify green table for giga */
+	r8168d_phy_param(phydev, 0x8b54, 0x0800, 0x0000);
+	r8168d_phy_param(phydev, 0x8b5d, 0x0800, 0x0000);
+	r8168d_phy_param(phydev, 0x8a7c, 0x0100, 0x0000);
+	r8168d_phy_param(phydev, 0x8a7f, 0x0000, 0x0100);
+	r8168d_phy_param(phydev, 0x8a82, 0x0100, 0x0000);
+	r8168d_phy_param(phydev, 0x8a85, 0x0100, 0x0000);
+	r8168d_phy_param(phydev, 0x8a88, 0x0100, 0x0000);
+
+	/* uc same-seed solution */
+	r8168d_phy_param(phydev, 0x8b85, 0x0000, 0x8000);
+
+	/* Green feature */
+	phy_write(phydev, 0x1f, 0x0003);
+	phy_clear_bits(phydev, 0x19, BIT(0));
+	phy_clear_bits(phydev, 0x10, BIT(10));
+	phy_write(phydev, 0x1f, 0x0000);
+}
+
+static void rtl8168g_disable_aldps(struct phy_device *phydev)
+{
+	phy_modify_paged(phydev, 0x0a43, 0x10, BIT(2), 0);
+}
+
+static void rtl8168g_enable_gphy_10m(struct phy_device *phydev)
+{
+	phy_modify_paged(phydev, 0x0a44, 0x11, 0, BIT(11));
+}
+
+static void rtl8168g_phy_adjust_10m_aldps(struct phy_device *phydev)
+{
+	phy_modify_paged(phydev, 0x0bcc, 0x14, BIT(8), 0);
+	phy_modify_paged(phydev, 0x0a44, 0x11, 0, BIT(7) | BIT(6));
+	r8168g_phy_param(phydev, 0x8084, 0x6000, 0x0000);
+	phy_modify_paged(phydev, 0x0a43, 0x10, 0x0000, 0x1003);
+}
+
+static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	int ret;
+
+	r8169_apply_firmware(tp);
+
+	ret = phy_read_paged(phydev, 0x0a46, 0x10);
+	if (ret & BIT(8))
+		phy_modify_paged(phydev, 0x0bcc, 0x12, BIT(15), 0);
+	else
+		phy_modify_paged(phydev, 0x0bcc, 0x12, 0, BIT(15));
+
+	ret = phy_read_paged(phydev, 0x0a46, 0x13);
+	if (ret & BIT(8))
+		phy_modify_paged(phydev, 0x0c41, 0x15, 0, BIT(1));
+	else
+		phy_modify_paged(phydev, 0x0c41, 0x15, BIT(1), 0);
+
+	/* Enable PHY auto speed down */
+	phy_modify_paged(phydev, 0x0a44, 0x11, 0, BIT(3) | BIT(2));
+
+	rtl8168g_phy_adjust_10m_aldps(phydev);
+
+	/* EEE auto-fallback function */
+	phy_modify_paged(phydev, 0x0a4b, 0x11, 0, BIT(2));
+
+	/* Enable UC LPF tune function */
+	r8168g_phy_param(phydev, 0x8012, 0x0000, 0x8000);
+
+	phy_modify_paged(phydev, 0x0c42, 0x11, BIT(13), BIT(14));
+
+	/* Improve SWR Efficiency */
+	phy_write(phydev, 0x1f, 0x0bcd);
+	phy_write(phydev, 0x14, 0x5065);
+	phy_write(phydev, 0x14, 0xd065);
+	phy_write(phydev, 0x1f, 0x0bc8);
+	phy_write(phydev, 0x11, 0x5655);
+	phy_write(phydev, 0x1f, 0x0bcd);
+	phy_write(phydev, 0x14, 0x1065);
+	phy_write(phydev, 0x14, 0x9065);
+	phy_write(phydev, 0x14, 0x1065);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	rtl8168g_disable_aldps(phydev);
+	rtl8168g_config_eee_phy(phydev);
+}
+
+static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	r8169_apply_firmware(tp);
+	rtl8168g_config_eee_phy(phydev);
+}
+
+static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	u16 ioffset, rlen;
+	u32 data;
+
+	r8169_apply_firmware(tp);
+
+	/* CHIN EST parameter update */
+	r8168g_phy_param(phydev, 0x808a, 0x003f, 0x000a);
+
+	/* enable R-tune & PGA-retune function */
+	r8168g_phy_param(phydev, 0x0811, 0x0000, 0x0800);
+	phy_modify_paged(phydev, 0x0a42, 0x16, 0x0000, 0x0002);
+
+	rtl8168g_enable_gphy_10m(phydev);
+
+	ioffset = rtl8168h_2_get_adc_bias_ioffset(tp);
+	if (ioffset != 0xffff)
+		phy_write_paged(phydev, 0x0bcf, 0x16, ioffset);
+
+	/* Modify rlen (TX LPF corner frequency) level */
+	data = phy_read_paged(phydev, 0x0bcd, 0x16);
+	data &= 0x000f;
+	rlen = 0;
+	if (data > 3)
+		rlen = data - 3;
+	data = rlen | (rlen << 4) | (rlen << 8) | (rlen << 12);
+	phy_write_paged(phydev, 0x0bcd, 0x17, data);
+
+	/* disable phy pfm mode */
+	phy_modify_paged(phydev, 0x0a44, 0x11, BIT(7), 0);
+
+	/* disable 10m pll off */
+	phy_modify_paged(phydev, 0x0a43, 0x10, BIT(0), 0);
+
+	rtl8168g_disable_aldps(phydev);
+	rtl8168g_config_eee_phy(phydev);
+}
+
+static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp,
+				      struct phy_device *phydev)
+{
+	rtl8168g_phy_adjust_10m_aldps(phydev);
+
+	/* Enable UC LPF tune function */
+	r8168g_phy_param(phydev, 0x8012, 0x0000, 0x8000);
+
+	/* Set rg_sel_sdm_rate */
+	phy_modify_paged(phydev, 0x0c42, 0x11, BIT(13), BIT(14));
+
+	/* Channel estimation parameters */
+	r8168g_phy_param(phydev, 0x80f3, 0xff00, 0x8b00);
+	r8168g_phy_param(phydev, 0x80f0, 0xff00, 0x3a00);
+	r8168g_phy_param(phydev, 0x80ef, 0xff00, 0x0500);
+	r8168g_phy_param(phydev, 0x80f6, 0xff00, 0x6e00);
+	r8168g_phy_param(phydev, 0x80ec, 0xff00, 0x6800);
+	r8168g_phy_param(phydev, 0x80ed, 0xff00, 0x7c00);
+	r8168g_phy_param(phydev, 0x80f2, 0xff00, 0xf400);
+	r8168g_phy_param(phydev, 0x80f4, 0xff00, 0x8500);
+	r8168g_phy_param(phydev, 0x8110, 0xff00, 0xa800);
+	r8168g_phy_param(phydev, 0x810f, 0xff00, 0x1d00);
+	r8168g_phy_param(phydev, 0x8111, 0xff00, 0xf500);
+	r8168g_phy_param(phydev, 0x8113, 0xff00, 0x6100);
+	r8168g_phy_param(phydev, 0x8115, 0xff00, 0x9200);
+	r8168g_phy_param(phydev, 0x810e, 0xff00, 0x0400);
+	r8168g_phy_param(phydev, 0x810c, 0xff00, 0x7c00);
+	r8168g_phy_param(phydev, 0x810b, 0xff00, 0x5a00);
+	r8168g_phy_param(phydev, 0x80d1, 0xff00, 0xff00);
+	r8168g_phy_param(phydev, 0x80cd, 0xff00, 0x9e00);
+	r8168g_phy_param(phydev, 0x80d3, 0xff00, 0x0e00);
+	r8168g_phy_param(phydev, 0x80d5, 0xff00, 0xca00);
+	r8168g_phy_param(phydev, 0x80d7, 0xff00, 0x8400);
+
+	/* Force PWM-mode */
+	phy_write(phydev, 0x1f, 0x0bcd);
+	phy_write(phydev, 0x14, 0x5065);
+	phy_write(phydev, 0x14, 0xd065);
+	phy_write(phydev, 0x1f, 0x0bc8);
+	phy_write(phydev, 0x12, 0x00ed);
+	phy_write(phydev, 0x1f, 0x0bcd);
+	phy_write(phydev, 0x14, 0x1065);
+	phy_write(phydev, 0x14, 0x9065);
+	phy_write(phydev, 0x14, 0x1065);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	rtl8168g_disable_aldps(phydev);
+	rtl8168g_config_eee_phy(phydev);
+}
+
+static void rtl8117_hw_phy_config(struct rtl8169_private *tp,
+				  struct phy_device *phydev)
+{
+	/* CHN EST parameters adjust - fnet */
+	r8168g_phy_param(phydev, 0x808e, 0xff00, 0x4800);
+	r8168g_phy_param(phydev, 0x8090, 0xff00, 0xcc00);
+	r8168g_phy_param(phydev, 0x8092, 0xff00, 0xb000);
+
+	r8168g_phy_param(phydev, 0x8088, 0xff00, 0x6000);
+	r8168g_phy_param(phydev, 0x808b, 0x3f00, 0x0b00);
+	r8168g_phy_param(phydev, 0x808d, 0x1f00, 0x0600);
+	r8168g_phy_param(phydev, 0x808c, 0xff00, 0xb000);
+	r8168g_phy_param(phydev, 0x80a0, 0xff00, 0x2800);
+	r8168g_phy_param(phydev, 0x80a2, 0xff00, 0x5000);
+	r8168g_phy_param(phydev, 0x809b, 0xf800, 0xb000);
+	r8168g_phy_param(phydev, 0x809a, 0xff00, 0x4b00);
+	r8168g_phy_param(phydev, 0x809d, 0x3f00, 0x0800);
+	r8168g_phy_param(phydev, 0x80a1, 0xff00, 0x7000);
+	r8168g_phy_param(phydev, 0x809f, 0x1f00, 0x0300);
+	r8168g_phy_param(phydev, 0x809e, 0xff00, 0x8800);
+	r8168g_phy_param(phydev, 0x80b2, 0xff00, 0x2200);
+	r8168g_phy_param(phydev, 0x80ad, 0xf800, 0x9800);
+	r8168g_phy_param(phydev, 0x80af, 0x3f00, 0x0800);
+	r8168g_phy_param(phydev, 0x80b3, 0xff00, 0x6f00);
+	r8168g_phy_param(phydev, 0x80b1, 0x1f00, 0x0300);
+	r8168g_phy_param(phydev, 0x80b0, 0xff00, 0x9300);
+
+	r8168g_phy_param(phydev, 0x8011, 0x0000, 0x0800);
+
+	rtl8168g_enable_gphy_10m(phydev);
+
+	r8168g_phy_param(phydev, 0x8016, 0x0000, 0x0400);
+
+	rtl8168g_disable_aldps(phydev);
+	rtl8168h_config_eee_phy(phydev);
+}
+
+static void rtl8102e_hw_phy_config(struct rtl8169_private *tp,
+				   struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0003 },
+		{ 0x08, 0x441d },
+		{ 0x01, 0x9100 },
+		{ 0x1f, 0x0000 }
+	};
+
+	phy_set_bits(phydev, 0x11, BIT(12));
+	phy_set_bits(phydev, 0x19, BIT(13));
+	phy_set_bits(phydev, 0x10, BIT(15));
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+}
+
+static void rtl8401_hw_phy_config(struct rtl8169_private *tp,
+				  struct phy_device *phydev)
+{
+	phy_set_bits(phydev, 0x11, BIT(12));
+	phy_modify_paged(phydev, 0x0002, 0x0f, 0x0000, 0x0003);
+}
+
+static void rtl8105e_hw_phy_config(struct rtl8169_private *tp,
+				   struct phy_device *phydev)
+{
+	/* Disable ALDPS before ram code */
+	phy_write(phydev, 0x18, 0x0310);
+	mdelay(100);
+
+	r8169_apply_firmware(tp);
+
+	phy_write_paged(phydev, 0x0005, 0x1a, 0x0000);
+	phy_write_paged(phydev, 0x0004, 0x1c, 0x0000);
+	phy_write_paged(phydev, 0x0001, 0x15, 0x7701);
+}
+
+static void rtl8402_hw_phy_config(struct rtl8169_private *tp,
+				  struct phy_device *phydev)
+{
+	/* Disable ALDPS before setting firmware */
+	phy_write(phydev, 0x18, 0x0310);
+	mdelay(20);
+
+	r8169_apply_firmware(tp);
+
+	/* EEE setting */
+	phy_write(phydev, 0x1f, 0x0004);
+	phy_write(phydev, 0x10, 0x401f);
+	phy_write(phydev, 0x19, 0x7030);
+	phy_write(phydev, 0x1f, 0x0000);
+}
+
+static void rtl8106e_hw_phy_config(struct rtl8169_private *tp,
+				   struct phy_device *phydev)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0004 },
+		{ 0x10, 0xc07f },
+		{ 0x19, 0x7030 },
+		{ 0x1f, 0x0000 }
+	};
+
+	/* Disable ALDPS before ram code */
+	phy_write(phydev, 0x18, 0x0310);
+	mdelay(100);
+
+	r8169_apply_firmware(tp);
+
+	rtl_writephy_batch(phydev, phy_reg_init);
+}
+
+static void rtl8125_legacy_force_mode(struct phy_device *phydev)
+{
+	phy_modify_paged(phydev, 0xa5b, 0x12, BIT(15), 0);
+}
+
+static void rtl8125a_2_hw_phy_config(struct rtl8169_private *tp,
+				     struct phy_device *phydev)
+{
+	int i;
+
+	phy_modify_paged(phydev, 0xad4, 0x17, 0x0000, 0x0010);
+	phy_modify_paged(phydev, 0xad1, 0x13, 0x03ff, 0x03ff);
+	phy_modify_paged(phydev, 0xad3, 0x11, 0x003f, 0x0006);
+	phy_modify_paged(phydev, 0xac0, 0x14, 0x1100, 0x0000);
+	phy_modify_paged(phydev, 0xacc, 0x10, 0x0003, 0x0002);
+	phy_modify_paged(phydev, 0xad4, 0x10, 0x00e7, 0x0044);
+	phy_modify_paged(phydev, 0xac1, 0x12, 0x0080, 0x0000);
+	phy_modify_paged(phydev, 0xac8, 0x10, 0x0300, 0x0000);
+	phy_modify_paged(phydev, 0xac5, 0x17, 0x0007, 0x0002);
+	phy_write_paged(phydev, 0xad4, 0x16, 0x00a8);
+	phy_write_paged(phydev, 0xac5, 0x16, 0x01ff);
+	phy_modify_paged(phydev, 0xac8, 0x15, 0x00f0, 0x0030);
+
+	phy_write(phydev, 0x1f, 0x0b87);
+	phy_write(phydev, 0x16, 0x80a2);
+	phy_write(phydev, 0x17, 0x0153);
+	phy_write(phydev, 0x16, 0x809c);
+	phy_write(phydev, 0x17, 0x0153);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	phy_write(phydev, 0x1f, 0x0a43);
+	phy_write(phydev, 0x13, 0x81B3);
+	phy_write(phydev, 0x14, 0x0043);
+	phy_write(phydev, 0x14, 0x00A7);
+	phy_write(phydev, 0x14, 0x00D6);
+	phy_write(phydev, 0x14, 0x00EC);
+	phy_write(phydev, 0x14, 0x00F6);
+	phy_write(phydev, 0x14, 0x00FB);
+	phy_write(phydev, 0x14, 0x00FD);
+	phy_write(phydev, 0x14, 0x00FF);
+	phy_write(phydev, 0x14, 0x00BB);
+	phy_write(phydev, 0x14, 0x0058);
+	phy_write(phydev, 0x14, 0x0029);
+	phy_write(phydev, 0x14, 0x0013);
+	phy_write(phydev, 0x14, 0x0009);
+	phy_write(phydev, 0x14, 0x0004);
+	phy_write(phydev, 0x14, 0x0002);
+	for (i = 0; i < 25; i++)
+		phy_write(phydev, 0x14, 0x0000);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	r8168g_phy_param(phydev, 0x8257, 0xffff, 0x020F);
+	r8168g_phy_param(phydev, 0x80ea, 0xffff, 0x7843);
+
+	r8169_apply_firmware(tp);
+
+	phy_modify_paged(phydev, 0xd06, 0x14, 0x0000, 0x2000);
+
+	r8168g_phy_param(phydev, 0x81a2, 0x0000, 0x0100);
+
+	phy_modify_paged(phydev, 0xb54, 0x16, 0xff00, 0xdb00);
+	phy_modify_paged(phydev, 0xa45, 0x12, 0x0001, 0x0000);
+	phy_modify_paged(phydev, 0xa5d, 0x12, 0x0000, 0x0020);
+	phy_modify_paged(phydev, 0xad4, 0x17, 0x0010, 0x0000);
+	phy_modify_paged(phydev, 0xa86, 0x15, 0x0001, 0x0000);
+	rtl8168g_enable_gphy_10m(phydev);
+
+	rtl8125a_config_eee_phy(phydev);
+}
+
+static void rtl8125b_hw_phy_config(struct rtl8169_private *tp,
+				   struct phy_device *phydev)
+{
+	r8169_apply_firmware(tp);
+
+	phy_modify_paged(phydev, 0xa44, 0x11, 0x0000, 0x0800);
+	phy_modify_paged(phydev, 0xac4, 0x13, 0x00f0, 0x0090);
+	phy_modify_paged(phydev, 0xad3, 0x10, 0x0003, 0x0001);
+
+	phy_write(phydev, 0x1f, 0x0b87);
+	phy_write(phydev, 0x16, 0x80f5);
+	phy_write(phydev, 0x17, 0x760e);
+	phy_write(phydev, 0x16, 0x8107);
+	phy_write(phydev, 0x17, 0x360e);
+	phy_write(phydev, 0x16, 0x8551);
+	phy_modify(phydev, 0x17, 0xff00, 0x0800);
+	phy_write(phydev, 0x1f, 0x0000);
+
+	phy_modify_paged(phydev, 0xbf0, 0x10, 0xe000, 0xa000);
+	phy_modify_paged(phydev, 0xbf4, 0x13, 0x0f00, 0x0300);
+
+	r8168g_phy_param(phydev, 0x8044, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x804a, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x8050, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x8056, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x805c, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x8062, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x8068, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x806e, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x8074, 0xffff, 0x2417);
+	r8168g_phy_param(phydev, 0x807a, 0xffff, 0x2417);
+
+	phy_modify_paged(phydev, 0xa4c, 0x15, 0x0000, 0x0040);
+	phy_modify_paged(phydev, 0xbf8, 0x12, 0xe000, 0xa000);
+
+	rtl8125_legacy_force_mode(phydev);
+	rtl8125b_config_eee_phy(phydev);
+}
+
+void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
+			 enum mac_version ver)
+{
+	static const rtl_phy_cfg_fct phy_configs[] = {
+		/* PCI devices. */
+		[RTL_GIGA_MAC_VER_02] = rtl8169s_hw_phy_config,
+		[RTL_GIGA_MAC_VER_03] = rtl8169s_hw_phy_config,
+		[RTL_GIGA_MAC_VER_04] = rtl8169sb_hw_phy_config,
+		[RTL_GIGA_MAC_VER_05] = rtl8169scd_hw_phy_config,
+		[RTL_GIGA_MAC_VER_06] = rtl8169sce_hw_phy_config,
+		/* PCI-E devices. */
+		[RTL_GIGA_MAC_VER_07] = rtl8102e_hw_phy_config,
+		[RTL_GIGA_MAC_VER_08] = rtl8102e_hw_phy_config,
+		[RTL_GIGA_MAC_VER_09] = rtl8102e_hw_phy_config,
+		[RTL_GIGA_MAC_VER_10] = NULL,
+		[RTL_GIGA_MAC_VER_11] = rtl8168bb_hw_phy_config,
+		[RTL_GIGA_MAC_VER_14] = rtl8401_hw_phy_config,
+		[RTL_GIGA_MAC_VER_17] = rtl8168bef_hw_phy_config,
+		[RTL_GIGA_MAC_VER_18] = rtl8168cp_1_hw_phy_config,
+		[RTL_GIGA_MAC_VER_19] = rtl8168c_1_hw_phy_config,
+		[RTL_GIGA_MAC_VER_20] = rtl8168c_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_21] = rtl8168c_3_hw_phy_config,
+		[RTL_GIGA_MAC_VER_22] = rtl8168c_3_hw_phy_config,
+		[RTL_GIGA_MAC_VER_23] = rtl8168cp_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_24] = rtl8168cp_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_25] = rtl8168d_1_hw_phy_config,
+		[RTL_GIGA_MAC_VER_26] = rtl8168d_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_28] = rtl8168d_4_hw_phy_config,
+		[RTL_GIGA_MAC_VER_29] = rtl8105e_hw_phy_config,
+		[RTL_GIGA_MAC_VER_30] = rtl8105e_hw_phy_config,
+		[RTL_GIGA_MAC_VER_31] = NULL,
+		[RTL_GIGA_MAC_VER_32] = rtl8168e_1_hw_phy_config,
+		[RTL_GIGA_MAC_VER_33] = rtl8168e_1_hw_phy_config,
+		[RTL_GIGA_MAC_VER_34] = rtl8168e_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_35] = rtl8168f_1_hw_phy_config,
+		[RTL_GIGA_MAC_VER_36] = rtl8168f_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_37] = rtl8402_hw_phy_config,
+		[RTL_GIGA_MAC_VER_38] = rtl8411_hw_phy_config,
+		[RTL_GIGA_MAC_VER_39] = rtl8106e_hw_phy_config,
+		[RTL_GIGA_MAC_VER_40] = rtl8168g_1_hw_phy_config,
+		[RTL_GIGA_MAC_VER_42] = rtl8168g_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_43] = rtl8168g_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_44] = rtl8168g_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_46] = rtl8168h_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_48] = rtl8168h_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_51] = rtl8168ep_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_52] = rtl8117_hw_phy_config,
+		[RTL_GIGA_MAC_VER_53] = rtl8117_hw_phy_config,
+		[RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config,
+	};
+
+	if (phy_configs[ver])
+		phy_configs[ver](tp, phydev);
+}
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
deleted file mode 100644
index cbcd065980..0000000000
--- a/drivers/net/rtl8169.c
+++ /dev/null
@@ -1,562 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2014 Lucas Stach <l.stach@pengutronix.de>
- */
-
-#include <common.h>
-#include <dma.h>
-#include <init.h>
-#include <net.h>
-#include <malloc.h>
-#include <linux/pci.h>
-
-#define NUM_TX_DESC	1
-#define NUM_RX_DESC	4
-#define PKT_BUF_SIZE	1536
-#define ETH_ZLEN	60
-
-struct rtl8169_chip_info {
-	const char *name;
-	u8 version;
-	u32 RxConfigMask;
-};
-
-#define BD_STAT_OWN	0x80000000
-#define BD_STAT_EOR	0x40000000
-#define BD_STAT_FS	0x20000000
-#define BD_STAT_LS	0x10000000
-#define BD_STAT_RX_RES	0x00200000
-struct bufdesc {
-	u32 status;
-	u32 vlan_tag;
-	u32 buf_addr;
-	u32 buf_Haddr;
-};
-
-struct rtl8169_priv {
-	struct eth_device	edev;
-	void __iomem		*base;
-	struct pci_dev		*pci_dev;
-	int			chipset;
-
-	volatile struct bufdesc	*tx_desc;
-	dma_addr_t		tx_desc_phys;
-	void			*tx_buf;
-	dma_addr_t		tx_buf_phys;
-	unsigned int		cur_tx;
-
-	volatile struct bufdesc	*rx_desc;
-	dma_addr_t		rx_desc_phys;
-	void			*rx_buf;
-	dma_addr_t		rx_buf_phys;
-	unsigned int		cur_rx;
-
-	struct mii_bus miibus;
-};
-
-#define MAC0 			0x00
-#define MAR0			0x08
-#define TxDescStartAddrLow	0x20
-#define TxDescStartAddrHigh	0x24
-#define TxHDescStartAddrLow	0x28
-#define TxHDescStartAddrHigh	0x2c
-#define FLASH			0x30
-#define ERSR			0x36
-#define ChipCmd			0x37
-#define  CmdReset		0x10
-#define  CmdRxEnb		0x08
-#define  CmdTxEnb		0x04
-#define  RxBufEmpty		0x01
-#define TxPoll			0x38
-#define IntrMask		0x3c
-#define IntrStatus		0x3e
-#define  SYSErr			0x8000
-#define  PCSTimeout		0x4000
-#define  SWInt			0x0100
-#define  TxDescUnavail		0x80
-#define  RxFIFOOver		0x40
-#define  RxUnderrun		0x20
-#define  RxOverflow		0x10
-#define  TxErr			0x08
-#define  TxOK			0x04
-#define  RxErr			0x02
-#define  RxOK			0x01
-#define TxConfig		0x40
-#define  TxInterFrameGapShift	24
-#define  TxDMAShift		8
-#define RxConfig		0x44
-#define  AcceptErr		0x20
-#define  AcceptRunt		0x10
-#define  AcceptBroadcast	0x08
-#define  AcceptMulticast	0x04
-#define  AcceptMyPhys		0x02
-#define  AcceptAllPhys		0x01
-#define  RxCfgFIFOShift		13
-#define  RxCfgDMAShift		8
-#define RxMissed		0x4c
-#define Cfg9346			0x50
-#define  Cfg9346_Lock		0x00
-#define  Cfg9346_Unlock		0xc0
-#define Config0			0x51
-#define Config1			0x52
-#define Config2			0x53
-#define Config3			0x54
-#define Config4			0x55
-#define Config5			0x56
-#define MultiIntr		0x5c
-#define PHYAR			0x60
-#define TBICSR			0x64
-#define TBI_ANAR		0x68
-#define TBI_LPAR		0x6a
-#define PHYstatus		0x6c
-#define RxMaxSize		0xda
-#define CPlusCmd		0xe0
-#define RxDescStartAddrLow	0xe4
-#define RxDescStartAddrHigh	0xe8
-#define EarlyTxThres		0xec
-#define FuncEvent		0xf0
-#define FuncEventMask		0xf4
-#define FuncPresetState		0xf8
-#define FuncForceEvent		0xfc
-
-/* write MMIO register */
-#define RTL_W8(priv, reg, val)	writeb(val, ((char *)(priv->base) + reg))
-#define RTL_W16(priv, reg, val)	writew(val, ((char *)(priv->base) + reg))
-#define RTL_W32(priv, reg, val)	writel(val, ((char *)(priv->base) + reg))
-
-/* read MMIO register */
-#define RTL_R8(priv, reg)	readb(((char *)(priv->base) + reg))
-#define RTL_R16(priv, reg)	readw(((char *)(priv->base) + reg))
-#define RTL_R32(priv, reg)	readl(((char *)(priv->base) + reg))
-
-static const u32 rtl8169_rx_config =
-		 (7 << RxCfgFIFOShift) | (6 << RxCfgDMAShift);
-
-static void rtl8169_chip_reset(struct rtl8169_priv *priv)
-{
-	int i;
-
-	/* Soft reset the chip. */
-	RTL_W8(priv, ChipCmd, CmdReset);
-
-	/* Check that the chip has finished the reset. */
-	for (i = 1000; i > 0; i--) {
-		if ((RTL_R8(priv, ChipCmd) & CmdReset) == 0)
-			break;
-		udelay(10);
-	}
-}
-
-static struct rtl8169_chip_info chip_info[] = {
-	{"RTL-8169",		0x00,	0xff7e1880},
-	{"RTL-8169",		0x04,	0xff7e1880},
-	{"RTL-8169",		0x00,	0xff7e1880},
-	{"RTL-8169s/8110s",	0x02,	0xff7e1880},
-	{"RTL-8169s/8110s",	0x04,	0xff7e1880},
-	{"RTL-8169sb/8110sb",	0x10,	0xff7e1880},
-	{"RTL-8169sc/8110sc",	0x18,	0xff7e1880},
-	{"RTL-8168b/8111sb",	0x30,	0xff7e1880},
-	{"RTL-8168b/8111sb",	0x38,	0xff7e1880},
-	{"RTL-8168d/8111d",	0x28,	0xff7e1880},
-	{"RTL-8168evl/8111evl",	0x2e,	0xff7e1880},
-	{"RTL-8168/8111g",	0x4c,	0xff7e1880,},
-	{"RTL-8101e",		0x34,	0xff7e1880},
-	{"RTL-8100e",		0x32,	0xff7e1880},
-};
-
-static void rtl8169_chip_identify(struct rtl8169_priv *priv)
-{
-	u32 val;
-	int i;
-
-	val = RTL_R32(priv, TxConfig);
-	val = ((val & 0x7c000000) + ((val & 0x00800000) << 2)) >> 24;
-
-	for (i = ARRAY_SIZE(chip_info) - 1; i >= 0; i--){
-		if (val == chip_info[i].version) {
-			priv->chipset = i;
-			dev_dbg(&priv->pci_dev->dev, "found %s chipset\n",
-				chip_info[i].name);
-			return;
-		}
-	}
-
-	dev_dbg(&priv->pci_dev->dev,
-		"no matching chip version found, assuming RTL-8169\n");
-	priv->chipset = 0;
-}
-
-static int rtl8169_init_dev(struct eth_device *edev)
-{
-	struct rtl8169_priv *priv = edev->priv;
-
-	rtl8169_chip_reset(priv);
-	rtl8169_chip_identify(priv);
-	pci_set_master(priv->pci_dev);
-
-	return 0;
-}
-
-static void __set_rx_mode(struct rtl8169_priv *priv)
-{
-	u32 mc_filter[2], val;
-
-	/* IFF_ALLMULTI */
-	/* Too many to filter perfectly -- accept all multicasts. */
-	mc_filter[1] = mc_filter[0] = 0xffffffff;
-
-	val = AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
-	      rtl8169_rx_config | (RTL_R32(priv, RxConfig) &
-				  chip_info[priv->chipset].RxConfigMask);
-
-	RTL_W32(priv, RxConfig, val);
-	RTL_W32(priv, MAR0 + 0, mc_filter[0]);
-	RTL_W32(priv, MAR0 + 4, mc_filter[1]);
-}
-
-static void rtl8169_init_ring(struct rtl8169_priv *priv)
-{
-	struct eth_device *edev = &priv->edev;
-	int i;
-
-	priv->cur_rx = priv->cur_tx = 0;
-
-	priv->tx_desc = dma_alloc_coherent(NUM_TX_DESC * sizeof(struct bufdesc),
-					   &priv->tx_desc_phys);
-	priv->tx_buf = malloc(NUM_TX_DESC * PKT_BUF_SIZE);
-	priv->tx_buf_phys = dma_map_single(edev->parent, priv->tx_buf,
-					   NUM_TX_DESC * PKT_BUF_SIZE, DMA_TO_DEVICE);
-
-	priv->rx_desc = dma_alloc_coherent(NUM_RX_DESC * sizeof(struct bufdesc),
-					   &priv->rx_desc_phys);
-	priv->rx_buf = malloc(NUM_RX_DESC * PKT_BUF_SIZE);
-	priv->rx_buf_phys = dma_map_single(edev->parent, priv->rx_buf,
-					   NUM_RX_DESC * PKT_BUF_SIZE, DMA_FROM_DEVICE);
-
-	for (i = 0; i < NUM_RX_DESC; i++) {
-		if (i == (NUM_RX_DESC - 1))
-			priv->rx_desc[i].status =
-				cpu_to_le32(BD_STAT_OWN | BD_STAT_EOR | PKT_BUF_SIZE);
-		else
-			priv->rx_desc[i].status =
-				cpu_to_le32(BD_STAT_OWN | PKT_BUF_SIZE);
-
-		priv->rx_desc[i].buf_addr =
-				cpu_to_le32(priv->rx_buf_phys + i * PKT_BUF_SIZE);
-	}
-}
-
-static void rtl8169_hw_start(struct rtl8169_priv *priv)
-{
-	u32 val;
-
-	RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
-
-	/* RTL-8169sb/8110sb or previous version */
-	if (priv->chipset <= 5)
-		RTL_W8(priv, ChipCmd, CmdTxEnb | CmdRxEnb);
-
-	RTL_W8(priv, EarlyTxThres, 0x3f);
-
-	/* For gigabit rtl8169 */
-	RTL_W16(priv, RxMaxSize, 0x800);
-
-	/* Set Rx Config register */
-	val = rtl8169_rx_config | (RTL_R32(priv, RxConfig) &
-	      chip_info[priv->chipset].RxConfigMask);
-	RTL_W32(priv, RxConfig, val);
-
-	/* Set DMA burst size and Interframe Gap Time */
-	RTL_W32(priv, TxConfig, (6 << TxDMAShift) | (3 << TxInterFrameGapShift));
-
-	RTL_W32(priv, TxDescStartAddrLow, priv->tx_desc_phys);
-	RTL_W32(priv, TxDescStartAddrHigh, 0);
-	RTL_W32(priv, RxDescStartAddrLow, priv->rx_desc_phys);
-	RTL_W32(priv, RxDescStartAddrHigh, 0);
-
-	/* RTL-8169sc/8110sc or later version */
-	if (priv->chipset > 5)
-		RTL_W8(priv, ChipCmd, CmdTxEnb | CmdRxEnb);
-
-	RTL_W8(priv, Cfg9346, Cfg9346_Lock);
-	udelay(10);
-
-	RTL_W32(priv, RxMissed, 0);
-
-	__set_rx_mode(priv);
-
-	/* no early-rx interrupts */
-	RTL_W16(priv, MultiIntr, RTL_R16(priv, MultiIntr) & 0xf000);
-}
-
-static int rtl8169_eth_open(struct eth_device *edev)
-{
-	struct rtl8169_priv *priv = edev->priv;
-	int ret;
-
-	pci_set_master(priv->pci_dev);
-
-	rtl8169_init_ring(priv);
-	rtl8169_hw_start(priv);
-
-	ret = phy_device_connect(edev, &priv->miibus, 0, NULL, 0,
-				 PHY_INTERFACE_MODE_NA);
-
-	return ret;
-}
-
-static int rtl8169_phy_write(struct mii_bus *bus, int phy_addr,
-	int reg, u16 val)
-{
-	struct rtl8169_priv *priv = bus->priv;
-	int i;
-
-	if (phy_addr != 0)
-		return -1;
-
-	RTL_W32(priv, PHYAR, 0x80000000 | (reg & 0xff) << 16 | val);
-	mdelay(1);
-
-	for (i = 2000; i > 0; i--) {
-		if (!(RTL_R32(priv, PHYAR) & 0x80000000)) {
-			return 0;
-		} else {
-			udelay(100);
-		}
-	}
-
-	return -1;
-}
-
-static int rtl8169_phy_read(struct mii_bus *bus, int phy_addr, int reg)
-{
-	struct rtl8169_priv *priv = bus->priv;
-	int i, val = 0xffff;
-
-	RTL_W32(priv, PHYAR, 0x0 | (reg & 0xff) << 16);
-	mdelay(10);
-
-	if (phy_addr != 0)
-		return val;
-
-	for (i = 2000; i > 0; i--) {
-		if (RTL_R32(priv, PHYAR) & 0x80000000) {
-			val = (int) (RTL_R32(priv, PHYAR) & 0xffff);
-			break;
-		} else {
-			udelay(100);
-		}
-	}
-	return val;
-}
-
-static int rtl8169_eth_send(struct eth_device *edev, void *packet,
-				int packet_length)
-{
-	struct rtl8169_priv *priv = edev->priv;
-	unsigned int entry;
-
-	entry = priv->cur_tx % NUM_TX_DESC;
-
-	if (packet_length < ETH_ZLEN)
-		memset(priv->tx_buf + entry * PKT_BUF_SIZE, 0, ETH_ZLEN);
-	memcpy(priv->tx_buf + entry * PKT_BUF_SIZE, packet, packet_length);
-	dma_sync_single_for_device(priv->tx_buf_phys + entry *
-				   PKT_BUF_SIZE, PKT_BUF_SIZE, DMA_TO_DEVICE);
-
-	priv->tx_desc[entry].buf_Haddr = 0;
-	priv->tx_desc[entry].buf_addr =
-		cpu_to_le32(priv->tx_buf_phys + entry * PKT_BUF_SIZE);
-
-	if (entry != (NUM_TX_DESC - 1)) {
-		priv->tx_desc[entry].status =
-			cpu_to_le32(BD_STAT_OWN | BD_STAT_FS | BD_STAT_LS |
-			((packet_length > ETH_ZLEN) ? packet_length : ETH_ZLEN));
-	} else {
-		priv->tx_desc[entry].status =
-			cpu_to_le32(BD_STAT_OWN | BD_STAT_EOR | BD_STAT_FS | BD_STAT_LS |
-			((packet_length > ETH_ZLEN) ? packet_length : ETH_ZLEN));
-	}
-
-	RTL_W8(priv, TxPoll, 0x40);
-
-	while (le32_to_cpu(priv->tx_desc[entry].status) & BD_STAT_OWN)
-		;
-
-	dma_sync_single_for_cpu(priv->tx_buf_phys + entry * PKT_BUF_SIZE,
-				PKT_BUF_SIZE, DMA_TO_DEVICE);
-
-	priv->cur_tx++;
-
-	return 0;
-}
-
-static int rtl8169_eth_rx(struct eth_device *edev)
-{
-	struct rtl8169_priv *priv = edev->priv;
-	unsigned int entry, pkt_size = 0;
-	u8 status;
-
-	entry = priv->cur_rx % NUM_RX_DESC;
-
-	if ((le32_to_cpu(priv->rx_desc[entry].status) & BD_STAT_OWN) == 0) {
-		if (!(le32_to_cpu(priv->rx_desc[entry].status) & BD_STAT_RX_RES)) {
-			pkt_size = (le32_to_cpu(priv->rx_desc[entry].status) & 0x1fff) - 4;
-
-			dma_sync_single_for_cpu(priv->rx_buf_phys + entry * PKT_BUF_SIZE,
-						pkt_size, DMA_FROM_DEVICE);
-
-			net_receive(edev, priv->rx_buf + entry * PKT_BUF_SIZE,
-			            pkt_size);
-
-			dma_sync_single_for_device(priv->rx_buf_phys + entry * PKT_BUF_SIZE,
-						   pkt_size, DMA_FROM_DEVICE);
-
-			if (entry == NUM_RX_DESC - 1)
-				priv->rx_desc[entry].status = cpu_to_le32(BD_STAT_OWN |
-					BD_STAT_EOR | PKT_BUF_SIZE);
-			else
-				priv->rx_desc[entry].status =
-					cpu_to_le32(BD_STAT_OWN | PKT_BUF_SIZE);
-			priv->rx_desc[entry].buf_addr =
-				cpu_to_le32(priv->rx_buf_phys +
-					    entry * PKT_BUF_SIZE);
-		} else {
-			dev_err(&edev->dev, "rx error\n");
-		}
-
-		priv->cur_rx++;
-
-		return pkt_size;
-
-	} else {
-		status = RTL_R8(priv, IntrStatus);
-		RTL_W8(priv, IntrStatus, status & ~(TxErr | RxErr | SYSErr));
-		udelay(100);	/* wait */
-	}
-
-	return 0;
-}
-
-static int rtl8169_get_ethaddr(struct eth_device *edev, unsigned char *m)
-{
-	struct rtl8169_priv *priv = edev->priv;
-	int i;
-
-	for (i = 0; i < 6; i++) {
-		m[i] = RTL_R8(priv, MAC0 + i);
-	}
-
-	return 0;
-}
-
-static int rtl8169_set_ethaddr(struct eth_device *edev, const unsigned char *mac_addr)
-{
-	struct rtl8169_priv *priv = edev->priv;
-	int i;
-
-	RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
-
-	for (i = 0; i < 6; i++) {
-		RTL_W8(priv, (MAC0 + i), mac_addr[i]);
-		RTL_R8(priv, mac_addr[i]);
-	}
-
-	RTL_W8(priv, Cfg9346, Cfg9346_Lock);
-
-	return 0;
-}
-
-static void rtl8169_eth_halt(struct eth_device *edev)
-{
-	struct rtl8169_priv *priv = edev->priv;
-
-	/* Stop the chip's Tx and Rx DMA processes. */
-	RTL_W8(priv, ChipCmd, 0x00);
-
-	/* Disable interrupts by clearing the interrupt mask. */
-	RTL_W16(priv, IntrMask, 0x0000);
-	RTL_W32(priv, RxMissed, 0);
-
-	pci_clear_master(priv->pci_dev);
-
-	dma_unmap_single(edev->parent, priv->tx_buf_phys, NUM_TX_DESC * PKT_BUF_SIZE,
-			 DMA_TO_DEVICE);
-	free(priv->tx_buf);
-	dma_free_coherent((void *)priv->tx_desc, priv->tx_desc_phys,
-			  NUM_TX_DESC * sizeof(struct bufdesc));
-
-	dma_unmap_single(edev->parent, priv->rx_buf_phys, NUM_RX_DESC * PKT_BUF_SIZE,
-			 DMA_FROM_DEVICE);
-	free(priv->rx_buf);
-	dma_free_coherent((void *)priv->rx_desc, priv->rx_desc_phys,
-			  NUM_RX_DESC * sizeof(struct bufdesc));
-}
-
-static int rtl8169_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct device *dev = &pdev->dev;
-	struct eth_device *edev;
-	struct rtl8169_priv *priv;
-	int ret;
-
-	/* enable pci device */
-	pci_enable_device(pdev);
-
-	priv = xzalloc(sizeof(struct rtl8169_priv));
-
-	edev = &priv->edev;
-	dev->type_data = edev;
-	edev->priv = priv;
-
-	priv->pci_dev = pdev;
-
-	priv->miibus.read = rtl8169_phy_read;
-	priv->miibus.write = rtl8169_phy_write;
-	priv->miibus.priv = priv;
-	priv->miibus.parent = &edev->dev;
-
-	priv->base = pci_iomap(pdev, pdev->device == 0x8168 ? 2 : 1);
-
-	dev_dbg(dev, "rtl%04x (rev %02x) (base=%p)\n",
-		 pdev->device, pdev->revision, priv->base);
-
-	edev->init = rtl8169_init_dev;
-	edev->open = rtl8169_eth_open;
-	edev->send = rtl8169_eth_send;
-	edev->recv = rtl8169_eth_rx;
-	edev->get_ethaddr = rtl8169_get_ethaddr;
-	edev->set_ethaddr = rtl8169_set_ethaddr;
-	edev->halt = rtl8169_eth_halt;
-	edev->parent = dev;
-	ret = eth_register(edev);
-	if (ret)
-		goto eth_err;
-
-	ret = mdiobus_register(&priv->miibus);
-	if (ret)
-		goto mdio_err;
-
-	return 0;
-
-mdio_err:
-	eth_unregister(edev);
-
-eth_err:
-	free(priv);
-
-	return ret;
-}
-static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), },
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), },
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
-	{ /* sentinel */ }
-};
-
-static struct pci_driver rtl8169_eth_driver = {
-	.name = "rtl8169_eth",
-	.id_table = rtl8169_pci_tbl,
-	.probe = rtl8169_probe,
-};
-device_pci_driver(rtl8169_eth_driver);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 15/18] ARM: rockchip: Add rk3588 support
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (13 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 14/18] net: Update Realtek r8169 driver Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 16/18] ARM: dts: Add rk3588 device trees Sascha Hauer
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

This adds the assorted rk3588 support stuff which is very similar
to the existing rk3568 support

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-rockchip/Kconfig      |  5 +++++
 arch/arm/mach-rockchip/Makefile     |  1 +
 arch/arm/mach-rockchip/atf.c        | 35 +++++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rk3588.c     | 20 +++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c   |  5 +++++
 common/Kconfig                      |  9 ++++++++
 firmware/Makefile                   |  2 ++
 include/mach/rockchip/atf.h         |  6 +++++
 include/mach/rockchip/debug_ll.h    |  6 +++++
 include/mach/rockchip/rk3588-regs.h | 20 +++++++++++++++++
 include/mach/rockchip/rockchip.h    | 10 +++++++++
 11 files changed, 119 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/rk3588.c
 create mode 100644 include/mach/rockchip/rk3588-regs.h

diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 6f32a440a1..7d540974f5 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -47,6 +47,11 @@ config ARCH_RK3568
 	select ARCH_ROCKCHIP_V8
 	select HW_HAS_PCI
 
+config ARCH_RK3588
+	bool
+	select ARCH_ROCKCHIP_V8
+	select HW_HAS_PCI
+
 comment "select Rockchip boards:"
 
 if 32BIT
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 04d75ce287..28ba3ebec8 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -5,6 +5,7 @@ pbl-$(CONFIG_ARCH_ROCKCHIP_ATF) += atf.o
 obj-$(CONFIG_ARCH_RK3188) += rk3188.o
 obj-$(CONFIG_ARCH_RK3288) += rk3288.o
 obj-pbl-$(CONFIG_ARCH_RK3568) += rk3568.o
+obj-pbl-$(CONFIG_ARCH_RK3588) += rk3588.o
 obj-$(CONFIG_ARCH_ROCKCHIP_V8) += bootm.o
 obj-pbl-$(CONFIG_ARCH_ROCKCHIP_V8) += dmc.o
 obj-$(CONFIG_BAREBOX_UPDATE) += bbu.o
diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c
index d1431cc526..eaba209ff3 100644
--- a/arch/arm/mach-rockchip/atf.c
+++ b/arch/arm/mach-rockchip/atf.c
@@ -10,6 +10,7 @@
 #include <mach/rockchip/rockchip.h>
 #include <mach/rockchip/bootrom.h>
 #include <mach/rockchip/rk3568-regs.h>
+#include <mach/rockchip/rk3588-regs.h>
 
 static unsigned long load_elf64_image_phdr(const void *elf)
 {
@@ -103,3 +104,37 @@ void __noreturn rk3568_barebox_entry(void *fdt)
 
 	barebox_arm_entry(membase, memsize, fdt);
 }
+
+void rk3588_atf_load_bl31(void *fdt)
+{
+	rockchip_atf_load_bl31(RK3588, rk3588_bl31_bin, rk3588_op_tee_bin, fdt);
+}
+
+void __noreturn rk3588_barebox_entry(void *fdt)
+{
+       unsigned long membase, memsize;
+
+       membase = RK3588_DRAM_BOTTOM;
+       memsize = rk3588_ram0_size() - RK3588_DRAM_BOTTOM;
+
+       if (current_el() == 3) {
+               rk3588_lowlevel_init();
+               rockchip_store_bootrom_iram(membase, memsize, IOMEM(RK3588_IRAM_BASE));
+
+               /*
+                * The downstream TF-A doesn't cope with our device tree when
+                * CONFIG_OF_OVERLAY_LIVE is enabled, supposedly because it is
+                * too big for some reason. Otherwise it doesn't have any visible
+                * effect if we pass a device tree or not, except that the TF-A
+                * fills in the ethernet MAC address into the device tree.
+                * The upstream TF-A doesn't use the device tree at all.
+                *
+                * Pass NULL for now until we have a good reason to pass a real
+                * device tree.
+                */
+               rk3588_atf_load_bl31(NULL);
+               /* not reached when CONFIG_ARCH_ROCKCHIP_ATF */
+       }
+
+       barebox_arm_entry(membase, memsize, fdt);
+}
diff --git a/arch/arm/mach-rockchip/rk3588.c b/arch/arm/mach-rockchip/rk3588.c
new file mode 100644
index 0000000000..25f1481296
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3588.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier:     GPL-2.0+
+#include <common.h>
+#include <io.h>
+#include <bootsource.h>
+#include <mach/rockchip/rk3588-regs.h>
+#include <mach/rockchip/rockchip.h>
+#include <asm/barebox-arm-head.h>
+#include <mach/rockchip/bootrom.h>
+
+void rk3588_lowlevel_init(void)
+{
+	arm_cpu_lowlevel_init();
+}
+
+int rk3588_init(void)
+{
+	rockchip_parse_bootrom_iram(rockchip_scratch_space());
+
+	return 0;
+}
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index e75238481c..9dc1fd18fb 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -32,6 +32,11 @@ static int rockchip_init(void)
 		return rk3568_init();
 	}
 
+	if (of_machine_is_compatible("rockchip,rk3588")) {
+		__rockchip_soc = 3588;
+		return rk3588_init();
+	}
+
 	return 0;
 }
 postcore_initcall(rockchip_init);
diff --git a/common/Kconfig b/common/Kconfig
index ac3df75acb..3003d91dc5 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1426,6 +1426,14 @@ config DEBUG_ROCKCHIP_RK3568_UART
 	  Say Y here if you want kernel low-level debugging support
 	  on RK3568.
 
+config DEBUG_ROCKCHIP_RK3588_UART
+	bool "RK3588 Debug UART"
+	depends on ARCH_RK3588
+	select DEBUG_ROCKCHIP_UART
+	help
+	  Say Y here if you want kernel low-level debugging support
+	  on RK3588.
+
 config DEBUG_ROCKCHIP_RK3399_UART
 	bool "RK3399 Debug UART"
 	depends on ARCH_RK3399
@@ -1585,6 +1593,7 @@ config DEBUG_ROCKCHIP_UART_PORT
 	int "RK3xxx UART debug port" if DEBUG_ROCKCHIP_RK3188_UART || \
 				DEBUG_ROCKCHIP_RK3288_UART || \
 				DEBUG_ROCKCHIP_RK3568_UART || \
+				DEBUG_ROCKCHIP_RK3588_UART || \
 				DEBUG_ROCKCHIP_RK3399_UART
 	default 2
 	depends on ARCH_ROCKCHIP
diff --git a/firmware/Makefile b/firmware/Makefile
index 984192f030..75812cb6bf 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -21,6 +21,8 @@ fw-external-$(CONFIG_FIRMWARE_IMX8MN_OPTEE) += imx8mn-bl32.bin
 fw-external-$(CONFIG_FIRMWARE_IMX8MP_OPTEE) += imx8mp-bl32.bin
 firmware-$(CONFIG_ARCH_RK3568) += rk3568-bl31.bin
 firmware-$(CONFIG_ARCH_RK3568_OPTEE) += rk3568-op-tee.bin
+firmware-$(CONFIG_ARCH_RK3588) += rk3588-bl31.bin
+firmware-$(CONFIG_ARCH_RK3588_OPTEE) += rk3588-op-tee.bin
 firmware-$(CONFIG_ARCH_RK3399) += rk3399-bl31.bin
 firmware-$(CONFIG_ARCH_RK3399_OPTEE) += rk3399-op-tee.bin
 firmware-$(CONFIG_DRIVER_NET_FSL_FMAN) += fsl_fman_ucode_ls1046_r1.0_106_4_18.bin
diff --git a/include/mach/rockchip/atf.h b/include/mach/rockchip/atf.h
index e1e68825d1..89129abc01 100644
--- a/include/mach/rockchip/atf.h
+++ b/include/mach/rockchip/atf.h
@@ -6,10 +6,12 @@
 /* First usable DRAM address. Lower mem is used for ATF and OP-TEE */
 #define RK3399_DRAM_BOTTOM		0xa00000
 #define RK3568_DRAM_BOTTOM		0xa00000
+#define RK3588_DRAM_BOTTOM		0xa00000
 
 /* OP-TEE expects to be loaded here */
 #define RK3399_OPTEE_LOAD_ADDRESS	0x200000
 #define RK3568_OPTEE_LOAD_ADDRESS	0x200000
+#define RK3588_OPTEE_LOAD_ADDRESS	0x200000
 
 /*
  * board lowlevel code should relocate barebox here. This is where
@@ -17,17 +19,21 @@
  */
 #define RK3399_BAREBOX_LOAD_ADDRESS	(RK3399_DRAM_BOTTOM + 1024*1024)
 #define RK3568_BAREBOX_LOAD_ADDRESS	(RK3568_DRAM_BOTTOM + 1024*1024)
+#define RK3588_BAREBOX_LOAD_ADDRESS	(RK3588_DRAM_BOTTOM + 1024*1024)
 
 #ifndef __ASSEMBLY__
 #ifdef CONFIG_ARCH_ROCKCHIP_ATF
 void rk3399_atf_load_bl31(void *fdt);
 void rk3568_atf_load_bl31(void *fdt);
+void rk3588_atf_load_bl31(void *fdt);
 #else
 static inline void rk3399_atf_load_bl31(void *fdt) { }
 static inline void rk3568_atf_load_bl31(void *fdt) { }
+static inline void rk3588_atf_load_bl31(void *fdt) { }
 #endif
 #endif
 
 void __noreturn rk3568_barebox_entry(void *fdt);
+void __noreturn rk3588_barebox_entry(void *fdt);
 
 #endif /* __MACH_ATF_H */
diff --git a/include/mach/rockchip/debug_ll.h b/include/mach/rockchip/debug_ll.h
index b1cf16a2dc..b68d91165d 100644
--- a/include/mach/rockchip/debug_ll.h
+++ b/include/mach/rockchip/debug_ll.h
@@ -8,6 +8,7 @@
 #include <mach/rockchip/rk3188-regs.h>
 #include <mach/rockchip/rk3288-regs.h>
 #include <mach/rockchip/rk3568-regs.h>
+#include <mach/rockchip/rk3588-regs.h>
 #include <mach/rockchip/rk3399-regs.h>
 
 #ifdef CONFIG_DEBUG_ROCKCHIP_UART
@@ -27,6 +28,11 @@
 #define RK_DEBUG_UART_CLOCK	24000000
 #define RK_DEBUG_SOC		RK3568
 
+#elif defined CONFIG_DEBUG_ROCKCHIP_RK3588_UART
+
+#define RK_DEBUG_UART_CLOCK	24000000
+#define RK_DEBUG_SOC		RK3588
+
 #elif defined CONFIG_DEBUG_ROCKCHIP_RK3399_UART
 
 #define RK_DEBUG_UART_CLOCK	24000000
diff --git a/include/mach/rockchip/rk3588-regs.h b/include/mach/rockchip/rk3588-regs.h
new file mode 100644
index 0000000000..c42d206a52
--- /dev/null
+++ b/include/mach/rockchip/rk3588-regs.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __MACH_RK3588_REGS_H
+#define __MACH_RK3588_REGS_H
+
+/* UART */
+#define RK3588_UART0_BASE       0xfd890000
+#define RK3588_UART1_BASE       0xfeb40000
+#define RK3588_UART2_BASE       0xfeb50000
+#define RK3588_UART3_BASE       0xfeb60000
+#define RK3588_UART4_BASE       0xfeb70000
+#define RK3588_UART5_BASE       0xfeb80000
+#define RK3588_UART6_BASE       0xfeb90000
+#define RK3588_UART7_BASE       0xfeba0000
+#define RK3588_UART8_BASE       0xfebb0000
+#define RK3588_UART9_BASE       0xfebc0000
+
+#define RK3588_IRAM_BASE        0xff000000
+
+#endif /* __MACH_RK3588_REGS_H */
diff --git a/include/mach/rockchip/rockchip.h b/include/mach/rockchip/rockchip.h
index 485526ef53..8d68651cf4 100644
--- a/include/mach/rockchip/rockchip.h
+++ b/include/mach/rockchip/rockchip.h
@@ -35,7 +35,17 @@ static inline int rk3568_init(void)
 }
 #endif
 
+#ifdef CONFIG_ARCH_RK3588
+int rk3588_init(void);
+#else
+static inline int rk3588_init(void)
+{
+	return -ENOTSUPP;
+}
+#endif
+
 void rk3568_lowlevel_init(void);
+void rk3588_lowlevel_init(void);
 
 int rockchip_soc(void);
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 16/18] ARM: dts: Add rk3588 device trees
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (14 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 15/18] ARM: rockchip: Add rk3588 support Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 17/18] ARM: rockchip: rk3588: add memsize detection Sascha Hauer
  2023-05-04  8:17 ` [PATCH 18/18] ARM: rockchip: Add Radxa ROCK 5B support Sascha Hauer
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

We have upstream device trees in dts/src/arm64/rockchip/rk3588*.dtsi.
This patch adds some pieces not yet in upstream, like PCIe nodes,
DMC node and sdmmc node.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/dts/rk3588.dtsi  | 152 ++++++++++++++++++++++++++++++++++++++
 arch/arm/dts/rk3588s.dtsi | 135 +++++++++++++++++++++++++++++++++
 2 files changed, 287 insertions(+)
 create mode 100644 arch/arm/dts/rk3588.dtsi
 create mode 100644 arch/arm/dts/rk3588s.dtsi

diff --git a/arch/arm/dts/rk3588.dtsi b/arch/arm/dts/rk3588.dtsi
new file mode 100644
index 0000000000..28bcb2f643
--- /dev/null
+++ b/arch/arm/dts/rk3588.dtsi
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+#include <dt-bindings/phy/phy.h>
+#include "rk3588s.dtsi"
+
+/ {
+	pcie30_phy_grf: syscon@fd5b8000 {
+		compatible = "rockchip,pcie30-phy-grf", "syscon";
+		reg = <0x0 0xfd5b8000 0x0 0x10000>;
+	};
+
+	pipe_phy0_grf: syscon@fd5bc000 {
+		compatible = "rockchip,pipe-phy-grf", "syscon";
+		reg = <0x0 0xfd5bc000 0x0 0x100>;
+	};
+
+	pipe_phy1_grf: syscon@fd5c0000 {
+		compatible = "rockchip,pipe-phy-grf", "syscon";
+		reg = <0x0 0xfd5c0000 0x0 0x100>;
+	};
+
+	pcie3x4: pcie@fe150000 {
+		compatible = "rockchip,rk3588-pcie", "snps,dw-pcie";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x00 0x0f>;
+		clocks = <&cru ACLK_PCIE_4L_MSTR>, <&cru ACLK_PCIE_4L_SLV>,
+			 <&cru ACLK_PCIE_4L_DBI>, <&cru PCLK_PCIE_4L>,
+			 <&cru CLK_PCIE_AUX0>, <&cru CLK_PCIE4L_PIPE>;
+		clock-names = "aclk_mst", "aclk_slv",
+			      "aclk_dbi", "pclk",
+			      "aux", "pipe";
+		device_type = "pci";
+		linux,pci-domain = <0>;
+		num-ib-windows = <16>;
+		num-ob-windows = <16>;
+		num-viewport = <8>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		phys = <&pcie30phy>;
+		phy-names = "pcie-phy";
+		power-domains = <&power RK3588_PD_PCIE>;
+		ranges = <0x81000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x100000
+			  0x82000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0xe00000
+			  0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;
+		reg = <0x0 0xfe150000 0x0 0x10000>,
+		      <0xa 0x40000000 0x0 0x400000>,
+		      <0x0 0xf0000000 0x0 0x100000>;
+		reg-names = "apb", "dbi", "config";
+		resets = <&cru SRST_PCIE0_POWER_UP>, <&cru SRST_P_PCIE0>;
+		reset-names = "pcie", "periph";
+		rockchip,pipe-grf = <&php_grf>;
+		status = "disabled";
+	};
+
+	pcie3x2: pcie@fe160000 {
+		compatible = "rockchip,rk3588-pcie", "snps,dw-pcie";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x10 0x1f>;
+		clocks = <&cru ACLK_PCIE_2L_MSTR>, <&cru ACLK_PCIE_2L_SLV>,
+			 <&cru ACLK_PCIE_2L_DBI>, <&cru PCLK_PCIE_2L>,
+			 <&cru CLK_PCIE_AUX1>, <&cru CLK_PCIE2L_PIPE>;
+		clock-names = "aclk_mst", "aclk_slv",
+			      "aclk_dbi", "pclk",
+			      "aux", "pipe";
+		device_type = "pci";
+		linux,pci-domain = <1>;
+		num-ib-windows = <16>;
+		num-ob-windows = <16>;
+		num-viewport = <8>;
+		max-link-speed = <3>;
+		num-lanes = <2>;
+		phys = <&pcie30phy>;
+		phy-names = "pcie-phy";
+		power-domains = <&power RK3588_PD_PCIE>;
+		ranges = <0x81000000 0x0 0xf1100000 0x0 0xf1100000 0x0 0x100000
+			  0x82000000 0x0 0xf1200000 0x0 0xf1200000 0x0 0xe00000
+			  0xc3000000 0x9 0x40000000 0x9 0x40000000 0x0 0x40000000>;
+		reg = <0x0 0xfe160000 0x0 0x10000>,
+		      <0xa 0x40400000 0x0 0x400000>,
+		      <0x0 0xf1000000 0x0 0x100000>;
+		reg-names = "apb", "dbi", "config";
+		resets = <&cru SRST_PCIE1_POWER_UP>, <&cru SRST_P_PCIE1>;
+		reset-names = "pcie", "periph";
+		rockchip,pipe-grf = <&php_grf>;
+		status = "disabled";
+	};
+
+	pcie2x1l0: pcie@fe170000 {
+		compatible = "rockchip,rk3588-pcie", "snps,dw-pcie";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x20 0x2f>;
+		clocks = <&cru ACLK_PCIE_1L0_MSTR>, <&cru ACLK_PCIE_1L0_SLV>,
+			 <&cru ACLK_PCIE_1L0_DBI>, <&cru PCLK_PCIE_1L0>,
+			 <&cru CLK_PCIE_AUX2>, <&cru CLK_PCIE1L0_PIPE>;
+		clock-names = "aclk_mst", "aclk_slv",
+			      "aclk_dbi", "pclk",
+			      "aux", "pipe";
+		device_type = "pci";
+		linux,pci-domain = <2>;
+		num-ib-windows = <8>;
+		num-ob-windows = <8>;
+		num-viewport = <4>;
+		max-link-speed = <2>;
+		num-lanes = <1>;
+		phys = <&combphy1_ps PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy";
+		ranges = <0x81000000 0x0 0xf2100000 0x0 0xf2100000 0x0 0x100000
+			  0x82000000 0x0 0xf2200000 0x0 0xf2200000 0x0 0xe00000
+			  0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>;
+		reg = <0x0 0xfe170000 0x0 0x10000>,
+		      <0xa 0x40800000 0x0 0x400000>,
+		      <0x0 0xf2000000 0x0 0x100000>;
+		reg-names = "apb", "dbi", "config";
+		resets = <&cru SRST_PCIE2_POWER_UP>, <&cru SRST_P_PCIE2>;
+		reset-names = "pcie", "periph";
+		rockchip,pipe-grf = <&php_grf>;
+		status = "disabled";
+	};
+
+	combphy1_ps: phy@fee10000 {
+		compatible = "rockchip,rk3588-naneng-combphy";
+		reg = <0x0 0xfee10000 0x0 0x100>;
+		#phy-cells = <1>;
+		clocks = <&cru CLK_REF_PIPE_PHY1>, <&cru PCLK_PCIE_COMBO_PIPE_PHY1>,
+			 <&cru PCLK_PHP_ROOT>;
+		clock-names = "refclk", "apbclk", "phpclk";
+		assigned-clocks = <&cru CLK_REF_PIPE_PHY1>;
+		assigned-clock-rates = <100000000>;
+		resets = <&cru SRST_P_PCIE2_PHY1>, <&cru SRST_REF_PIPE_PHY1>;
+		reset-names = "combphy-apb", "combphy";
+		rockchip,pipe-grf = <&php_grf>;
+		rockchip,pipe-phy-grf = <&pipe_phy1_grf>;
+		rockchip,pcie1ln-sel-bits = <0x100 0 0 0>;
+		status = "disabled";
+	};
+
+	pcie30phy: phy@fee80000 {
+		compatible = "rockchip,rk3588-pcie3-phy";
+		reg = <0x0 0xfee80000 0x0 0x20000>;
+		#phy-cells = <0>;
+		clocks = <&cru PCLK_PCIE_COMBO_PIPE_PHY>;
+		clock-names = "pclk";
+		resets = <&cru SRST_PCIE30_PHY>;
+		reset-names = "phy";
+		rockchip,pipe-grf = <&php_grf>;
+		rockchip,phy-grf = <&pcie30_phy_grf>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/rk3588s.dtsi b/arch/arm/dts/rk3588s.dtsi
new file mode 100644
index 0000000000..ba6561f97e
--- /dev/null
+++ b/arch/arm/dts/rk3588s.dtsi
@@ -0,0 +1,135 @@
+/ {
+	dmc: memory-controller {
+		compatible = "rockchip,rk3588-dmc";
+		rockchip,pmu = <&pmugrf>;
+	};
+
+	pmugrf: syscon@fd58a000 {
+		compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd";
+		reg = <0x0 0xfd58a000 0x0 0x10000>;
+	};
+
+	pipe_phy2_grf: syscon@fd5c4000 {
+		compatible = "rockchip,pipe-phy-grf", "syscon";
+		reg = <0x0 0xfd5c4000 0x0 0x100>;
+	};
+
+	pcie2x1l1: pcie@fe180000 {
+		compatible = "rockchip,rk3588-pcie", "snps,dw-pcie";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x30 0x3f>;
+		clocks = <&cru ACLK_PCIE_1L1_MSTR>, <&cru ACLK_PCIE_1L1_SLV>,
+			 <&cru ACLK_PCIE_1L1_DBI>, <&cru PCLK_PCIE_1L1>,
+			 <&cru CLK_PCIE_AUX3>, <&cru CLK_PCIE1L1_PIPE>;
+		clock-names = "aclk_mst", "aclk_slv",
+			      "aclk_dbi", "pclk",
+			      "aux", "pipe";
+		device_type = "pci";
+		linux,pci-domain = <3>;
+		num-ib-windows = <8>;
+		num-ob-windows = <8>;
+		num-viewport = <4>;
+		max-link-speed = <2>;
+		num-lanes = <1>;
+		phys = <&combphy2_psu PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy";
+		ranges = <0x81000000 0x0 0xf3100000 0x0 0xf3100000 0x0 0x100000
+			  0x82000000 0x0 0xf3200000 0x0 0xf3200000 0x0 0xe00000
+			  0xc3000000 0x9 0xc0000000 0x9 0xc0000000 0x0 0x40000000>;
+		reg = <0x0 0xfe180000 0x0 0x10000>,
+		      <0xa 0x40c00000 0x0 0x400000>,
+		      <0x0 0xf3000000 0x0 0x100000>;
+		reg-names = "apb", "dbi", "config";
+		resets = <&cru SRST_PCIE3_POWER_UP>, <&cru SRST_P_PCIE3>;
+		reset-names = "pcie", "periph";
+		rockchip,pipe-grf = <&php_grf>;
+		status = "disabled";
+	};
+
+	pcie2x1l2: pcie@fe190000 {
+		compatible = "rockchip,rk3588-pcie", "snps,dw-pcie";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x40 0x4f>;
+		clocks = <&cru ACLK_PCIE_1L2_MSTR>, <&cru ACLK_PCIE_1L2_SLV>,
+			 <&cru ACLK_PCIE_1L2_DBI>, <&cru PCLK_PCIE_1L2>,
+			 <&cru CLK_PCIE_AUX4>, <&cru CLK_PCIE1L2_PIPE>;
+		clock-names = "aclk_mst", "aclk_slv",
+			      "aclk_dbi", "pclk",
+			      "aux", "pipe";
+		device_type = "pci";
+		linux,pci-domain = <4>;
+		num-ib-windows = <8>;
+		num-ob-windows = <8>;
+		num-viewport = <4>;
+		max-link-speed = <2>;
+		num-lanes = <1>;
+		phys = <&combphy0_ps PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy";
+		ranges = <0x81000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x100000
+			  0x82000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0xe00000
+			  0xc3000000 0xa 0x00000000 0xa 0x00000000 0x0 0x40000000>;
+		reg = <0x0 0xfe190000 0x0 0x10000>,
+		      <0xa 0x41000000 0x0 0x400000>,
+		      <0x0 0xf4000000 0x0 0x100000>;
+		reg-names = "apb", "dbi", "config";
+		resets = <&cru SRST_PCIE4_POWER_UP>, <&cru SRST_P_PCIE4>;
+		reset-names = "pcie", "periph";
+		rockchip,pipe-grf = <&php_grf>;
+		status = "disabled";
+	};
+
+	sdmmc: mmc@fe2c0000 {
+		compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xfe2c0000 0x0 0x4000>;
+		interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&scmi_clk SCMI_HCLK_SD>, <&scmi_clk SCMI_CCLK_SD>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		max-frequency = <200000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
+		power-domains = <&power RK3588_PD_SDMMC>;
+		status = "disabled";
+	};
+
+	combphy0_ps: phy@fee00000 {
+		compatible = "rockchip,rk3588-naneng-combphy";
+		reg = <0x0 0xfee00000 0x0 0x100>;
+		#phy-cells = <1>;
+		clocks = <&cru CLK_REF_PIPE_PHY0>, <&cru PCLK_PCIE_COMBO_PIPE_PHY0>,
+			 <&cru PCLK_PHP_ROOT>;
+		clock-names = "refclk", "apbclk", "phpclk";
+		assigned-clocks = <&cru CLK_REF_PIPE_PHY0>;
+		assigned-clock-rates = <100000000>;
+		resets = <&cru SRST_P_PCIE2_PHY0>, <&cru SRST_REF_PIPE_PHY0>;
+		reset-names = "combphy-apb", "combphy";
+		rockchip,pipe-grf = <&php_grf>;
+		rockchip,pipe-phy-grf = <&pipe_phy0_grf>;
+		status = "disabled";
+	};
+
+	combphy2_psu: phy@fee20000 {
+		compatible = "rockchip,rk3588-naneng-combphy";
+		reg = <0x0 0xfee20000 0x0 0x100>;
+		#phy-cells = <1>;
+		clocks = <&cru CLK_REF_PIPE_PHY2>, <&cru PCLK_PCIE_COMBO_PIPE_PHY2>,
+			 <&cru PCLK_PHP_ROOT>;
+		clock-names = "refclk", "apbclk", "phpclk";
+		assigned-clocks = <&cru CLK_REF_PIPE_PHY2>;
+		assigned-clock-rates = <100000000>;
+		resets = <&cru SRST_P_PCIE2_PHY2>, <&cru SRST_REF_PIPE_PHY2>;
+		reset-names = "combphy-apb", "combphy";
+		rockchip,pipe-grf = <&php_grf>;
+		rockchip,pipe-phy-grf = <&pipe_phy2_grf>;
+		rockchip,pcie1ln-sel-bits = <0x100 1 1 0>;
+		status = "disabled";
+	};
+};
+
+&scmi_clk {
+	/delete-property/ assigned-clocks;
+	/delete-property/ assigned-clock-rates;
+};
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 17/18] ARM: rockchip: rk3588: add memsize detection
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (15 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 16/18] ARM: dts: Add rk3588 device trees Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  8:17 ` [PATCH 18/18] ARM: rockchip: Add Radxa ROCK 5B support Sascha Hauer
  17 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Extend the DMC driver for rk3588

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-rockchip/dmc.c | 52 +++++++++++++++++++++++++++++++-----
 include/mach/rockchip/dmc.h  |  1 +
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-rockchip/dmc.c b/arch/arm/mach-rockchip/dmc.c
index dd60db5830..85fa8acd19 100644
--- a/arch/arm/mach-rockchip/dmc.c
+++ b/arch/arm/mach-rockchip/dmc.c
@@ -29,6 +29,8 @@
 struct rockchip_dmc_drvdata {
 	unsigned int os_reg2;
 	unsigned int os_reg3;
+	unsigned int os_reg4;
+	unsigned int os_reg5;
 	resource_size_t internal_registers_start;
 };
 
@@ -151,12 +153,39 @@ resource_size_t rk3568_ram0_size(void)
 	return size;
 }
 
+#define RK3588_PMUGRF_BASE 0xfd58a000
+#define RK3588_PMUGRF_OS_REG2           0x208
+#define RK3588_PMUGRF_OS_REG3           0x20c
+#define RK3588_PMUGRF_OS_REG4           0x210
+#define RK3588_PMUGRF_OS_REG5           0x214
+
+resource_size_t rk3588_ram0_size(void)
+{
+	void __iomem *pmugrf = IOMEM(RK3588_PMUGRF_BASE);
+	u32 sys_reg2, sys_reg3, sys_reg4, sys_reg5;
+	resource_size_t size, size1, size2;
+
+	sys_reg2 = readl(pmugrf + RK3588_PMUGRF_OS_REG2);
+	sys_reg3 = readl(pmugrf + RK3588_PMUGRF_OS_REG3);
+	sys_reg4 = readl(pmugrf + RK3588_PMUGRF_OS_REG4);
+	sys_reg5 = readl(pmugrf + RK3588_PMUGRF_OS_REG5);
+
+	size1 = rockchip_sdram_size(sys_reg2, sys_reg3);
+	size2 = rockchip_sdram_size(sys_reg4, sys_reg5);
+
+	pr_info("%s() size1 = %llu, size2 = %llu\n", __func__, (u64)size1, (u64)size2);
+
+	size = min_t(resource_size_t, RK3568_INT_REG_START, size1 + size2);
+
+	return size;
+}
+
 static int rockchip_dmc_probe(struct device *dev)
 {
 	const struct rockchip_dmc_drvdata *drvdata;
 	resource_size_t membase, memsize;
 	struct regmap *regmap;
-	u32 sys_reg2, sys_reg3;
+	u32 sys_rega, sys_regb;
 
 	regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu");
 	if (IS_ERR(regmap))
@@ -166,10 +195,15 @@ static int rockchip_dmc_probe(struct device *dev)
 	if (!drvdata)
 		return -ENOENT;
 
-	regmap_read(regmap, drvdata->os_reg2, &sys_reg2);
-	regmap_read(regmap, drvdata->os_reg3, &sys_reg3);
+	regmap_read(regmap, drvdata->os_reg2, &sys_rega);
+	regmap_read(regmap, drvdata->os_reg3, &sys_regb);
+	memsize = rockchip_sdram_size(sys_rega, sys_regb);
 
-	memsize = rockchip_sdram_size(sys_reg2, sys_reg3);
+	if (drvdata->os_reg4) {
+		regmap_read(regmap, drvdata->os_reg4, &sys_rega);
+		regmap_read(regmap, drvdata->os_reg5, &sys_regb);
+		memsize += rockchip_sdram_size(sys_rega, sys_regb);
+	}
 
 	dev_info(dev, "Detected memory size: %pa\n", &memsize);
 
@@ -194,8 +228,10 @@ static const struct rockchip_dmc_drvdata rk3399_drvdata = {
 };
 
 static const struct rockchip_dmc_drvdata rk3568_drvdata = {
-	.os_reg2 = RK3568_PMUGRF_OS_REG2,
-	.os_reg3 = RK3568_PMUGRF_OS_REG3,
+	.os_reg2 = RK3588_PMUGRF_OS_REG2,
+	.os_reg3 = RK3588_PMUGRF_OS_REG3,
+	.os_reg4 = RK3588_PMUGRF_OS_REG4,
+	.os_reg5 = RK3588_PMUGRF_OS_REG5,
 	.internal_registers_start = RK3568_INT_REG_START,
 };
 
@@ -208,6 +244,10 @@ static struct of_device_id rockchip_dmc_dt_ids[] = {
 		.compatible = "rockchip,rk3568-dmc",
 		.data = &rk3568_drvdata,
 	},
+	{
+		.compatible = "rockchip,rk3588-dmc",
+		.data = &rk3568_drvdata,
+	},
 	{ /* sentinel */ }
 };
 
diff --git a/include/mach/rockchip/dmc.h b/include/mach/rockchip/dmc.h
index ff197d50a0..ed256f6daf 100644
--- a/include/mach/rockchip/dmc.h
+++ b/include/mach/rockchip/dmc.h
@@ -82,5 +82,6 @@ enum {
 
 resource_size_t rk3399_ram0_size(void);
 resource_size_t rk3568_ram0_size(void);
+resource_size_t rk3588_ram0_size(void);
 
 #endif
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 18/18] ARM: rockchip: Add Radxa ROCK 5B support
  2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
                   ` (16 preceding siblings ...)
  2023-05-04  8:17 ` [PATCH 17/18] ARM: rockchip: rk3588: add memsize detection Sascha Hauer
@ 2023-05-04  8:17 ` Sascha Hauer
  2023-05-04  9:36   ` Ahmad Fatoum
  17 siblings, 1 reply; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04  8:17 UTC (permalink / raw)
  To: Barebox List

Add support for the Radxa ROCK 5B board.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boards/Makefile               |   1 +
 arch/arm/boards/radxa-rock5/.gitignore |   1 +
 arch/arm/boards/radxa-rock5/Makefile   |   3 +
 arch/arm/boards/radxa-rock5/board.c    |  55 +++++++++++++
 arch/arm/boards/radxa-rock5/lowlevel.c |  25 ++++++
 arch/arm/dts/Makefile                  |   1 +
 arch/arm/dts/rk3588-rock-5b.dts        | 110 +++++++++++++++++++++++++
 arch/arm/mach-rockchip/Kconfig         |   6 ++
 images/Makefile.rockchip               |   7 ++
 9 files changed, 209 insertions(+)
 create mode 100644 arch/arm/boards/radxa-rock5/.gitignore
 create mode 100644 arch/arm/boards/radxa-rock5/Makefile
 create mode 100644 arch/arm/boards/radxa-rock5/board.c
 create mode 100644 arch/arm/boards/radxa-rock5/lowlevel.c
 create mode 100644 arch/arm/dts/rk3588-rock-5b.dts

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index b204c257f6..2877debad5 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -189,5 +189,6 @@ obj-$(CONFIG_MACH_RK3568_EVB)			+= rockchip-rk3568-evb/
 obj-$(CONFIG_MACH_RK3568_BPI_R2PRO)			+= rockchip-rk3568-bpi-r2pro/
 obj-$(CONFIG_MACH_PINE64_QUARTZ64)		+= pine64-quartz64/
 obj-$(CONFIG_MACH_RADXA_ROCK3)			+= radxa-rock3/
+obj-$(CONFIG_MACH_RADXA_ROCK5)			+= radxa-rock5/
 obj-$(CONFIG_MACH_VARISCITE_DT8MCUSTOMBOARD_IMX8MP)	+= variscite-dt8mcustomboard-imx8mp/
 obj-$(CONFIG_MACH_RADXA_CM3)			+= radxa-cm3/
diff --git a/arch/arm/boards/radxa-rock5/.gitignore b/arch/arm/boards/radxa-rock5/.gitignore
new file mode 100644
index 0000000000..f458f794b5
--- /dev/null
+++ b/arch/arm/boards/radxa-rock5/.gitignore
@@ -0,0 +1 @@
+sdram-init.bin
diff --git a/arch/arm/boards/radxa-rock5/Makefile b/arch/arm/boards/radxa-rock5/Makefile
new file mode 100644
index 0000000000..b37b6c870b
--- /dev/null
+++ b/arch/arm/boards/radxa-rock5/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += board.o
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/radxa-rock5/board.c b/arch/arm/boards/radxa-rock5/board.c
new file mode 100644
index 0000000000..369e73834d
--- /dev/null
+++ b/arch/arm/boards/radxa-rock5/board.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <bootsource.h>
+#include <common.h>
+#include <deep-probe.h>
+#include <init.h>
+#include <mach/rockchip/bbu.h>
+
+struct rock5_model {
+	const char *name;
+	const char *shortname;
+};
+
+static int rock5_probe(struct device *dev)
+{
+	enum bootsource bootsource = bootsource_get();
+	int instance = bootsource_get_instance();
+	const struct rock5_model *model;
+
+	model = device_get_match_data(dev);
+
+	barebox_set_model(model->name);
+	barebox_set_hostname(model->shortname);
+
+	if (bootsource == BOOTSOURCE_MMC && instance == 1)
+		of_device_enable_path("/chosen/environment-sd");
+	else
+		of_device_enable_path("/chosen/environment-emmc");
+
+	rk3568_bbu_mmc_register("emmc", BBU_HANDLER_FLAG_DEFAULT, "/dev/mmc0");
+	rk3568_bbu_mmc_register("sd", 0, "/dev/mmc1");
+
+	return 0;
+}
+
+static const struct rock5_model rock5b = {
+	.name = "Radxa ROCK5 Model B",
+	.shortname = "rock5b",
+};
+
+static const struct of_device_id rock5_of_match[] = {
+	{
+		.compatible = "radxa,rock-5b",
+		.data = &rock5b,
+	},
+	{ /* sentinel */ },
+};
+
+static struct driver rock5_board_driver = {
+	.name = "board-rock5",
+	.probe = rock5_probe,
+	.of_compatible = rock5_of_match,
+};
+coredevice_platform_driver(rock5_board_driver);
+
+BAREBOX_DEEP_PROBE_ENABLE(rock5_of_match);
diff --git a/arch/arm/boards/radxa-rock5/lowlevel.c b/arch/arm/boards/radxa-rock5/lowlevel.c
new file mode 100644
index 0000000000..6f0ac732cc
--- /dev/null
+++ b/arch/arm/boards/radxa-rock5/lowlevel.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <common.h>
+#include <linux/sizes.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <mach/rockchip/hardware.h>
+#include <mach/rockchip/atf.h>
+#include <debug_ll.h>
+#include <mach/rockchip/rockchip.h>
+
+extern char __dtb_rk3588_rock_5b_start[];
+
+ENTRY_FUNCTION(start_rock5b, r0, r1, r2)
+{
+	putc_ll('>');
+
+	if (current_el() == 3)
+		relocate_to_adr_full(RK3588_BAREBOX_LOAD_ADDRESS);
+	else
+		relocate_to_current_adr();
+
+	setup_c();
+
+	rk3588_barebox_entry(__dtb_rk3588_rock_5b_start);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 220e1617e3..98f4c4e019 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -109,6 +109,7 @@ lwl-$(CONFIG_MACH_PROTONIC_STM32MP1) += \
 	stm32mp151-prtt1s.dtb.o
 lwl-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o
 lwl-$(CONFIG_MACH_RADXA_ROCK3) += rk3568-rock-3a.dtb.o
+lwl-$(CONFIG_MACH_RADXA_ROCK5) += rk3588-rock-5b.dtb.o
 lwl-$(CONFIG_MACH_RADXA_CM3) += rk3566-cm3-io.dtb.o
 lwl-$(CONFIG_MACH_PHYTEC_SOM_RK3288) += rk3288-phycore-som.dtb.o
 lwl-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o
diff --git a/arch/arm/dts/rk3588-rock-5b.dts b/arch/arm/dts/rk3588-rock-5b.dts
new file mode 100644
index 0000000000..737498df3d
--- /dev/null
+++ b/arch/arm/dts/rk3588-rock-5b.dts
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <arm64/rockchip/rk3588-rock-5b.dts>
+#include "rk3588.dtsi"
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	aliases {
+		mmc1 = &sdmmc;
+	};
+
+	chosen: chosen {
+		environment-emmc {
+			compatible = "barebox,environment";
+			device-path = &environment_emmc;
+			status = "disabled";
+		};
+
+		environment-sd {
+			compatible = "barebox,environment";
+			device-path = &environment_sd;
+			status = "disabled";
+		};
+	};
+
+	vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_pcie2x1l2";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <5000>;
+	};
+
+	vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_pcie2x1l0";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		regulator-boot-on;
+		regulator-always-on;
+		gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <50000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc3v3_pcie30: vcc3v3-pcie30 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_pcie30";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <5000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+};
+
+&combphy0_ps {
+	status = "okay";
+};
+
+&pcie2x1l2 {
+	reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
+	vpcie3v3-supply = <&vcc3v3_pcie2x1l2>;
+	status = "okay";
+};
+
+/* Not yet working in barebox */
+&sdhci {
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		environment_emmc: partition@408000 {
+			label = "barebox-environment";
+			reg = <0x0 0x408000 0x0 0x8000>;
+		};
+	};
+};
+
+/* Not yet working in barebox */
+&sdmmc {
+	max-frequency = <200000000>;
+	no-sdio;
+	no-mmc;
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	disable-wp;
+	sd-uhs-sdr104;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_det>;
+	status = "okay";
+
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		environment_sd: partition@408000 {
+			label = "barebox-environment";
+			reg = <0x0 0x408000 0x0 0x8000>;
+		};
+	};
+};
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 7d540974f5..26b23b3214 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -97,6 +97,12 @@ config MACH_RADXA_ROCK3
        help
 	  Say Y here if you are using a Radxa ROCK3
 
+config MACH_RADXA_ROCK5
+       select ARCH_RK3588
+       bool "Radxa ROCK5"
+       help
+	  Say Y here if you are using a Radxa ROCK5
+
 config MACH_RADXA_CM3
 	select ARCH_RK3568
 	bool "Radxa CM3"
diff --git a/images/Makefile.rockchip b/images/Makefile.rockchip
index 490e1ddb4d..47779a7d35 100644
--- a/images/Makefile.rockchip
+++ b/images/Makefile.rockchip
@@ -23,6 +23,9 @@ image-$(CONFIG_MACH_PINE64_QUARTZ64) += barebox-quartz64a.img
 pblb-$(CONFIG_MACH_RADXA_ROCK3) += start_rock3a
 image-$(CONFIG_MACH_RADXA_ROCK3) += barebox-rock3a.img
 
+pblb-$(CONFIG_MACH_RADXA_ROCK5) += start_rock5b
+image-$(CONFIG_MACH_RADXA_ROCK5) += barebox-rock5b.img
+
 pblb-$(CONFIG_MACH_RADXA_CM3) += start_radxa-cm3-io.img
 image-$(CONFIG_MACH_RADXA_CM3) += barebox-radxa-cm3-io.img
 
@@ -45,6 +48,10 @@ $(obj)/barebox-rock3a.img: $(obj)/start_rock3a.pblb \
                 $(board)/radxa-rock3/sdram-init.bin
 	$(call if_changed,rkimg_image)
 
+$(obj)/barebox-rock5b.img: $(obj)/start_rock5b.pblb \
+                $(board)/radxa-rock5/sdram-init.bin
+	$(call if_changed,rkimg_image)
+
 $(obj)/barebox-radxa-cm3-io.img: $(obj)/start_radxa_cm3_io.pblb \
                 $(board)/radxa-cm3/sdram-init.bin
 	$(call if_changed,rkimg_image)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 18/18] ARM: rockchip: Add Radxa ROCK 5B support
  2023-05-04  8:17 ` [PATCH 18/18] ARM: rockchip: Add Radxa ROCK 5B support Sascha Hauer
@ 2023-05-04  9:36   ` Ahmad Fatoum
  2023-05-04 10:08     ` Sascha Hauer
  0 siblings, 1 reply; 21+ messages in thread
From: Ahmad Fatoum @ 2023-05-04  9:36 UTC (permalink / raw)
  To: Sascha Hauer, Barebox List

Hello Sascha,

On 04.05.23 10:17, Sascha Hauer wrote:
> Add support for the Radxa ROCK 5B board.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/boards/Makefile               |   1 +
>  arch/arm/boards/radxa-rock5/.gitignore |   1 +
>  arch/arm/boards/radxa-rock5/Makefile   |   3 +
>  arch/arm/boards/radxa-rock5/board.c    |  55 +++++++++++++
>  arch/arm/boards/radxa-rock5/lowlevel.c |  25 ++++++
>  arch/arm/dts/Makefile                  |   1 +
>  arch/arm/dts/rk3588-rock-5b.dts        | 110 +++++++++++++++++++++++++
>  arch/arm/mach-rockchip/Kconfig         |   6 ++
>  images/Makefile.rockchip               |   7 ++

Can you enable it in the appropriate defconfigs as well?

>  9 files changed, 209 insertions(+)
>  create mode 100644 arch/arm/boards/radxa-rock5/.gitignore
>  create mode 100644 arch/arm/boards/radxa-rock5/Makefile
>  create mode 100644 arch/arm/boards/radxa-rock5/board.c
>  create mode 100644 arch/arm/boards/radxa-rock5/lowlevel.c
>  create mode 100644 arch/arm/dts/rk3588-rock-5b.dts
> 
> diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
> index b204c257f6..2877debad5 100644
> --- a/arch/arm/boards/Makefile
> +++ b/arch/arm/boards/Makefile
> @@ -189,5 +189,6 @@ obj-$(CONFIG_MACH_RK3568_EVB)			+= rockchip-rk3568-evb/
>  obj-$(CONFIG_MACH_RK3568_BPI_R2PRO)			+= rockchip-rk3568-bpi-r2pro/
>  obj-$(CONFIG_MACH_PINE64_QUARTZ64)		+= pine64-quartz64/
>  obj-$(CONFIG_MACH_RADXA_ROCK3)			+= radxa-rock3/
> +obj-$(CONFIG_MACH_RADXA_ROCK5)			+= radxa-rock5/
>  obj-$(CONFIG_MACH_VARISCITE_DT8MCUSTOMBOARD_IMX8MP)	+= variscite-dt8mcustomboard-imx8mp/
>  obj-$(CONFIG_MACH_RADXA_CM3)			+= radxa-cm3/
> diff --git a/arch/arm/boards/radxa-rock5/.gitignore b/arch/arm/boards/radxa-rock5/.gitignore
> new file mode 100644
> index 0000000000..f458f794b5
> --- /dev/null
> +++ b/arch/arm/boards/radxa-rock5/.gitignore
> @@ -0,0 +1 @@
> +sdram-init.bin
> diff --git a/arch/arm/boards/radxa-rock5/Makefile b/arch/arm/boards/radxa-rock5/Makefile
> new file mode 100644
> index 0000000000..b37b6c870b
> --- /dev/null
> +++ b/arch/arm/boards/radxa-rock5/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-y += board.o
> +lwl-y += lowlevel.o
> diff --git a/arch/arm/boards/radxa-rock5/board.c b/arch/arm/boards/radxa-rock5/board.c
> new file mode 100644
> index 0000000000..369e73834d
> --- /dev/null
> +++ b/arch/arm/boards/radxa-rock5/board.c
> @@ -0,0 +1,55 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +#include <bootsource.h>
> +#include <common.h>
> +#include <deep-probe.h>
> +#include <init.h>
> +#include <mach/rockchip/bbu.h>
> +
> +struct rock5_model {
> +	const char *name;
> +	const char *shortname;
> +};
> +
> +static int rock5_probe(struct device *dev)
> +{
> +	enum bootsource bootsource = bootsource_get();
> +	int instance = bootsource_get_instance();
> +	const struct rock5_model *model;
> +
> +	model = device_get_match_data(dev);
> +
> +	barebox_set_model(model->name);

This can be set in the DT via /model.

> +	barebox_set_hostname(model->shortname);

This would be rock-5b with the current machine compatible.
Why set it in board code?

> +
> +	if (bootsource == BOOTSOURCE_MMC && instance == 1)
> +		of_device_enable_path("/chosen/environment-sd");
> +	else
> +		of_device_enable_path("/chosen/environment-emmc");
> +
> +	rk3568_bbu_mmc_register("emmc", BBU_HANDLER_FLAG_DEFAULT, "/dev/mmc0");
> +	rk3568_bbu_mmc_register("sd", 0, "/dev/mmc1");
> +
> +	return 0;
> +}
> +
> +static const struct rock5_model rock5b = {
> +	.name = "Radxa ROCK5 Model B",
> +	.shortname = "rock5b",
> +};
> +
> +static const struct of_device_id rock5_of_match[] = {
> +	{
> +		.compatible = "radxa,rock-5b",
> +		.data = &rock5b,
> +	},
> +	{ /* sentinel */ },
> +};
> +
> +static struct driver rock5_board_driver = {
> +	.name = "board-rock5",
> +	.probe = rock5_probe,
> +	.of_compatible = rock5_of_match,
> +};
> +coredevice_platform_driver(rock5_board_driver);
> +
> +BAREBOX_DEEP_PROBE_ENABLE(rock5_of_match);
> diff --git a/arch/arm/boards/radxa-rock5/lowlevel.c b/arch/arm/boards/radxa-rock5/lowlevel.c
> new file mode 100644
> index 0000000000..6f0ac732cc
> --- /dev/null
> +++ b/arch/arm/boards/radxa-rock5/lowlevel.c
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +#include <common.h>
> +#include <linux/sizes.h>
> +#include <asm/barebox-arm-head.h>
> +#include <asm/barebox-arm.h>
> +#include <mach/rockchip/hardware.h>
> +#include <mach/rockchip/atf.h>
> +#include <debug_ll.h>
> +#include <mach/rockchip/rockchip.h>
> +
> +extern char __dtb_rk3588_rock_5b_start[];
> +
> +ENTRY_FUNCTION(start_rock5b, r0, r1, r2)
> +{
> +	putc_ll('>');
> +
> +	if (current_el() == 3)
> +		relocate_to_adr_full(RK3588_BAREBOX_LOAD_ADDRESS);
> +	else
> +		relocate_to_current_adr();
> +
> +	setup_c();
> +
> +	rk3588_barebox_entry(__dtb_rk3588_rock_5b_start);
> +}
> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> index 220e1617e3..98f4c4e019 100644
> --- a/arch/arm/dts/Makefile
> +++ b/arch/arm/dts/Makefile
> @@ -109,6 +109,7 @@ lwl-$(CONFIG_MACH_PROTONIC_STM32MP1) += \
>  	stm32mp151-prtt1s.dtb.o
>  lwl-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o
>  lwl-$(CONFIG_MACH_RADXA_ROCK3) += rk3568-rock-3a.dtb.o
> +lwl-$(CONFIG_MACH_RADXA_ROCK5) += rk3588-rock-5b.dtb.o
>  lwl-$(CONFIG_MACH_RADXA_CM3) += rk3566-cm3-io.dtb.o
>  lwl-$(CONFIG_MACH_PHYTEC_SOM_RK3288) += rk3288-phycore-som.dtb.o
>  lwl-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o
> diff --git a/arch/arm/dts/rk3588-rock-5b.dts b/arch/arm/dts/rk3588-rock-5b.dts
> new file mode 100644
> index 0000000000..737498df3d
> --- /dev/null
> +++ b/arch/arm/dts/rk3588-rock-5b.dts
> @@ -0,0 +1,110 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +
> +/dts-v1/;
> +
> +#include <arm64/rockchip/rk3588-rock-5b.dts>
> +#include "rk3588.dtsi"
> +#include <dt-bindings/pinctrl/rockchip.h>
> +#include <dt-bindings/gpio/gpio.h>
> +
> +/ {
> +	aliases {
> +		mmc1 = &sdmmc;

Are there no aliases in the upstream DT? And why only
mmc1 and not mmc0?

> +	};
> +
> +	chosen: chosen {
> +		environment-emmc {
> +			compatible = "barebox,environment";
> +			device-path = &environment_emmc;
> +			status = "disabled";
> +		};
> +
> +		environment-sd {
> +			compatible = "barebox,environment";
> +			device-path = &environment_sd;
> +			status = "disabled";
> +		};
> +	};
> +
> +	vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "vcc3v3_pcie2x1l2";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		startup-delay-us = <5000>;
> +	};
> +
> +	vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "vcc3v3_pcie2x1l0";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		enable-active-high;
> +		regulator-boot-on;
> +		regulator-always-on;
> +		gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
> +		startup-delay-us = <50000>;
> +		vin-supply = <&vcc5v0_sys>;
> +	};
> +
> +	vcc3v3_pcie30: vcc3v3-pcie30 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "vcc3v3_pcie30";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		enable-active-high;
> +		gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
> +		startup-delay-us = <5000>;
> +		vin-supply = <&vcc5v0_sys>;
> +	};
> +};
> +
> +&combphy0_ps {
> +	status = "okay";
> +};
> +
> +&pcie2x1l2 {
> +	reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
> +	vpcie3v3-supply = <&vcc3v3_pcie2x1l2>;
> +	status = "okay";
> +};
> +
> +/* Not yet working in barebox */
> +&sdhci {
> +	partitions {
> +		compatible = "fixed-partitions";
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +
> +		environment_emmc: partition@408000 {
> +			label = "barebox-environment";
> +			reg = <0x0 0x408000 0x0 0x8000>;
> +		};
> +	};
> +};
> +
> +/* Not yet working in barebox */
> +&sdmmc {
> +	max-frequency = <200000000>;
> +	no-sdio;
> +	no-mmc;
> +	bus-width = <4>;
> +	cap-mmc-highspeed;
> +	cap-sd-highspeed;
> +	disable-wp;
> +	sd-uhs-sdr104;
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_det>;
> +	status = "okay";
> +
> +	partitions {
> +		compatible = "fixed-partitions";
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +
> +		environment_sd: partition@408000 {
> +			label = "barebox-environment";
> +			reg = <0x0 0x408000 0x0 0x8000>;
> +		};
> +	};
> +};
> diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
> index 7d540974f5..26b23b3214 100644
> --- a/arch/arm/mach-rockchip/Kconfig
> +++ b/arch/arm/mach-rockchip/Kconfig
> @@ -97,6 +97,12 @@ config MACH_RADXA_ROCK3
>         help
>  	  Say Y here if you are using a Radxa ROCK3
>  
> +config MACH_RADXA_ROCK5
> +       select ARCH_RK3588
> +       bool "Radxa ROCK5"
> +       help
> +	  Say Y here if you are using a Radxa ROCK5
> +
>  config MACH_RADXA_CM3
>  	select ARCH_RK3568
>  	bool "Radxa CM3"
> diff --git a/images/Makefile.rockchip b/images/Makefile.rockchip
> index 490e1ddb4d..47779a7d35 100644
> --- a/images/Makefile.rockchip
> +++ b/images/Makefile.rockchip
> @@ -23,6 +23,9 @@ image-$(CONFIG_MACH_PINE64_QUARTZ64) += barebox-quartz64a.img
>  pblb-$(CONFIG_MACH_RADXA_ROCK3) += start_rock3a
>  image-$(CONFIG_MACH_RADXA_ROCK3) += barebox-rock3a.img
>  
> +pblb-$(CONFIG_MACH_RADXA_ROCK5) += start_rock5b
> +image-$(CONFIG_MACH_RADXA_ROCK5) += barebox-rock5b.img
> +
>  pblb-$(CONFIG_MACH_RADXA_CM3) += start_radxa-cm3-io.img
>  image-$(CONFIG_MACH_RADXA_CM3) += barebox-radxa-cm3-io.img
>  
> @@ -45,6 +48,10 @@ $(obj)/barebox-rock3a.img: $(obj)/start_rock3a.pblb \
>                  $(board)/radxa-rock3/sdram-init.bin
>  	$(call if_changed,rkimg_image)
>  
> +$(obj)/barebox-rock5b.img: $(obj)/start_rock5b.pblb \
> +                $(board)/radxa-rock5/sdram-init.bin
> +	$(call if_changed,rkimg_image)
> +
>  $(obj)/barebox-radxa-cm3-io.img: $(obj)/start_radxa_cm3_io.pblb \
>                  $(board)/radxa-cm3/sdram-init.bin
>  	$(call if_changed,rkimg_image)

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |




^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 18/18] ARM: rockchip: Add Radxa ROCK 5B support
  2023-05-04  9:36   ` Ahmad Fatoum
@ 2023-05-04 10:08     ` Sascha Hauer
  0 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2023-05-04 10:08 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: Barebox List

On Thu, May 04, 2023 at 11:36:55AM +0200, Ahmad Fatoum wrote:
> Hello Sascha,
> 
> On 04.05.23 10:17, Sascha Hauer wrote:
> > Add support for the Radxa ROCK 5B board.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm/boards/Makefile               |   1 +
> >  arch/arm/boards/radxa-rock5/.gitignore |   1 +
> >  arch/arm/boards/radxa-rock5/Makefile   |   3 +
> >  arch/arm/boards/radxa-rock5/board.c    |  55 +++++++++++++
> >  arch/arm/boards/radxa-rock5/lowlevel.c |  25 ++++++
> >  arch/arm/dts/Makefile                  |   1 +
> >  arch/arm/dts/rk3588-rock-5b.dts        | 110 +++++++++++++++++++++++++
> >  arch/arm/mach-rockchip/Kconfig         |   6 ++
> >  images/Makefile.rockchip               |   7 ++
> 
> Can you enable it in the appropriate defconfigs as well?

Yes, sure.

> > +static int rock5_probe(struct device *dev)
> > +{
> > +	enum bootsource bootsource = bootsource_get();
> > +	int instance = bootsource_get_instance();
> > +	const struct rock5_model *model;
> > +
> > +	model = device_get_match_data(dev);
> > +
> > +	barebox_set_model(model->name);
> 
> This can be set in the DT via /model.
> 
> > +	barebox_set_hostname(model->shortname);
> 
> This would be rock-5b with the current machine compatible.
> Why set it in board code?

Wrong template copied. I'll just remove these lines.

> > +#include <arm64/rockchip/rk3588-rock-5b.dts>
> > +#include "rk3588.dtsi"
> > +#include <dt-bindings/pinctrl/rockchip.h>
> > +#include <dt-bindings/gpio/gpio.h>
> > +
> > +/ {
> > +	aliases {
> > +		mmc1 = &sdmmc;
> 
> Are there no aliases in the upstream DT? And why only
> mmc1 and not mmc0?

The upstream dts has:

		mmc0 = &sdhci;

sdmmc is not yet supported upstream, it's added in
arch/arm/dts/rk3588s.dtsi.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2023-05-04 10:10 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-04  8:17 [PATCH 00/18] Add Rockchip RK3588 support Sascha Hauer
2023-05-04  8:17 ` [PATCH 01/18] firmware: make drivers/firmware/ obj-y Sascha Hauer
2023-05-04  8:17 ` [PATCH 02/18] stddef: add sizeof_field() Sascha Hauer
2023-05-04  8:17 ` [PATCH 03/18] pci: add pci_select_bars() helper Sascha Hauer
2023-05-04  8:17 ` [PATCH 04/18] pci: set upper word for 64bit base addresses Sascha Hauer
2023-05-04  8:17 ` [PATCH 05/18] ARM: SCMI: Use correct smc/hvc instructions on ARM64 Sascha Hauer
2023-05-04  8:17 ` [PATCH 06/18] clk: rockchip: Add rk3588 support Sascha Hauer
2023-05-04  8:17 ` [PATCH 07/18] pinctrl: rockchip: Move struct definitions to separate header file Sascha Hauer
2023-05-04  8:17 ` [PATCH 08/18] pinctrl/gpio: rockchip: separate gpio from pinctrl driver Sascha Hauer
2023-05-04  8:17 ` [PATCH 09/18] pinctrl: Update pinctrl-rockchip from kernel Sascha Hauer
2023-05-04  8:17 ` [PATCH 10/18] phy: rockchip: naneng-combphy: add rk3588 support Sascha Hauer
2023-05-04  8:17 ` [PATCH 11/18] reset: Implement reset array support Sascha Hauer
2023-05-04  8:17 ` [PATCH 12/18] pci: designware: add rockchip support Sascha Hauer
2023-05-04  8:17 ` [PATCH 13/18] phy: realtek: Add RTL8125 internal phy support Sascha Hauer
2023-05-04  8:17 ` [PATCH 14/18] net: Update Realtek r8169 driver Sascha Hauer
2023-05-04  8:17 ` [PATCH 15/18] ARM: rockchip: Add rk3588 support Sascha Hauer
2023-05-04  8:17 ` [PATCH 16/18] ARM: dts: Add rk3588 device trees Sascha Hauer
2023-05-04  8:17 ` [PATCH 17/18] ARM: rockchip: rk3588: add memsize detection Sascha Hauer
2023-05-04  8:17 ` [PATCH 18/18] ARM: rockchip: Add Radxa ROCK 5B support Sascha Hauer
2023-05-04  9:36   ` Ahmad Fatoum
2023-05-04 10:08     ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox