+++ /dev/null
-From 99a186dbbbc9869d705fb3c189bcafc87c3bfe75 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Thu, 19 Jan 2023 23:40:20 +0000
-Subject: [PATCH 4000/4031] ARM: dts: sun8i: a83t: bananapi-m3: describe SATA
- disk regulator
-
-The Bananapi-M3 has a SATA connector, driven by a USB-to-SATA bridge
-soldered on the board. The power for the SATA device is provided by a
-GPIO controlled regulator. Since the SATA device is behind USB, it has
-no DT node, so we never described this regulator. Instead U-Boot was
-turning this on in a rather hackish way, which we now want to get rid of.
-On top of that it seems fragile to leave this GPIO undescribed, as
-userland could claim it and turn the disk off.
-
-Add a fixed regulator, controlled by the PD25 GPIO, and mark it as
-always-on. This would mimic the current situation, but in a safer way,
-and would allow U-Boot to drop the CONFIG_SATAPWR enable hack.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/dts/sun8i-a83t-bananapi-m3.dts | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-diff --git a/arch/arm/dts/sun8i-a83t-bananapi-m3.dts b/arch/arm/dts/sun8i-a83t-bananapi-m3.dts
-index b60016a442..197cf6959b 100644
---- a/arch/arm/dts/sun8i-a83t-bananapi-m3.dts
-+++ b/arch/arm/dts/sun8i-a83t-bananapi-m3.dts
-@@ -105,6 +105,21 @@
- /* enables internal regulator and de-asserts reset */
- reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 WL-PMU-EN */
- };
-+
-+ /*
-+ * Power supply for the SATA disk, behind a USB-SATA bridge.
-+ * Since it is a USB device, there is no consumer in the DT, so we
-+ * have to keep this always on.
-+ */
-+ regulator-sata-disk-pwr {
-+ compatible = "regulator-fixed";
-+ regulator-name = "sata-disk-pwr";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ regulator-always-on;
-+ enable-active-high;
-+ gpio = <&pio 3 25 GPIO_ACTIVE_HIGH>; /* PD25 */
-+ };
- };
-
- &cpu0 {
---
-2.20.1
-
--- /dev/null
+From cb7c055953c65ce4b532e3548fb6676515c1c1b9 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 15 Jul 2022 16:52:14 +0100
+Subject: [PATCH 4000/4044] sunxi: remove CONFIG_SATAPWR
+
+The CONFIG_SATAPWR Kconfig symbol was used to point to a GPIO that
+enables the power for a SATA harddisk.
+In the DT this is described with the target-supply property in the AHCI
+DT node, pointing to a (GPIO controlled) regulator. Since we need SATA
+only in U-Boot proper, and use a DM driver for AHCI there, we should use
+the DT instead of hardcoding this.
+
+Add code to the sunxi AHCI driver to check the DT for that regulator and
+enable it, at probe time. Then drop the current code from board.c, which
+was doing that job before.
+This allows us to remove the SATAPWR Kconfig definition and the
+respective values from the defconfigs.
+We also select the generic fixed regulator driver, which handles those
+GPIO controlled regulators.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/Kconfig | 2 ++
+ arch/arm/mach-sunxi/Kconfig | 8 --------
+ board/sunxi/board.c | 16 +---------------
+ configs/A10-OLinuXino-Lime_defconfig | 1 -
+ configs/A20-OLinuXino-Lime2-eMMC_defconfig | 1 -
+ configs/A20-OLinuXino-Lime2_defconfig | 1 -
+ configs/A20-OLinuXino-Lime_defconfig | 1 -
+ configs/A20-OLinuXino_MICRO-eMMC_defconfig | 1 -
+ configs/A20-OLinuXino_MICRO_defconfig | 1 -
+ configs/A20-Olimex-SOM-EVB_defconfig | 1 -
+ configs/A20-Olimex-SOM204-EVB-eMMC_defconfig | 1 -
+ configs/A20-Olimex-SOM204-EVB_defconfig | 1 -
+ configs/Cubieboard2_defconfig | 1 -
+ configs/Cubieboard_defconfig | 1 -
+ configs/Cubietruck_defconfig | 1 -
+ configs/Itead_Ibox_A20_defconfig | 1 -
+ configs/Lamobo_R1_defconfig | 1 -
+ configs/Linksprite_pcDuino3_Nano_defconfig | 1 -
+ configs/Linksprite_pcDuino3_defconfig | 1 -
+ configs/Sinovoip_BPI_M3_defconfig | 1 -
+ configs/orangepi_plus_defconfig | 2 +-
+ drivers/ata/ahci_sunxi.c | 9 +++++++++
+ 22 files changed, 13 insertions(+), 41 deletions(-)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 8a1e223422..d5a6d293ce 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1130,6 +1130,8 @@ config ARCH_SUNXI
+ imply CMD_GPT
+ imply CMD_UBI if MTD_RAW_NAND
+ imply DISTRO_DEFAULTS
++ imply DM_REGULATOR
++ imply DM_REGULATOR_FIXED
+ imply FAT_WRITE
+ imply FIT
+ imply OF_LIBFDT_OVERLAY
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index 6417aee944..c78a553493 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -958,14 +958,6 @@ config VIDEO_LCD_TL059WV5C0
+
+ endchoice
+
+-config SATAPWR
+- string "SATA power pin"
+- default ""
+- help
+- Set the pins used to power the SATA. This takes a string in the
+- format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of
+- port H.
+-
+ config GMAC_TX_DELAY
+ int "GMAC Transmit Clock Delay Chain"
+ default 0
+diff --git a/board/sunxi/board.c b/board/sunxi/board.c
+index 827e545032..fe0e7bc2d9 100644
+--- a/board/sunxi/board.c
++++ b/board/sunxi/board.c
+@@ -187,7 +187,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
+ /* add board specific code here */
+ int board_init(void)
+ {
+- __maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
++ __maybe_unused int id_pfr1, ret, macpwr_pin;
+
+ gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
+
+@@ -225,20 +225,6 @@ int board_init(void)
+ return ret;
+
+ /* strcmp() would look better, but doesn't get optimised away. */
+- if (CONFIG_SATAPWR[0]) {
+- satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
+- if (satapwr_pin >= 0) {
+- gpio_request(satapwr_pin, "satapwr");
+- gpio_direction_output(satapwr_pin, 1);
+-
+- /*
+- * Give the attached SATA device time to power-up
+- * to avoid link timeouts
+- */
+- mdelay(500);
+- }
+- }
+-
+ if (CONFIG_MACPWR[0]) {
+ macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
+ if (macpwr_pin >= 0) {
+diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
+index df4fdfaba4..57e91d0f01 100644
+--- a/configs/A10-OLinuXino-Lime_defconfig
++++ b/configs/A10-OLinuXino-Lime_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=480
+ CONFIG_DRAM_EMR1=4
+ CONFIG_SYS_CLK_FREQ=912000000
+ CONFIG_I2C1_ENABLE=y
+-CONFIG_SATAPWR="PC3"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+index be49e9323a..44770ffb04 100644
+--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
++++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB0_VBUS_PIN="PC17"
+ CONFIG_USB0_VBUS_DET="PH5"
+ CONFIG_I2C1_ENABLE=y
+-CONFIG_SATAPWR="PC3"
+ CONFIG_SPL_SPI_SUNXI=y
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
+index 43cd28c3dd..e10660c933 100644
+--- a/configs/A20-OLinuXino-Lime2_defconfig
++++ b/configs/A20-OLinuXino-Lime2_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
+ CONFIG_USB0_VBUS_PIN="PC17"
+ CONFIG_USB0_VBUS_DET="PH5"
+ CONFIG_I2C1_ENABLE=y
+-CONFIG_SATAPWR="PC3"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
+index 7c77f38fba..4ed666a034 100644
+--- a/configs/A20-OLinuXino-Lime_defconfig
++++ b/configs/A20-OLinuXino-Lime_defconfig
+@@ -5,7 +5,6 @@ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=384
+ CONFIG_I2C1_ENABLE=y
+-CONFIG_SATAPWR="PC3"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
+index 02116995a3..ca5869f43d 100644
+--- a/configs/A20-OLinuXino_MICRO-eMMC_defconfig
++++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_I2C1_ENABLE=y
+ CONFIG_VIDEO_VGA=y
+-CONFIG_SATAPWR="PB8"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
+index 895e8dbcbd..db4270f9b2 100644
+--- a/configs/A20-OLinuXino_MICRO_defconfig
++++ b/configs/A20-OLinuXino_MICRO_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=3
+ CONFIG_I2C1_ENABLE=y
+ CONFIG_VIDEO_VGA=y
+-CONFIG_SATAPWR="PB8"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig
+index 5bcc9f9f3c..ac900477d1 100644
+--- a/configs/A20-Olimex-SOM-EVB_defconfig
++++ b/configs/A20-Olimex-SOM-EVB_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=3
+ CONFIG_USB0_VBUS_PIN="PB9"
+ CONFIG_USB0_VBUS_DET="PH5"
+-CONFIG_SATAPWR="PC3"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
+index e5881090dd..00a98140b3 100644
+--- a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
++++ b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
+@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB0_VBUS_PIN="PC17"
+ CONFIG_USB0_VBUS_DET="PH5"
+ CONFIG_I2C1_ENABLE=y
+-CONFIG_SATAPWR="PC3"
+ CONFIG_GMAC_TX_DELAY=4
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
+index 592a79a6c7..f4ae3ae6d8 100644
+--- a/configs/A20-Olimex-SOM204-EVB_defconfig
++++ b/configs/A20-Olimex-SOM204-EVB_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
+ CONFIG_USB0_VBUS_PIN="PC17"
+ CONFIG_USB0_VBUS_DET="PH5"
+ CONFIG_I2C1_ENABLE=y
+-CONFIG_SATAPWR="PC3"
+ CONFIG_GMAC_TX_DELAY=4
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
+index 0c23368741..ef4f11b7c6 100644
+--- a/configs/Cubieboard2_defconfig
++++ b/configs/Cubieboard2_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-cubieboard2"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=480
+-CONFIG_SATAPWR="PB8"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
+index 71743f7b8a..ab3f65ad66 100644
+--- a/configs/Cubieboard_defconfig
++++ b/configs/Cubieboard_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-cubieboard"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN4I=y
+ CONFIG_DRAM_CLK=480
+-CONFIG_SATAPWR="PB8"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
+index 184f305b19..184143d708 100644
+--- a/configs/Cubietruck_defconfig
++++ b/configs/Cubietruck_defconfig
+@@ -8,7 +8,6 @@ CONFIG_USB0_VBUS_PIN="PH17"
+ CONFIG_USB0_VBUS_DET="PH22"
+ CONFIG_USB0_ID_DET="PH19"
+ CONFIG_VIDEO_VGA=y
+-CONFIG_SATAPWR="PH12"
+ CONFIG_GMAC_TX_DELAY=1
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
+index 5d05f33798..d03fa62196 100644
+--- a/configs/Itead_Ibox_A20_defconfig
++++ b/configs/Itead_Ibox_A20_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-itead-ibox"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=480
+-CONFIG_SATAPWR="PB8"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
+index 5294608459..9639cb6aad 100644
+--- a/configs/Lamobo_R1_defconfig
++++ b/configs/Lamobo_R1_defconfig
+@@ -5,7 +5,6 @@ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=432
+ CONFIG_MACPWR="PH23"
+-CONFIG_SATAPWR="PB3"
+ CONFIG_GMAC_TX_DELAY=4
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
+index e3e30a4949..9eb9a918ae 100644
+--- a/configs/Linksprite_pcDuino3_Nano_defconfig
++++ b/configs/Linksprite_pcDuino3_Nano_defconfig
+@@ -6,7 +6,6 @@ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=408
+ CONFIG_DRAM_ZQ=122
+ CONFIG_USB1_VBUS_PIN="PH11"
+-CONFIG_SATAPWR="PH2"
+ CONFIG_GMAC_TX_DELAY=3
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
+index 1fda0db4c9..7db10e685b 100644
+--- a/configs/Linksprite_pcDuino3_defconfig
++++ b/configs/Linksprite_pcDuino3_defconfig
+@@ -5,7 +5,6 @@ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=480
+ CONFIG_DRAM_ZQ=122
+-CONFIG_SATAPWR="PH2"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
+index 5116fab52d..5545b3d464 100644
+--- a/configs/Sinovoip_BPI_M3_defconfig
++++ b/configs/Sinovoip_BPI_M3_defconfig
+@@ -13,7 +13,6 @@ CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
+ CONFIG_USB0_ID_DET="PH11"
+ CONFIG_USB1_VBUS_PIN="PD24"
+ CONFIG_AXP_GPIO=y
+-CONFIG_SATAPWR="PD25"
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_CONSOLE_MUX=y
+ CONFIG_PHY_REALTEK=y
+diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
+index 76de72aa22..ed585881d4 100644
+--- a/configs/orangepi_plus_defconfig
++++ b/configs/orangepi_plus_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=672
+ CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB1_VBUS_PIN="PG13"
+-CONFIG_SATAPWR="PG11"
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+ CONFIG_SPL_SYS_I2C_LEGACY=y
+@@ -16,3 +15,4 @@ CONFIG_SUN8I_EMAC=y
+ CONFIG_SY8106A_POWER=y
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_USB_OHCI_HCD=y
++CONFIG_USB3_VBUS_PIN="PG11"
+diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
+index 94a3379c53..9064774e66 100644
+--- a/drivers/ata/ahci_sunxi.c
++++ b/drivers/ata/ahci_sunxi.c
+@@ -7,6 +7,7 @@
+ #include <asm/io.h>
+ #include <asm/gpio.h>
+ #include <linux/delay.h>
++#include <power/regulator.h>
+
+ #define AHCI_PHYCS0R 0x00c0
+ #define AHCI_PHYCS1R 0x00c4
+@@ -74,6 +75,7 @@ static int sunxi_ahci_phy_init(u8 *reg_base)
+
+ static int sunxi_sata_probe(struct udevice *dev)
+ {
++ struct udevice *reg_dev;
+ ulong base;
+ u8 *reg;
+ int ret;
+@@ -89,6 +91,13 @@ static int sunxi_sata_probe(struct udevice *dev)
+ debug("%s: Failed to init phy (err=%d)\n", __func__, ret);
+ return ret;
+ }
++
++ ret = device_get_supply_regulator(dev, "target-supply", ®_dev);
++ if (ret == 0) {
++ regulator_set_enable(reg_dev, true);
++ mdelay(500);
++ }
++
+ ret = ahci_probe_scsi(dev, base);
+ if (ret) {
+ debug("%s: Failed to probe (err=%d)\n", __func__, ret);
+--
+2.20.1
+
--- /dev/null
+From b68b48654248dedb7127631003a206cbfe7c5a2c Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marek.vasut+renesas@mailbox.org>
+Date: Wed, 31 May 2023 00:51:24 +0200
+Subject: [PATCH 4001/4044] net: sunxi_emac: Switch to new U-Boot PHY API
+
+Use new U-Boot phy_connect() API which also supports fixed PHYs.
+
+Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
+Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
+---
+ drivers/net/sunxi_emac.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
+index ad9e1abd16..4c90d4b498 100644
+--- a/drivers/net/sunxi_emac.c
++++ b/drivers/net/sunxi_emac.c
+@@ -248,10 +248,10 @@ static int emac_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+
+ static int sunxi_emac_init_phy(struct emac_eth_dev *priv, void *dev)
+ {
+- int ret, mask = 0xffffffff;
++ int ret, mask = -1;
+
+ #ifdef CONFIG_PHY_ADDR
+- mask = 1 << CONFIG_PHY_ADDR;
++ mask = CONFIG_PHY_ADDR;
+ #endif
+
+ priv->bus = mdio_alloc();
+@@ -269,11 +269,10 @@ static int sunxi_emac_init_phy(struct emac_eth_dev *priv, void *dev)
+ if (ret)
+ return ret;
+
+- priv->phydev = phy_find_by_mask(priv->bus, mask);
++ priv->phydev = phy_connect(priv->bus, mask, dev, PHY_INTERFACE_MODE_MII);
+ if (!priv->phydev)
+ return -ENODEV;
+
+- phy_connect_dev(priv->phydev, dev, PHY_INTERFACE_MODE_MII);
+ phy_config(priv->phydev);
+
+ return 0;
+--
+2.20.1
+
+++ /dev/null
-From f79b84dca3597605c29793ad69ada86d5932d8cb Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Fri, 15 Jul 2022 16:52:14 +0100
-Subject: [PATCH 4001/4031] sunxi: remove CONFIG_SATAPWR
-
-The CONFIG_SATAPWR Kconfig symbol was used to point to a GPIO that
-enables the power for a SATA harddisk.
-In the DT this is described with the target-supply property in the AHCI
-DT node, pointing to a (GPIO controlled) regulator. Since we need SATA
-only in U-Boot proper, and use a DM driver for AHCI there, we should use
-the DT instead of hardcoding this.
-
-Add code to the sunxi AHCI driver to check the DT for that regulator and
-enable it, at probe time. Then drop the current code from board.c, which
-was doing that job before.
-This allows us to remove the SATAPWR Kconfig definition and the
-respective values from the defconfigs.
-We also select the generic fixed regulator driver, which handles those
-GPIO controlled regulators.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/Kconfig | 2 ++
- arch/arm/mach-sunxi/Kconfig | 8 --------
- board/sunxi/board.c | 16 +---------------
- configs/A10-OLinuXino-Lime_defconfig | 1 -
- configs/A20-OLinuXino-Lime2-eMMC_defconfig | 1 -
- configs/A20-OLinuXino-Lime2_defconfig | 1 -
- configs/A20-OLinuXino-Lime_defconfig | 1 -
- configs/A20-OLinuXino_MICRO-eMMC_defconfig | 1 -
- configs/A20-OLinuXino_MICRO_defconfig | 1 -
- configs/A20-Olimex-SOM-EVB_defconfig | 1 -
- configs/A20-Olimex-SOM204-EVB-eMMC_defconfig | 1 -
- configs/A20-Olimex-SOM204-EVB_defconfig | 1 -
- configs/Cubieboard2_defconfig | 1 -
- configs/Cubieboard_defconfig | 1 -
- configs/Cubietruck_defconfig | 1 -
- configs/Itead_Ibox_A20_defconfig | 1 -
- configs/Lamobo_R1_defconfig | 1 -
- configs/Linksprite_pcDuino3_Nano_defconfig | 1 -
- configs/Linksprite_pcDuino3_defconfig | 1 -
- configs/Sinovoip_BPI_M3_defconfig | 1 -
- configs/orangepi_plus_defconfig | 2 +-
- drivers/ata/ahci_sunxi.c | 9 +++++++++
- 22 files changed, 13 insertions(+), 41 deletions(-)
-
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index 8a1e223422..d5a6d293ce 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -1130,6 +1130,8 @@ config ARCH_SUNXI
- imply CMD_GPT
- imply CMD_UBI if MTD_RAW_NAND
- imply DISTRO_DEFAULTS
-+ imply DM_REGULATOR
-+ imply DM_REGULATOR_FIXED
- imply FAT_WRITE
- imply FIT
- imply OF_LIBFDT_OVERLAY
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index 6417aee944..c78a553493 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -958,14 +958,6 @@ config VIDEO_LCD_TL059WV5C0
-
- endchoice
-
--config SATAPWR
-- string "SATA power pin"
-- default ""
-- help
-- Set the pins used to power the SATA. This takes a string in the
-- format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of
-- port H.
--
- config GMAC_TX_DELAY
- int "GMAC Transmit Clock Delay Chain"
- default 0
-diff --git a/board/sunxi/board.c b/board/sunxi/board.c
-index 827e545032..fe0e7bc2d9 100644
---- a/board/sunxi/board.c
-+++ b/board/sunxi/board.c
-@@ -187,7 +187,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
- /* add board specific code here */
- int board_init(void)
- {
-- __maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
-+ __maybe_unused int id_pfr1, ret, macpwr_pin;
-
- gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
-
-@@ -225,20 +225,6 @@ int board_init(void)
- return ret;
-
- /* strcmp() would look better, but doesn't get optimised away. */
-- if (CONFIG_SATAPWR[0]) {
-- satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
-- if (satapwr_pin >= 0) {
-- gpio_request(satapwr_pin, "satapwr");
-- gpio_direction_output(satapwr_pin, 1);
--
-- /*
-- * Give the attached SATA device time to power-up
-- * to avoid link timeouts
-- */
-- mdelay(500);
-- }
-- }
--
- if (CONFIG_MACPWR[0]) {
- macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
- if (macpwr_pin >= 0) {
-diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
-index df4fdfaba4..57e91d0f01 100644
---- a/configs/A10-OLinuXino-Lime_defconfig
-+++ b/configs/A10-OLinuXino-Lime_defconfig
-@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=480
- CONFIG_DRAM_EMR1=4
- CONFIG_SYS_CLK_FREQ=912000000
- CONFIG_I2C1_ENABLE=y
--CONFIG_SATAPWR="PC3"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
-index be49e9323a..44770ffb04 100644
---- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
-+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
-@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_USB0_VBUS_PIN="PC17"
- CONFIG_USB0_VBUS_DET="PH5"
- CONFIG_I2C1_ENABLE=y
--CONFIG_SATAPWR="PC3"
- CONFIG_SPL_SPI_SUNXI=y
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
-index 43cd28c3dd..e10660c933 100644
---- a/configs/A20-OLinuXino-Lime2_defconfig
-+++ b/configs/A20-OLinuXino-Lime2_defconfig
-@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
- CONFIG_USB0_VBUS_PIN="PC17"
- CONFIG_USB0_VBUS_DET="PH5"
- CONFIG_I2C1_ENABLE=y
--CONFIG_SATAPWR="PC3"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
-index 7c77f38fba..4ed666a034 100644
---- a/configs/A20-OLinuXino-Lime_defconfig
-+++ b/configs/A20-OLinuXino-Lime_defconfig
-@@ -5,7 +5,6 @@ CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=384
- CONFIG_I2C1_ENABLE=y
--CONFIG_SATAPWR="PC3"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
-index 02116995a3..ca5869f43d 100644
---- a/configs/A20-OLinuXino_MICRO-eMMC_defconfig
-+++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
-@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_I2C1_ENABLE=y
- CONFIG_VIDEO_VGA=y
--CONFIG_SATAPWR="PB8"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
-index 895e8dbcbd..db4270f9b2 100644
---- a/configs/A20-OLinuXino_MICRO_defconfig
-+++ b/configs/A20-OLinuXino_MICRO_defconfig
-@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
- CONFIG_MMC_SUNXI_SLOT_EXTRA=3
- CONFIG_I2C1_ENABLE=y
- CONFIG_VIDEO_VGA=y
--CONFIG_SATAPWR="PB8"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig
-index 5bcc9f9f3c..ac900477d1 100644
---- a/configs/A20-Olimex-SOM-EVB_defconfig
-+++ b/configs/A20-Olimex-SOM-EVB_defconfig
-@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
- CONFIG_MMC_SUNXI_SLOT_EXTRA=3
- CONFIG_USB0_VBUS_PIN="PB9"
- CONFIG_USB0_VBUS_DET="PH5"
--CONFIG_SATAPWR="PC3"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
-index e5881090dd..00a98140b3 100644
---- a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
-+++ b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
-@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_USB0_VBUS_PIN="PC17"
- CONFIG_USB0_VBUS_DET="PH5"
- CONFIG_I2C1_ENABLE=y
--CONFIG_SATAPWR="PC3"
- CONFIG_GMAC_TX_DELAY=4
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
-index 592a79a6c7..f4ae3ae6d8 100644
---- a/configs/A20-Olimex-SOM204-EVB_defconfig
-+++ b/configs/A20-Olimex-SOM204-EVB_defconfig
-@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
- CONFIG_USB0_VBUS_PIN="PC17"
- CONFIG_USB0_VBUS_DET="PH5"
- CONFIG_I2C1_ENABLE=y
--CONFIG_SATAPWR="PC3"
- CONFIG_GMAC_TX_DELAY=4
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
-index 0c23368741..ef4f11b7c6 100644
---- a/configs/Cubieboard2_defconfig
-+++ b/configs/Cubieboard2_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-cubieboard2"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=480
--CONFIG_SATAPWR="PB8"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
-index 71743f7b8a..ab3f65ad66 100644
---- a/configs/Cubieboard_defconfig
-+++ b/configs/Cubieboard_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-cubieboard"
- CONFIG_SPL=y
- CONFIG_MACH_SUN4I=y
- CONFIG_DRAM_CLK=480
--CONFIG_SATAPWR="PB8"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
-index 184f305b19..184143d708 100644
---- a/configs/Cubietruck_defconfig
-+++ b/configs/Cubietruck_defconfig
-@@ -8,7 +8,6 @@ CONFIG_USB0_VBUS_PIN="PH17"
- CONFIG_USB0_VBUS_DET="PH22"
- CONFIG_USB0_ID_DET="PH19"
- CONFIG_VIDEO_VGA=y
--CONFIG_SATAPWR="PH12"
- CONFIG_GMAC_TX_DELAY=1
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
-index 5d05f33798..d03fa62196 100644
---- a/configs/Itead_Ibox_A20_defconfig
-+++ b/configs/Itead_Ibox_A20_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-itead-ibox"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=480
--CONFIG_SATAPWR="PB8"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
-index 5294608459..9639cb6aad 100644
---- a/configs/Lamobo_R1_defconfig
-+++ b/configs/Lamobo_R1_defconfig
-@@ -5,7 +5,6 @@ CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=432
- CONFIG_MACPWR="PH23"
--CONFIG_SATAPWR="PB3"
- CONFIG_GMAC_TX_DELAY=4
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
-index e3e30a4949..9eb9a918ae 100644
---- a/configs/Linksprite_pcDuino3_Nano_defconfig
-+++ b/configs/Linksprite_pcDuino3_Nano_defconfig
-@@ -6,7 +6,6 @@ CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=408
- CONFIG_DRAM_ZQ=122
- CONFIG_USB1_VBUS_PIN="PH11"
--CONFIG_SATAPWR="PH2"
- CONFIG_GMAC_TX_DELAY=3
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
-index 1fda0db4c9..7db10e685b 100644
---- a/configs/Linksprite_pcDuino3_defconfig
-+++ b/configs/Linksprite_pcDuino3_defconfig
-@@ -5,7 +5,6 @@ CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=480
- CONFIG_DRAM_ZQ=122
--CONFIG_SATAPWR="PH2"
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
-index 5116fab52d..5545b3d464 100644
---- a/configs/Sinovoip_BPI_M3_defconfig
-+++ b/configs/Sinovoip_BPI_M3_defconfig
-@@ -13,7 +13,6 @@ CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
- CONFIG_USB0_ID_DET="PH11"
- CONFIG_USB1_VBUS_PIN="PD24"
- CONFIG_AXP_GPIO=y
--CONFIG_SATAPWR="PD25"
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_CONSOLE_MUX=y
- CONFIG_PHY_REALTEK=y
-diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
-index 76de72aa22..ed585881d4 100644
---- a/configs/orangepi_plus_defconfig
-+++ b/configs/orangepi_plus_defconfig
-@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=672
- CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_USB1_VBUS_PIN="PG13"
--CONFIG_SATAPWR="PG11"
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
- CONFIG_SPL_SYS_I2C_LEGACY=y
-@@ -16,3 +15,4 @@ CONFIG_SUN8I_EMAC=y
- CONFIG_SY8106A_POWER=y
- CONFIG_USB_EHCI_HCD=y
- CONFIG_USB_OHCI_HCD=y
-+CONFIG_USB3_VBUS_PIN="PG11"
-diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
-index 94a3379c53..9064774e66 100644
---- a/drivers/ata/ahci_sunxi.c
-+++ b/drivers/ata/ahci_sunxi.c
-@@ -7,6 +7,7 @@
- #include <asm/io.h>
- #include <asm/gpio.h>
- #include <linux/delay.h>
-+#include <power/regulator.h>
-
- #define AHCI_PHYCS0R 0x00c0
- #define AHCI_PHYCS1R 0x00c4
-@@ -74,6 +75,7 @@ static int sunxi_ahci_phy_init(u8 *reg_base)
-
- static int sunxi_sata_probe(struct udevice *dev)
- {
-+ struct udevice *reg_dev;
- ulong base;
- u8 *reg;
- int ret;
-@@ -89,6 +91,13 @@ static int sunxi_sata_probe(struct udevice *dev)
- debug("%s: Failed to init phy (err=%d)\n", __func__, ret);
- return ret;
- }
-+
-+ ret = device_get_supply_regulator(dev, "target-supply", ®_dev);
-+ if (ret == 0) {
-+ regulator_set_enable(reg_dev, true);
-+ mdelay(500);
-+ }
-+
- ret = ahci_probe_scsi(dev, base);
- if (ret) {
- debug("%s: Failed to probe (err=%d)\n", __func__, ret);
---
-2.20.1
-
--- /dev/null
+From 91d57f14ebe23a425354a039d0a68926f3292d5f Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:47 +0100
+Subject: [PATCH 4002/4044] net: sunxi_emac: chase DT nodes to find PHY
+ regulator
+
+At the moment the sun4i EMAC driver relies on hardcoded CONFIG_MACPWR
+Kconfig symbols to enable potential PHY regulators. As we want to get rid
+of those, we need to find the regulator by chasing up the DT.
+
+The sun4i-emac binding puts the PHY regulator into the MDIO node, which
+is the parent of the PHY device. U-Boot does not have (and does not
+need) an MDIO driver, so we need to chase down the regulator through the
+EMAC node: we follow the "phy-handle" property to find the PHY node,
+then go up to its parent, where we find the "phy-supply" link to the
+regulator. Let U-Boot find the associated regulator device, and put that
+into the private device struct, so we can find and enable the regulator
+at probe time, later.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Sam Edwards <CFSworks@gmail.com>
+---
+ drivers/net/sunxi_emac.c | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
+index 4c90d4b498..f1f0e5bbbb 100644
+--- a/drivers/net/sunxi_emac.c
++++ b/drivers/net/sunxi_emac.c
+@@ -17,6 +17,7 @@
+ #include <net.h>
+ #include <asm/io.h>
+ #include <asm/arch/clock.h>
++#include <power/regulator.h>
+
+ /* EMAC register */
+ struct emac_regs {
+@@ -165,6 +166,7 @@ struct emac_eth_dev {
+ struct phy_device *phydev;
+ int link_printed;
+ uchar rx_buf[EMAC_RX_BUFSIZE];
++ struct udevice *phy_reg;
+ };
+
+ struct emac_rxhdr {
+@@ -572,6 +574,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
+ if (ret)
+ return ret;
+
++ if (priv->phy_reg)
++ regulator_set_enable(priv->phy_reg, true);
++
+ return sunxi_emac_init_phy(priv, dev);
+ }
+
+@@ -585,9 +590,43 @@ static const struct eth_ops sunxi_emac_eth_ops = {
+ static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
+ {
+ struct eth_pdata *pdata = dev_get_plat(dev);
++ struct emac_eth_dev *priv = dev_get_priv(dev);
++ struct ofnode_phandle_args args;
++ ofnode mdio_node;
++ int ret;
+
+ pdata->iobase = dev_read_addr(dev);
+
++ /* The PHY regulator is in the MDIO node, not the EMAC or PHY node. */
++ ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &args);
++ if (ret) {
++ dev_err(dev, "failed to get PHY node\n");
++ return ret;
++ }
++
++ /*
++ * U-Boot does not have (and does not need) a device driver for the
++ * MDIO device, so just "pass through" that DT node to get to the
++ * regulator phandle.
++ * The PHY regulator is optional, though: ignore if we cannot find
++ * a phy-supply property.
++ */
++ mdio_node = ofnode_get_parent(args.node);
++ ret= ofnode_parse_phandle_with_args(mdio_node, "phy-supply", NULL, 0, 0,
++ &args);
++ if (ret && ret != -ENOENT) {
++ dev_err(dev, "failed to get PHY supply node\n");
++ return ret;
++ }
++ if (!ret) {
++ ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR, args.node,
++ &priv->phy_reg);
++ if (ret) {
++ dev_err(dev, "failed to get PHY regulator node\n");
++ return ret;
++ }
++ }
++
+ return 0;
+ }
+
+--
+2.20.1
+
+++ /dev/null
-From 9c399ed4ff3e2eb5a4e051be211e9da1fe9c27cb Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Wed, 8 Jun 2022 14:56:56 +0100
-Subject: [PATCH 4002/4031] sunxi: remove CONFIG_MACPWR
-
-The CONFIG_MACPWR Kconfig symbol is used to point to a GPIO that enables
-the power for the Ethernet "MAC" (mostly PHY, really).
-In the DT this is described with the phy-supply property in the MAC DT
-node, pointing to a (GPIO controlled) regulator. Since we need Ethernet
-only in U-Boot proper, and use a DM driver there, we should use the DT
-instead of hardcoding this.
-
-Add code to the sun8i_emac and sunxi_emac drivers to check the DT for
-that regulator and enable it, at probe time. Then drop the current code
-from board.c, which was doing that job before.
-This allows us to remove the MACPWR Kconfig definition and the respective
-values from the defconfigs.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/mach-sunxi/Kconfig | 7 -------
- board/sunxi/board.c | 12 +-----------
- configs/Bananapi_M2_Ultra_defconfig | 1 -
- configs/Bananapi_defconfig | 1 -
- configs/Bananapro_defconfig | 1 -
- configs/Lamobo_R1_defconfig | 1 -
- configs/Mele_A1000_defconfig | 1 -
- configs/Orangepi_defconfig | 1 -
- configs/Orangepi_mini_defconfig | 1 -
- configs/bananapi_m1_plus_defconfig | 1 -
- configs/bananapi_m2_plus_h3_defconfig | 1 -
- configs/bananapi_m2_plus_h5_defconfig | 1 -
- configs/i12-tvbox_defconfig | 1 -
- configs/jesurun_q5_defconfig | 1 -
- configs/mixtile_loftq_defconfig | 1 -
- configs/nanopi_m1_plus_defconfig | 1 -
- configs/nanopi_neo_plus2_defconfig | 1 -
- configs/nanopi_r1s_h5_defconfig | 1 -
- configs/orangepi_pc2_defconfig | 1 -
- configs/orangepi_plus2e_defconfig | 1 -
- configs/orangepi_plus_defconfig | 1 -
- configs/orangepi_win_defconfig | 1 -
- configs/pine_h64_defconfig | 1 -
- configs/zeropi_defconfig | 1 -
- drivers/net/sun8i_emac.c | 9 +++++++--
- drivers/net/sunxi_emac.c | 8 ++++++++
- 26 files changed, 16 insertions(+), 42 deletions(-)
-
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index c78a553493..d716054f72 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -645,13 +645,6 @@ config OLD_SUNXI_KERNEL_COMPAT
- Set this to enable various workarounds for old kernels, this results in
- sub-optimal settings for newer kernels, only enable if needed.
-
--config MACPWR
-- string "MAC power pin"
-- default ""
-- help
-- Set the pin used to power the MAC. This takes a string in the format
-- understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
--
- config MMC1_PINS_PH
- bool "Pins for mmc1 are on Port H"
- depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40
-diff --git a/board/sunxi/board.c b/board/sunxi/board.c
-index fe0e7bc2d9..9900c66ed0 100644
---- a/board/sunxi/board.c
-+++ b/board/sunxi/board.c
-@@ -187,7 +187,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
- /* add board specific code here */
- int board_init(void)
- {
-- __maybe_unused int id_pfr1, ret, macpwr_pin;
-+ __maybe_unused int id_pfr1, ret;
-
- gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
-
-@@ -224,15 +224,6 @@ int board_init(void)
- if (ret)
- return ret;
-
-- /* strcmp() would look better, but doesn't get optimised away. */
-- if (CONFIG_MACPWR[0]) {
-- macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
-- if (macpwr_pin >= 0) {
-- gpio_request(macpwr_pin, "macpwr");
-- gpio_direction_output(macpwr_pin, 1);
-- }
-- }
--
- #if CONFIG_IS_ENABLED(DM_I2C)
- /*
- * Temporary workaround for enabling I2C clocks until proper sunxi DM
-@@ -240,7 +231,6 @@ int board_init(void)
- */
- i2c_init_board();
- #endif
--
- eth_init_board();
-
- return 0;
-diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig
-index a5fe76af56..2cc7bbbd8b 100644
---- a/configs/Bananapi_M2_Ultra_defconfig
-+++ b/configs/Bananapi_M2_Ultra_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-r40-bananapi-m2-ultra"
- CONFIG_SPL=y
- CONFIG_MACH_SUN8I_R40=y
- CONFIG_DRAM_CLK=576
--CONFIG_MACPWR="PA17"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_USB1_VBUS_PIN="PH23"
- CONFIG_USB2_VBUS_PIN="PH23"
-diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
-index 6c2a1f630e..f4910ba13a 100644
---- a/configs/Bananapi_defconfig
-+++ b/configs/Bananapi_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=432
--CONFIG_MACPWR="PH23"
- CONFIG_VIDEO_COMPOSITE=y
- CONFIG_GMAC_TX_DELAY=3
- CONFIG_AHCI=y
-diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
-index 94fd74754e..02be8971df 100644
---- a/configs/Bananapro_defconfig
-+++ b/configs/Bananapro_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapro"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=432
--CONFIG_MACPWR="PH23"
- CONFIG_USB1_VBUS_PIN="PH0"
- CONFIG_USB2_VBUS_PIN="PH1"
- CONFIG_VIDEO_COMPOSITE=y
-diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
-index 9639cb6aad..66f57ab3c8 100644
---- a/configs/Lamobo_R1_defconfig
-+++ b/configs/Lamobo_R1_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-lamobo-r1"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=432
--CONFIG_MACPWR="PH23"
- CONFIG_GMAC_TX_DELAY=4
- CONFIG_AHCI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig
-index f5b6d908cd..9ac2e4839d 100644
---- a/configs/Mele_A1000_defconfig
-+++ b/configs/Mele_A1000_defconfig
-@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
- CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-a1000"
- CONFIG_SPL=y
- CONFIG_MACH_SUN4I=y
--CONFIG_MACPWR="PH15"
- CONFIG_VIDEO_VGA=y
- CONFIG_VIDEO_COMPOSITE=y
- CONFIG_AHCI=y
-diff --git a/configs/Orangepi_defconfig b/configs/Orangepi_defconfig
-index c89a9a1f9d..53edf525ec 100644
---- a/configs/Orangepi_defconfig
-+++ b/configs/Orangepi_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=432
--CONFIG_MACPWR="PH23"
- CONFIG_USB1_VBUS_PIN="PH26"
- CONFIG_USB2_VBUS_PIN="PH22"
- CONFIG_VIDEO_VGA=y
-diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
-index fe9ce808a1..ccf3267017 100644
---- a/configs/Orangepi_mini_defconfig
-+++ b/configs/Orangepi_mini_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi-mini"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=432
--CONFIG_MACPWR="PH23"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=3
- CONFIG_USB1_VBUS_PIN="PH26"
- CONFIG_USB2_VBUS_PIN="PH22"
-diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
-index 0fbb619d62..a432a01f6b 100644
---- a/configs/bananapi_m1_plus_defconfig
-+++ b/configs/bananapi_m1_plus_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi-m1-plus"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=432
--CONFIG_MACPWR="PH23"
- CONFIG_VIDEO_COMPOSITE=y
- CONFIG_GMAC_TX_DELAY=3
- CONFIG_AHCI=y
-diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig
-index 26ced59fb0..a8f9b5044b 100644
---- a/configs/bananapi_m2_plus_h3_defconfig
-+++ b/configs/bananapi_m2_plus_h3_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus"
- CONFIG_SPL=y
- CONFIG_MACH_SUN8I_H3=y
- CONFIG_DRAM_CLK=672
--CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SUN8I_EMAC=y
-diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig
-index fb6c945919..1634f62619 100644
---- a/configs/bananapi_m2_plus_h5_defconfig
-+++ b/configs/bananapi_m2_plus_h5_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-bananapi-m2-plus"
- CONFIG_SPL=y
- CONFIG_MACH_SUN50I_H5=y
- CONFIG_DRAM_CLK=672
--CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SUN8I_EMAC=y
-diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
-index 257dd89af4..37f0f53ae7 100644
---- a/configs/i12-tvbox_defconfig
-+++ b/configs/i12-tvbox_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-i12-tvbox"
- CONFIG_SPL=y
- CONFIG_MACH_SUN7I=y
- CONFIG_DRAM_CLK=384
--CONFIG_MACPWR="PH21"
- CONFIG_VIDEO_COMPOSITE=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/jesurun_q5_defconfig b/configs/jesurun_q5_defconfig
-index 0ff666b2ee..c99be7cea4 100644
---- a/configs/jesurun_q5_defconfig
-+++ b/configs/jesurun_q5_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-jesurun-q5"
- CONFIG_SPL=y
- CONFIG_MACH_SUN4I=y
- CONFIG_DRAM_CLK=312
--CONFIG_MACPWR="PH19"
- CONFIG_USB0_VBUS_PIN="PB9"
- CONFIG_VIDEO_COMPOSITE=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/mixtile_loftq_defconfig b/configs/mixtile_loftq_defconfig
-index 0e4cdc4467..2f92228eb7 100644
---- a/configs/mixtile_loftq_defconfig
-+++ b/configs/mixtile_loftq_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-mixtile-loftq"
- CONFIG_SPL=y
- CONFIG_MACH_SUN6I=y
- CONFIG_DRAM_ZQ=251
--CONFIG_MACPWR="PA21"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_USB1_VBUS_PIN="PH24"
- CONFIG_USB2_VBUS_PIN=""
-diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
-index 76655d79ae..078e98b644 100644
---- a/configs/nanopi_m1_plus_defconfig
-+++ b/configs/nanopi_m1_plus_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
- CONFIG_SPL=y
- CONFIG_MACH_SUN8I_H3=y
- CONFIG_DRAM_CLK=408
--CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SUN8I_EMAC=y
-diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
-index 924ff38f17..85ff31c6fe 100644
---- a/configs/nanopi_neo_plus2_defconfig
-+++ b/configs/nanopi_neo_plus2_defconfig
-@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
- CONFIG_DRAM_CLK=408
- CONFIG_DRAM_ZQ=3881977
- # CONFIG_DRAM_ODT_EN is not set
--CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SUN8I_EMAC=y
-diff --git a/configs/nanopi_r1s_h5_defconfig b/configs/nanopi_r1s_h5_defconfig
-index 27cf172d72..2a6f94afe4 100644
---- a/configs/nanopi_r1s_h5_defconfig
-+++ b/configs/nanopi_r1s_h5_defconfig
-@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
- CONFIG_DRAM_CLK=672
- CONFIG_DRAM_ZQ=3881977
- # CONFIG_DRAM_ODT_EN is not set
--CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SUN8I_EMAC=y
-diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
-index 777af8c60e..fb6fbaf787 100644
---- a/configs/orangepi_pc2_defconfig
-+++ b/configs/orangepi_pc2_defconfig
-@@ -5,7 +5,6 @@ CONFIG_SPL=y
- CONFIG_MACH_SUN50I_H5=y
- CONFIG_DRAM_CLK=672
- CONFIG_DRAM_ZQ=3881977
--CONFIG_MACPWR="PD6"
- CONFIG_SPL_SPI_SUNXI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
-index 138a6a72b8..5e2cbc48ea 100644
---- a/configs/orangepi_plus2e_defconfig
-+++ b/configs/orangepi_plus2e_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus2e"
- CONFIG_SPL=y
- CONFIG_MACH_SUN8I_H3=y
- CONFIG_DRAM_CLK=672
--CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPL_I2C=y
-diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
-index ed585881d4..092ce77a6c 100644
---- a/configs/orangepi_plus_defconfig
-+++ b/configs/orangepi_plus_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus"
- CONFIG_SPL=y
- CONFIG_MACH_SUN8I_H3=y
- CONFIG_DRAM_CLK=672
--CONFIG_MACPWR="PD6"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_USB1_VBUS_PIN="PG13"
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
-index 3b78ad7e52..bf52d1ea6b 100644
---- a/configs/orangepi_win_defconfig
-+++ b/configs/orangepi_win_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win"
- CONFIG_SPL=y
- CONFIG_MACH_SUN50I=y
- CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
--CONFIG_MACPWR="PD14"
- CONFIG_SPL_SPI_SUNXI=y
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_SPI_FLASH_WINBOND=y
-diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
-index 6dac6098d0..4712b8e469 100644
---- a/configs/pine_h64_defconfig
-+++ b/configs/pine_h64_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-pine-h64"
- CONFIG_SPL=y
- CONFIG_MACH_SUN50I_H6=y
- CONFIG_SUNXI_DRAM_H6_LPDDR3=y
--CONFIG_MACPWR="PC16"
- CONFIG_MMC_SUNXI_SLOT_EXTRA=2
- CONFIG_USB3_VBUS_PIN="PL5"
- CONFIG_SPL_SPI_SUNXI=y
-diff --git a/configs/zeropi_defconfig b/configs/zeropi_defconfig
-index 11f3715e6d..7901bffd15 100644
---- a/configs/zeropi_defconfig
-+++ b/configs/zeropi_defconfig
-@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-zeropi"
- CONFIG_SPL=y
- CONFIG_MACH_SUN8I_H3=y
- CONFIG_DRAM_CLK=408
--CONFIG_MACPWR="PD6"
- # CONFIG_VIDEO_DE2 is not set
- # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
- CONFIG_CONSOLE_MUX=y
-diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
-index e800a326b8..0937ec3c86 100644
---- a/drivers/net/sun8i_emac.c
-+++ b/drivers/net/sun8i_emac.c
-@@ -29,6 +29,7 @@
- #include <net.h>
- #include <reset.h>
- #include <wait_bit.h>
-+#include <power/regulator.h>
-
- #define MDIO_CMD_MII_BUSY BIT(0)
- #define MDIO_CMD_MII_WRITE BIT(1)
-@@ -169,9 +170,8 @@ struct emac_eth_dev {
- struct clk ephy_clk;
- struct reset_ctl tx_rst;
- struct reset_ctl ephy_rst;
--#if CONFIG_IS_ENABLED(DM_GPIO)
- struct gpio_desc reset_gpio;
--#endif
-+ struct udevice *phy_reg;
- };
-
-
-@@ -738,6 +738,9 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
-
- sun8i_emac_set_syscon(sun8i_pdata, priv);
-
-+ if (priv->phy_reg)
-+ regulator_set_enable(priv->phy_reg, true);
-+
- sun8i_mdio_init(dev->name, dev);
- priv->bus = miiphy_get_dev_by_name(dev->name);
-
-@@ -844,6 +847,8 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
- return -EINVAL;
- }
-
-+ device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
-+
- pdata->phy_interface = -1;
- priv->phyaddr = -1;
- priv->use_internal_phy = false;
-diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
-index ad9e1abd16..ee8b8a1667 100644
---- a/drivers/net/sunxi_emac.c
-+++ b/drivers/net/sunxi_emac.c
-@@ -17,6 +17,7 @@
- #include <net.h>
- #include <asm/io.h>
- #include <asm/arch/clock.h>
-+#include <power/regulator.h>
-
- /* EMAC register */
- struct emac_regs {
-@@ -165,6 +166,7 @@ struct emac_eth_dev {
- struct phy_device *phydev;
- int link_printed;
- uchar rx_buf[EMAC_RX_BUFSIZE];
-+ struct udevice *phy_reg;
- };
-
- struct emac_rxhdr {
-@@ -573,6 +575,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
- if (ret)
- return ret;
-
-+ if (priv->phy_reg)
-+ regulator_set_enable(priv->phy_reg, true);
-+
- return sunxi_emac_init_phy(priv, dev);
- }
-
-@@ -586,9 +591,12 @@ static const struct eth_ops sunxi_emac_eth_ops = {
- static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
- {
- struct eth_pdata *pdata = dev_get_plat(dev);
-+ struct emac_eth_dev *priv = dev_get_priv(dev);
-
- pdata->iobase = dev_read_addr(dev);
-
-+ device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
-+
- return 0;
- }
-
---
-2.20.1
-
--- /dev/null
+From 418993044499a9466a6be214c9d996e6e3b09798 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sun, 22 Jan 2023 16:51:02 -0600
+Subject: [PATCH 4003/4044] net: sun8i-emac: Add a structure for variant data
+
+Currently, EMAC variants are distinguished by their identity, but this
+gets unwieldy as more overlapping variants are added. Add a structure so
+we can describe the individual feature differences between the variants.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
+---
+ drivers/net/sun8i_emac.c | 65 +++++++++++++++++++++++++++-------------
+ 1 file changed, 45 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
+index e800a326b8..986e565cd8 100644
+--- a/drivers/net/sun8i_emac.c
++++ b/drivers/net/sun8i_emac.c
+@@ -127,7 +127,7 @@
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+-enum emac_variant {
++enum emac_variant_id {
+ A83T_EMAC = 1,
+ H3_EMAC,
+ A64_EMAC,
+@@ -135,6 +135,10 @@ enum emac_variant {
+ H6_EMAC,
+ };
+
++struct emac_variant {
++ enum emac_variant_id variant;
++};
++
+ struct emac_dma_desc {
+ u32 status;
+ u32 ctl_size;
+@@ -160,7 +164,7 @@ struct emac_eth_dev {
+ u32 tx_slot;
+ bool use_internal_phy;
+
+- enum emac_variant variant;
++ const struct emac_variant *variant;
+ void *mac_reg;
+ phys_addr_t sysctl_reg;
+ struct phy_device *phydev;
+@@ -317,7 +321,7 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ {
+ u32 reg;
+
+- if (priv->variant == R40_GMAC) {
++ if (priv->variant->variant == R40_GMAC) {
+ /* Select RGMII for R40 */
+ reg = readl(priv->sysctl_reg + 0x164);
+ reg |= SC_ETCS_INT_GMII |
+@@ -333,9 +337,9 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ reg = sun8i_emac_set_syscon_ephy(priv, reg);
+
+ reg &= ~(SC_ETCS_MASK | SC_EPIT);
+- if (priv->variant == H3_EMAC ||
+- priv->variant == A64_EMAC ||
+- priv->variant == H6_EMAC)
++ if (priv->variant->variant == H3_EMAC ||
++ priv->variant->variant == A64_EMAC ||
++ priv->variant->variant == H6_EMAC)
+ reg &= ~SC_RMII_EN;
+
+ switch (priv->interface) {
+@@ -349,9 +353,9 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ reg |= SC_EPIT | SC_ETCS_INT_GMII;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+- if (priv->variant == H3_EMAC ||
+- priv->variant == A64_EMAC ||
+- priv->variant == H6_EMAC) {
++ if (priv->variant->variant == H3_EMAC ||
++ priv->variant->variant == A64_EMAC ||
++ priv->variant->variant == H6_EMAC) {
+ reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
+ break;
+ }
+@@ -806,7 +810,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+ return -EINVAL;
+ }
+
+- priv->variant = dev_get_driver_data(dev);
++ priv->variant = (const void *)dev_get_driver_data(dev);
+
+ if (!priv->variant) {
+ printf("%s: Missing variant\n", __func__);
+@@ -860,7 +864,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
+ return -EINVAL;
+
+- if (priv->variant == H3_EMAC) {
++ if (priv->variant->variant == H3_EMAC) {
+ ret = sun8i_handle_internal_phy(dev, priv);
+ if (ret)
+ return ret;
+@@ -900,16 +904,37 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+ return 0;
+ }
+
++static const struct emac_variant emac_variant_a83t = {
++ .variant = A83T_EMAC,
++};
++
++static const struct emac_variant emac_variant_h3 = {
++ .variant = H3_EMAC,
++};
++
++static const struct emac_variant emac_variant_r40 = {
++ .variant = R40_GMAC,
++};
++
++static const struct emac_variant emac_variant_a64 = {
++ .variant = A64_EMAC,
++};
++
++static const struct emac_variant emac_variant_h6 = {
++ .variant = H6_EMAC,
++};
++
+ static const struct udevice_id sun8i_emac_eth_ids[] = {
+- {.compatible = "allwinner,sun8i-h3-emac", .data = (uintptr_t)H3_EMAC },
+- {.compatible = "allwinner,sun50i-a64-emac",
+- .data = (uintptr_t)A64_EMAC },
+- {.compatible = "allwinner,sun8i-a83t-emac",
+- .data = (uintptr_t)A83T_EMAC },
+- {.compatible = "allwinner,sun8i-r40-gmac",
+- .data = (uintptr_t)R40_GMAC },
+- {.compatible = "allwinner,sun50i-h6-emac",
+- .data = (uintptr_t)H6_EMAC },
++ { .compatible = "allwinner,sun8i-a83t-emac",
++ .data = (ulong)&emac_variant_a83t },
++ { .compatible = "allwinner,sun8i-h3-emac",
++ .data = (ulong)&emac_variant_h3 },
++ { .compatible = "allwinner,sun8i-r40-gmac",
++ .data = (ulong)&emac_variant_r40 },
++ { .compatible = "allwinner,sun50i-a64-emac",
++ .data = (ulong)&emac_variant_a64 },
++ { .compatible = "allwinner,sun50i-h6-emac",
++ .data = (ulong)&emac_variant_h6 },
+ { }
+ };
+
+--
+2.20.1
+
+++ /dev/null
-From 32d2c051ef1568445a5a27b1d2d5ffe6a9483ef3 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Mon, 5 Sep 2022 18:12:39 +0100
-Subject: [PATCH 4003/4031] pinctrl: sunxi: remove struct sunxi_gpio
-
-So far every Allwinner SoC used the same basic pincontroller/GPIO
-register frame, and just differed by the number of implemented banks and
-pins, plus some special functionality from time to time. However the D1
-and successors use a slightly different pinctrl register layout.
-Use that opportunity to drop "struct sunxi_gpio", that described that
-MMIO frame in a C struct. That approach is somewhat frowned upon in the
-Linux world and rarely used there, though still popular with U-Boot.
-
-Switching from a C struct to a "base address plus offset" approach allows
-to switch between the two models more dynamically, without reverting to
-preprocessor macros and #ifdef's.
-
-Model the pinctrl MMIO register frame in the usual "base address +
-offset" way, and replace a hard-to-parse CPP macro with a more readable
-static function.
-All the users get converted over. There are no functional changes at
-this point, it just prepares the stages for the D1 and friends.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/include/asm/arch-sunxi/gpio.h | 63 +++++++++++---------------
- arch/arm/mach-sunxi/pinmux.c | 51 +++++++++++----------
- drivers/gpio/sunxi_gpio.c | 15 +++---
- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 14 +++---
- 4 files changed, 68 insertions(+), 75 deletions(-)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
-index 437e86479c..8333810a69 100644
---- a/arch/arm/include/asm/arch-sunxi/gpio.h
-+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
-@@ -28,13 +28,6 @@
- #define SUNXI_GPIO_H 7
- #define SUNXI_GPIO_I 8
-
--/*
-- * This defines the number of GPIO banks for the _main_ GPIO controller.
-- * You should fix up the padding in struct sunxi_gpio_reg below if you
-- * change this.
-- */
--#define SUNXI_GPIO_BANKS 9
--
- /*
- * sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
- * at a different register offset.
-@@ -52,46 +45,42 @@
- #define SUNXI_GPIO_M 12
- #define SUNXI_GPIO_N 13
-
--struct sunxi_gpio {
-- u32 cfg[4];
-- u32 dat;
-- u32 drv[2];
-- u32 pull[2];
--};
--
--/* gpio interrupt control */
--struct sunxi_gpio_int {
-- u32 cfg[3];
-- u32 ctl;
-- u32 sta;
-- u32 deb; /* interrupt debounce */
--};
--
--struct sunxi_gpio_reg {
-- struct sunxi_gpio gpio_bank[SUNXI_GPIO_BANKS];
-- u8 res[0xbc];
-- struct sunxi_gpio_int gpio_int;
--};
--
- #define SUN50I_H6_GPIO_POW_MOD_SEL 0x340
- #define SUN50I_H6_GPIO_POW_MOD_VAL 0x348
-
--#define BANK_TO_GPIO(bank) (((bank) < SUNXI_GPIO_L) ? \
-- &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
-- &((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
--
- #define GPIO_BANK(pin) ((pin) >> 5)
- #define GPIO_NUM(pin) ((pin) & 0x1f)
-
-+#define GPIO_CFG_REG_OFFSET 0x00
- #define GPIO_CFG_INDEX(pin) (((pin) & 0x1f) >> 3)
- #define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1f) & 0x7) << 2)
-
-+#define GPIO_DAT_REG_OFFSET 0x10
-+
-+#define GPIO_DRV_REG_OFFSET 0x14
- #define GPIO_DRV_INDEX(pin) (((pin) & 0x1f) >> 4)
- #define GPIO_DRV_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-
-+#define GPIO_PULL_REG_OFFSET 0x1c
- #define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
- #define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-
-+#define SUNXI_PINCTRL_BANK_SIZE 0x24
-+
-+static inline void* BANK_TO_GPIO(int bank)
-+{
-+ void *pio_base;
-+
-+ if (bank < SUNXI_GPIO_L) {
-+ pio_base = (void *)(uintptr_t)SUNXI_PIO_BASE;
-+ } else {
-+ pio_base = (void *)(uintptr_t)SUNXI_R_PIO_BASE;
-+ bank -= SUNXI_GPIO_L;
-+ }
-+
-+ return pio_base + bank * SUNXI_PINCTRL_BANK_SIZE;
-+}
-+
- /* GPIO bank sizes */
- #define SUNXI_GPIOS_PER_BANK 32
-
-@@ -214,18 +203,18 @@ enum sunxi_gpio_number {
- #define SUNXI_GPIO_AXP0_GPIO_COUNT 6
-
- struct sunxi_gpio_plat {
-- struct sunxi_gpio *regs;
-+ void *regs;
- char bank_name[3];
- };
-
--void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
-+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
- void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
--int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
-+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
- int sunxi_gpio_get_cfgpin(u32 pin);
- void sunxi_gpio_set_drv(u32 pin, u32 val);
--void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
-+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
- void sunxi_gpio_set_pull(u32 pin, u32 val);
--void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val);
-+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val);
- int sunxi_name_to_gpio(const char *name);
-
- #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
-diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
-index c95fcee9f6..b650f6b1ae 100644
---- a/arch/arm/mach-sunxi/pinmux.c
-+++ b/arch/arm/mach-sunxi/pinmux.c
-@@ -9,29 +9,30 @@
- #include <asm/io.h>
- #include <asm/arch/gpio.h>
-
--void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
- {
-- u32 index = GPIO_CFG_INDEX(bank_offset);
-- u32 offset = GPIO_CFG_OFFSET(bank_offset);
-+ u32 index = GPIO_CFG_INDEX(pin_offset);
-+ u32 offset = GPIO_CFG_OFFSET(pin_offset);
-
-- clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
-+ clrsetbits_le32(bank_base + GPIO_CFG_REG_OFFSET + index * 4,
-+ 0xfU << offset, val << offset);
- }
-
- void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
- {
- u32 bank = GPIO_BANK(pin);
-- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-+ void *pio = BANK_TO_GPIO(bank);
-
-- sunxi_gpio_set_cfgbank(pio, pin, val);
-+ sunxi_gpio_set_cfgbank(pio, pin % 32, val);
- }
-
--int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
-+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset)
- {
-- u32 index = GPIO_CFG_INDEX(bank_offset);
-- u32 offset = GPIO_CFG_OFFSET(bank_offset);
-+ u32 index = GPIO_CFG_INDEX(pin_offset);
-+ u32 offset = GPIO_CFG_OFFSET(pin_offset);
- u32 cfg;
-
-- cfg = readl(&pio->cfg[index]);
-+ cfg = readl(bank_base + GPIO_CFG_REG_OFFSET + index * 4);
- cfg >>= offset;
-
- return cfg & 0xf;
-@@ -40,39 +41,41 @@ int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
- int sunxi_gpio_get_cfgpin(u32 pin)
- {
- u32 bank = GPIO_BANK(pin);
-- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-+ void *bank_base = BANK_TO_GPIO(bank);
-
-- return sunxi_gpio_get_cfgbank(pio, pin);
-+ return sunxi_gpio_get_cfgbank(bank_base, pin % 32);
- }
-
- void sunxi_gpio_set_drv(u32 pin, u32 val)
- {
- u32 bank = GPIO_BANK(pin);
-- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-+ void *bank_base = BANK_TO_GPIO(bank);
-
-- sunxi_gpio_set_drv_bank(pio, pin, val);
-+ sunxi_gpio_set_drv_bank(bank_base, pin % 32, val);
- }
-
--void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
-+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val)
- {
-- u32 index = GPIO_DRV_INDEX(bank_offset);
-- u32 offset = GPIO_DRV_OFFSET(bank_offset);
-+ u32 index = GPIO_DRV_INDEX(pin_offset);
-+ u32 offset = GPIO_DRV_OFFSET(pin_offset);
-
-- clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
-+ clrsetbits_le32(bank_base + GPIO_DRV_REG_OFFSET + index * 4,
-+ 0x3U << offset, val << offset);
- }
-
- void sunxi_gpio_set_pull(u32 pin, u32 val)
- {
- u32 bank = GPIO_BANK(pin);
-- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-+ void *bank_base = BANK_TO_GPIO(bank);
-
-- sunxi_gpio_set_pull_bank(pio, pin, val);
-+ sunxi_gpio_set_pull_bank(bank_base, pin % 32, val);
- }
-
--void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val)
- {
-- u32 index = GPIO_PULL_INDEX(bank_offset);
-- u32 offset = GPIO_PULL_OFFSET(bank_offset);
-+ u32 index = GPIO_PULL_INDEX(pin_offset);
-+ u32 offset = GPIO_PULL_OFFSET(pin_offset);
-
-- clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
-+ clrsetbits_le32(bank_base + GPIO_PULL_REG_OFFSET + index * 4,
-+ 0x3U << offset, val << offset);
- }
-diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
-index 1e85db179a..1bf691a204 100644
---- a/drivers/gpio/sunxi_gpio.c
-+++ b/drivers/gpio/sunxi_gpio.c
-@@ -24,15 +24,15 @@ static int sunxi_gpio_output(u32 pin, u32 val)
- u32 dat;
- u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
-- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-+ void *pio = BANK_TO_GPIO(bank);
-
-- dat = readl(&pio->dat);
-+ dat = readl(pio + 0x10);
- if (val)
- dat |= 0x1 << num;
- else
- dat &= ~(0x1 << num);
-
-- writel(dat, &pio->dat);
-+ writel(dat, pio + 0x10);
-
- return 0;
- }
-@@ -42,9 +42,9 @@ static int sunxi_gpio_input(u32 pin)
- u32 dat;
- u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
-- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-+ void *pio = BANK_TO_GPIO(bank);
-
-- dat = readl(&pio->dat);
-+ dat = readl(pio + 0x10);
- dat >>= num;
-
- return dat & 0x1;
-@@ -138,7 +138,7 @@ static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
- u32 num = GPIO_NUM(offset);
- unsigned dat;
-
-- dat = readl(&plat->regs->dat);
-+ dat = readl(plat->regs + GPIO_DAT_REG_OFFSET);
- dat >>= num;
-
- return dat & 0x1;
-@@ -181,7 +181,8 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
- u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
- u32 num = GPIO_NUM(offset);
-
-- clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
-+ clrsetbits_le32(plat->regs + GPIO_DAT_REG_OFFSET,
-+ 1 << num, value << num);
- sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
- } else if (flags & GPIOD_IS_IN) {
- u32 pull = 0;
-diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-index c4fbda7a92..b0144edcf4 100644
---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-@@ -35,7 +35,7 @@ struct sunxi_pinctrl_desc {
- };
-
- struct sunxi_pinctrl_plat {
-- struct sunxi_gpio __iomem *base;
-+ void __iomem *base;
- };
-
- static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
-@@ -86,8 +86,8 @@ static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
- sunxi_pinctrl_get_function_name(dev, func_selector),
- desc->functions[func_selector].mux);
-
-- sunxi_gpio_set_cfgbank(plat->base + bank, pin,
-- desc->functions[func_selector].mux);
-+ sunxi_gpio_set_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE,
-+ pin, desc->functions[func_selector].mux);
-
- return 0;
- }
-@@ -102,7 +102,7 @@ static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
- static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
- uint bank, uint pin, uint bias)
- {
-- struct sunxi_gpio *regs = &plat->base[bank];
-+ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
-
- sunxi_gpio_set_pull_bank(regs, pin, bias);
-
-@@ -112,7 +112,7 @@ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
- static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
- uint bank, uint pin, uint drive)
- {
-- struct sunxi_gpio *regs = &plat->base[bank];
-+ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
-
- if (drive < 10 || drive > 40)
- return -EINVAL;
-@@ -148,7 +148,7 @@ static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
- struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
- int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
- int pin = pin_selector % SUNXI_GPIOS_PER_BANK;
-- int mux = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
-+ int mux = sunxi_gpio_get_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE, pin);
-
- switch (mux) {
- case SUNXI_GPIO_INPUT:
-@@ -206,7 +206,7 @@ static int sunxi_pinctrl_bind(struct udevice *dev)
- if (!gpio_plat)
- return -ENOMEM;
-
-- gpio_plat->regs = plat->base + i;
-+ gpio_plat->regs = plat->base + i * SUNXI_PINCTRL_BANK_SIZE;
- gpio_plat->bank_name[0] = 'P';
- gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
- gpio_plat->bank_name[2] = '\0';
---
-2.20.1
-
--- /dev/null
+From d9fd9f067e9bfcc03a70a0ead0bbe14595976edd Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sun, 22 Jan 2023 16:51:03 -0600
+Subject: [PATCH 4004/4044] net: sun8i-emac: Add a flag for RMII support
+
+Describe this feature instead of using the SoC ID.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
+---
+ drivers/net/sun8i_emac.c | 15 +++++++--------
+ 1 file changed, 7 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
+index 986e565cd8..f232b8f087 100644
+--- a/drivers/net/sun8i_emac.c
++++ b/drivers/net/sun8i_emac.c
+@@ -137,6 +137,7 @@ enum emac_variant_id {
+
+ struct emac_variant {
+ enum emac_variant_id variant;
++ bool support_rmii;
+ };
+
+ struct emac_dma_desc {
+@@ -337,9 +338,7 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ reg = sun8i_emac_set_syscon_ephy(priv, reg);
+
+ reg &= ~(SC_ETCS_MASK | SC_EPIT);
+- if (priv->variant->variant == H3_EMAC ||
+- priv->variant->variant == A64_EMAC ||
+- priv->variant->variant == H6_EMAC)
++ if (priv->variant->support_rmii)
+ reg &= ~SC_RMII_EN;
+
+ switch (priv->interface) {
+@@ -353,13 +352,10 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ reg |= SC_EPIT | SC_ETCS_INT_GMII;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+- if (priv->variant->variant == H3_EMAC ||
+- priv->variant->variant == A64_EMAC ||
+- priv->variant->variant == H6_EMAC) {
++ if (priv->variant->support_rmii) {
+ reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
+- break;
++ break;
+ }
+- /* RMII not supported on A83T */
+ default:
+ debug("%s: Invalid PHY interface\n", __func__);
+ return -EINVAL;
+@@ -910,6 +906,7 @@ static const struct emac_variant emac_variant_a83t = {
+
+ static const struct emac_variant emac_variant_h3 = {
+ .variant = H3_EMAC,
++ .support_rmii = true,
+ };
+
+ static const struct emac_variant emac_variant_r40 = {
+@@ -918,10 +915,12 @@ static const struct emac_variant emac_variant_r40 = {
+
+ static const struct emac_variant emac_variant_a64 = {
+ .variant = A64_EMAC,
++ .support_rmii = true,
+ };
+
+ static const struct emac_variant emac_variant_h6 = {
+ .variant = H6_EMAC,
++ .support_rmii = true,
+ };
+
+ static const struct udevice_id sun8i_emac_eth_ids[] = {
+--
+2.20.1
+
+++ /dev/null
-From be773ad59da355ca608287db4c4771bf9120241c Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Tue, 6 Sep 2022 10:07:18 +0100
-Subject: [PATCH 4004/4031] pinctrl: sunxi: add GPIO in/out wrappers
-
-So far we were open-coding the pincontroller's GPIO output/input access
-in each function using that.
-
-Provide two functions that wrap that nicely, so users don't need to know
-about the internals, and we can abstract the new D1 pinctrl more easily.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/include/asm/arch-sunxi/gpio.h | 2 ++
- arch/arm/mach-sunxi/pinmux.c | 10 ++++++++++
- drivers/gpio/sunxi_gpio.c | 26 +++++---------------------
- 3 files changed, 17 insertions(+), 21 deletions(-)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
-index 8333810a69..42ca03d8c1 100644
---- a/arch/arm/include/asm/arch-sunxi/gpio.h
-+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
-@@ -211,6 +211,8 @@ void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
- void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
- int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
- int sunxi_gpio_get_cfgpin(u32 pin);
-+void sunxi_gpio_set_output_bank(void *bank_base, u32 clear_mask, u32 set_mask);
-+u32 sunxi_gpio_get_output_bank(void *bank_base);
- void sunxi_gpio_set_drv(u32 pin, u32 val);
- void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
- void sunxi_gpio_set_pull(u32 pin, u32 val);
-diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
-index b650f6b1ae..91acbf9269 100644
---- a/arch/arm/mach-sunxi/pinmux.c
-+++ b/arch/arm/mach-sunxi/pinmux.c
-@@ -46,6 +46,16 @@ int sunxi_gpio_get_cfgpin(u32 pin)
- return sunxi_gpio_get_cfgbank(bank_base, pin % 32);
- }
-
-+void sunxi_gpio_set_output_bank(void *bank_base, u32 clear_mask, u32 set_mask)
-+{
-+ clrsetbits_le32(bank_base + GPIO_DAT_REG_OFFSET, clear_mask, set_mask);
-+}
-+
-+u32 sunxi_gpio_get_output_bank(void *bank_base)
-+{
-+ return readl(bank_base + GPIO_DAT_REG_OFFSET);
-+}
-+
- void sunxi_gpio_set_drv(u32 pin, u32 val)
- {
- u32 bank = GPIO_BANK(pin);
-diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
-index 1bf691a204..767996c10f 100644
---- a/drivers/gpio/sunxi_gpio.c
-+++ b/drivers/gpio/sunxi_gpio.c
-@@ -21,33 +21,22 @@
- #if !CONFIG_IS_ENABLED(DM_GPIO)
- static int sunxi_gpio_output(u32 pin, u32 val)
- {
-- u32 dat;
- u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
- void *pio = BANK_TO_GPIO(bank);
-
-- dat = readl(pio + 0x10);
-- if (val)
-- dat |= 0x1 << num;
-- else
-- dat &= ~(0x1 << num);
--
-- writel(dat, pio + 0x10);
--
-+ sunxi_gpio_set_output_bank(pio, val ? 0 : 1U << num,
-+ val ? 1U << num : 0);
- return 0;
- }
-
- static int sunxi_gpio_input(u32 pin)
- {
-- u32 dat;
- u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
- void *pio = BANK_TO_GPIO(bank);
-
-- dat = readl(pio + 0x10);
-- dat >>= num;
--
-- return dat & 0x1;
-+ return (sunxi_gpio_get_output_bank(pio) >> num) & 0x1;
- }
-
- int gpio_request(unsigned gpio, const char *label)
-@@ -136,12 +125,8 @@ static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
- {
- struct sunxi_gpio_plat *plat = dev_get_plat(dev);
- u32 num = GPIO_NUM(offset);
-- unsigned dat;
--
-- dat = readl(plat->regs + GPIO_DAT_REG_OFFSET);
-- dat >>= num;
-
-- return dat & 0x1;
-+ return (sunxi_gpio_get_output_bank(plat->regs) >> num) & 0x1;
- }
-
- static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
-@@ -181,8 +166,7 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
- u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
- u32 num = GPIO_NUM(offset);
-
-- clrsetbits_le32(plat->regs + GPIO_DAT_REG_OFFSET,
-- 1 << num, value << num);
-+ sunxi_gpio_set_output_bank(plat->regs, 1U << num, value << num);
- sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
- } else if (flags & GPIOD_IS_IN) {
- u32 pull = 0;
---
-2.20.1
-
--- /dev/null
+From 0b22263387bb55c70fb774ea70dd386bf6228c97 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sun, 22 Jan 2023 16:51:04 -0600
+Subject: [PATCH 4005/4044] net: sun8i-emac: Add a flag for the internal PHY
+ switch
+
+Describe this feature instead of using the SoC ID.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
+---
+ drivers/net/sun8i_emac.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
+index f232b8f087..36cc2498b5 100644
+--- a/drivers/net/sun8i_emac.c
++++ b/drivers/net/sun8i_emac.c
+@@ -137,6 +137,7 @@ enum emac_variant_id {
+
+ struct emac_variant {
+ enum emac_variant_id variant;
++ bool soc_has_internal_phy;
+ bool support_rmii;
+ };
+
+@@ -860,7 +861,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
+ return -EINVAL;
+
+- if (priv->variant->variant == H3_EMAC) {
++ if (priv->variant->soc_has_internal_phy) {
+ ret = sun8i_handle_internal_phy(dev, priv);
+ if (ret)
+ return ret;
+@@ -906,6 +907,7 @@ static const struct emac_variant emac_variant_a83t = {
+
+ static const struct emac_variant emac_variant_h3 = {
+ .variant = H3_EMAC,
++ .soc_has_internal_phy = true,
+ .support_rmii = true,
+ };
+
+--
+2.20.1
+
+++ /dev/null
-From 3e291cf021a0fd248c4a4d86e8bb2b65ca1b0f5c Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Tue, 6 Sep 2022 10:36:38 +0100
-Subject: [PATCH 4005/4031] pinctrl: sunxi: move pinctrl code and remove
- GPIO_EXTRA_HEADER
-
-U-Boot's generic GPIO_EXTRA_HEADER is a convenience symbol to allow code
-to more easily include platform specific GPIO headers. This should not
-be needed in a DM world anymore, since the generic GPIO framework
-handles that nicely.
-For Allwinner boards we still need to deal with non-DM GPIO in the SPL,
-but this should become the exception, not the rule.
-
-Make this more obvious by removing the definition of GPIO_EXTRA_HEADER,
-and just force every legacy user of platform specific GPIO to include
-the new sunxi_gpio.h header explicitly. Everyone doing so should feel
-ashamed and should find a way to avoid it from now on.
-This also moves and renames the existing sunxi-specific low level
-pinctrl routines from arch/arm/mach-sunxi into board/sunxi, and the
-gpio.h header to the generic include/ directory, so the common code can
-be shared outside of arch/arm.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/Kconfig | 1 -
- arch/arm/mach-sunxi/Makefile | 1 -
- arch/arm/mach-sunxi/board.c | 1 +
- arch/arm/mach-sunxi/dram_suniv.c | 2 +-
- arch/arm/mach-sunxi/spl_spi_sunxi.c | 1 +
- board/sunxi/Makefile | 1 +
- board/sunxi/board.c | 1 +
- board/sunxi/chip.c | 2 +-
- arch/arm/mach-sunxi/pinmux.c => board/sunxi/pinctrl.c | 5 ++++-
- drivers/gpio/axp_gpio.c | 1 +
- drivers/gpio/sunxi_gpio.c | 1 +
- drivers/i2c/sun6i_p2wi.c | 2 +-
- drivers/i2c/sun8i_rsb.c | 2 +-
- drivers/mmc/sunxi_mmc.c | 1 +
- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 1 +
- drivers/video/hitachi_tx18d42vm_lcd.c | 1 +
- drivers/video/ssd2828.c | 1 -
- drivers/video/sunxi/sunxi_display.c | 1 +
- drivers/video/sunxi/sunxi_lcd.c | 1 +
- .../include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h | 0
- 20 files changed, 19 insertions(+), 8 deletions(-)
- rename arch/arm/mach-sunxi/pinmux.c => board/sunxi/pinctrl.c (93%)
- rename arch/arm/include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h (100%)
-
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index d5a6d293ce..2904e91ad3 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -1106,7 +1106,6 @@ config ARCH_SUNXI
- select DM_MMC if MMC
- select DM_SCSI if SCSI
- select DM_SERIAL
-- select GPIO_EXTRA_HEADER
- select OF_BOARD_SETUP
- select OF_CONTROL
- select OF_SEPARATE
-diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
-index 58f807cb82..671211e932 100644
---- a/arch/arm/mach-sunxi/Makefile
-+++ b/arch/arm/mach-sunxi/Makefile
-@@ -10,7 +10,6 @@ obj-y += board.o
- obj-y += clock.o
- obj-y += cpu_info.o
- obj-y += dram_helpers.o
--obj-y += pinmux.o
- obj-$(CONFIG_SUN6I_PRCM) += prcm.o
- obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o
- obj-$(CONFIG_MACH_SUNIV) += clock_sun6i.o
-diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
-index 391a65a549..ec46ab9279 100644
---- a/arch/arm/mach-sunxi/board.c
-+++ b/arch/arm/mach-sunxi/board.c
-@@ -17,6 +17,7 @@
- #include <i2c.h>
- #include <serial.h>
- #include <spl.h>
-+#include <sunxi_gpio.h>
- #include <asm/cache.h>
- #include <asm/gpio.h>
- #include <asm/io.h>
-diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c
-index 3aa3ce7627..9e583e1855 100644
---- a/arch/arm/mach-sunxi/dram_suniv.c
-+++ b/arch/arm/mach-sunxi/dram_suniv.c
-@@ -13,10 +13,10 @@
- #include <asm/io.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/dram.h>
--#include <asm/arch/gpio.h>
- #include <linux/bitops.h>
- #include <linux/delay.h>
- #include <hang.h>
-+#include <sunxi_gpio.h>
-
- #define SDR_T_CAS (0x2)
- #define SDR_T_RAS (0x8)
-diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
-index 81159cfee6..c2410dd7bb 100644
---- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
-+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
-@@ -13,6 +13,7 @@
- #include <linux/bitops.h>
- #include <linux/delay.h>
- #include <linux/libfdt.h>
-+#include <sunxi_gpio.h>
-
- #ifdef CONFIG_SPL_OS_BOOT
- #error CONFIG_SPL_OS_BOOT is not supported yet
-diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
-index d96b7897b6..7763b032c8 100644
---- a/board/sunxi/Makefile
-+++ b/board/sunxi/Makefile
-@@ -7,6 +7,7 @@
- # (C) Copyright 2000-2003
- # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- obj-y += board.o
-+obj-y += pinctrl.o
- obj-$(CONFIG_SUN7I_GMAC) += gmac.o
- obj-$(CONFIG_MACH_SUN4I) += dram_sun4i_auto.o
- obj-$(CONFIG_MACH_SUN5I) += dram_sun5i_auto.o
-diff --git a/board/sunxi/board.c b/board/sunxi/board.c
-index 9900c66ed0..661137f43c 100644
---- a/board/sunxi/board.c
-+++ b/board/sunxi/board.c
-@@ -38,6 +38,7 @@
- #include <asm/armv7.h>
- #endif
- #include <asm/gpio.h>
-+#include <sunxi_gpio.h>
- #include <asm/io.h>
- #include <u-boot/crc.h>
- #include <env_internal.h>
-diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c
-index cde04bebe9..eeee6319e7 100644
---- a/board/sunxi/chip.c
-+++ b/board/sunxi/chip.c
-@@ -12,7 +12,7 @@
- #include <w1-eeprom.h>
- #include <dm/device-internal.h>
-
--#include <asm/arch/gpio.h>
-+#include <sunxi_gpio.h>
-
- #include <extension_board.h>
-
-diff --git a/arch/arm/mach-sunxi/pinmux.c b/board/sunxi/pinctrl.c
-similarity index 93%
-rename from arch/arm/mach-sunxi/pinmux.c
-rename to board/sunxi/pinctrl.c
-index 91acbf9269..aac37f639b 100644
---- a/arch/arm/mach-sunxi/pinmux.c
-+++ b/board/sunxi/pinctrl.c
-@@ -3,11 +3,14 @@
- * (C) Copyright 2007-2011
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Tom Cubie <tangliang@allwinnertech.com>
-+ *
-+ * Low level GPIO/pin controller access functions, to be shared by non-DM
-+ * SPL code and the DM pinctrl/GPIO drivers.
- */
-
- #include <common.h>
- #include <asm/io.h>
--#include <asm/arch/gpio.h>
-+#include <sunxi_gpio.h>
-
- void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
- {
-diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c
-index 35585dc8ac..14a99ce4c9 100644
---- a/drivers/gpio/axp_gpio.c
-+++ b/drivers/gpio/axp_gpio.c
-@@ -14,6 +14,7 @@
- #include <dm/lists.h>
- #include <dm/root.h>
- #include <errno.h>
-+#include <sunxi_gpio.h>
-
- static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val);
-
-diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
-index 767996c10f..49a6be6fd0 100644
---- a/drivers/gpio/sunxi_gpio.c
-+++ b/drivers/gpio/sunxi_gpio.c
-@@ -17,6 +17,7 @@
- #include <asm/io.h>
- #include <asm/gpio.h>
- #include <dt-bindings/gpio/gpio.h>
-+#include <sunxi_gpio.h>
-
- #if !CONFIG_IS_ENABLED(DM_GPIO)
- static int sunxi_gpio_output(u32 pin, u32 val)
-diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c
-index d221323295..b8e07a533c 100644
---- a/drivers/i2c/sun6i_p2wi.c
-+++ b/drivers/i2c/sun6i_p2wi.c
-@@ -20,10 +20,10 @@
- #include <errno.h>
- #include <i2c.h>
- #include <reset.h>
-+#include <sunxi_gpio.h>
- #include <time.h>
- #include <asm/io.h>
- #include <asm/arch/cpu.h>
--#include <asm/arch/gpio.h>
- #include <asm/arch/p2wi.h>
- #include <asm/arch/prcm.h>
- #include <asm/arch/sys_proto.h>
-diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c
-index 47fa05b6d1..f36f2c7afa 100644
---- a/drivers/i2c/sun8i_rsb.c
-+++ b/drivers/i2c/sun8i_rsb.c
-@@ -14,10 +14,10 @@
- #include <dm.h>
- #include <errno.h>
- #include <i2c.h>
-+#include <sunxi_gpio.h>
- #include <reset.h>
- #include <time.h>
- #include <asm/arch/cpu.h>
--#include <asm/arch/gpio.h>
- #include <asm/arch/prcm.h>
- #include <asm/arch/rsb.h>
-
-diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
-index 23bc7da917..03e33753fc 100644
---- a/drivers/mmc/sunxi_mmc.c
-+++ b/drivers/mmc/sunxi_mmc.c
-@@ -27,6 +27,7 @@
- #include <asm/arch/cpu.h>
- #include <asm/arch/mmc.h>
- #include <linux/delay.h>
-+#include <sunxi_gpio.h>
-
- #ifndef CCM_MMC_CTRL_MODE_SEL_NEW
- #define CCM_MMC_CTRL_MODE_SEL_NEW 0
-diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-index b0144edcf4..4c52e3fa74 100644
---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-@@ -7,6 +7,7 @@
- #include <dm/pinctrl.h>
- #include <errno.h>
- #include <malloc.h>
-+#include <sunxi_gpio.h>
-
- #include <asm/gpio.h>
-
-diff --git a/drivers/video/hitachi_tx18d42vm_lcd.c b/drivers/video/hitachi_tx18d42vm_lcd.c
-index 87c4d27438..95984fe3d3 100644
---- a/drivers/video/hitachi_tx18d42vm_lcd.c
-+++ b/drivers/video/hitachi_tx18d42vm_lcd.c
-@@ -10,6 +10,7 @@
- #include <linux/delay.h>
-
- #include <asm/gpio.h>
-+#include <sunxi_gpio.h>
- #include <errno.h>
-
- /*
-diff --git a/drivers/video/ssd2828.c b/drivers/video/ssd2828.c
-index 4cdcbe7755..948f5e74d0 100644
---- a/drivers/video/ssd2828.c
-+++ b/drivers/video/ssd2828.c
-@@ -12,7 +12,6 @@
- #include <common.h>
- #include <malloc.h>
- #include <mipi_display.h>
--#include <asm/arch/gpio.h>
- #include <asm/gpio.h>
- #include <linux/delay.h>
-
-diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
-index 9110a48482..8da44a1bb6 100644
---- a/drivers/video/sunxi/sunxi_display.c
-+++ b/drivers/video/sunxi/sunxi_display.c
-@@ -31,6 +31,7 @@
- #include <malloc.h>
- #include <video.h>
- #include <dm/uclass-internal.h>
-+#include <sunxi_gpio.h>
- #include "../videomodes.h"
- #include "../anx9804.h"
- #include "../hitachi_tx18d42vm_lcd.h"
-diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c
-index 8b9c3b2bfa..7a01cc343c 100644
---- a/drivers/video/sunxi/sunxi_lcd.c
-+++ b/drivers/video/sunxi/sunxi_lcd.c
-@@ -17,6 +17,7 @@
- #include <asm/arch/lcdc.h>
- #include <asm/global_data.h>
- #include <asm/gpio.h>
-+#include <sunxi_gpio.h>
-
- struct sunxi_lcd_priv {
- struct display_timing timing;
-diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/include/sunxi_gpio.h
-similarity index 100%
-rename from arch/arm/include/asm/arch-sunxi/gpio.h
-rename to include/sunxi_gpio.h
---
-2.20.1
-
--- /dev/null
+From e2305bd1beef8597351e6036c7c1597c6cd5ca0d Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sun, 22 Jan 2023 16:51:05 -0600
+Subject: [PATCH 4006/4044] net: sun8i-emac: Use common syscon setup for R40
+
+While R40 puts the EMAC syscon register at a different address from
+other variants, the relevant portion of the register's layout is the
+same. Factor out the register offset so the same code can be shared
+by all variants. This matches what the Linux driver does.
+
+This change provides two benefits beyond the simplification:
+ - R40 boards now respect the RX delays from the devicetree
+ - This resolves a warning on architectures where readl/writel
+ expect the address to have a pointer type, not phys_addr_t.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
+---
+ drivers/net/sun8i_emac.c | 32 +++++++++++++++-----------------
+ 1 file changed, 15 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
+index 36cc2498b5..231aac19e3 100644
+--- a/drivers/net/sun8i_emac.c
++++ b/drivers/net/sun8i_emac.c
+@@ -137,6 +137,7 @@ enum emac_variant_id {
+
+ struct emac_variant {
+ enum emac_variant_id variant;
++ uint syscon_offset;
+ bool soc_has_internal_phy;
+ bool support_rmii;
+ };
+@@ -168,7 +169,7 @@ struct emac_eth_dev {
+
+ const struct emac_variant *variant;
+ void *mac_reg;
+- phys_addr_t sysctl_reg;
++ void *sysctl_reg;
+ struct phy_device *phydev;
+ struct mii_dev *bus;
+ struct clk tx_clk;
+@@ -323,18 +324,7 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ {
+ u32 reg;
+
+- if (priv->variant->variant == R40_GMAC) {
+- /* Select RGMII for R40 */
+- reg = readl(priv->sysctl_reg + 0x164);
+- reg |= SC_ETCS_INT_GMII |
+- SC_EPIT |
+- (CONFIG_GMAC_TX_DELAY << SC_ETXDC_OFFSET);
+-
+- writel(reg, priv->sysctl_reg + 0x164);
+- return 0;
+- }
+-
+- reg = readl(priv->sysctl_reg + 0x30);
++ reg = readl(priv->sysctl_reg);
+
+ reg = sun8i_emac_set_syscon_ephy(priv, reg);
+
+@@ -370,7 +360,7 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET)
+ & SC_ERXDC_MASK;
+
+- writel(reg, priv->sysctl_reg + 0x30);
++ writel(reg, priv->sysctl_reg);
+
+ return 0;
+ }
+@@ -793,6 +783,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+ struct sun8i_eth_pdata *sun8i_pdata = dev_get_plat(dev);
+ struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
+ struct emac_eth_dev *priv = dev_get_priv(dev);
++ phys_addr_t syscon_base;
+ const fdt32_t *reg;
+ int node = dev_of_offset(dev);
+ int offset = 0;
+@@ -838,13 +829,15 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+ __func__);
+ return -EINVAL;
+ }
+- priv->sysctl_reg = fdt_translate_address((void *)gd->fdt_blob,
+- offset, reg);
+- if (priv->sysctl_reg == FDT_ADDR_T_NONE) {
++
++ syscon_base = fdt_translate_address((void *)gd->fdt_blob, offset, reg);
++ if (syscon_base == FDT_ADDR_T_NONE) {
+ debug("%s: Cannot find syscon base address\n", __func__);
+ return -EINVAL;
+ }
+
++ priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
++
+ pdata->phy_interface = -1;
+ priv->phyaddr = -1;
+ priv->use_internal_phy = false;
+@@ -903,25 +896,30 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+
+ static const struct emac_variant emac_variant_a83t = {
+ .variant = A83T_EMAC,
++ .syscon_offset = 0x30,
+ };
+
+ static const struct emac_variant emac_variant_h3 = {
+ .variant = H3_EMAC,
++ .syscon_offset = 0x30,
+ .soc_has_internal_phy = true,
+ .support_rmii = true,
+ };
+
+ static const struct emac_variant emac_variant_r40 = {
+ .variant = R40_GMAC,
++ .syscon_offset = 0x164,
+ };
+
+ static const struct emac_variant emac_variant_a64 = {
+ .variant = A64_EMAC,
++ .syscon_offset = 0x30,
+ .support_rmii = true,
+ };
+
+ static const struct emac_variant emac_variant_h6 = {
+ .variant = H6_EMAC,
++ .syscon_offset = 0x30,
+ .support_rmii = true,
+ };
+
+--
+2.20.1
+
+++ /dev/null
-From 69c0dbc968700d57189fd19e082f0f8a4b1df878 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Tue, 6 Sep 2022 11:50:54 +0100
-Subject: [PATCH 4006/4031] pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h
-
-On the Allwinner platform we were describing a quite comprehensive
-memory map in a per-SoC header unser arch/arm.
-In the old days that was used by every driver, but nowadays it should
-only be needed by SPL drivers (not using the DT). Many addresses in
-there were never used, and some are not needed anymore.
-
-To avoid a dependency on CPU specific headers in an arch specific
-directory, move the definition of the pinctroller MMIO base address into
-the sunxi_gpio.h header, because the SPL routines for GPIO should be the
-only one needing this address.
-This is a first step towards getting rid of cpu_sun[x]i.h completely,
-and allows to remove the inclusion of that file from the sunxi_gpio.h
-header.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 2 --
- arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h | 2 --
- arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 2 --
- include/sunxi_gpio.h | 12 +++++++++++-
- 4 files changed, 11 insertions(+), 7 deletions(-)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
-index f7ecc790db..d6fe51f24b 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
-@@ -91,7 +91,6 @@
-
- #define SUNXI_CCM_BASE 0x01c20000
- #define SUNXI_INTC_BASE 0x01c20400
--#define SUNXI_PIO_BASE 0x01c20800
- #define SUNXI_TIMER_BASE 0x01c20c00
- #ifndef CONFIG_SUNXI_GEN_SUN6I
- #define SUNXI_PWM_BASE 0x01c20e00
-@@ -210,7 +209,6 @@ defined(CONFIG_MACH_SUN50I)
-
- #define SUNXI_R_TWI_BASE 0x01f02400
- #define SUNXI_R_UART_BASE 0x01f02800
--#define SUNXI_R_PIO_BASE 0x01f02c00
- #define SUN6I_P2WI_BASE 0x01f03400
- #define SUNXI_RSB_BASE 0x01f03400
-
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
-index d9cf8ae042..9b6bf84360 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
-@@ -22,7 +22,6 @@
- #define SUNXI_SIDC_BASE 0x03006000
- #define SUNXI_SID_BASE 0x03006200
- #define SUNXI_TIMER_BASE 0x03009000
--#define SUNXI_PIO_BASE 0x0300B000
- #define SUNXI_PSI_BASE 0x0300C000
-
- #define SUNXI_GIC400_BASE 0x03020000
-@@ -68,7 +67,6 @@
- #define SUNXI_R_CPUCFG_BASE 0x07000400
- #define SUNXI_PRCM_BASE 0x07010000
- #define SUNXI_R_WDOG_BASE 0x07020400
--#define SUNXI_R_PIO_BASE 0x07022000
- #define SUNXI_R_UART_BASE 0x07080000
- #define SUNXI_R_TWI_BASE 0x07081400
-
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
-index 9c2d11b590..20025be231 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
-@@ -81,7 +81,6 @@
- /* APB0 Module */
- #define SUNXI_CCM_BASE (REGS_APB0_BASE + 0x0000)
- #define SUNXI_CCMMODULE_BASE (REGS_APB0_BASE + 0x0400)
--#define SUNXI_PIO_BASE (REGS_APB0_BASE + 0x0800)
- #define SUNXI_TIMER_BASE (REGS_APB0_BASE + 0x0C00)
- #define SUNXI_PWM_BASE (REGS_APB0_BASE + 0x1400)
- #define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800)
-@@ -102,7 +101,6 @@
- /* RCPUS Module */
- #define SUNXI_PRCM_BASE (REGS_RCPUS_BASE + 0x1400)
- #define SUNXI_R_UART_BASE (REGS_RCPUS_BASE + 0x2800)
--#define SUNXI_R_PIO_BASE (REGS_RCPUS_BASE + 0x2c00)
- #define SUNXI_RSB_BASE (REGS_RCPUS_BASE + 0x3400)
-
- /* Misc. */
-diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
-index 42ca03d8c1..5ac476f960 100644
---- a/include/sunxi_gpio.h
-+++ b/include/sunxi_gpio.h
-@@ -9,7 +9,17 @@
- #define _SUNXI_GPIO_H
-
- #include <linux/types.h>
--#include <asm/arch/cpu.h>
-+
-+#if defined(CONFIG_MACH_SUN9I)
-+#define SUNXI_PIO_BASE 0x06000800
-+#define SUNXI_R_PIO_BASE 0x08002c00
-+#elif defined(CONFIG_SUN50I_GEN_H6)
-+#define SUNXI_PIO_BASE 0x0300b000
-+#define SUNXI_R_PIO_BASE 0x07022000
-+#else
-+#define SUNXI_PIO_BASE 0x01c20800
-+#define SUNXI_R_PIO_BASE 0x01f02c00
-+#endif
-
- /*
- * sunxi has 9 banks of gpio, they are:
---
-2.20.1
-
--- /dev/null
+From 3cfbf01d126f127aa812102f9c42f9787748cc21 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sun, 22 Jan 2023 16:51:06 -0600
+Subject: [PATCH 4007/4044] net: sun8i-emac: Remove the SoC variant ID
+
+Now that all differences in functionality are covered by individual
+flags, remove the enumeration of SoC variants.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
+---
+ drivers/net/sun8i_emac.c | 14 --------------
+ 1 file changed, 14 deletions(-)
+
+diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
+index 231aac19e3..04c3274fbe 100644
+--- a/drivers/net/sun8i_emac.c
++++ b/drivers/net/sun8i_emac.c
+@@ -127,16 +127,7 @@
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+-enum emac_variant_id {
+- A83T_EMAC = 1,
+- H3_EMAC,
+- A64_EMAC,
+- R40_GMAC,
+- H6_EMAC,
+-};
+-
+ struct emac_variant {
+- enum emac_variant_id variant;
+ uint syscon_offset;
+ bool soc_has_internal_phy;
+ bool support_rmii;
+@@ -895,30 +886,25 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+ }
+
+ static const struct emac_variant emac_variant_a83t = {
+- .variant = A83T_EMAC,
+ .syscon_offset = 0x30,
+ };
+
+ static const struct emac_variant emac_variant_h3 = {
+- .variant = H3_EMAC,
+ .syscon_offset = 0x30,
+ .soc_has_internal_phy = true,
+ .support_rmii = true,
+ };
+
+ static const struct emac_variant emac_variant_r40 = {
+- .variant = R40_GMAC,
+ .syscon_offset = 0x164,
+ };
+
+ static const struct emac_variant emac_variant_a64 = {
+- .variant = A64_EMAC,
+ .syscon_offset = 0x30,
+ .support_rmii = true,
+ };
+
+ static const struct emac_variant emac_variant_h6 = {
+- .variant = H6_EMAC,
+ .syscon_offset = 0x30,
+ .support_rmii = true,
+ };
+--
+2.20.1
+
+++ /dev/null
-From 20903c89595e5ad0eb5fd91eebf0a02f6843e8a6 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Tue, 6 Sep 2022 12:12:50 +0100
-Subject: [PATCH 4007/4031] pinctrl: sunxi: add new D1 pinctrl support
-
-For the first time since at least the Allwinner A10 SoCs, the D1 (and
-related cores) use a new pincontroller MMIO register layout, so we
-cannot use our hardcoded, fixed offsets anymore.
-Ideally this would all be handled by devicetree and DM drivers, but for
-the DT-less SPL we still need the legacy interfaces.
-
-Add a new Kconfig symbol to differenciate between the two generations of
-pincontrollers, and just use that to just switch some basic symbols.
-The rest is already abstracted enough, so works out of the box.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/mach-sunxi/Kconfig | 6 ++++++
- include/sunxi_gpio.h | 26 +++++++++++++++++++++-----
- 2 files changed, 27 insertions(+), 5 deletions(-)
-
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index d716054f72..b328ce8960 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -113,6 +113,12 @@ config SUNXI_SRAM_ADDRESS
- config SUNXI_A64_TIMER_ERRATUM
- bool
-
-+config SUNXI_NEW_PINCTRL
-+ bool
-+ ---help---
-+ The Allwinner D1 and other new SoCs use a different register map
-+ for the GPIO block, which we need to know about in the SPL.
-+
- # Note only one of these may be selected at a time! But hidden choices are
- # not supported by Kconfig
- config SUNXI_GEN_SUN4I
-diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
-index 5ac476f960..2f8b220f75 100644
---- a/include/sunxi_gpio.h
-+++ b/include/sunxi_gpio.h
-@@ -68,15 +68,32 @@
- #define GPIO_DAT_REG_OFFSET 0x10
-
- #define GPIO_DRV_REG_OFFSET 0x14
--#define GPIO_DRV_INDEX(pin) (((pin) & 0x1f) >> 4)
--#define GPIO_DRV_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-+
-+/* Newer SoCs use a slightly different register layout */
-+#ifdef CONFIG_SUNXI_NEW_PINCTRL
-+/* pin drive strength: 4 bits per pin */
-+#define GPIO_DRV_INDEX(pin) ((pin) / 8)
-+#define GPIO_DRV_OFFSET(pin) (((pin) % 8) * 4)
-+
-+#define GPIO_PULL_REG_OFFSET 0x24
-+
-+#define SUNXI_PINCTRL_BANK_SIZE 0x30
-+#define SUNXI_GPIO_DISABLE 0xf
-+
-+#else /* older generation pin controllers */
-+/* pin drive strength: 2 bits per pin */
-+#define GPIO_DRV_INDEX(pin) ((pin) / 16)
-+#define GPIO_DRV_OFFSET(pin) (((pin) % 16) * 2)
-
- #define GPIO_PULL_REG_OFFSET 0x1c
-+
-+#define SUNXI_PINCTRL_BANK_SIZE 0x24
-+#define SUNXI_GPIO_DISABLE 0x7
-+#endif
-+
- #define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
- #define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-
--#define SUNXI_PINCTRL_BANK_SIZE 0x24
--
- static inline void* BANK_TO_GPIO(int bank)
- {
- void *pio_base;
-@@ -132,7 +149,6 @@ enum sunxi_gpio_number {
- /* GPIO pin function config */
- #define SUNXI_GPIO_INPUT 0
- #define SUNXI_GPIO_OUTPUT 1
--#define SUNXI_GPIO_DISABLE 7
-
- #define SUN8I_H3_GPA_UART0 2
- #define SUN8I_H3_GPA_UART2 2
---
-2.20.1
-
+++ /dev/null
-From fccd059eaa3b1fa5873606ffbc700e300a4aec17 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Wed, 5 Oct 2022 17:54:19 +0100
-Subject: [PATCH 4008/4031] sunxi: introduce NCAT2 generation model
-
-Allwinner seems to typically stick to a common MMIO memory map for
-several SoCs, but from time to time does some breaking changes, which
-also introduce new generations of some peripherals. The last time this
-happened with the H6, which apart from re-organising the base addresses
-also changed the clock controller significantly. We added a
-CONFIG_SUN50I_GEN_H6 symbol back then to mark SoCs sharing those traits.
-
-Now the Allwinner D1 changes the memory map again, and also extends the
-pincontroller, among other peripherals.
-To mark this generation of SoCs, add a CONFIG_SUNXI_GEN_NCAT2 symbol,
-this name is reportedly used in the Allwinner BSP code, and prevents us
-from inventing our own name.
-
-Add this new symbol to some guards that were already checking for the H6
-generation, since many features are shared between the two (like the
-renovated clock controller).
-
-This paves the way to introduce a first user of this generation.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/include/asm/arch-sunxi/clock.h | 2 +-
- arch/arm/include/asm/arch-sunxi/cpu.h | 2 +
- .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h | 54 +++++++++++++++++++
- arch/arm/include/asm/arch-sunxi/mmc.h | 2 +-
- arch/arm/include/asm/arch-sunxi/prcm.h | 2 +-
- arch/arm/include/asm/arch-sunxi/timer.h | 2 +-
- arch/arm/mach-sunxi/Kconfig | 14 ++++-
- arch/arm/mach-sunxi/Makefile | 1 +
- arch/arm/mach-sunxi/board.c | 4 +-
- common/spl/Kconfig | 2 +-
- drivers/mmc/sunxi_mmc.c | 10 ++--
- include/sunxi_gpio.h | 3 ++
- 12 files changed, 86 insertions(+), 12 deletions(-)
- create mode 100644 arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-
-diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
-index 2cfd540742..3d34261b0e 100644
---- a/arch/arm/include/asm/arch-sunxi/clock.h
-+++ b/arch/arm/include/asm/arch-sunxi/clock.h
-@@ -16,7 +16,7 @@
- /* clock control module regs definition */
- #if defined(CONFIG_MACH_SUN8I_A83T)
- #include <asm/arch/clock_sun8i_a83t.h>
--#elif defined(CONFIG_SUN50I_GEN_H6)
-+#elif defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- #include <asm/arch/clock_sun50i_h6.h>
- #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
- defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
-index b08f202374..768c6572d6 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
-@@ -10,6 +10,8 @@
- #include <asm/arch/cpu_sun9i.h>
- #elif defined(CONFIG_SUN50I_GEN_H6)
- #include <asm/arch/cpu_sun50i_h6.h>
-+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
-+#include <asm/arch/cpu_sunxi_ncat2.h>
- #else
- #include <asm/arch/cpu_sun4i.h>
- #endif
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-new file mode 100644
-index 0000000000..13093085a5
---- /dev/null
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-@@ -0,0 +1,54 @@
-+/*
-+ * (C) Copyright 2022 Arm Limited
-+ *
-+ * SPDX-License-Identifier: GPL-2.0+
-+ */
-+
-+#ifndef _SUNXI_CPU_SUNXI_NCAT2_H
-+#define _SUNXI_CPU_SUNXI_NCAT2_H
-+
-+#define SUNXI_SRAM_A1_BASE CONFIG_SUNXI_SRAM_ADDRESS
-+#define SUNXI_SRAM_C_BASE 0x00028000
-+#define SUNXI_SRAM_A2_BASE 0x00100000
-+
-+#define SUNXI_SRAMC_BASE 0x02800000
-+#define SUNXI_CCM_BASE 0x02001000
-+/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
-+#define SUNXI_SIDC_BASE 0x03006000
-+#define SUNXI_SID_BASE 0x03006200
-+#define SUNXI_TIMER_BASE 0x02050000
-+
-+#ifdef CONFIG_MACH_SUN50I_H6
-+#define SUNXI_DRAM_COM_BASE 0x04002000
-+#define SUNXI_DRAM_CTL0_BASE 0x04003000
-+#define SUNXI_DRAM_PHY0_BASE 0x04005000
-+#endif
-+#define SUNXI_MMC0_BASE 0x04020000
-+#define SUNXI_MMC1_BASE 0x04021000
-+#define SUNXI_MMC2_BASE 0x04022000
-+
-+#define SUNXI_UART0_BASE 0x02500000
-+#define SUNXI_UART1_BASE 0x02500400
-+#define SUNXI_UART2_BASE 0x02500800
-+#define SUNXI_UART3_BASE 0x02500C00
-+#define SUNXI_TWI0_BASE 0x02502000
-+#define SUNXI_TWI1_BASE 0x02502400
-+#define SUNXI_TWI2_BASE 0x02502800
-+#define SUNXI_TWI3_BASE 0x02502C00
-+#define SUNXI_SPI0_BASE 0x04025000
-+#define SUNXI_SPI1_BASE 0x04026000
-+
-+#define SUNXI_RTC_BASE 0x07000000
-+#define SUNXI_R_CPUCFG_BASE 0x07000400
-+#define SUNXI_PRCM_BASE 0x07010000
-+#define SUNXI_R_WDOG_BASE 0x07020400
-+#define SUNXI_R_UART_BASE 0x07080000
-+#define SUNXI_R_TWI_BASE 0x07081400
-+
-+#ifndef __ASSEMBLY__
-+void sunxi_board_init(void);
-+void sunxi_reset(void);
-+int sunxi_get_sid(unsigned int *sid);
-+#endif
-+
-+#endif /* _SUNXI_CPU_SUNXI_NCAT2_H */
-diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
-index 5daacf10eb..8ed3e0459c 100644
---- a/arch/arm/include/asm/arch-sunxi/mmc.h
-+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
-@@ -45,7 +45,7 @@ struct sunxi_mmc {
- u32 chda; /* 0x90 */
- u32 cbda; /* 0x94 */
- u32 res2[26];
--#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
-+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- u32 res3[17];
- u32 samp_dl;
- u32 res4[46];
-diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
-index 5106076f5e..c5418cfd28 100644
---- a/arch/arm/include/asm/arch-sunxi/prcm.h
-+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
-@@ -9,7 +9,7 @@
- #define _SUNXI_PRCM_H
-
- /* prcm regs definition */
--#if defined(CONFIG_SUN50I_GEN_H6)
-+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- #include <asm/arch/prcm_sun50i.h>
- #else
- #include <asm/arch/prcm_sun6i.h>
-diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
-index bb5626d893..e17db8588e 100644
---- a/arch/arm/include/asm/arch-sunxi/timer.h
-+++ b/arch/arm/include/asm/arch-sunxi/timer.h
-@@ -76,7 +76,7 @@ struct sunxi_timer_reg {
- struct sunxi_tgp tgp[4];
- u8 res5[8];
- u32 cpu_cfg;
--#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
-+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- u8 res3[16];
- struct sunxi_wdog wdog[5]; /* We have 5 watchdogs */
- #endif
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index b328ce8960..057b0ccd33 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -102,7 +102,7 @@ config AXP_PMIC_BUS
- config SUNXI_SRAM_ADDRESS
- hex
- default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
-- default 0x20000 if SUN50I_GEN_H6
-+ default 0x20000 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
- default 0x0
- ---help---
- Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
-@@ -144,6 +144,16 @@ config SUN50I_GEN_H6
- Select this for sunxi SoCs which have H6 like peripherals, clocks
- and memory map.
-
-+config SUNXI_GEN_NCAT2
-+ bool
-+ select FIT
-+ select SPL_LOAD_FIT
-+ select MMC_SUNXI_HAS_NEW_MODE
-+ select SUPPORT_SPL
-+ ---help---
-+ Select this for sunxi SoCs which have D1 like peripherals, clocks
-+ and memory map.
-+
- config SUNXI_DRAM_DW
- bool
- ---help---
-@@ -760,6 +770,7 @@ config VIDEO_SUNXI
- depends on !MACH_SUN9I
- depends on !MACH_SUN50I
- depends on !SUN50I_GEN_H6
-+ depends on !SUNXI_GEN_NCAT2
- select VIDEO
- select DISPLAY
- imply VIDEO_DT_SIMPLEFB
-@@ -973,6 +984,7 @@ config SPL_STACK_R_ADDR
- default 0x2fe00000 if MACH_SUN9I
- default 0x4fe00000 if MACH_SUN50I
- default 0x4fe00000 if SUN50I_GEN_H6
-+ default 0x4fe00000 if SUNXI_GEN_NCAT2
-
- config SPL_SPI_SUNXI
- bool "Support for SPI Flash on Allwinner SoCs in SPL"
-diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
-index 671211e932..1d4c70ec35 100644
---- a/arch/arm/mach-sunxi/Makefile
-+++ b/arch/arm/mach-sunxi/Makefile
-@@ -25,6 +25,7 @@ obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o
- endif
- obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o gtbus_sun9i.o
- obj-$(CONFIG_SUN50I_GEN_H6) += clock_sun50i_h6.o
-+obj-$(CONFIG_SUNXI_GEN_NCAT2) += clock_sun50i_h6.o
- ifndef CONFIG_ARM64
- obj-y += timer.o
- endif
-diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
-index ec46ab9279..6d96182226 100644
---- a/arch/arm/mach-sunxi/board.c
-+++ b/arch/arm/mach-sunxi/board.c
-@@ -176,7 +176,7 @@ static int gpio_init(void)
- #error Unsupported console port number. Please fix pin mux settings in board.c
- #endif
-
--#ifdef CONFIG_SUN50I_GEN_H6
-+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- /* Update PIO power bias configuration by copy hardware detected value */
- val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
- writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
-@@ -481,7 +481,7 @@ void reset_cpu(void)
- /* sun5i sometimes gets stuck without this */
- writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
- }
--#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
-+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- #if defined(CONFIG_MACH_SUN50I_H6)
- /* WDOG is broken for some H6 rev. use the R_WDOG instead */
- static const struct sunxi_wdog *wdog =
-diff --git a/common/spl/Kconfig b/common/spl/Kconfig
-index 3c2af453ab..06bcedca7d 100644
---- a/common/spl/Kconfig
-+++ b/common/spl/Kconfig
-@@ -265,7 +265,7 @@ config SPL_TEXT_BASE
- default 0x402F0400 if AM33XX
- default 0x40301350 if OMAP54XX
- default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
-- default 0x20060 if SUN50I_GEN_H6
-+ default 0x20060 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
- default 0x00060 if ARCH_SUNXI
- default 0xfffc0000 if ARCH_ZYNQMP
- default 0x0
-diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
-index 03e33753fc..a8e590561c 100644
---- a/drivers/mmc/sunxi_mmc.c
-+++ b/drivers/mmc/sunxi_mmc.c
-@@ -57,6 +57,7 @@ static bool sunxi_mmc_can_calibrate(void)
- return IS_ENABLED(CONFIG_MACH_SUN50I) ||
- IS_ENABLED(CONFIG_MACH_SUN50I_H5) ||
- IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
-+ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
- IS_ENABLED(CONFIG_MACH_SUN8I_R40);
- }
-
-@@ -191,7 +192,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc)
- rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
- writel(rval, &priv->reg->clkcr);
-
--#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
-+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- /* A64 supports calibration of delays on MMC controller and we
- * have to set delay of zero before starting calibration.
- * Allwinner BSP driver sets a delay only in the case of
-@@ -530,7 +531,8 @@ struct mmc *sunxi_mmc_init(int sdc_no)
- cfg->host_caps = MMC_MODE_4BIT;
-
- if ((IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN8I) ||
-- IS_ENABLED(CONFIG_SUN50I_GEN_H6)) && (sdc_no == 2))
-+ IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
-+ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) && (sdc_no == 2))
- cfg->host_caps = MMC_MODE_8BIT;
-
- cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
-@@ -544,7 +546,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
-
- /* config ahb clock */
- debug("init mmc %d clock and io\n", sdc_no);
--#if !defined(CONFIG_SUN50I_GEN_H6)
-+#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
- setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
-
- #ifdef CONFIG_SUNXI_GEN_SUN6I
-@@ -619,7 +621,7 @@ static unsigned get_mclk_offset(void)
- if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
- return 0x410;
-
-- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
-+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
- return 0x830;
-
- return 0x88;
-diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
-index 2f8b220f75..04d7aa3d63 100644
---- a/include/sunxi_gpio.h
-+++ b/include/sunxi_gpio.h
-@@ -16,6 +16,9 @@
- #elif defined(CONFIG_SUN50I_GEN_H6)
- #define SUNXI_PIO_BASE 0x0300b000
- #define SUNXI_R_PIO_BASE 0x07022000
-+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
-+#define SUNXI_PIO_BASE 0x02000000
-+#define SUNXI_R_PIO_BASE 0
- #else
- #define SUNXI_PIO_BASE 0x01c20800
- #define SUNXI_R_PIO_BASE 0x01f02c00
---
-2.20.1
-
--- /dev/null
+From 0f7241f68bd8dc76665a050b4012e5882e7badaa Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:48 +0100
+Subject: [PATCH 4008/4044] sunxi: remove CONFIG_MACPWR
+
+The CONFIG_MACPWR Kconfig symbol is used to point to a GPIO that enables
+the power for the Ethernet "MAC" (mostly PHY, really).
+In the DT this is described with the phy-supply property in the MAC DT
+node, pointing to a (GPIO controlled) regulator. Since we need Ethernet
+only in U-Boot proper, and use a DM driver there, we should use the DT
+instead of hardcoding this.
+
+Add code to the sun8i_emac and sunxi_emac drivers to check the DT for
+that regulator and enable it, at probe time. Then drop the current code
+from board.c, which was doing that job before.
+This allows us to remove the MACPWR Kconfig definition and the respective
+values from the defconfigs.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Sam Edwards <CFSworks@gmail.com>
+---
+ arch/arm/mach-sunxi/Kconfig | 7 -------
+ board/sunxi/board.c | 12 +-----------
+ configs/Bananapi_M2_Ultra_defconfig | 1 -
+ configs/Bananapi_defconfig | 1 -
+ configs/Bananapro_defconfig | 1 -
+ configs/Lamobo_R1_defconfig | 1 -
+ configs/Mele_A1000_defconfig | 1 -
+ configs/Orangepi_defconfig | 1 -
+ configs/Orangepi_mini_defconfig | 1 -
+ configs/bananapi_m1_plus_defconfig | 1 -
+ configs/bananapi_m2_plus_h3_defconfig | 1 -
+ configs/bananapi_m2_plus_h5_defconfig | 1 -
+ configs/i12-tvbox_defconfig | 1 -
+ configs/jesurun_q5_defconfig | 1 -
+ configs/mixtile_loftq_defconfig | 1 -
+ configs/nanopi_m1_plus_defconfig | 1 -
+ configs/nanopi_neo_plus2_defconfig | 1 -
+ configs/nanopi_r1s_h5_defconfig | 1 -
+ configs/orangepi_pc2_defconfig | 1 -
+ configs/orangepi_plus2e_defconfig | 1 -
+ configs/orangepi_plus_defconfig | 1 -
+ configs/pine_h64_defconfig | 1 -
+ configs/zeropi_defconfig | 1 -
+ drivers/net/sun8i_emac.c | 9 +++++++--
+ 24 files changed, 8 insertions(+), 41 deletions(-)
+
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index c78a553493..d716054f72 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -645,13 +645,6 @@ config OLD_SUNXI_KERNEL_COMPAT
+ Set this to enable various workarounds for old kernels, this results in
+ sub-optimal settings for newer kernels, only enable if needed.
+
+-config MACPWR
+- string "MAC power pin"
+- default ""
+- help
+- Set the pin used to power the MAC. This takes a string in the format
+- understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
+-
+ config MMC1_PINS_PH
+ bool "Pins for mmc1 are on Port H"
+ depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40
+diff --git a/board/sunxi/board.c b/board/sunxi/board.c
+index fe0e7bc2d9..9900c66ed0 100644
+--- a/board/sunxi/board.c
++++ b/board/sunxi/board.c
+@@ -187,7 +187,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
+ /* add board specific code here */
+ int board_init(void)
+ {
+- __maybe_unused int id_pfr1, ret, macpwr_pin;
++ __maybe_unused int id_pfr1, ret;
+
+ gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
+
+@@ -224,15 +224,6 @@ int board_init(void)
+ if (ret)
+ return ret;
+
+- /* strcmp() would look better, but doesn't get optimised away. */
+- if (CONFIG_MACPWR[0]) {
+- macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
+- if (macpwr_pin >= 0) {
+- gpio_request(macpwr_pin, "macpwr");
+- gpio_direction_output(macpwr_pin, 1);
+- }
+- }
+-
+ #if CONFIG_IS_ENABLED(DM_I2C)
+ /*
+ * Temporary workaround for enabling I2C clocks until proper sunxi DM
+@@ -240,7 +231,6 @@ int board_init(void)
+ */
+ i2c_init_board();
+ #endif
+-
+ eth_init_board();
+
+ return 0;
+diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig
+index a5fe76af56..2cc7bbbd8b 100644
+--- a/configs/Bananapi_M2_Ultra_defconfig
++++ b/configs/Bananapi_M2_Ultra_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-r40-bananapi-m2-ultra"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN8I_R40=y
+ CONFIG_DRAM_CLK=576
+-CONFIG_MACPWR="PA17"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB1_VBUS_PIN="PH23"
+ CONFIG_USB2_VBUS_PIN="PH23"
+diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
+index 6c2a1f630e..f4910ba13a 100644
+--- a/configs/Bananapi_defconfig
++++ b/configs/Bananapi_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=432
+-CONFIG_MACPWR="PH23"
+ CONFIG_VIDEO_COMPOSITE=y
+ CONFIG_GMAC_TX_DELAY=3
+ CONFIG_AHCI=y
+diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
+index 94fd74754e..02be8971df 100644
+--- a/configs/Bananapro_defconfig
++++ b/configs/Bananapro_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapro"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=432
+-CONFIG_MACPWR="PH23"
+ CONFIG_USB1_VBUS_PIN="PH0"
+ CONFIG_USB2_VBUS_PIN="PH1"
+ CONFIG_VIDEO_COMPOSITE=y
+diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
+index 9639cb6aad..66f57ab3c8 100644
+--- a/configs/Lamobo_R1_defconfig
++++ b/configs/Lamobo_R1_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-lamobo-r1"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=432
+-CONFIG_MACPWR="PH23"
+ CONFIG_GMAC_TX_DELAY=4
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig
+index f5b6d908cd..9ac2e4839d 100644
+--- a/configs/Mele_A1000_defconfig
++++ b/configs/Mele_A1000_defconfig
+@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
+ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-a1000"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN4I=y
+-CONFIG_MACPWR="PH15"
+ CONFIG_VIDEO_VGA=y
+ CONFIG_VIDEO_COMPOSITE=y
+ CONFIG_AHCI=y
+diff --git a/configs/Orangepi_defconfig b/configs/Orangepi_defconfig
+index c89a9a1f9d..53edf525ec 100644
+--- a/configs/Orangepi_defconfig
++++ b/configs/Orangepi_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=432
+-CONFIG_MACPWR="PH23"
+ CONFIG_USB1_VBUS_PIN="PH26"
+ CONFIG_USB2_VBUS_PIN="PH22"
+ CONFIG_VIDEO_VGA=y
+diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
+index fe9ce808a1..ccf3267017 100644
+--- a/configs/Orangepi_mini_defconfig
++++ b/configs/Orangepi_mini_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi-mini"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=432
+-CONFIG_MACPWR="PH23"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=3
+ CONFIG_USB1_VBUS_PIN="PH26"
+ CONFIG_USB2_VBUS_PIN="PH22"
+diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
+index 0fbb619d62..a432a01f6b 100644
+--- a/configs/bananapi_m1_plus_defconfig
++++ b/configs/bananapi_m1_plus_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi-m1-plus"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=432
+-CONFIG_MACPWR="PH23"
+ CONFIG_VIDEO_COMPOSITE=y
+ CONFIG_GMAC_TX_DELAY=3
+ CONFIG_AHCI=y
+diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig
+index 26ced59fb0..a8f9b5044b 100644
+--- a/configs/bananapi_m2_plus_h3_defconfig
++++ b/configs/bananapi_m2_plus_h3_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN8I_H3=y
+ CONFIG_DRAM_CLK=672
+-CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SUN8I_EMAC=y
+diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig
+index fb6c945919..1634f62619 100644
+--- a/configs/bananapi_m2_plus_h5_defconfig
++++ b/configs/bananapi_m2_plus_h5_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-bananapi-m2-plus"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN50I_H5=y
+ CONFIG_DRAM_CLK=672
+-CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SUN8I_EMAC=y
+diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
+index 257dd89af4..37f0f53ae7 100644
+--- a/configs/i12-tvbox_defconfig
++++ b/configs/i12-tvbox_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-i12-tvbox"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN7I=y
+ CONFIG_DRAM_CLK=384
+-CONFIG_MACPWR="PH21"
+ CONFIG_VIDEO_COMPOSITE=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/jesurun_q5_defconfig b/configs/jesurun_q5_defconfig
+index 0ff666b2ee..c99be7cea4 100644
+--- a/configs/jesurun_q5_defconfig
++++ b/configs/jesurun_q5_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-jesurun-q5"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN4I=y
+ CONFIG_DRAM_CLK=312
+-CONFIG_MACPWR="PH19"
+ CONFIG_USB0_VBUS_PIN="PB9"
+ CONFIG_VIDEO_COMPOSITE=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/mixtile_loftq_defconfig b/configs/mixtile_loftq_defconfig
+index 0e4cdc4467..2f92228eb7 100644
+--- a/configs/mixtile_loftq_defconfig
++++ b/configs/mixtile_loftq_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-mixtile-loftq"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN6I=y
+ CONFIG_DRAM_ZQ=251
+-CONFIG_MACPWR="PA21"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB1_VBUS_PIN="PH24"
+ CONFIG_USB2_VBUS_PIN=""
+diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
+index 76655d79ae..078e98b644 100644
+--- a/configs/nanopi_m1_plus_defconfig
++++ b/configs/nanopi_m1_plus_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN8I_H3=y
+ CONFIG_DRAM_CLK=408
+-CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SUN8I_EMAC=y
+diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
+index 924ff38f17..85ff31c6fe 100644
+--- a/configs/nanopi_neo_plus2_defconfig
++++ b/configs/nanopi_neo_plus2_defconfig
+@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
+ CONFIG_DRAM_CLK=408
+ CONFIG_DRAM_ZQ=3881977
+ # CONFIG_DRAM_ODT_EN is not set
+-CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SUN8I_EMAC=y
+diff --git a/configs/nanopi_r1s_h5_defconfig b/configs/nanopi_r1s_h5_defconfig
+index 27cf172d72..2a6f94afe4 100644
+--- a/configs/nanopi_r1s_h5_defconfig
++++ b/configs/nanopi_r1s_h5_defconfig
+@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
+ CONFIG_DRAM_CLK=672
+ CONFIG_DRAM_ZQ=3881977
+ # CONFIG_DRAM_ODT_EN is not set
+-CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SUN8I_EMAC=y
+diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
+index 777af8c60e..fb6fbaf787 100644
+--- a/configs/orangepi_pc2_defconfig
++++ b/configs/orangepi_pc2_defconfig
+@@ -5,7 +5,6 @@ CONFIG_SPL=y
+ CONFIG_MACH_SUN50I_H5=y
+ CONFIG_DRAM_CLK=672
+ CONFIG_DRAM_ZQ=3881977
+-CONFIG_MACPWR="PD6"
+ CONFIG_SPL_SPI_SUNXI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
+index 138a6a72b8..5e2cbc48ea 100644
+--- a/configs/orangepi_plus2e_defconfig
++++ b/configs/orangepi_plus2e_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus2e"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN8I_H3=y
+ CONFIG_DRAM_CLK=672
+-CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_SPL_I2C=y
+diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
+index ed585881d4..092ce77a6c 100644
+--- a/configs/orangepi_plus_defconfig
++++ b/configs/orangepi_plus_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN8I_H3=y
+ CONFIG_DRAM_CLK=672
+-CONFIG_MACPWR="PD6"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB1_VBUS_PIN="PG13"
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
+index 6dac6098d0..4712b8e469 100644
+--- a/configs/pine_h64_defconfig
++++ b/configs/pine_h64_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-pine-h64"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN50I_H6=y
+ CONFIG_SUNXI_DRAM_H6_LPDDR3=y
+-CONFIG_MACPWR="PC16"
+ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB3_VBUS_PIN="PL5"
+ CONFIG_SPL_SPI_SUNXI=y
+diff --git a/configs/zeropi_defconfig b/configs/zeropi_defconfig
+index 11f3715e6d..7901bffd15 100644
+--- a/configs/zeropi_defconfig
++++ b/configs/zeropi_defconfig
+@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-zeropi"
+ CONFIG_SPL=y
+ CONFIG_MACH_SUN8I_H3=y
+ CONFIG_DRAM_CLK=408
+-CONFIG_MACPWR="PD6"
+ # CONFIG_VIDEO_DE2 is not set
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+ CONFIG_CONSOLE_MUX=y
+diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
+index 04c3274fbe..7b60a60ad5 100644
+--- a/drivers/net/sun8i_emac.c
++++ b/drivers/net/sun8i_emac.c
+@@ -29,6 +29,7 @@
+ #include <net.h>
+ #include <reset.h>
+ #include <wait_bit.h>
++#include <power/regulator.h>
+
+ #define MDIO_CMD_MII_BUSY BIT(0)
+ #define MDIO_CMD_MII_WRITE BIT(1)
+@@ -167,9 +168,8 @@ struct emac_eth_dev {
+ struct clk ephy_clk;
+ struct reset_ctl tx_rst;
+ struct reset_ctl ephy_rst;
+-#if CONFIG_IS_ENABLED(DM_GPIO)
+ struct gpio_desc reset_gpio;
+-#endif
++ struct udevice *phy_reg;
+ };
+
+
+@@ -720,6 +720,9 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
+
+ sun8i_emac_set_syscon(sun8i_pdata, priv);
+
++ if (priv->phy_reg)
++ regulator_set_enable(priv->phy_reg, true);
++
+ sun8i_mdio_init(dev->name, dev);
+ priv->bus = miiphy_get_dev_by_name(dev->name);
+
+@@ -829,6 +832,8 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
+
+ priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
+
++ device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
++
+ pdata->phy_interface = -1;
+ priv->phyaddr = -1;
+ priv->use_internal_phy = false;
+--
+2.20.1
+
+++ /dev/null
-From c02a1ec850b5ff48527776589a0407004a92a33e Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Mon, 5 Sep 2022 16:25:57 +0100
-Subject: [PATCH 4009/4031] pinctrl: sunxi: add Allwinner D1 pinctrl
- description
-
-Apart from using the new pinctrl MMIO register layout, the Allwinner D1
-and related SoCs still need to usual set of mux values hardcoded in
-U-Boot's pinctrl driver.
-Add the values we need so far to this list, so that DM based drivers
-will just work without further ado.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- drivers/pinctrl/sunxi/Kconfig | 4 ++++
- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 28 +++++++++++++++++++++++++++
- 2 files changed, 32 insertions(+)
-
-diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
-index 77da90836b..c8f937d91e 100644
---- a/drivers/pinctrl/sunxi/Kconfig
-+++ b/drivers/pinctrl/sunxi/Kconfig
-@@ -124,4 +124,8 @@ config PINCTRL_SUN50I_H616_R
- default MACH_SUN50I_H616
- select PINCTRL_SUNXI
-
-+config PINCTRL_SUN20I_D1
-+ bool "Support for the Allwinner D1/R528 PIO"
-+ select PINCTRL_SUNXI
-+
- endif
-diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-index 4c52e3fa74..614cfe6b73 100644
---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-@@ -735,6 +735,28 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc
- .num_banks = 1,
- };
-
-+static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
-+ { "emac", 8 }, /* PE0-PE15 */
-+ { "gpio_in", 0 },
-+ { "gpio_out", 1 },
-+ { "mmc0", 2 }, /* PF0-PF5 */
-+ { "mmc2", 3 }, /* PC1-PC7 */
-+ { "spi0", 2 }, /* PC2-PC7 */
-+#if IS_ENABLED(CONFIG_UART0_PORT_F)
-+ { "uart0", 3 }, /* PF2-PF4 */
-+#else
-+ { "uart0", 6 }, /* PB2-PB3 */
-+#endif
-+ { "uart3", 7 }, /* PB6-PB9 */
-+};
-+
-+static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
-+ .functions = sun20i_d1_pinctrl_functions,
-+ .num_functions = ARRAY_SIZE(sun20i_d1_pinctrl_functions),
-+ .first_bank = SUNXI_GPIO_A,
-+ .num_banks = 7,
-+};
-+
- static const struct udevice_id sunxi_pinctrl_ids[] = {
- #ifdef CONFIG_PINCTRL_SUNIV_F1C100S
- {
-@@ -891,6 +913,12 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
- .compatible = "allwinner,sun50i-h616-r-pinctrl",
- .data = (ulong)&sun50i_h616_r_pinctrl_desc,
- },
-+#endif
-+#ifdef CONFIG_PINCTRL_SUN20I_D1
-+ {
-+ .compatible = "allwinner,sun20i-d1-pinctrl",
-+ .data = (ulong)&sun20i_d1_pinctrl_desc,
-+ },
- #endif
- {}
- };
---
-2.20.1
-
--- /dev/null
+From 83871970cde779ab23107aa46cc840afd435314e Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:49 +0100
+Subject: [PATCH 4009/4044] pinctrl: sunxi: add GPIO in/out wrappers
+
+So far we were open-coding the pincontroller's GPIO output/input access
+in each function using that.
+
+Provide functions that wrap that nicely, and follow the existing pattern
+(set/get_{bank,}), so users don't need to know about the internals, and
+we can abstract the new D1 pinctrl more easily.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Sam Edwards <CFSworks@gmail.com>
+Tested-by: Sam Edwards <CFSworks@gmail.com>
+---
+ arch/arm/include/asm/arch-sunxi/gpio.h | 4 +++
+ arch/arm/mach-sunxi/pinmux.c | 28 +++++++++++++++
+ drivers/gpio/sunxi_gpio.c | 49 +++++---------------------
+ 3 files changed, 40 insertions(+), 41 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
+index 437e86479c..2e7c84e410 100644
+--- a/arch/arm/include/asm/arch-sunxi/gpio.h
++++ b/arch/arm/include/asm/arch-sunxi/gpio.h
+@@ -222,6 +222,10 @@ void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
+ void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
+ int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
+ int sunxi_gpio_get_cfgpin(u32 pin);
++void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, int pin, bool set);
++void sunxi_gpio_set_output(u32 pin, bool set);
++int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin);
++int sunxi_gpio_get_output(u32 pin);
+ void sunxi_gpio_set_drv(u32 pin, u32 val);
+ void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
+ void sunxi_gpio_set_pull(u32 pin, u32 val);
+diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
+index c95fcee9f6..751cac8e09 100644
+--- a/arch/arm/mach-sunxi/pinmux.c
++++ b/arch/arm/mach-sunxi/pinmux.c
+@@ -45,6 +45,34 @@ int sunxi_gpio_get_cfgpin(u32 pin)
+ return sunxi_gpio_get_cfgbank(pio, pin);
+ }
+
++void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, int pin, bool set)
++{
++ u32 mask = 1U << GPIO_NUM(pin);
++
++ clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
++}
++
++void sunxi_gpio_set_output(u32 pin, bool set)
++{
++ u32 bank = GPIO_BANK(pin);
++ struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++
++ sunxi_gpio_set_output_bank(pio, pin, set);
++}
++
++int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)
++{
++ return !!(readl(&pio->dat) & (1U << GPIO_NUM(pin)));
++}
++
++int sunxi_gpio_get_output(u32 pin)
++{
++ u32 bank = GPIO_BANK(pin);
++ struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++
++ return sunxi_gpio_get_output_bank(pio, pin);
++}
++
+ void sunxi_gpio_set_drv(u32 pin, u32 val)
+ {
+ u32 bank = GPIO_BANK(pin);
+diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+index 1e85db179a..6796375d35 100644
+--- a/drivers/gpio/sunxi_gpio.c
++++ b/drivers/gpio/sunxi_gpio.c
+@@ -19,37 +19,6 @@
+ #include <dt-bindings/gpio/gpio.h>
+
+ #if !CONFIG_IS_ENABLED(DM_GPIO)
+-static int sunxi_gpio_output(u32 pin, u32 val)
+-{
+- u32 dat;
+- u32 bank = GPIO_BANK(pin);
+- u32 num = GPIO_NUM(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+-
+- dat = readl(&pio->dat);
+- if (val)
+- dat |= 0x1 << num;
+- else
+- dat &= ~(0x1 << num);
+-
+- writel(dat, &pio->dat);
+-
+- return 0;
+-}
+-
+-static int sunxi_gpio_input(u32 pin)
+-{
+- u32 dat;
+- u32 bank = GPIO_BANK(pin);
+- u32 num = GPIO_NUM(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+-
+- dat = readl(&pio->dat);
+- dat >>= num;
+-
+- return dat & 0x1;
+-}
+-
+ int gpio_request(unsigned gpio, const char *label)
+ {
+ return 0;
+@@ -70,18 +39,21 @@ int gpio_direction_input(unsigned gpio)
+ int gpio_direction_output(unsigned gpio, int value)
+ {
+ sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
++ sunxi_gpio_set_output(gpio, value);
+
+- return sunxi_gpio_output(gpio, value);
++ return 0;
+ }
+
+ int gpio_get_value(unsigned gpio)
+ {
+- return sunxi_gpio_input(gpio);
++ return sunxi_gpio_get_output(gpio);
+ }
+
+ int gpio_set_value(unsigned gpio, int value)
+ {
+- return sunxi_gpio_output(gpio, value);
++ sunxi_gpio_set_output(gpio, value);
++
++ return 0;
+ }
+
+ int sunxi_name_to_gpio(const char *name)
+@@ -135,13 +107,8 @@ int sunxi_name_to_gpio(const char *name)
+ static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
+ {
+ struct sunxi_gpio_plat *plat = dev_get_plat(dev);
+- u32 num = GPIO_NUM(offset);
+- unsigned dat;
+-
+- dat = readl(&plat->regs->dat);
+- dat >>= num;
+
+- return dat & 0x1;
++ return sunxi_gpio_get_output_bank(plat->regs, offset) & 0x1;
+ }
+
+ static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
+@@ -181,7 +148,7 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
+ u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
+ u32 num = GPIO_NUM(offset);
+
+- clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
++ sunxi_gpio_set_output_bank(plat->regs, num, value);
+ sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
+ } else if (flags & GPIOD_IS_IN) {
+ u32 pull = 0;
+--
+2.20.1
+
+++ /dev/null
-From 67617005348057a6546b99125d64a7dcc440901a Mon Sep 17 00:00:00 2001
-From: Samuel Holland <samuel@sholland.org>
-Date: Sat, 30 Apr 2022 22:38:37 -0500
-Subject: [PATCH 4010/4031] clk: sunxi: Add support for the D1 CCU
-
-Since the D1 CCU binding is defined, we can add support for its
-gates/resets, following the pattern of the existing drivers.
-
-Signed-off-by: Samuel Holland <samuel@sholland.org>
-Reviewed-by: Andre Przywara <andre.przywara@arm.com>
-Acked-by: Sean Anderson <seanga2@gmail.com>
----
- drivers/clk/sunxi/Kconfig | 6 +
- drivers/clk/sunxi/Makefile | 1 +
- drivers/clk/sunxi/clk_d1.c | 101 ++++++++++++++
- include/dt-bindings/clock/sun20i-d1-ccu.h | 156 ++++++++++++++++++++++
- include/dt-bindings/reset/sun20i-d1-ccu.h | 77 +++++++++++
- 5 files changed, 341 insertions(+)
- create mode 100644 drivers/clk/sunxi/clk_d1.c
- create mode 100644 include/dt-bindings/clock/sun20i-d1-ccu.h
- create mode 100644 include/dt-bindings/reset/sun20i-d1-ccu.h
-
-diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
-index bf11fad6ee..f65e482ba4 100644
---- a/drivers/clk/sunxi/Kconfig
-+++ b/drivers/clk/sunxi/Kconfig
-@@ -87,6 +87,12 @@ config CLK_SUN8I_H3
- This enables common clock driver support for platforms based
- on Allwinner H3/H5 SoC.
-
-+config CLK_SUN20I_D1
-+ bool "Clock driver for Allwinner D1"
-+ help
-+ This enables common clock driver support for platforms based
-+ on Allwinner D1 SoC.
-+
- config CLK_SUN50I_H6
- bool "Clock driver for Allwinner H6"
- default MACH_SUN50I_H6
-diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
-index 895da02ebe..90a277489d 100644
---- a/drivers/clk/sunxi/Makefile
-+++ b/drivers/clk/sunxi/Makefile
-@@ -19,6 +19,7 @@ obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
- obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
- obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
- obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
-+obj-$(CONFIG_CLK_SUN20I_D1) += clk_d1.o
- obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
- obj-$(CONFIG_CLK_SUN50I_H6_R) += clk_h6_r.o
- obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
-diff --git a/drivers/clk/sunxi/clk_d1.c b/drivers/clk/sunxi/clk_d1.c
-new file mode 100644
-index 0000000000..9412b77a54
---- /dev/null
-+++ b/drivers/clk/sunxi/clk_d1.c
-@@ -0,0 +1,101 @@
-+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-+/*
-+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
-+ */
-+
-+#include <common.h>
-+#include <clk-uclass.h>
-+#include <dm.h>
-+#include <errno.h>
-+#include <clk/sunxi.h>
-+#include <dt-bindings/clock/sun20i-d1-ccu.h>
-+#include <dt-bindings/reset/sun20i-d1-ccu.h>
-+#include <linux/bitops.h>
-+
-+static struct ccu_clk_gate d1_gates[] = {
-+ [CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
-+ [CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
-+ [CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
-+ [CLK_BUS_UART0] = GATE(0x90c, BIT(0)),
-+ [CLK_BUS_UART1] = GATE(0x90c, BIT(1)),
-+ [CLK_BUS_UART2] = GATE(0x90c, BIT(2)),
-+ [CLK_BUS_UART3] = GATE(0x90c, BIT(3)),
-+ [CLK_BUS_UART4] = GATE(0x90c, BIT(4)),
-+ [CLK_BUS_UART5] = GATE(0x90c, BIT(5)),
-+ [CLK_BUS_I2C0] = GATE(0x91c, BIT(0)),
-+ [CLK_BUS_I2C1] = GATE(0x91c, BIT(1)),
-+ [CLK_BUS_I2C2] = GATE(0x91c, BIT(2)),
-+ [CLK_BUS_I2C3] = GATE(0x91c, BIT(3)),
-+ [CLK_SPI0] = GATE(0x940, BIT(31)),
-+ [CLK_SPI1] = GATE(0x944, BIT(31)),
-+ [CLK_BUS_SPI0] = GATE(0x96c, BIT(0)),
-+ [CLK_BUS_SPI1] = GATE(0x96c, BIT(1)),
-+
-+ [CLK_BUS_EMAC] = GATE(0x97c, BIT(0)),
-+
-+ [CLK_USB_OHCI0] = GATE(0xa70, BIT(31)),
-+ [CLK_USB_OHCI1] = GATE(0xa74, BIT(31)),
-+ [CLK_BUS_OHCI0] = GATE(0xa8c, BIT(0)),
-+ [CLK_BUS_OHCI1] = GATE(0xa8c, BIT(1)),
-+ [CLK_BUS_EHCI0] = GATE(0xa8c, BIT(4)),
-+ [CLK_BUS_EHCI1] = GATE(0xa8c, BIT(5)),
-+ [CLK_BUS_OTG] = GATE(0xa8c, BIT(8)),
-+ [CLK_BUS_LRADC] = GATE(0xa9c, BIT(0)),
-+
-+ [CLK_RISCV] = GATE(0xd04, BIT(31)),
-+};
-+
-+static struct ccu_reset d1_resets[] = {
-+ [RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
-+ [RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
-+ [RST_BUS_MMC2] = RESET(0x84c, BIT(18)),
-+ [RST_BUS_UART0] = RESET(0x90c, BIT(16)),
-+ [RST_BUS_UART1] = RESET(0x90c, BIT(17)),
-+ [RST_BUS_UART2] = RESET(0x90c, BIT(18)),
-+ [RST_BUS_UART3] = RESET(0x90c, BIT(19)),
-+ [RST_BUS_UART4] = RESET(0x90c, BIT(20)),
-+ [RST_BUS_UART5] = RESET(0x90c, BIT(21)),
-+ [RST_BUS_I2C0] = RESET(0x91c, BIT(16)),
-+ [RST_BUS_I2C1] = RESET(0x91c, BIT(17)),
-+ [RST_BUS_I2C2] = RESET(0x91c, BIT(18)),
-+ [RST_BUS_I2C3] = RESET(0x91c, BIT(19)),
-+ [RST_BUS_SPI0] = RESET(0x96c, BIT(16)),
-+ [RST_BUS_SPI1] = RESET(0x96c, BIT(17)),
-+
-+ [RST_BUS_EMAC] = RESET(0x97c, BIT(16)),
-+
-+ [RST_USB_PHY0] = RESET(0xa70, BIT(30)),
-+ [RST_USB_PHY1] = RESET(0xa74, BIT(30)),
-+ [RST_BUS_OHCI0] = RESET(0xa8c, BIT(16)),
-+ [RST_BUS_OHCI1] = RESET(0xa8c, BIT(17)),
-+ [RST_BUS_EHCI0] = RESET(0xa8c, BIT(20)),
-+ [RST_BUS_EHCI1] = RESET(0xa8c, BIT(21)),
-+ [RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
-+ [RST_BUS_LRADC] = RESET(0xa9c, BIT(16)),
-+};
-+
-+static const struct ccu_desc d1_ccu_desc = {
-+ .gates = d1_gates,
-+ .resets = d1_resets,
-+};
-+
-+static int d1_clk_bind(struct udevice *dev)
-+{
-+ return sunxi_reset_bind(dev, ARRAY_SIZE(d1_resets));
-+}
-+
-+static const struct udevice_id d1_ccu_ids[] = {
-+ { .compatible = "allwinner,sun20i-d1-ccu",
-+ .data = (ulong)&d1_ccu_desc },
-+ { }
-+};
-+
-+U_BOOT_DRIVER(clk_sun20i_d1) = {
-+ .name = "sun20i_d1_ccu",
-+ .id = UCLASS_CLK,
-+ .of_match = d1_ccu_ids,
-+ .priv_auto = sizeof(struct ccu_priv),
-+ .ops = &sunxi_clk_ops,
-+ .probe = sunxi_clk_probe,
-+ .bind = d1_clk_bind,
-+};
-diff --git a/include/dt-bindings/clock/sun20i-d1-ccu.h b/include/dt-bindings/clock/sun20i-d1-ccu.h
-new file mode 100644
-index 0000000000..e3ac53315e
---- /dev/null
-+++ b/include/dt-bindings/clock/sun20i-d1-ccu.h
-@@ -0,0 +1,156 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
-+/*
-+ * Copyright (C) 2020 huangzhenwei@allwinnertech.com
-+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
-+ */
-+
-+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
-+#define _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
-+
-+#define CLK_PLL_CPUX 0
-+#define CLK_PLL_DDR0 1
-+#define CLK_PLL_PERIPH0_4X 2
-+#define CLK_PLL_PERIPH0_2X 3
-+#define CLK_PLL_PERIPH0_800M 4
-+#define CLK_PLL_PERIPH0 5
-+#define CLK_PLL_PERIPH0_DIV3 6
-+#define CLK_PLL_VIDEO0_4X 7
-+#define CLK_PLL_VIDEO0_2X 8
-+#define CLK_PLL_VIDEO0 9
-+#define CLK_PLL_VIDEO1_4X 10
-+#define CLK_PLL_VIDEO1_2X 11
-+#define CLK_PLL_VIDEO1 12
-+#define CLK_PLL_VE 13
-+#define CLK_PLL_AUDIO0_4X 14
-+#define CLK_PLL_AUDIO0_2X 15
-+#define CLK_PLL_AUDIO0 16
-+#define CLK_PLL_AUDIO1 17
-+#define CLK_PLL_AUDIO1_DIV2 18
-+#define CLK_PLL_AUDIO1_DIV5 19
-+#define CLK_CPUX 20
-+#define CLK_CPUX_AXI 21
-+#define CLK_CPUX_APB 22
-+#define CLK_PSI_AHB 23
-+#define CLK_APB0 24
-+#define CLK_APB1 25
-+#define CLK_MBUS 26
-+#define CLK_DE 27
-+#define CLK_BUS_DE 28
-+#define CLK_DI 29
-+#define CLK_BUS_DI 30
-+#define CLK_G2D 31
-+#define CLK_BUS_G2D 32
-+#define CLK_CE 33
-+#define CLK_BUS_CE 34
-+#define CLK_VE 35
-+#define CLK_BUS_VE 36
-+#define CLK_BUS_DMA 37
-+#define CLK_BUS_MSGBOX0 38
-+#define CLK_BUS_MSGBOX1 39
-+#define CLK_BUS_MSGBOX2 40
-+#define CLK_BUS_SPINLOCK 41
-+#define CLK_BUS_HSTIMER 42
-+#define CLK_AVS 43
-+#define CLK_BUS_DBG 44
-+#define CLK_BUS_PWM 45
-+#define CLK_BUS_IOMMU 46
-+#define CLK_DRAM 47
-+#define CLK_MBUS_DMA 48
-+#define CLK_MBUS_VE 49
-+#define CLK_MBUS_CE 50
-+#define CLK_MBUS_TVIN 51
-+#define CLK_MBUS_CSI 52
-+#define CLK_MBUS_G2D 53
-+#define CLK_MBUS_RISCV 54
-+#define CLK_BUS_DRAM 55
-+#define CLK_MMC0 56
-+#define CLK_MMC1 57
-+#define CLK_MMC2 58
-+#define CLK_BUS_MMC0 59
-+#define CLK_BUS_MMC1 60
-+#define CLK_BUS_MMC2 61
-+#define CLK_BUS_UART0 62
-+#define CLK_BUS_UART1 63
-+#define CLK_BUS_UART2 64
-+#define CLK_BUS_UART3 65
-+#define CLK_BUS_UART4 66
-+#define CLK_BUS_UART5 67
-+#define CLK_BUS_I2C0 68
-+#define CLK_BUS_I2C1 69
-+#define CLK_BUS_I2C2 70
-+#define CLK_BUS_I2C3 71
-+#define CLK_SPI0 72
-+#define CLK_SPI1 73
-+#define CLK_BUS_SPI0 74
-+#define CLK_BUS_SPI1 75
-+#define CLK_EMAC_25M 76
-+#define CLK_BUS_EMAC 77
-+#define CLK_IR_TX 78
-+#define CLK_BUS_IR_TX 79
-+#define CLK_BUS_GPADC 80
-+#define CLK_BUS_THS 81
-+#define CLK_I2S0 82
-+#define CLK_I2S1 83
-+#define CLK_I2S2 84
-+#define CLK_I2S2_ASRC 85
-+#define CLK_BUS_I2S0 86
-+#define CLK_BUS_I2S1 87
-+#define CLK_BUS_I2S2 88
-+#define CLK_SPDIF_TX 89
-+#define CLK_SPDIF_RX 90
-+#define CLK_BUS_SPDIF 91
-+#define CLK_DMIC 92
-+#define CLK_BUS_DMIC 93
-+#define CLK_AUDIO_DAC 94
-+#define CLK_AUDIO_ADC 95
-+#define CLK_BUS_AUDIO 96
-+#define CLK_USB_OHCI0 97
-+#define CLK_USB_OHCI1 98
-+#define CLK_BUS_OHCI0 99
-+#define CLK_BUS_OHCI1 100
-+#define CLK_BUS_EHCI0 101
-+#define CLK_BUS_EHCI1 102
-+#define CLK_BUS_OTG 103
-+#define CLK_BUS_LRADC 104
-+#define CLK_BUS_DPSS_TOP 105
-+#define CLK_HDMI_24M 106
-+#define CLK_HDMI_CEC_32K 107
-+#define CLK_HDMI_CEC 108
-+#define CLK_BUS_HDMI 109
-+#define CLK_MIPI_DSI 110
-+#define CLK_BUS_MIPI_DSI 111
-+#define CLK_TCON_LCD0 112
-+#define CLK_BUS_TCON_LCD0 113
-+#define CLK_TCON_TV 114
-+#define CLK_BUS_TCON_TV 115
-+#define CLK_TVE 116
-+#define CLK_BUS_TVE_TOP 117
-+#define CLK_BUS_TVE 118
-+#define CLK_TVD 119
-+#define CLK_BUS_TVD_TOP 120
-+#define CLK_BUS_TVD 121
-+#define CLK_LEDC 122
-+#define CLK_BUS_LEDC 123
-+#define CLK_CSI_TOP 124
-+#define CLK_CSI_MCLK 125
-+#define CLK_BUS_CSI 126
-+#define CLK_TPADC 127
-+#define CLK_BUS_TPADC 128
-+#define CLK_BUS_TZMA 129
-+#define CLK_DSP 130
-+#define CLK_BUS_DSP_CFG 131
-+#define CLK_RISCV 132
-+#define CLK_RISCV_AXI 133
-+#define CLK_BUS_RISCV_CFG 134
-+#define CLK_FANOUT_24M 135
-+#define CLK_FANOUT_12M 136
-+#define CLK_FANOUT_16M 137
-+#define CLK_FANOUT_25M 138
-+#define CLK_FANOUT_32K 139
-+#define CLK_FANOUT_27M 140
-+#define CLK_FANOUT_PCLK 141
-+#define CLK_FANOUT0 142
-+#define CLK_FANOUT1 143
-+#define CLK_FANOUT2 144
-+
-+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ */
-diff --git a/include/dt-bindings/reset/sun20i-d1-ccu.h b/include/dt-bindings/reset/sun20i-d1-ccu.h
-new file mode 100644
-index 0000000000..de9ff52032
---- /dev/null
-+++ b/include/dt-bindings/reset/sun20i-d1-ccu.h
-@@ -0,0 +1,77 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
-+/*
-+ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
-+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
-+ */
-+
-+#ifndef _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
-+#define _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
-+
-+#define RST_MBUS 0
-+#define RST_BUS_DE 1
-+#define RST_BUS_DI 2
-+#define RST_BUS_G2D 3
-+#define RST_BUS_CE 4
-+#define RST_BUS_VE 5
-+#define RST_BUS_DMA 6
-+#define RST_BUS_MSGBOX0 7
-+#define RST_BUS_MSGBOX1 8
-+#define RST_BUS_MSGBOX2 9
-+#define RST_BUS_SPINLOCK 10
-+#define RST_BUS_HSTIMER 11
-+#define RST_BUS_DBG 12
-+#define RST_BUS_PWM 13
-+#define RST_BUS_DRAM 14
-+#define RST_BUS_MMC0 15
-+#define RST_BUS_MMC1 16
-+#define RST_BUS_MMC2 17
-+#define RST_BUS_UART0 18
-+#define RST_BUS_UART1 19
-+#define RST_BUS_UART2 20
-+#define RST_BUS_UART3 21
-+#define RST_BUS_UART4 22
-+#define RST_BUS_UART5 23
-+#define RST_BUS_I2C0 24
-+#define RST_BUS_I2C1 25
-+#define RST_BUS_I2C2 26
-+#define RST_BUS_I2C3 27
-+#define RST_BUS_SPI0 28
-+#define RST_BUS_SPI1 29
-+#define RST_BUS_EMAC 30
-+#define RST_BUS_IR_TX 31
-+#define RST_BUS_GPADC 32
-+#define RST_BUS_THS 33
-+#define RST_BUS_I2S0 34
-+#define RST_BUS_I2S1 35
-+#define RST_BUS_I2S2 36
-+#define RST_BUS_SPDIF 37
-+#define RST_BUS_DMIC 38
-+#define RST_BUS_AUDIO 39
-+#define RST_USB_PHY0 40
-+#define RST_USB_PHY1 41
-+#define RST_BUS_OHCI0 42
-+#define RST_BUS_OHCI1 43
-+#define RST_BUS_EHCI0 44
-+#define RST_BUS_EHCI1 45
-+#define RST_BUS_OTG 46
-+#define RST_BUS_LRADC 47
-+#define RST_BUS_DPSS_TOP 48
-+#define RST_BUS_HDMI_SUB 49
-+#define RST_BUS_HDMI_MAIN 50
-+#define RST_BUS_MIPI_DSI 51
-+#define RST_BUS_TCON_LCD0 52
-+#define RST_BUS_TCON_TV 53
-+#define RST_BUS_LVDS0 54
-+#define RST_BUS_TVE 55
-+#define RST_BUS_TVE_TOP 56
-+#define RST_BUS_TVD 57
-+#define RST_BUS_TVD_TOP 58
-+#define RST_BUS_LEDC 59
-+#define RST_BUS_CSI 60
-+#define RST_BUS_TPADC 61
-+#define RST_DSP 62
-+#define RST_BUS_DSP_CFG 63
-+#define RST_BUS_DSP_DBG 64
-+#define RST_BUS_RISCV_CFG 65
-+
-+#endif /* _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ */
---
-2.20.1
-
--- /dev/null
+From d795f4442b8c044346c0a7d7acf99481f5bbc45f Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:50 +0100
+Subject: [PATCH 4010/4044] pinctrl: sunxi: remove struct sunxi_gpio
+
+So far every Allwinner SoC used the same basic pincontroller/GPIO
+register frame, and just differed by the number of implemented banks and
+pins, plus some special functionality from time to time. However the D1
+and successors use a slightly different pinctrl register layout.
+Use that opportunity to drop "struct sunxi_gpio", that described that
+MMIO frame in a C struct. That approach is somewhat frowned upon in the
+Linux world and rarely used there, though still popular with U-Boot.
+
+Switching from a C struct to a "base address plus offset" approach allows
+to switch between the two models more dynamically, without reverting to
+preprocessor macros and #ifdef's.
+
+Model the pinctrl MMIO register frame in the usual "base address +
+offset" way, and replace a hard-to-parse CPP macro with a more readable
+static function.
+All the users get converted over. There are no functional changes at
+this point, it just prepares the stages for the D1 and friends.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/include/asm/arch-sunxi/gpio.h | 67 +++++++++++---------------
+ arch/arm/mach-sunxi/pinmux.c | 66 +++++++++++++------------
+ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 14 +++---
+ 3 files changed, 71 insertions(+), 76 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
+index 2e7c84e410..96a29aa023 100644
+--- a/arch/arm/include/asm/arch-sunxi/gpio.h
++++ b/arch/arm/include/asm/arch-sunxi/gpio.h
+@@ -28,13 +28,6 @@
+ #define SUNXI_GPIO_H 7
+ #define SUNXI_GPIO_I 8
+
+-/*
+- * This defines the number of GPIO banks for the _main_ GPIO controller.
+- * You should fix up the padding in struct sunxi_gpio_reg below if you
+- * change this.
+- */
+-#define SUNXI_GPIO_BANKS 9
+-
+ /*
+ * sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
+ * at a different register offset.
+@@ -52,46 +45,42 @@
+ #define SUNXI_GPIO_M 12
+ #define SUNXI_GPIO_N 13
+
+-struct sunxi_gpio {
+- u32 cfg[4];
+- u32 dat;
+- u32 drv[2];
+- u32 pull[2];
+-};
+-
+-/* gpio interrupt control */
+-struct sunxi_gpio_int {
+- u32 cfg[3];
+- u32 ctl;
+- u32 sta;
+- u32 deb; /* interrupt debounce */
+-};
+-
+-struct sunxi_gpio_reg {
+- struct sunxi_gpio gpio_bank[SUNXI_GPIO_BANKS];
+- u8 res[0xbc];
+- struct sunxi_gpio_int gpio_int;
+-};
+-
+ #define SUN50I_H6_GPIO_POW_MOD_SEL 0x340
+ #define SUN50I_H6_GPIO_POW_MOD_VAL 0x348
+
+-#define BANK_TO_GPIO(bank) (((bank) < SUNXI_GPIO_L) ? \
+- &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
+- &((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
+-
+ #define GPIO_BANK(pin) ((pin) >> 5)
+ #define GPIO_NUM(pin) ((pin) & 0x1f)
+
++#define GPIO_CFG_REG_OFFSET 0x00
+ #define GPIO_CFG_INDEX(pin) (((pin) & 0x1f) >> 3)
+ #define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1f) & 0x7) << 2)
+
++#define GPIO_DAT_REG_OFFSET 0x10
++
++#define GPIO_DRV_REG_OFFSET 0x14
+ #define GPIO_DRV_INDEX(pin) (((pin) & 0x1f) >> 4)
+ #define GPIO_DRV_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+
++#define GPIO_PULL_REG_OFFSET 0x1c
+ #define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
+ #define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+
++#define SUNXI_PINCTRL_BANK_SIZE 0x24
++
++static inline void* BANK_TO_GPIO(int bank)
++{
++ void *pio_base;
++
++ if (bank < SUNXI_GPIO_L) {
++ pio_base = (void *)(uintptr_t)SUNXI_PIO_BASE;
++ } else {
++ pio_base = (void *)(uintptr_t)SUNXI_R_PIO_BASE;
++ bank -= SUNXI_GPIO_L;
++ }
++
++ return pio_base + bank * SUNXI_PINCTRL_BANK_SIZE;
++}
++
+ /* GPIO bank sizes */
+ #define SUNXI_GPIOS_PER_BANK 32
+
+@@ -214,22 +203,22 @@ enum sunxi_gpio_number {
+ #define SUNXI_GPIO_AXP0_GPIO_COUNT 6
+
+ struct sunxi_gpio_plat {
+- struct sunxi_gpio *regs;
++ void *regs;
+ char bank_name[3];
+ };
+
+-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
++void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
+ void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
+-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
++int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
+ int sunxi_gpio_get_cfgpin(u32 pin);
+-void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, int pin, bool set);
++void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set);
+ void sunxi_gpio_set_output(u32 pin, bool set);
+-int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin);
++int sunxi_gpio_get_output_bank(void *bank_base, int pin);
+ int sunxi_gpio_get_output(u32 pin);
+ void sunxi_gpio_set_drv(u32 pin, u32 val);
+-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
++void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
+ void sunxi_gpio_set_pull(u32 pin, u32 val);
+-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val);
++void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val);
+ int sunxi_name_to_gpio(const char *name);
+
+ #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
+diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
+index 751cac8e09..17d1a7bdb9 100644
+--- a/arch/arm/mach-sunxi/pinmux.c
++++ b/arch/arm/mach-sunxi/pinmux.c
+@@ -9,29 +9,30 @@
+ #include <asm/io.h>
+ #include <asm/arch/gpio.h>
+
+-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
++void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
+ {
+- u32 index = GPIO_CFG_INDEX(bank_offset);
+- u32 offset = GPIO_CFG_OFFSET(bank_offset);
++ u32 index = GPIO_CFG_INDEX(pin_offset);
++ u32 offset = GPIO_CFG_OFFSET(pin_offset);
+
+- clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
++ clrsetbits_le32(bank_base + GPIO_CFG_REG_OFFSET + index * 4,
++ 0xfU << offset, val << offset);
+ }
+
+ void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
+ {
+ u32 bank = GPIO_BANK(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++ void *pio = BANK_TO_GPIO(bank);
+
+- sunxi_gpio_set_cfgbank(pio, pin, val);
++ sunxi_gpio_set_cfgbank(pio, pin % 32, val);
+ }
+
+-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
++int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset)
+ {
+- u32 index = GPIO_CFG_INDEX(bank_offset);
+- u32 offset = GPIO_CFG_OFFSET(bank_offset);
++ u32 index = GPIO_CFG_INDEX(pin_offset);
++ u32 offset = GPIO_CFG_OFFSET(pin_offset);
+ u32 cfg;
+
+- cfg = readl(&pio->cfg[index]);
++ cfg = readl(bank_base + GPIO_CFG_REG_OFFSET + index * 4);
+ cfg >>= offset;
+
+ return cfg & 0xf;
+@@ -40,35 +41,38 @@ int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
+ int sunxi_gpio_get_cfgpin(u32 pin)
+ {
+ u32 bank = GPIO_BANK(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++ void *bank_base = BANK_TO_GPIO(bank);
+
+- return sunxi_gpio_get_cfgbank(pio, pin);
++ return sunxi_gpio_get_cfgbank(bank_base, pin % 32);
+ }
+
+-void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, int pin, bool set)
++void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set)
+ {
+ u32 mask = 1U << GPIO_NUM(pin);
+
+- clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
++ clrsetbits_le32(bank_base + GPIO_DAT_REG_OFFSET,
++ set ? 0 : mask, set ? mask : 0);
+ }
+
+ void sunxi_gpio_set_output(u32 pin, bool set)
+ {
+ u32 bank = GPIO_BANK(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++ void *pio = BANK_TO_GPIO(bank);
+
+ sunxi_gpio_set_output_bank(pio, pin, set);
+ }
+
+-int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)
++int sunxi_gpio_get_output_bank(void *bank_base, int pin)
+ {
+- return !!(readl(&pio->dat) & (1U << GPIO_NUM(pin)));
++ u32 mask = 1U << GPIO_NUM(pin);
++
++ return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & mask);
+ }
+
+ int sunxi_gpio_get_output(u32 pin)
+ {
+ u32 bank = GPIO_BANK(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++ void *pio = BANK_TO_GPIO(bank);
+
+ return sunxi_gpio_get_output_bank(pio, pin);
+ }
+@@ -76,31 +80,33 @@ int sunxi_gpio_get_output(u32 pin)
+ void sunxi_gpio_set_drv(u32 pin, u32 val)
+ {
+ u32 bank = GPIO_BANK(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++ void *bank_base = BANK_TO_GPIO(bank);
+
+- sunxi_gpio_set_drv_bank(pio, pin, val);
++ sunxi_gpio_set_drv_bank(bank_base, pin % 32, val);
+ }
+
+-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
++void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val)
+ {
+- u32 index = GPIO_DRV_INDEX(bank_offset);
+- u32 offset = GPIO_DRV_OFFSET(bank_offset);
++ u32 index = GPIO_DRV_INDEX(pin_offset);
++ u32 offset = GPIO_DRV_OFFSET(pin_offset);
+
+- clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
++ clrsetbits_le32(bank_base + GPIO_DRV_REG_OFFSET + index * 4,
++ 0x3U << offset, val << offset);
+ }
+
+ void sunxi_gpio_set_pull(u32 pin, u32 val)
+ {
+ u32 bank = GPIO_BANK(pin);
+- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++ void *bank_base = BANK_TO_GPIO(bank);
+
+- sunxi_gpio_set_pull_bank(pio, pin, val);
++ sunxi_gpio_set_pull_bank(bank_base, pin % 32, val);
+ }
+
+-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
++void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val)
+ {
+- u32 index = GPIO_PULL_INDEX(bank_offset);
+- u32 offset = GPIO_PULL_OFFSET(bank_offset);
++ u32 index = GPIO_PULL_INDEX(pin_offset);
++ u32 offset = GPIO_PULL_OFFSET(pin_offset);
+
+- clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
++ clrsetbits_le32(bank_base + GPIO_PULL_REG_OFFSET + index * 4,
++ 0x3U << offset, val << offset);
+ }
+diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+index c4fbda7a92..b0144edcf4 100644
+--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+@@ -35,7 +35,7 @@ struct sunxi_pinctrl_desc {
+ };
+
+ struct sunxi_pinctrl_plat {
+- struct sunxi_gpio __iomem *base;
++ void __iomem *base;
+ };
+
+ static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
+@@ -86,8 +86,8 @@ static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
+ sunxi_pinctrl_get_function_name(dev, func_selector),
+ desc->functions[func_selector].mux);
+
+- sunxi_gpio_set_cfgbank(plat->base + bank, pin,
+- desc->functions[func_selector].mux);
++ sunxi_gpio_set_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE,
++ pin, desc->functions[func_selector].mux);
+
+ return 0;
+ }
+@@ -102,7 +102,7 @@ static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
+ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
+ uint bank, uint pin, uint bias)
+ {
+- struct sunxi_gpio *regs = &plat->base[bank];
++ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
+
+ sunxi_gpio_set_pull_bank(regs, pin, bias);
+
+@@ -112,7 +112,7 @@ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
+ static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
+ uint bank, uint pin, uint drive)
+ {
+- struct sunxi_gpio *regs = &plat->base[bank];
++ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
+
+ if (drive < 10 || drive > 40)
+ return -EINVAL;
+@@ -148,7 +148,7 @@ static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
+ struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
+ int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
+ int pin = pin_selector % SUNXI_GPIOS_PER_BANK;
+- int mux = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
++ int mux = sunxi_gpio_get_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE, pin);
+
+ switch (mux) {
+ case SUNXI_GPIO_INPUT:
+@@ -206,7 +206,7 @@ static int sunxi_pinctrl_bind(struct udevice *dev)
+ if (!gpio_plat)
+ return -ENOMEM;
+
+- gpio_plat->regs = plat->base + i;
++ gpio_plat->regs = plat->base + i * SUNXI_PINCTRL_BANK_SIZE;
+ gpio_plat->bank_name[0] = 'P';
+ gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
+ gpio_plat->bank_name[2] = '\0';
+--
+2.20.1
+
--- /dev/null
+From 0fe6de16aa4a6164cd46ec5f8993bc058567fdd1 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:51 +0100
+Subject: [PATCH 4011/4044] pinctrl: sunxi: move pinctrl code and remove
+ GPIO_EXTRA_HEADER
+
+U-Boot's generic GPIO_EXTRA_HEADER is a convenience symbol to allow code
+to more easily include platform specific GPIO headers. This should not
+be needed in a DM world anymore, since the generic GPIO framework
+handles that nicely.
+For Allwinner boards we still need to deal with non-DM GPIO in the SPL,
+but this should become the exception, not the rule.
+
+Make this more obvious by removing the definition of GPIO_EXTRA_HEADER,
+and just force every legacy user of platform specific GPIO to include
+the new sunxi_gpio.h header explicitly. Everyone doing so should feel
+ashamed and should find a way to avoid it from now on.
+This also moves and renames the existing sunxi-specific low level
+pinctrl routines from arch/arm/mach-sunxi into board/sunxi, and the
+gpio.h header to the generic include/ directory, so the common code can
+be shared outside of arch/arm.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/Kconfig | 1 -
+ arch/arm/mach-sunxi/Makefile | 1 -
+ arch/arm/mach-sunxi/board.c | 1 +
+ arch/arm/mach-sunxi/dram_suniv.c | 2 +-
+ arch/arm/mach-sunxi/spl_spi_sunxi.c | 1 +
+ board/sunxi/Makefile | 1 +
+ board/sunxi/board.c | 1 +
+ board/sunxi/chip.c | 2 +-
+ arch/arm/mach-sunxi/pinmux.c => board/sunxi/pinctrl.c | 5 ++++-
+ drivers/gpio/axp_gpio.c | 1 +
+ drivers/gpio/sunxi_gpio.c | 1 +
+ drivers/i2c/sun6i_p2wi.c | 2 +-
+ drivers/i2c/sun8i_rsb.c | 2 +-
+ drivers/mmc/sunxi_mmc.c | 1 +
+ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 1 +
+ drivers/video/hitachi_tx18d42vm_lcd.c | 1 +
+ drivers/video/ssd2828.c | 1 -
+ drivers/video/sunxi/sunxi_display.c | 1 +
+ drivers/video/sunxi/sunxi_lcd.c | 1 +
+ .../include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h | 0
+ 20 files changed, 19 insertions(+), 8 deletions(-)
+ rename arch/arm/mach-sunxi/pinmux.c => board/sunxi/pinctrl.c (94%)
+ rename arch/arm/include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h (100%)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index d5a6d293ce..2904e91ad3 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1106,7 +1106,6 @@ config ARCH_SUNXI
+ select DM_MMC if MMC
+ select DM_SCSI if SCSI
+ select DM_SERIAL
+- select GPIO_EXTRA_HEADER
+ select OF_BOARD_SETUP
+ select OF_CONTROL
+ select OF_SEPARATE
+diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
+index 58f807cb82..671211e932 100644
+--- a/arch/arm/mach-sunxi/Makefile
++++ b/arch/arm/mach-sunxi/Makefile
+@@ -10,7 +10,6 @@ obj-y += board.o
+ obj-y += clock.o
+ obj-y += cpu_info.o
+ obj-y += dram_helpers.o
+-obj-y += pinmux.o
+ obj-$(CONFIG_SUN6I_PRCM) += prcm.o
+ obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o
+ obj-$(CONFIG_MACH_SUNIV) += clock_sun6i.o
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index 391a65a549..ec46ab9279 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -17,6 +17,7 @@
+ #include <i2c.h>
+ #include <serial.h>
+ #include <spl.h>
++#include <sunxi_gpio.h>
+ #include <asm/cache.h>
+ #include <asm/gpio.h>
+ #include <asm/io.h>
+diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c
+index 3aa3ce7627..9e583e1855 100644
+--- a/arch/arm/mach-sunxi/dram_suniv.c
++++ b/arch/arm/mach-sunxi/dram_suniv.c
+@@ -13,10 +13,10 @@
+ #include <asm/io.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/dram.h>
+-#include <asm/arch/gpio.h>
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+ #include <hang.h>
++#include <sunxi_gpio.h>
+
+ #define SDR_T_CAS (0x2)
+ #define SDR_T_RAS (0x8)
+diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
+index 81159cfee6..c2410dd7bb 100644
+--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
++++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
+@@ -13,6 +13,7 @@
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+ #include <linux/libfdt.h>
++#include <sunxi_gpio.h>
+
+ #ifdef CONFIG_SPL_OS_BOOT
+ #error CONFIG_SPL_OS_BOOT is not supported yet
+diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
+index d96b7897b6..7763b032c8 100644
+--- a/board/sunxi/Makefile
++++ b/board/sunxi/Makefile
+@@ -7,6 +7,7 @@
+ # (C) Copyright 2000-2003
+ # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ obj-y += board.o
++obj-y += pinctrl.o
+ obj-$(CONFIG_SUN7I_GMAC) += gmac.o
+ obj-$(CONFIG_MACH_SUN4I) += dram_sun4i_auto.o
+ obj-$(CONFIG_MACH_SUN5I) += dram_sun5i_auto.o
+diff --git a/board/sunxi/board.c b/board/sunxi/board.c
+index 9900c66ed0..661137f43c 100644
+--- a/board/sunxi/board.c
++++ b/board/sunxi/board.c
+@@ -38,6 +38,7 @@
+ #include <asm/armv7.h>
+ #endif
+ #include <asm/gpio.h>
++#include <sunxi_gpio.h>
+ #include <asm/io.h>
+ #include <u-boot/crc.h>
+ #include <env_internal.h>
+diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c
+index cde04bebe9..eeee6319e7 100644
+--- a/board/sunxi/chip.c
++++ b/board/sunxi/chip.c
+@@ -12,7 +12,7 @@
+ #include <w1-eeprom.h>
+ #include <dm/device-internal.h>
+
+-#include <asm/arch/gpio.h>
++#include <sunxi_gpio.h>
+
+ #include <extension_board.h>
+
+diff --git a/arch/arm/mach-sunxi/pinmux.c b/board/sunxi/pinctrl.c
+similarity index 94%
+rename from arch/arm/mach-sunxi/pinmux.c
+rename to board/sunxi/pinctrl.c
+index 17d1a7bdb9..494d92c73b 100644
+--- a/arch/arm/mach-sunxi/pinmux.c
++++ b/board/sunxi/pinctrl.c
+@@ -3,11 +3,14 @@
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
++ *
++ * Low level GPIO/pin controller access functions, to be shared by non-DM
++ * SPL code and the DM pinctrl/GPIO drivers.
+ */
+
+ #include <common.h>
+ #include <asm/io.h>
+-#include <asm/arch/gpio.h>
++#include <sunxi_gpio.h>
+
+ void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
+ {
+diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c
+index 35585dc8ac..14a99ce4c9 100644
+--- a/drivers/gpio/axp_gpio.c
++++ b/drivers/gpio/axp_gpio.c
+@@ -14,6 +14,7 @@
+ #include <dm/lists.h>
+ #include <dm/root.h>
+ #include <errno.h>
++#include <sunxi_gpio.h>
+
+ static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val);
+
+diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+index 6796375d35..921cf43b25 100644
+--- a/drivers/gpio/sunxi_gpio.c
++++ b/drivers/gpio/sunxi_gpio.c
+@@ -17,6 +17,7 @@
+ #include <asm/io.h>
+ #include <asm/gpio.h>
+ #include <dt-bindings/gpio/gpio.h>
++#include <sunxi_gpio.h>
+
+ #if !CONFIG_IS_ENABLED(DM_GPIO)
+ int gpio_request(unsigned gpio, const char *label)
+diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c
+index d221323295..b8e07a533c 100644
+--- a/drivers/i2c/sun6i_p2wi.c
++++ b/drivers/i2c/sun6i_p2wi.c
+@@ -20,10 +20,10 @@
+ #include <errno.h>
+ #include <i2c.h>
+ #include <reset.h>
++#include <sunxi_gpio.h>
+ #include <time.h>
+ #include <asm/io.h>
+ #include <asm/arch/cpu.h>
+-#include <asm/arch/gpio.h>
+ #include <asm/arch/p2wi.h>
+ #include <asm/arch/prcm.h>
+ #include <asm/arch/sys_proto.h>
+diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c
+index 47fa05b6d1..f36f2c7afa 100644
+--- a/drivers/i2c/sun8i_rsb.c
++++ b/drivers/i2c/sun8i_rsb.c
+@@ -14,10 +14,10 @@
+ #include <dm.h>
+ #include <errno.h>
+ #include <i2c.h>
++#include <sunxi_gpio.h>
+ #include <reset.h>
+ #include <time.h>
+ #include <asm/arch/cpu.h>
+-#include <asm/arch/gpio.h>
+ #include <asm/arch/prcm.h>
+ #include <asm/arch/rsb.h>
+
+diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
+index 23bc7da917..03e33753fc 100644
+--- a/drivers/mmc/sunxi_mmc.c
++++ b/drivers/mmc/sunxi_mmc.c
+@@ -27,6 +27,7 @@
+ #include <asm/arch/cpu.h>
+ #include <asm/arch/mmc.h>
+ #include <linux/delay.h>
++#include <sunxi_gpio.h>
+
+ #ifndef CCM_MMC_CTRL_MODE_SEL_NEW
+ #define CCM_MMC_CTRL_MODE_SEL_NEW 0
+diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+index b0144edcf4..4c52e3fa74 100644
+--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+@@ -7,6 +7,7 @@
+ #include <dm/pinctrl.h>
+ #include <errno.h>
+ #include <malloc.h>
++#include <sunxi_gpio.h>
+
+ #include <asm/gpio.h>
+
+diff --git a/drivers/video/hitachi_tx18d42vm_lcd.c b/drivers/video/hitachi_tx18d42vm_lcd.c
+index 87c4d27438..95984fe3d3 100644
+--- a/drivers/video/hitachi_tx18d42vm_lcd.c
++++ b/drivers/video/hitachi_tx18d42vm_lcd.c
+@@ -10,6 +10,7 @@
+ #include <linux/delay.h>
+
+ #include <asm/gpio.h>
++#include <sunxi_gpio.h>
+ #include <errno.h>
+
+ /*
+diff --git a/drivers/video/ssd2828.c b/drivers/video/ssd2828.c
+index 4cdcbe7755..948f5e74d0 100644
+--- a/drivers/video/ssd2828.c
++++ b/drivers/video/ssd2828.c
+@@ -12,7 +12,6 @@
+ #include <common.h>
+ #include <malloc.h>
+ #include <mipi_display.h>
+-#include <asm/arch/gpio.h>
+ #include <asm/gpio.h>
+ #include <linux/delay.h>
+
+diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
+index 9110a48482..8da44a1bb6 100644
+--- a/drivers/video/sunxi/sunxi_display.c
++++ b/drivers/video/sunxi/sunxi_display.c
+@@ -31,6 +31,7 @@
+ #include <malloc.h>
+ #include <video.h>
+ #include <dm/uclass-internal.h>
++#include <sunxi_gpio.h>
+ #include "../videomodes.h"
+ #include "../anx9804.h"
+ #include "../hitachi_tx18d42vm_lcd.h"
+diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c
+index 8b9c3b2bfa..7a01cc343c 100644
+--- a/drivers/video/sunxi/sunxi_lcd.c
++++ b/drivers/video/sunxi/sunxi_lcd.c
+@@ -17,6 +17,7 @@
+ #include <asm/arch/lcdc.h>
+ #include <asm/global_data.h>
+ #include <asm/gpio.h>
++#include <sunxi_gpio.h>
+
+ struct sunxi_lcd_priv {
+ struct display_timing timing;
+diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/include/sunxi_gpio.h
+similarity index 100%
+rename from arch/arm/include/asm/arch-sunxi/gpio.h
+rename to include/sunxi_gpio.h
+--
+2.20.1
+
+++ /dev/null
-From 90edf658a24549c3f5c568e54caa3230890918d8 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Fri, 2 Dec 2022 20:30:40 +0000
-Subject: [PATCH 4011/4031] sunxi: clock: D1/R528: Enable PLL LDO during PLL1
- setup
-
-The D1/R528/T113s SoCs introduce a new "LDO enable" bit in the CPUX_PLL.
-Just enable that when we program that PLL.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h | 1 +
- arch/arm/mach-sunxi/clock_sun50i_h6.c | 12 +++++++-----
- 2 files changed, 8 insertions(+), 5 deletions(-)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-index 37df4410ea..9895c2c220 100644
---- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-@@ -228,6 +228,7 @@ struct sunxi_ccm_reg {
-
- /* pll1 bit field */
- #define CCM_PLL1_CTRL_EN BIT(31)
-+#define CCM_PLL1_LDO_EN BIT(30)
- #define CCM_PLL1_LOCK_EN BIT(29)
- #define CCM_PLL1_LOCK BIT(28)
- #define CCM_PLL1_OUT_EN BIT(27)
-diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
-index 7926394cf7..90110eab10 100644
---- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
-+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
-@@ -86,11 +86,13 @@ void clock_set_pll1(unsigned int clk)
- writel(val, &ccm->cpu_axi_cfg);
-
- /* clk = 24*n/p, p is ignored if clock is >288MHz */
-- writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
--#ifdef CONFIG_MACH_SUN50I_H616
-- CCM_PLL1_OUT_EN |
--#endif
-- CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
-+ val = CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2;
-+ val |= CCM_PLL1_CTRL_N(clk / 24000000);
-+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
-+ val |= CCM_PLL1_OUT_EN;
-+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
-+ val |= CCM_PLL1_OUT_EN | CCM_PLL1_LDO_EN;
-+ writel(val, &ccm->pll1_cfg);
- while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
-
- /* Switch CPU to PLL1 */
---
-2.20.1
-
--- /dev/null
+From 9dfef76a7374b5da636a50d2a439cb1da0c43421 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:52 +0100
+Subject: [PATCH 4012/4044] pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h
+
+On the Allwinner platform we were describing a quite comprehensive
+memory map in a per-SoC header unser arch/arm.
+In the old days that was used by every driver, but nowadays it should
+only be needed by SPL drivers (not using the DT). Many addresses in
+there were never used, and some are not needed anymore.
+
+To avoid a dependency on CPU specific headers in an arch specific
+directory, move the definition of the pinctroller MMIO base address into
+the sunxi_gpio.h header, because the SPL routines for GPIO should be the
+only one needing this address.
+This is a first step towards getting rid of cpu_sun[x]i.h completely,
+and allows to remove the inclusion of that file from the sunxi_gpio.h
+header.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 2 --
+ arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h | 2 --
+ arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 2 --
+ include/sunxi_gpio.h | 12 +++++++++++-
+ 4 files changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+index f7ecc790db..d6fe51f24b 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+@@ -91,7 +91,6 @@
+
+ #define SUNXI_CCM_BASE 0x01c20000
+ #define SUNXI_INTC_BASE 0x01c20400
+-#define SUNXI_PIO_BASE 0x01c20800
+ #define SUNXI_TIMER_BASE 0x01c20c00
+ #ifndef CONFIG_SUNXI_GEN_SUN6I
+ #define SUNXI_PWM_BASE 0x01c20e00
+@@ -210,7 +209,6 @@ defined(CONFIG_MACH_SUN50I)
+
+ #define SUNXI_R_TWI_BASE 0x01f02400
+ #define SUNXI_R_UART_BASE 0x01f02800
+-#define SUNXI_R_PIO_BASE 0x01f02c00
+ #define SUN6I_P2WI_BASE 0x01f03400
+ #define SUNXI_RSB_BASE 0x01f03400
+
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+index d9cf8ae042..9b6bf84360 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+@@ -22,7 +22,6 @@
+ #define SUNXI_SIDC_BASE 0x03006000
+ #define SUNXI_SID_BASE 0x03006200
+ #define SUNXI_TIMER_BASE 0x03009000
+-#define SUNXI_PIO_BASE 0x0300B000
+ #define SUNXI_PSI_BASE 0x0300C000
+
+ #define SUNXI_GIC400_BASE 0x03020000
+@@ -68,7 +67,6 @@
+ #define SUNXI_R_CPUCFG_BASE 0x07000400
+ #define SUNXI_PRCM_BASE 0x07010000
+ #define SUNXI_R_WDOG_BASE 0x07020400
+-#define SUNXI_R_PIO_BASE 0x07022000
+ #define SUNXI_R_UART_BASE 0x07080000
+ #define SUNXI_R_TWI_BASE 0x07081400
+
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+index 9c2d11b590..20025be231 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+@@ -81,7 +81,6 @@
+ /* APB0 Module */
+ #define SUNXI_CCM_BASE (REGS_APB0_BASE + 0x0000)
+ #define SUNXI_CCMMODULE_BASE (REGS_APB0_BASE + 0x0400)
+-#define SUNXI_PIO_BASE (REGS_APB0_BASE + 0x0800)
+ #define SUNXI_TIMER_BASE (REGS_APB0_BASE + 0x0C00)
+ #define SUNXI_PWM_BASE (REGS_APB0_BASE + 0x1400)
+ #define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800)
+@@ -102,7 +101,6 @@
+ /* RCPUS Module */
+ #define SUNXI_PRCM_BASE (REGS_RCPUS_BASE + 0x1400)
+ #define SUNXI_R_UART_BASE (REGS_RCPUS_BASE + 0x2800)
+-#define SUNXI_R_PIO_BASE (REGS_RCPUS_BASE + 0x2c00)
+ #define SUNXI_RSB_BASE (REGS_RCPUS_BASE + 0x3400)
+
+ /* Misc. */
+diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
+index 96a29aa023..2e06745a1c 100644
+--- a/include/sunxi_gpio.h
++++ b/include/sunxi_gpio.h
+@@ -9,7 +9,17 @@
+ #define _SUNXI_GPIO_H
+
+ #include <linux/types.h>
+-#include <asm/arch/cpu.h>
++
++#if defined(CONFIG_MACH_SUN9I)
++#define SUNXI_PIO_BASE 0x06000800
++#define SUNXI_R_PIO_BASE 0x08002c00
++#elif defined(CONFIG_SUN50I_GEN_H6)
++#define SUNXI_PIO_BASE 0x0300b000
++#define SUNXI_R_PIO_BASE 0x07022000
++#else
++#define SUNXI_PIO_BASE 0x01c20800
++#define SUNXI_R_PIO_BASE 0x01f02c00
++#endif
+
+ /*
+ * sunxi has 9 banks of gpio, they are:
+--
+2.20.1
+
+++ /dev/null
-From 434dce1b0bfd9d3ab3a28352b596d27de3622796 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Fri, 2 Dec 2022 21:48:19 +0000
-Subject: [PATCH 4012/4031] sunxi: clock: support D1/R528 PLL6 clock
-
-The PLL_PERIPH0 clock changed a bit in the D1/R528/T113s SoCs: there is
-new P0 divider at bits [18:16], and the M divider is 1.
-
-Add code to support this version of "PLL6".
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- .../include/asm/arch-sunxi/clock_sun50i_h6.h | 2 ++
- arch/arm/mach-sunxi/clock_sun50i_h6.c | 24 +++++++++++++------
- 2 files changed, 19 insertions(+), 7 deletions(-)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-index 9895c2c220..8471e11aa0 100644
---- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-@@ -249,6 +249,8 @@ struct sunxi_ccm_reg {
- #define CCM_PLL6_CTRL_EN BIT(31)
- #define CCM_PLL6_LOCK_EN BIT(29)
- #define CCM_PLL6_LOCK BIT(28)
-+#define CCM_PLL6_CTRL_P0_SHIFT 16
-+#define CCM_PLL6_CTRL_P0_MASK (0x7 << CCM_PLL6_CTRL_P0_SHIFT)
- #define CCM_PLL6_CTRL_N_SHIFT 8
- #define CCM_PLL6_CTRL_N_MASK (0xff << CCM_PLL6_CTRL_N_SHIFT)
- #define CCM_PLL6_CTRL_DIV1_SHIFT 0
-diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
-index 90110eab10..607efe6a9c 100644
---- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
-+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
-@@ -107,16 +107,26 @@ unsigned int clock_get_pll6(void)
- {
- struct sunxi_ccm_reg *const ccm =
- (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-- int m = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ? 4 : 2;
--
- uint32_t rval = readl(&ccm->pll6_cfg);
- int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
-- int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
-- CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
- int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
-- CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
-- /* The register defines PLL6-2X or PLL6-4X, not plain PLL6 */
-- return 24000000 / m * n / div1 / div2;
-+ CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
-+ int div1, m;
-+
-+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
-+ div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
-+ CCM_PLL6_CTRL_P0_SHIFT) + 1;
-+ m = 1;
-+ } else {
-+ div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
-+ CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
-+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
-+ m = 4;
-+ else
-+ m = 2;
-+ }
-+
-+ return 24000000U * n / m / div1 / div2;
- }
-
- int clock_twi_onoff(int port, int state)
---
-2.20.1
-
+++ /dev/null
-From af8381ba9b63dd3e79fb874da151d56af68b7930 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Sun, 18 Dec 2022 00:12:07 +0000
-Subject: [PATCH 4013/4031] Kconfig: sunxi: prepare for using drivers/ram/sunxi
-
-At the moment all Allwinner DRAM initialisation routines are stored in
-arch/arm/mach-sunxi, even though those "drivers" are just a giant
-collection of writel's, without any architectural dependency.
-
-The R528/T113-s SoC (with ARM cores) and the D1/D1s Soc (with RISC-V
-cores) share the same die, so should share the same DRAM init routines as
-well.
-
-To prepare for this, add a new sunxi directory inside drivers/ram, and
-add some stub entries to prepare for the addition of the share DRAM code
-for those SoCs.
-
-The RISC-V D1(s) SoCs will probably use SPL_DM, so make this entry
-depend on that already.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- drivers/ram/Kconfig | 3 ++-
- drivers/ram/sunxi/Kconfig | 13 +++++++++++++
- 2 files changed, 15 insertions(+), 1 deletion(-)
- create mode 100644 drivers/ram/sunxi/Kconfig
-
-diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
-index e085119963..d162a7f0d9 100644
---- a/drivers/ram/Kconfig
-+++ b/drivers/ram/Kconfig
-@@ -108,7 +108,8 @@ config IMXRT_SDRAM
- This driver is for the sdram memory interface with the SEMC.
-
- source "drivers/ram/aspeed/Kconfig"
-+source "drivers/ram/octeon/Kconfig"
- source "drivers/ram/rockchip/Kconfig"
- source "drivers/ram/sifive/Kconfig"
- source "drivers/ram/stm32mp1/Kconfig"
--source "drivers/ram/octeon/Kconfig"
-+source "drivers/ram/sunxi/Kconfig"
-diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
-new file mode 100644
-index 0000000000..97e261de54
---- /dev/null
-+++ b/drivers/ram/sunxi/Kconfig
-@@ -0,0 +1,13 @@
-+config DRAM_SUN20I_D1
-+ bool "DM DRAM driver support for Allwinner D1"
-+ depends on RAM && ARCH_SUNXI
-+ default y
-+ help
-+ This enables support for DRAM drivers using the driver model
-+ for Allwinner SoCs.
-+
-+config DRAM_SUN8I_R528
-+ bool "DRAM driver support for Allwinner R528/T113s"
-+ default y if MACH_SUN8I_R528
-+ help
-+ Select this DRAM controller driver for the R528/T113s SoCs.
---
-2.20.1
-
--- /dev/null
+From 1a97a80f9cd80d4ba65101ceef45de7d99d5aed6 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:53 +0100
+Subject: [PATCH 4013/4044] pinctrl: sunxi: add new D1 pinctrl support
+
+For the first time since at least the Allwinner A10 SoCs, the D1 (and
+related cores) use a new pincontroller MMIO register layout, so we
+cannot use our hardcoded, fixed offsets anymore.
+Ideally this would all be handled by devicetree and DM drivers, but for
+the DT-less SPL we still need the legacy interfaces.
+
+Add a new Kconfig symbol to differenciate between the two generations of
+pincontrollers, and just use that to just switch some basic symbols.
+The rest is already abstracted enough, so works out of the box.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Sam Edwards <CFSworks@gmail.com>
+Tested-by: Sam Edwards <CFSworks@gmail.com>
+---
+ arch/arm/mach-sunxi/Kconfig | 6 ++++++
+ include/sunxi_gpio.h | 26 +++++++++++++++++++++-----
+ 2 files changed, 27 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index d716054f72..b328ce8960 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -113,6 +113,12 @@ config SUNXI_SRAM_ADDRESS
+ config SUNXI_A64_TIMER_ERRATUM
+ bool
+
++config SUNXI_NEW_PINCTRL
++ bool
++ ---help---
++ The Allwinner D1 and other new SoCs use a different register map
++ for the GPIO block, which we need to know about in the SPL.
++
+ # Note only one of these may be selected at a time! But hidden choices are
+ # not supported by Kconfig
+ config SUNXI_GEN_SUN4I
+diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
+index 2e06745a1c..61978db6db 100644
+--- a/include/sunxi_gpio.h
++++ b/include/sunxi_gpio.h
+@@ -68,15 +68,32 @@
+ #define GPIO_DAT_REG_OFFSET 0x10
+
+ #define GPIO_DRV_REG_OFFSET 0x14
+-#define GPIO_DRV_INDEX(pin) (((pin) & 0x1f) >> 4)
+-#define GPIO_DRV_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
++
++/* Newer SoCs use a slightly different register layout */
++#ifdef CONFIG_SUNXI_NEW_PINCTRL
++/* pin drive strength: 4 bits per pin */
++#define GPIO_DRV_INDEX(pin) ((pin) / 8)
++#define GPIO_DRV_OFFSET(pin) (((pin) % 8) * 4)
++
++#define GPIO_PULL_REG_OFFSET 0x24
++
++#define SUNXI_PINCTRL_BANK_SIZE 0x30
++#define SUNXI_GPIO_DISABLE 0xf
++
++#else /* older generation pin controllers */
++/* pin drive strength: 2 bits per pin */
++#define GPIO_DRV_INDEX(pin) ((pin) / 16)
++#define GPIO_DRV_OFFSET(pin) (((pin) % 16) * 2)
+
+ #define GPIO_PULL_REG_OFFSET 0x1c
++
++#define SUNXI_PINCTRL_BANK_SIZE 0x24
++#define SUNXI_GPIO_DISABLE 0x7
++#endif
++
+ #define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
+ #define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+
+-#define SUNXI_PINCTRL_BANK_SIZE 0x24
+-
+ static inline void* BANK_TO_GPIO(int bank)
+ {
+ void *pio_base;
+@@ -132,7 +149,6 @@ enum sunxi_gpio_number {
+ /* GPIO pin function config */
+ #define SUNXI_GPIO_INPUT 0
+ #define SUNXI_GPIO_OUTPUT 1
+-#define SUNXI_GPIO_DISABLE 7
+
+ #define SUN8I_H3_GPA_UART0 2
+ #define SUN8I_H3_GPA_UART2 2
+--
+2.20.1
+
+++ /dev/null
-From 6da5b94e68464980cb4e3425746d8b3b24590709 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Sat, 31 Dec 2022 18:38:21 +0000
-Subject: [PATCH 4014/4031] sunxi: add R528/T113-s3/D1(s) DRAM initialisation
- code
-
-The Allwinner R528/T113-s/D1/D1s SoCs all share the same die, so use the
-same DRAM initialisation code.
-Make use of prior art here and lift some code from awboot[1], which
-carried init code based on earlier decompilation efforts, but with a
-GPL2 license tag.
-This code has been heavily reworked and cleaned up, to match previous
-DRAM routines for other SoCs, and also to be closer to U-Boot's coding
-style and support routines.
-The actual DRAM chip timing parameters are included in the main file,
-since they cover all DRAM types, and are protected by a new Kconfig
-CONFIG_SUNXI_DRAM_TYPE symbol, which allows the compiler to pick only
-the relevant settings, at build time.
-
-The relevant DRAM chips/board specific configuration parameters are
-delivered via Kconfig, so this code here should work for all supported
-SoCs and DRAM chips combinations.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- drivers/Makefile | 1 +
- drivers/ram/Makefile | 2 +
- drivers/ram/sunxi/Kconfig | 55 ++
- drivers/ram/sunxi/Makefile | 4 +
- drivers/ram/sunxi/dram_sun20i_d1.c | 1425 ++++++++++++++++++++++++++++
- drivers/ram/sunxi/dram_sun20i_d1.h | 70 ++
- 6 files changed, 1557 insertions(+)
- create mode 100644 drivers/ram/sunxi/Makefile
- create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.c
- create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.h
-
-diff --git a/drivers/Makefile b/drivers/Makefile
-index 15d19d0c8a..1542ce7caf 100644
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -52,6 +52,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
- obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
- obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
- obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
-+obj-$(CONFIG_DRAM_SUN8I_R528) += ram/
- obj-$(CONFIG_SPL_DM_RESET) += reset/
- obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
- obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
-diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
-index 83948e2c43..050c11e840 100644
---- a/drivers/ram/Makefile
-+++ b/drivers/ram/Makefile
-@@ -21,4 +21,6 @@ obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o
-
- obj-$(CONFIG_RAM_SIFIVE) += sifive/
-
-+obj-$(CONFIG_DRAM_SUN8I_R528) += sunxi/
-+
- obj-$(CONFIG_ARCH_OCTEON) += octeon/
-diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
-index 97e261de54..36875ddf22 100644
---- a/drivers/ram/sunxi/Kconfig
-+++ b/drivers/ram/sunxi/Kconfig
-@@ -11,3 +11,58 @@ config DRAM_SUN8I_R528
- default y if MACH_SUN8I_R528
- help
- Select this DRAM controller driver for the R528/T113s SoCs.
-+
-+config DRAM_SUNXI_ODT_EN
-+ hex "DRAM ODT EN parameter"
-+ default 0x1
-+ help
-+ ODT EN value from vendor DRAM settings.
-+
-+config DRAM_SUNXI_TPR0
-+ hex "DRAM TPR0 parameter"
-+ default 0x0
-+ help
-+ TPR0 value from vendor DRAM settings.
-+
-+config DRAM_SUNXI_TPR11
-+ hex "DRAM TPR11 parameter"
-+ default 0x0
-+ help
-+ TPR11 value from vendor DRAM settings.
-+
-+config DRAM_SUNXI_TPR12
-+ hex "DRAM TPR12 parameter"
-+ default 0x0
-+ help
-+ TPR12 value from vendor DRAM settings.
-+
-+config DRAM_SUNXI_TPR13
-+ hex "DRAM TPR13 parameter"
-+ default 0x0
-+ help
-+ TPR13 value from vendor DRAM settings. It tells which features
-+ should be configured.
-+
-+choice
-+ prompt "DRAM chip type"
-+ default SUNXI_DRAM_DDR3 if DRAM_SUN8I_R528 || DRAM_SUN20I_D1
-+
-+config SUNXI_DRAM_DDR2
-+ bool "DDR2 chips"
-+
-+config SUNXI_DRAM_DDR3
-+ bool "DDR3 chips"
-+
-+config SUNXI_DRAM_LPDDR2
-+ bool "LPDDR2 chips"
-+
-+config SUNXI_DRAM_LPDDR3
-+ bool "LPDDR3 chips"
-+endchoice
-+
-+config SUNXI_DRAM_TYPE
-+ int
-+ default 2 if SUNXI_DRAM_DDR2
-+ default 3 if SUNXI_DRAM_DDR3
-+ default 6 if SUNXI_DRAM_LPDDR2
-+ default 7 if SUNXI_DRAM_LPDDR3
-diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
-new file mode 100644
-index 0000000000..d6fb2cf0b6
---- /dev/null
-+++ b/drivers/ram/sunxi/Makefile
-@@ -0,0 +1,4 @@
-+# SPDX-License-Identifier: GPL-2.0+
-+
-+obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
-+obj-$(CONFIG_DRAM_SUN8I_R528) += dram_sun20i_d1.o
-diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
-new file mode 100644
-index 0000000000..25005ceefb
---- /dev/null
-+++ b/drivers/ram/sunxi/dram_sun20i_d1.c
-@@ -0,0 +1,1425 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * Allwinner D1/D1s/R528/T113-sx DRAM initialisation
-+ *
-+ * As usual there is no documentation for the memory controller or PHY IP
-+ * used here. The baseline of this code was lifted from awboot[1], which
-+ * seems to be based on some form of de-compilation of some original Allwinner
-+ * code bits (with a GPL2 license tag from the very beginning).
-+ * This version here is a reworked version, to match the U-Boot coding style
-+ * and style of the other Allwinner DRAM drivers.
-+ *
-+ * [1] https://github.com/szemzoa/awboot.git
-+ */
-+
-+#include <asm/io.h>
-+#include <common.h>
-+#ifdef CONFIG_RAM
-+ #include <dm.h>
-+ #include <ram.h>
-+#endif
-+#include <linux/delay.h>
-+
-+#include "dram_sun20i_d1.h"
-+
-+#ifndef SUNXI_SID_BASE
-+#define SUNXI_SID_BASE 0x3006200
-+#endif
-+
-+static void sid_read_ldoB_cal(dram_para_t *para)
-+{
-+ uint32_t reg;
-+
-+ reg = (readl(SUNXI_SID_BASE + 0x1c) & 0xff00) >> 8;
-+
-+ if (reg == 0)
-+ return;
-+
-+ switch (para->dram_type) {
-+ case SUNXI_DRAM_TYPE_DDR2:
-+ break;
-+ case SUNXI_DRAM_TYPE_DDR3:
-+ if (reg > 0x20)
-+ reg -= 0x16;
-+ break;
-+ default:
-+ reg = 0;
-+ break;
-+ }
-+
-+ clrsetbits_le32(0x3000150, 0xff00, reg << 8);
-+}
-+
-+static void dram_voltage_set(dram_para_t *para)
-+{
-+ int vol;
-+
-+ switch (para->dram_type) {
-+ case SUNXI_DRAM_TYPE_DDR2:
-+ vol = 47;
-+ break;
-+ case SUNXI_DRAM_TYPE_DDR3:
-+ vol = 25;
-+ break;
-+ default:
-+ vol = 0;
-+ break;
-+ }
-+
-+ clrsetbits_le32(0x3000150, 0x20ff00, vol << 8);
-+
-+ udelay(1);
-+
-+ sid_read_ldoB_cal(para);
-+}
-+
-+static void dram_enable_all_master(void)
-+{
-+ writel(~0, 0x3102020);
-+ writel(0xff, 0x3102024);
-+ writel(0xffff, 0x3102028);
-+ udelay(10);
-+}
-+
-+static void dram_disable_all_master(void)
-+{
-+ writel(1, 0x3102020);
-+ writel(0, 0x3102024);
-+ writel(0, 0x3102028);
-+ udelay(10);
-+}
-+
-+static void eye_delay_compensation(dram_para_t *para) // s1
-+{
-+ uint32_t delay;
-+ unsigned long ptr;
-+
-+ // DATn0IOCR, n = 0...7
-+ delay = (para->dram_tpr11 & 0xf) << 9;
-+ delay |= (para->dram_tpr12 & 0xf) << 1;
-+ for (ptr = 0x3103310; ptr < 0x3103334; ptr += 4)
-+ setbits_le32(ptr, delay);
-+
-+ // DATn1IOCR, n = 0...7
-+ delay = (para->dram_tpr11 & 0xf0) << 5;
-+ delay |= (para->dram_tpr12 & 0xf0) >> 3;
-+ for (ptr = 0x3103390; ptr != 0x31033b4; ptr += 4)
-+ setbits_le32(ptr, delay);
-+
-+ // PGCR0: assert AC loopback FIFO reset
-+ clrbits_le32(0x3103100, 0x04000000);
-+
-+ // ??
-+
-+ delay = (para->dram_tpr11 & 0xf0000) >> 7;
-+ delay |= (para->dram_tpr12 & 0xf0000) >> 15;
-+ setbits_le32(0x3103334, delay);
-+ setbits_le32(0x3103338, delay);
-+
-+ delay = (para->dram_tpr11 & 0xf00000) >> 11;
-+ delay |= (para->dram_tpr12 & 0xf00000) >> 19;
-+ setbits_le32(0x31033b4, delay);
-+ setbits_le32(0x31033b8, delay);
-+
-+ setbits_le32(0x310333c, (para->dram_tpr11 & 0xf0000) << 9);
-+ setbits_le32(0x31033bc, (para->dram_tpr11 & 0xf00000) << 5);
-+
-+ // PGCR0: release AC loopback FIFO reset
-+ setbits_le32(0x3103100, BIT(26));
-+
-+ udelay(1);
-+
-+ delay = (para->dram_tpr10 & 0xf0) << 4;
-+ for (ptr = 0x3103240; ptr != 0x310327c; ptr += 4)
-+ setbits_le32(ptr, delay);
-+ for (ptr = 0x3103228; ptr != 0x3103240; ptr += 4)
-+ setbits_le32(ptr, delay);
-+
-+ setbits_le32(0x3103218, (para->dram_tpr10 & 0x0f) << 8);
-+ setbits_le32(0x310321c, (para->dram_tpr10 & 0x0f) << 8);
-+
-+ setbits_le32(0x3103280, (para->dram_tpr10 & 0xf00) >> 4);
-+}
-+
-+/*
-+ * Main purpose of the auto_set_timing routine seems to be to calculate all
-+ * timing settings for the specific type of sdram used. Read together with
-+ * an sdram datasheet for context on the various variables.
-+ */
-+static void mctl_set_timing_params(dram_para_t *para)
-+{
-+ /* DRAM_TPR0 */
-+ u8 tccd = 2;
-+ u8 tfaw;
-+ u8 trrd;
-+ u8 trcd;
-+ u8 trc;
-+
-+ /* DRAM_TPR1 */
-+ u8 txp;
-+ u8 twtr;
-+ u8 trtp = 4;
-+ u8 twr;
-+ u8 trp;
-+ u8 tras;
-+
-+ /* DRAM_TPR2 */
-+ u16 trefi;
-+ u16 trfc;
-+
-+ u8 tcksrx;
-+ u8 tckesr;
-+ u8 trd2wr;
-+ u8 twr2rd;
-+ u8 trasmax;
-+ u8 twtp;
-+ u8 tcke;
-+ u8 tmod;
-+ u8 tmrd;
-+ u8 tmrw;
-+
-+ u8 tcl;
-+ u8 tcwl;
-+ u8 t_rdata_en;
-+ u8 wr_latency;
-+
-+ u32 mr0;
-+ u32 mr1;
-+ u32 mr2;
-+ u32 mr3;
-+
-+ u32 tdinit0;
-+ u32 tdinit1;
-+ u32 tdinit2;
-+ u32 tdinit3;
-+
-+ switch (CONFIG_SUNXI_DRAM_TYPE) {
-+ case SUNXI_DRAM_TYPE_DDR2:
-+ /* DRAM_TPR0 */
-+ tfaw = ns_to_t(50);
-+ trrd = ns_to_t(10);
-+ trcd = ns_to_t(20);
-+ trc = ns_to_t(65);
-+
-+ /* DRAM_TPR1 */
-+ txp = 2;
-+ twtr = ns_to_t(8);
-+ twr = ns_to_t(15);
-+ trp = ns_to_t(15);
-+ tras = ns_to_t(45);
-+
-+ /* DRAM_TRP2 */
-+ trfc = ns_to_t(328);
-+ trefi = ns_to_t(7800) / 32;
-+
-+ trasmax = CONFIG_DRAM_CLK / 30;
-+ if (CONFIG_DRAM_CLK < 409) {
-+ t_rdata_en = 1;
-+ tcl = 3;
-+ mr0 = 0x06a3;
-+ } else {
-+ t_rdata_en = 2;
-+ tcl = 4;
-+ mr0 = 0x0e73;
-+ }
-+ tmrd = 2;
-+ twtp = twr + 5;
-+ tcksrx = 5;
-+ tckesr = 4;
-+ trd2wr = 4;
-+ tcke = 3;
-+ tmod = 12;
-+ wr_latency = 1;
-+ tmrw = 0;
-+ twr2rd = twtr + 5;
-+ tcwl = 0;
-+
-+ mr1 = para->dram_mr1;
-+ mr2 = 0;
-+ mr3 = 0;
-+
-+ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
-+ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
-+ tdinit2 = 200 * CONFIG_DRAM_CLK + 1;
-+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
-+
-+ break;
-+ case SUNXI_DRAM_TYPE_DDR3:
-+ trfc = ns_to_t(350);
-+ trefi = ns_to_t(7800) / 32 + 1; // XXX
-+
-+ twtr = ns_to_t(8) + 2; // + 2 ? XXX
-+ /* Only used by trd2wr calculation, which gets discard below */
-+// twr = max(ns_to_t(15), 2);
-+ trrd = max(ns_to_t(10), 2);
-+ txp = max(ns_to_t(10), 2);
-+
-+ if (CONFIG_DRAM_CLK <= 800) {
-+ tfaw = ns_to_t(50);
-+ trcd = ns_to_t(15);
-+ trp = ns_to_t(15);
-+ trc = ns_to_t(53);
-+ tras = ns_to_t(38);
-+
-+ mr0 = 0x1c70;
-+ mr2 = 0x18;
-+ tcl = 6;
-+ wr_latency = 2;
-+ tcwl = 4;
-+ t_rdata_en = 4;
-+ } else {
-+ tfaw = ns_to_t(35);
-+ trcd = ns_to_t(14);
-+ trp = ns_to_t(14);
-+ trc = ns_to_t(48);
-+ tras = ns_to_t(34);
-+
-+ mr0 = 0x1e14;
-+ mr2 = 0x20;
-+ tcl = 7;
-+ wr_latency = 3;
-+ tcwl = 5;
-+ t_rdata_en = 5;
-+ }
-+
-+ trasmax = CONFIG_DRAM_CLK / 30;
-+ twtp = tcwl + 2 + twtr; // WL+BL/2+tWTR
-+ /* Gets overwritten below */
-+// trd2wr = tcwl + 2 + twr; // WL+BL/2+tWR
-+ twr2rd = tcwl + twtr; // WL+tWTR
-+
-+ tdinit0 = 500 * CONFIG_DRAM_CLK + 1; // 500 us
-+ tdinit1 = 360 * CONFIG_DRAM_CLK / 1000 + 1; // 360 ns
-+ tdinit2 = 200 * CONFIG_DRAM_CLK + 1; // 200 us
-+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1; // 1 us
-+
-+ mr1 = para->dram_mr1;
-+ mr3 = 0;
-+ tcke = 3;
-+ tcksrx = 5;
-+ tckesr = 4;
-+ if (((para->dram_tpr13 & 0xc) == 0x04) || CONFIG_DRAM_CLK < 912)
-+ trd2wr = 5;
-+ else
-+ trd2wr = 6;
-+
-+ tmod = 12;
-+ tmrd = 4;
-+ tmrw = 0;
-+
-+ break;
-+ case SUNXI_DRAM_TYPE_LPDDR2:
-+ tfaw = max(ns_to_t(50), 4);
-+ trrd = max(ns_to_t(10), 1);
-+ trcd = max(ns_to_t(24), 2);
-+ trc = ns_to_t(70);
-+ txp = ns_to_t(8);
-+ if (txp < 2) {
-+ txp++;
-+ twtr = 2;
-+ } else {
-+ twtr = txp;
-+ }
-+ twr = max(ns_to_t(15), 2);
-+ trp = ns_to_t(17);
-+ tras = ns_to_t(42);
-+ trefi = ns_to_t(3900) / 32;
-+ trfc = ns_to_t(210);
-+
-+ trasmax = CONFIG_DRAM_CLK / 60;
-+ mr3 = para->dram_mr3;
-+ twtp = twr + 5;
-+ mr2 = 6;
-+ mr1 = 5;
-+ tcksrx = 5;
-+ tckesr = 5;
-+ trd2wr = 10;
-+ tcke = 2;
-+ tmod = 5;
-+ tmrd = 5;
-+ tmrw = 3;
-+ tcl = 4;
-+ wr_latency = 1;
-+ t_rdata_en = 1;
-+
-+ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
-+ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
-+ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
-+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
-+ twr2rd = twtr + 5;
-+ tcwl = 2;
-+ mr1 = 195;
-+ mr0 = 0;
-+
-+ break;
-+ case SUNXI_DRAM_TYPE_LPDDR3:
-+ tfaw = max(ns_to_t(50), 4);
-+ trrd = max(ns_to_t(10), 1);
-+ trcd = max(ns_to_t(24), 2);
-+ trc = ns_to_t(70);
-+ twtr = max(ns_to_t(8), 2);
-+ twr = max(ns_to_t(15), 2);
-+ trp = ns_to_t(17);
-+ tras = ns_to_t(42);
-+ trefi = ns_to_t(3900) / 32;
-+ trfc = ns_to_t(210);
-+ txp = twtr;
-+
-+ trasmax = CONFIG_DRAM_CLK / 60;
-+ if (CONFIG_DRAM_CLK < 800) {
-+ tcwl = 4;
-+ wr_latency = 3;
-+ t_rdata_en = 6;
-+ mr2 = 12;
-+ } else {
-+ tcwl = 3;
-+ tcke = 6;
-+ wr_latency = 2;
-+ t_rdata_en = 5;
-+ mr2 = 10;
-+ }
-+ twtp = tcwl + 5;
-+ tcl = 7;
-+ mr3 = para->dram_mr3;
-+ tcksrx = 5;
-+ tckesr = 5;
-+ trd2wr = 13;
-+ tcke = 3;
-+ tmod = 12;
-+ tdinit0 = 400 * CONFIG_DRAM_CLK + 1;
-+ tdinit1 = 500 * CONFIG_DRAM_CLK / 1000 + 1;
-+ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
-+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
-+ tmrd = 5;
-+ tmrw = 5;
-+ twr2rd = tcwl + twtr + 5;
-+ mr1 = 195;
-+ mr0 = 0;
-+
-+ break;
-+ default:
-+ trfc = 128;
-+ trp = 6;
-+ trefi = 98;
-+ txp = 10;
-+ twr = 8;
-+ twtr = 3;
-+ tras = 14;
-+ tfaw = 16;
-+ trc = 20;
-+ trcd = 6;
-+ trrd = 3;
-+
-+ twr2rd = 8;
-+ tcksrx = 4;
-+ tckesr = 3;
-+ trd2wr = 4;
-+ trasmax = 27;
-+ twtp = 12;
-+ tcke = 2;
-+ tmod = 6;
-+ tmrd = 2;
-+ tmrw = 0;
-+ tcwl = 3;
-+ tcl = 3;
-+ wr_latency = 1;
-+ t_rdata_en = 1;
-+ mr3 = 0;
-+ mr2 = 0;
-+ mr1 = 0;
-+ mr0 = 0;
-+ tdinit3 = 0;
-+ tdinit2 = 0;
-+ tdinit1 = 0;
-+ tdinit0 = 0;
-+
-+ break;
-+ }
-+
-+ /* Set mode registers */
-+ writel(mr0, 0x3103030);
-+ writel(mr1, 0x3103034);
-+ writel(mr2, 0x3103038);
-+ writel(mr3, 0x310303c);
-+ /* TODO: dram_odt_en is either 0x0 or 0x1, so right shift looks weird */
-+ writel((para->dram_odt_en >> 4) & 0x3, 0x310302c);
-+
-+ /* Set dram timing DRAMTMG0 - DRAMTMG5 */
-+ writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0),
-+ 0x3103058);
-+ writel((txp << 16) | (trtp << 8) | (trc << 0),
-+ 0x310305c);
-+ writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0),
-+ 0x3103060);
-+ writel((tmrw << 16) | (tmrd << 12) | (tmod << 0),
-+ 0x3103064);
-+ writel((trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0),
-+ 0x3103068);
-+ writel((tcksrx << 24) | (tcksrx << 16) | (tckesr << 8) | (tcke << 0),
-+ 0x310306c);
-+
-+ /* Set dual rank timing */
-+ clrsetbits_le32(0x3103078, 0xf000ffff,
-+ (CONFIG_DRAM_CLK < 800) ? 0xf0006610 : 0xf0007610);
-+
-+ /* Set phy interface time PITMG0, PTR3, PTR4 */
-+ writel((0x2 << 24) | (t_rdata_en << 16) | BIT(8) | (wr_latency << 0),
-+ 0x3103080);
-+ writel(((tdinit0 << 0) | (tdinit1 << 20)), 0x3103050);
-+ writel(((tdinit2 << 0) | (tdinit3 << 20)), 0x3103054);
-+
-+ /* Set refresh timing and mode */
-+ writel((trefi << 16) | (trfc << 0), 0x3103090);
-+ writel((trefi << 15) & 0x0fff0000, 0x3103094);
-+}
-+
-+// Purpose of this routine seems to be to initialize the PLL driving
-+// the MBUS and sdram.
-+//
-+static int ccu_set_pll_ddr_clk(int index, dram_para_t *para)
-+{
-+ unsigned int val, clk, n;
-+
-+ if (para->dram_tpr13 & BIT(6))
-+ clk = para->dram_tpr9;
-+ else
-+ clk = para->dram_clk;
-+
-+ // set VCO clock divider
-+ n = (clk * 2) / 24;
-+
-+ val = readl(0x2001010);
-+ val &= 0xfff800fc; // clear dividers
-+ val |= (n - 1) << 8; // set PLL division
-+ val |= 0xc0000000; // enable PLL and LDO
-+ val &= 0xdfffffff;
-+ writel(val | 0x20000000, 0x2001010);
-+
-+ // wait for PLL to lock
-+ while ((readl(0x2001010) & 0x10000000) == 0) {
-+ ;
-+ }
-+
-+ udelay(20);
-+
-+ // enable PLL output
-+ val = readl(0x2001000);
-+ val |= 0x08000000;
-+ writel(val, 0x2001000);
-+
-+ // turn clock gate on
-+ val = readl(0x2001800);
-+ val &= 0xfcfffcfc; // select DDR clk source, n=1, m=1
-+ val |= 0x80000000; // turn clock on
-+ writel(val, 0x2001800);
-+
-+ return n * 24;
-+}
-+
-+// Main purpose of sys_init seems to be to initalise the clocks for
-+// the sdram controller.
-+//
-+static void mctl_sys_init(dram_para_t *para)
-+{
-+ // assert MBUS reset
-+ clrbits_le32(0x2001540, BIT(30));
-+
-+ // turn off sdram clock gate, assert sdram reset
-+ clrbits_le32(0x200180c, 0x10001);
-+ clrsetbits_le32(0x2001800, BIT(31) | BIT(30), BIT(27));
-+ udelay(10);
-+
-+ // set ddr pll clock
-+ para->dram_clk = ccu_set_pll_ddr_clk(0, para) / 2;
-+ udelay(100);
-+ dram_disable_all_master();
-+
-+ // release sdram reset
-+ setbits_le32(0x200180c, BIT(16));
-+
-+ // release MBUS reset
-+ setbits_le32(0x2001540, BIT(30));
-+ setbits_le32(0x2001800, BIT(30));
-+
-+ udelay(5);
-+
-+ // turn on sdram clock gate
-+ setbits_le32(0x200180c, BIT(0));
-+
-+ // turn dram clock gate on, trigger sdr clock update
-+ setbits_le32(0x2001800, BIT(31) | BIT(27));
-+ udelay(5);
-+
-+ // mCTL clock enable
-+ writel(0x8000, 0x310300c);
-+ udelay(10);
-+}
-+
-+// The main purpose of this routine seems to be to copy an address configuration
-+// from the dram_para1 and dram_para2 fields to the PHY configuration registers
-+// (0x3102000, 0x3102004).
-+//
-+static void mctl_com_init(dram_para_t *para)
-+{
-+ uint32_t val, width;
-+ unsigned long ptr;
-+ int i;
-+
-+ // purpose ??
-+ clrsetbits_le32(0x3102008, 0x3f00, 0x2000);
-+
-+ // set SDRAM type and word width
-+ val = readl(0x3102000) & ~0x00fff000;
-+ val |= (para->dram_type & 0x7) << 16; // DRAM type
-+ val |= (~para->dram_para2 & 0x1) << 12; // DQ width
-+ val |= BIT(22); // ??
-+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
-+ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
-+ val |= BIT(19); // type 6 and 7 must use 1T
-+ } else {
-+ if (para->dram_tpr13 & BIT(5))
-+ val |= BIT(19);
-+ }
-+ writel(val, 0x3102000);
-+
-+ // init rank / bank / row for single/dual or two different ranks
-+ if ((para->dram_para2 & BIT(8)) &&
-+ ((para->dram_para2 & 0xf000) != 0x1000))
-+ width = 32;
-+ else
-+ width = 16;
-+
-+ ptr = 0x3102000;
-+ for (i = 0; i < width; i += 16) {
-+ val = readl(ptr) & 0xfffff000;
-+
-+ val |= (para->dram_para2 >> 12) & 0x3; // rank
-+ val |= ((para->dram_para1 >> (i + 12)) << 2) & 0x4; // bank - 2
-+ val |= (((para->dram_para1 >> (i + 4)) - 1) << 4) & 0xff; // row - 1
-+
-+ // convert from page size to column addr width - 3
-+ switch ((para->dram_para1 >> i) & 0xf) {
-+ case 8: val |= 0xa00; break;
-+ case 4: val |= 0x900; break;
-+ case 2: val |= 0x800; break;
-+ case 1: val |= 0x700; break;
-+ default: val |= 0x600; break;
-+ }
-+ writel(val, ptr);
-+ ptr += 4;
-+ }
-+
-+ // set ODTMAP based on number of ranks in use
-+ val = (readl(0x3102000) & 0x1) ? 0x303 : 0x201;
-+ writel(val, 0x3103120);
-+
-+ // set mctl reg 3c4 to zero when using half DQ
-+ if (para->dram_para2 & BIT(0))
-+ writel(0, 0x31033c4);
-+
-+ // purpose ??
-+ if (para->dram_tpr4) {
-+ setbits_le32(0x3102000, (para->dram_tpr4 & 0x3) << 25);
-+ setbits_le32(0x3102004, (para->dram_tpr4 & 0x7fc) << 10);
-+ }
-+}
-+
-+static const uint8_t ac_remapping_tables[][22] = {
-+ [0] = { 0 },
-+ [1] = { 1, 9, 3, 7, 8, 18, 4, 13, 5, 6, 10,
-+ 2, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
-+ [2] = { 4, 9, 3, 7, 8, 18, 1, 13, 2, 6, 10,
-+ 5, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
-+ [3] = { 1, 7, 8, 12, 10, 18, 4, 13, 5, 6, 3,
-+ 2, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
-+ [4] = { 4, 12, 10, 7, 8, 18, 1, 13, 2, 6, 3,
-+ 5, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
-+ [5] = { 13, 2, 7, 9, 12, 19, 5, 1, 6, 3, 4,
-+ 8, 10, 0, 0, 0, 21, 22, 18, 17, 11, 20 },
-+ [6] = { 3, 10, 7, 13, 9, 11, 1, 2, 4, 6, 8,
-+ 5, 12, 0, 0, 0, 20, 1, 0, 21, 22, 17 },
-+ [7] = { 3, 2, 4, 7, 9, 1, 17, 12, 18, 14, 13,
-+ 8, 15, 6, 10, 5, 19, 22, 16, 21, 20, 11 },
-+};
-+
-+/*
-+ * This routine chooses one of several remapping tables for 22 lines.
-+ * It is unclear which lines are being remapped. It seems to pick
-+ * table cfg7 for the Nezha board.
-+ */
-+static void mctl_phy_ac_remapping(dram_para_t *para)
-+{
-+ const uint8_t *cfg;
-+ uint32_t fuse, val;
-+
-+ /*
-+ * It is unclear whether the LPDDRx types don't need any remapping,
-+ * or whether the original code just didn't provide tables.
-+ */
-+ if (para->dram_type != SUNXI_DRAM_TYPE_DDR2 &&
-+ para->dram_type != SUNXI_DRAM_TYPE_DDR3)
-+ return;
-+
-+ fuse = (readl(SUNXI_SID_BASE + 0x28) & 0xf00) >> 8;
-+ debug("DDR efuse: 0x%x\n", fuse);
-+
-+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR2) {
-+ if (fuse == 15)
-+ return;
-+ cfg = ac_remapping_tables[6];
-+ } else {
-+ if (para->dram_tpr13 & 0xc0000) {
-+ cfg = ac_remapping_tables[7];
-+ } else {
-+ switch (fuse) {
-+ case 8: cfg = ac_remapping_tables[2]; break;
-+ case 9: cfg = ac_remapping_tables[3]; break;
-+ case 10: cfg = ac_remapping_tables[5]; break;
-+ case 11: cfg = ac_remapping_tables[4]; break;
-+ default:
-+ case 12: cfg = ac_remapping_tables[1]; break;
-+ case 13:
-+ case 14: cfg = ac_remapping_tables[0]; break;
-+ }
-+ }
-+ }
-+
-+ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
-+ (cfg[1] << 10) | (cfg[0] << 5);
-+ writel(val, 0x3102500);
-+
-+ val = (cfg[10] << 25) | (cfg[9] << 20) | (cfg[8] << 15) |
-+ (cfg[ 7] << 10) | (cfg[6] << 5) | cfg[5];
-+ writel(val, 0x3102504);
-+
-+ val = (cfg[15] << 20) | (cfg[14] << 15) | (cfg[13] << 10) |
-+ (cfg[12] << 5) | cfg[11];
-+ writel(val, 0x3102508);
-+
-+ val = (cfg[21] << 25) | (cfg[20] << 20) | (cfg[19] << 15) |
-+ (cfg[18] << 10) | (cfg[17] << 5) | cfg[16];
-+ writel(val, 0x310250c);
-+
-+ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
-+ (cfg[1] << 10) | (cfg[0] << 5) | 1;
-+ writel(val, 0x3102500);
-+}
-+
-+// Init the controller channel. The key part is placing commands in the main
-+// command register (PIR, 0x3103000) and checking command status (PGSR0, 0x3103010).
-+//
-+static unsigned int mctl_channel_init(unsigned int ch_index, dram_para_t *para)
-+{
-+ unsigned int val, dqs_gating_mode;
-+
-+ dqs_gating_mode = (para->dram_tpr13 & 0xc) >> 2;
-+
-+ // set DDR clock to half of CPU clock
-+ clrsetbits_le32(0x310200c, 0xfff, (para->dram_clk / 2) - 1);
-+
-+ // MRCTRL0 nibble 3 undocumented
-+ clrsetbits_le32(0x3103108, 0xf00, 0x300);
-+
-+ if (para->dram_odt_en)
-+ val = 0;
-+ else
-+ val = BIT(5);
-+
-+ // DX0GCR0
-+ if (para->dram_clk > 672)
-+ clrsetbits_le32(0x3103344, 0xf63e, val);
-+ else
-+ clrsetbits_le32(0x3103344, 0xf03e, val);
-+
-+ // DX1GCR0
-+ if (para->dram_clk > 672) {
-+ setbits_le32(0x3103344, 0x400);
-+ clrsetbits_le32(0x31033c4, 0xf63e, val);
-+ } else {
-+ clrsetbits_le32(0x31033c4, 0xf03e, val);
-+ }
-+
-+ // 0x3103208 undocumented
-+ setbits_le32(0x3103208, BIT(1));
-+
-+ eye_delay_compensation(para);
-+
-+ // set PLL SSCG ?
-+ val = readl(0x3103108);
-+ if (dqs_gating_mode == 1) {
-+ clrsetbits_le32(0x3103108, 0xc0, 0);
-+ clrbits_le32(0x31030bc, 0x107);
-+ } else if (dqs_gating_mode == 2) {
-+ clrsetbits_le32(0x3103108, 0xc0, 0x80);
-+
-+ clrsetbits_le32(0x31030bc, 0x107,
-+ (((para->dram_tpr13 >> 16) & 0x1f) - 2) | 0x100);
-+ clrsetbits_le32(0x310311c, BIT(31), BIT(27));
-+ } else {
-+ clrbits_le32(0x3103108, 0x40);
-+ udelay(10);
-+ setbits_le32(0x3103108, 0xc0);
-+ }
-+
-+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
-+ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
-+ if (dqs_gating_mode == 1)
-+ clrsetbits_le32(0x310311c, 0x080000c0, 0x80000000);
-+ else
-+ clrsetbits_le32(0x310311c, 0x77000000, 0x22000000);
-+ }
-+
-+ clrsetbits_le32(0x31030c0, 0x0fffffff,
-+ (para->dram_para2 & BIT(12)) ? 0x03000001 : 0x01000007);
-+
-+ if (readl(0x70005d4) & (1 << 16)) {
-+ clrbits_le32(0x7010250, 0x2);
-+ udelay(10);
-+ }
-+
-+ // Set ZQ config
-+ clrsetbits_le32(0x3103140, 0x3ffffff,
-+ (para->dram_zq & 0x00ffffff) | BIT(25));
-+
-+ // Initialise DRAM controller
-+ if (dqs_gating_mode == 1) {
-+ //writel(0x52, 0x3103000); // prep PHY reset + PLL init + z-cal
-+ writel(0x53, 0x3103000); // Go
-+
-+ while ((readl(0x3103010) & 0x1) == 0) {
-+ } // wait for IDONE
-+ udelay(10);
-+
-+ // 0x520 = prep DQS gating + DRAM init + d-cal
-+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
-+ writel(0x5a0, 0x3103000); // + DRAM reset
-+ else
-+ writel(0x520, 0x3103000);
-+ } else {
-+ if ((readl(0x70005d4) & (1 << 16)) == 0) {
-+ // prep DRAM init + PHY reset + d-cal + PLL init + z-cal
-+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
-+ writel(0x1f2, 0x3103000); // + DRAM reset
-+ else
-+ writel(0x172, 0x3103000);
-+ } else {
-+ // prep PHY reset + d-cal + z-cal
-+ writel(0x62, 0x3103000);
-+ }
-+ }
-+
-+ setbits_le32(0x3103000, 0x1); // GO
-+
-+ udelay(10);
-+ while ((readl(0x3103010) & 0x1) == 0) {
-+ } // wait for IDONE
-+
-+ if (readl(0x70005d4) & (1 << 16)) {
-+ clrsetbits_le32(0x310310c, 0x06000000, 0x04000000);
-+ udelay(10);
-+
-+ setbits_le32(0x3103004, 0x1);
-+
-+ while ((readl(0x3103018) & 0x7) != 0x3) {
-+ }
-+
-+ clrbits_le32(0x7010250, 0x1);
-+ udelay(10);
-+
-+ clrbits_le32(0x3103004, 0x1);
-+
-+ while ((readl(0x3103018) & 0x7) != 0x1) {
-+ }
-+
-+ udelay(15);
-+
-+ if (dqs_gating_mode == 1) {
-+ clrbits_le32(0x3103108, 0xc0);
-+ clrsetbits_le32(0x310310c, 0x06000000, 0x02000000);
-+ udelay(1);
-+ writel(0x401, 0x3103000);
-+
-+ while ((readl(0x3103010) & 0x1) == 0) {
-+ }
-+ }
-+ }
-+
-+ // Check for training error
-+ if (readl(0x3103010) & BIT(20)) {
-+ printf("ZQ calibration error, check external 240 ohm resistor\n");
-+ return 0;
-+ }
-+
-+ // STATR = Zynq STAT? Wait for status 'normal'?
-+ while ((readl(0x3103018) & 0x1) == 0) {
-+ }
-+
-+ setbits_le32(0x310308c, BIT(31));
-+ udelay(10);
-+ clrbits_le32(0x310308c, BIT(31));
-+ udelay(10);
-+ setbits_le32(0x3102014, BIT(31));
-+ udelay(10);
-+
-+ clrbits_le32(0x310310c, 0x06000000);
-+
-+ if (dqs_gating_mode == 1)
-+ clrsetbits_le32(0x310311c, 0xc0, 0x40);
-+
-+ return 1;
-+}
-+
-+static unsigned int calculate_rank_size(uint32_t regval)
-+{
-+ unsigned int bits;
-+
-+ bits = (regval >> 8) & 0xf; /* page size - 3 */
-+ bits += (regval >> 4) & 0xf; /* row width - 1 */
-+ bits += (regval >> 2) & 0x3; /* bank count - 2 */
-+ bits -= 14; /* 1MB = 20 bits, minus above 6 = 14 */
-+
-+ return 1U << bits;
-+}
-+
-+/*
-+ * The below routine reads the dram config registers and extracts
-+ * the number of address bits in each rank available. It then calculates
-+ * total memory size in MB.
-+ */
-+static unsigned int DRAMC_get_dram_size(void)
-+{
-+ uint32_t val;
-+ unsigned int size;
-+
-+ val = readl(0x3102000); /* MC_WORK_MODE0 */
-+ size = calculate_rank_size(val);
-+ if ((val & 0x3) == 0) /* single rank? */
-+ return size;
-+
-+ val = readl(0x3102004); /* MC_WORK_MODE1 */
-+ if ((val & 0x3) == 0) /* two identical ranks? */
-+ return size * 2;
-+
-+ /* add sizes of both ranks */
-+ return size + calculate_rank_size(val);
-+}
-+
-+/*
-+ * The below routine reads the command status register to extract
-+ * DQ width and rank count. This follows the DQS training command in
-+ * channel_init. If error bit 22 is reset, we have two ranks and full DQ.
-+ * If there was an error, figure out whether it was half DQ, single rank,
-+ * or both. Set bit 12 and 0 in dram_para2 with the results.
-+ */
-+static int dqs_gate_detect(dram_para_t *para)
-+{
-+ uint32_t dx0, dx1;
-+
-+ if ((readl(0x3103010) & BIT(22)) == 0) {
-+ para->dram_para2 = (para->dram_para2 & ~0xf) | BIT(12);
-+ debug("dual rank and full DQ\n");
-+
-+ return 1;
-+ }
-+
-+ dx0 = (readl(0x03103348) & 0x3000000) >> 24;
-+ if (dx0 == 0) {
-+ para->dram_para2 = (para->dram_para2 & ~0xf) | 0x1001;
-+ debug("dual rank and half DQ\n");
-+
-+ return 1;
-+ }
-+
-+ if (dx0 == 2) {
-+ dx1 = (readl(0x031033c8) & 0x3000000) >> 24;
-+ if (dx1 == 2) {
-+ para->dram_para2 = para->dram_para2 & ~0xf00f;
-+ debug("single rank and full DQ\n");
-+ } else {
-+ para->dram_para2 = (para->dram_para2 & ~0xf00f) | BIT(0);
-+ debug("single rank and half DQ\n");
-+ }
-+
-+ return 1;
-+ }
-+
-+ if ((para->dram_tpr13 & BIT(29)) == 0)
-+ return 0;
-+
-+ debug("DX0 state: %d\n", dx0);
-+ debug("DX1 state: %d\n", dx1);
-+
-+ return 0;
-+}
-+
-+static int dramc_simple_wr_test(unsigned int mem_mb, int len)
-+{
-+ unsigned int offs = (mem_mb / 2) << 18; // half of memory size
-+ unsigned int patt1 = 0x01234567;
-+ unsigned int patt2 = 0xfedcba98;
-+ unsigned int *addr, v1, v2, i;
-+
-+ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
-+ for (i = 0; i != len; i++, addr++) {
-+ writel(patt1 + i, (unsigned long)addr);
-+ writel(patt2 + i, (unsigned long)(addr + offs));
-+ }
-+
-+ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
-+ for (i = 0; i != len; i++) {
-+ v1 = readl((unsigned long)(addr + i));
-+ v2 = patt1 + i;
-+ if (v1 != v2) {
-+ printf("DRAM: simple test FAIL\n");
-+ printf("%x != %x at address %p\n", v1, v2, addr + i);
-+ return 1;
-+ }
-+ v1 = readl((unsigned long)(addr + offs + i));
-+ v2 = patt2 + i;
-+ if (v1 != v2) {
-+ printf("DRAM: simple test FAIL\n");
-+ printf("%x != %x at address %p\n", v1, v2, addr + offs + i);
-+ return 1;
-+ }
-+ }
-+
-+ debug("DRAM: simple test OK\n");
-+ return 0;
-+}
-+
-+// Set the Vref mode for the controller
-+//
-+static void mctl_vrefzq_init(dram_para_t *para)
-+{
-+ if (para->dram_tpr13 & BIT(17))
-+ return;
-+
-+ clrsetbits_le32(0x3103110, 0x7f7f7f7f, para->dram_tpr5);
-+
-+ // IOCVR1
-+ if ((para->dram_tpr13 & BIT(16)) == 0)
-+ clrsetbits_le32(0x3103114, 0x7f, para->dram_tpr6 & 0x7f);
-+}
-+
-+// Perform an init of the controller. This is actually done 3 times. The first
-+// time to establish the number of ranks and DQ width. The second time to
-+// establish the actual ram size. The third time is final one, with the final
-+// settings.
-+//
-+static int mctl_core_init(dram_para_t *para)
-+{
-+ mctl_sys_init(para);
-+
-+ mctl_vrefzq_init(para);
-+
-+ mctl_com_init(para);
-+
-+ mctl_phy_ac_remapping(para);
-+
-+ mctl_set_timing_params(para);
-+
-+ return mctl_channel_init(0, para);
-+}
-+
-+/*
-+ * This routine sizes a DRAM device by cycling through address lines and
-+ * figuring out if they are connected to a real address line, or if the
-+ * address is a mirror.
-+ * First the column and bank bit allocations are set to low values (2 and 9
-+ * address lines). Then a maximum allocation (16 lines) is set for rows and
-+ * this is tested.
-+ * Next the BA2 line is checked. This seems to be placed above the column,
-+ * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
-+ * and these are tested. The results are placed in dram_para1 and dram_para2.
-+ */
-+static int auto_scan_dram_size(dram_para_t *para)
-+{
-+ unsigned int rval, i, j, rank, maxrank, offs;
-+ unsigned int shft;
-+ unsigned long ptr, mc_work_mode, chk;
-+
-+ if (mctl_core_init(para) == 0) {
-+ printf("DRAM initialisation error : 0\n");
-+ return 0;
-+ }
-+
-+ maxrank = (para->dram_para2 & 0xf000) ? 2 : 1;
-+ mc_work_mode = 0x3102000;
-+ offs = 0;
-+
-+ /* write test pattern */
-+ for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
-+ writel((i & 0x1) ? ptr : ~ptr, ptr);
-+
-+ for (rank = 0; rank < maxrank;) {
-+ /* set row mode */
-+ clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
-+ udelay(1);
-+
-+ // Scan per address line, until address wraps (i.e. see shadow)
-+ for (i = 11; i < 17; i++) {
-+ chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
-+ ptr = CFG_SYS_SDRAM_BASE;
-+ for (j = 0; j < 64; j++) {
-+ if (readl(chk) != ((j & 1) ? ptr : ~ptr))
-+ break;
-+ ptr += 4;
-+ chk += 4;
-+ }
-+ if (j == 64)
-+ break;
-+ }
-+ if (i > 16)
-+ i = 16;
-+ debug("rank %d row = %d\n", rank, i);
-+
-+ /* Store rows in para 1 */
-+ shft = offs + 4;
-+ rval = para->dram_para1;
-+ rval &= ~(0xff << shft);
-+ rval |= i << shft;
-+ para->dram_para1 = rval;
-+
-+ if (rank == 1) /* Set bank mode for rank0 */
-+ clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
-+
-+ /* Set bank mode for current rank */
-+ clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
-+ udelay(1);
-+
-+ // Test if bit A23 is BA2 or mirror XXX A22?
-+ chk = CFG_SYS_SDRAM_BASE + (1U << 22);
-+ ptr = CFG_SYS_SDRAM_BASE;
-+ for (i = 0, j = 0; i < 64; i++) {
-+ if (readl(chk) != ((i & 1) ? ptr : ~ptr)) {
-+ j = 1;
-+ break;
-+ }
-+ ptr += 4;
-+ chk += 4;
-+ }
-+
-+ debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
-+
-+ /* Store banks in para 1 */
-+ shft = 12 + offs;
-+ rval = para->dram_para1;
-+ rval &= ~(0xf << shft);
-+ rval |= j << shft;
-+ para->dram_para1 = rval;
-+
-+ if (rank == 1) /* Set page mode for rank0 */
-+ clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
-+
-+ /* Set page mode for current rank */
-+ clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
-+ udelay(1);
-+
-+ // Scan per address line, until address wraps (i.e. see shadow)
-+ for (i = 9; i < 14; i++) {
-+ chk = CFG_SYS_SDRAM_BASE + (1U << i);
-+ ptr = CFG_SYS_SDRAM_BASE;
-+ for (j = 0; j < 64; j++) {
-+ if (readl(chk) != ((j & 1) ? ptr : ~ptr))
-+ break;
-+ ptr += 4;
-+ chk += 4;
-+ }
-+ if (j == 64)
-+ break;
-+ }
-+ if (i > 13)
-+ i = 13;
-+
-+ unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
-+ debug("rank %d page size = %d KB\n", rank, pgsize);
-+
-+ /* Store page size */
-+ shft = offs;
-+ rval = para->dram_para1;
-+ rval &= ~(0xf << shft);
-+ rval |= pgsize << shft;
-+ para->dram_para1 = rval;
-+
-+ // Move to next rank
-+ rank++;
-+ if (rank != maxrank) {
-+ if (rank == 1) {
-+ /* MC_WORK_MODE */
-+ clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
-+
-+ /* MC_WORK_MODE2 */
-+ clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
-+ }
-+ /* store rank1 config in upper half of para1 */
-+ offs += 16;
-+ mc_work_mode += 4; /* move to MC_WORK_MODE2 */
-+ }
-+ }
-+ if (maxrank == 2) {
-+ para->dram_para2 &= 0xfffff0ff;
-+ /* note: rval is equal to para->dram_para1 here */
-+ if ((rval & 0xffff) == (rval >> 16)) {
-+ debug("rank1 config same as rank0\n");
-+ } else {
-+ para->dram_para2 |= BIT(8);
-+ debug("rank1 config different from rank0\n");
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/*
-+ * This routine sets up parameters with dqs_gating_mode equal to 1 and two
-+ * ranks enabled. It then configures the core and tests for 1 or 2 ranks and
-+ * full or half DQ width. It then resets the parameters to the original values.
-+ * dram_para2 is updated with the rank and width findings.
-+ */
-+static int auto_scan_dram_rank_width(dram_para_t *para)
-+{
-+ unsigned int s1 = para->dram_tpr13;
-+ unsigned int s2 = para->dram_para1;
-+
-+ para->dram_para1 = 0x00b000b0;
-+ para->dram_para2 = (para->dram_para2 & ~0xf) | BIT(12);
-+
-+ /* set DQS probe mode */
-+ para->dram_tpr13 = (para->dram_tpr13 & ~0x8) | BIT(2) | BIT(0);
-+
-+ mctl_core_init(para);
-+
-+ if (readl(0x3103010) & BIT(20))
-+ return 0;
-+
-+ if (dqs_gate_detect(para) == 0)
-+ return 0;
-+
-+ para->dram_tpr13 = s1;
-+ para->dram_para1 = s2;
-+
-+ return 1;
-+}
-+
-+/*
-+ * This routine determines the SDRAM topology. It first establishes the number
-+ * of ranks and the DQ width. Then it scans the SDRAM address lines to establish
-+ * the size of each rank. It then updates dram_tpr13 to reflect that the sizes
-+ * are now known: a re-init will not repeat the autoscan.
-+ */
-+static int auto_scan_dram_config(dram_para_t *para)
-+{
-+ if (((para->dram_tpr13 & BIT(14)) == 0) &&
-+ (auto_scan_dram_rank_width(para) == 0)) {
-+ printf("ERROR: auto scan dram rank & width failed\n");
-+ return 0;
-+ }
-+
-+ if (((para->dram_tpr13 & BIT(0)) == 0) &&
-+ (auto_scan_dram_size(para) == 0)) {
-+ printf("ERROR: auto scan dram size failed\n");
-+ return 0;
-+ }
-+
-+ if ((para->dram_tpr13 & BIT(15)) == 0)
-+ para->dram_tpr13 |= BIT(14) | BIT(13) | BIT(1) | BIT(0);
-+
-+ return 1;
-+}
-+
-+int init_DRAM(int type, dram_para_t *para)
-+{
-+ u32 rc, mem_size_mb;
-+
-+ debug("DRAM BOOT DRIVE INFO: %s\n", "V0.24");
-+ debug("DRAM CLK = %d MHz\n", para->dram_clk);
-+ debug("DRAM Type = %d (2:DDR2,3:DDR3)\n", para->dram_type);
-+ if ((para->dram_odt_en & 0x1) == 0)
-+ debug("DRAMC read ODT off\n");
-+ else
-+ debug("DRAMC ZQ value: 0x%x\n", para->dram_zq);
-+
-+ /* Test ZQ status */
-+ if (para->dram_tpr13 & BIT(16)) {
-+ debug("DRAM only have internal ZQ\n");
-+ setbits_le32(0x3000160, BIT(8));
-+ writel(0, 0x3000168);
-+ udelay(10);
-+ } else {
-+ clrbits_le32(0x3000160, 0x3);
-+ writel(para->dram_tpr13 & BIT(16), 0x7010254);
-+ udelay(10);
-+ clrsetbits_le32(0x3000160, 0x108, BIT(1));
-+ udelay(10);
-+ setbits_le32(0x3000160, BIT(0));
-+ udelay(20);
-+ debug("ZQ value = 0x%x\n", readl(0x300016c));
-+ }
-+
-+ dram_voltage_set(para);
-+
-+ /* Set SDRAM controller auto config */
-+ if ((para->dram_tpr13 & BIT(0)) == 0) {
-+ if (auto_scan_dram_config(para) == 0) {
-+ printf("auto_scan_dram_config() FAILED\n");
-+ return 0;
-+ }
-+ }
-+
-+ /* report ODT */
-+ rc = para->dram_mr1;
-+ if ((rc & 0x44) == 0)
-+ debug("DRAM ODT off\n");
-+ else
-+ debug("DRAM ODT value: 0x%x\n", rc);
-+
-+ /* Init core, final run */
-+ if (mctl_core_init(para) == 0) {
-+ printf("DRAM initialisation error: 1\n");
-+ return 0;
-+ }
-+
-+ /* Get SDRAM size */
-+ /* TODO: who ever puts a negative number in the top half? */
-+ rc = para->dram_para2;
-+ if (rc & BIT(31)) {
-+ rc = (rc >> 16) & ~BIT(15);
-+ } else {
-+ rc = DRAMC_get_dram_size();
-+ debug("DRAM: size = %dMB\n", rc);
-+ para->dram_para2 = (para->dram_para2 & 0xffffU) | rc << 16;
-+ }
-+ mem_size_mb = rc;
-+
-+ /* Purpose ?? */
-+ if (para->dram_tpr13 & BIT(30)) {
-+ rc = para->dram_tpr8;
-+ if (rc == 0)
-+ rc = 0x10000200;
-+ writel(rc, 0x31030a0);
-+ writel(0x40a, 0x310309c);
-+ setbits_le32(0x3103004, BIT(0));
-+ debug("Enable Auto SR\n");
-+ } else {
-+ clrbits_le32(0x31030a0, 0xffff);
-+ clrbits_le32(0x3103004, 0x1);
-+ }
-+
-+ /* Purpose ?? */
-+ if (para->dram_tpr13 & BIT(9)) {
-+ clrsetbits_le32(0x3103100, 0xf000, 0x5000);
-+ } else {
-+ if (para->dram_type != SUNXI_DRAM_TYPE_LPDDR2)
-+ clrbits_le32(0x3103100, 0xf000);
-+ }
-+
-+ setbits_le32(0x3103140, BIT(31));
-+
-+ /* CHECK: is that really writing to a different register? */
-+ if (para->dram_tpr13 & BIT(8))
-+ writel(readl(0x3103140) | 0x300, 0x31030b8);
-+
-+ if (para->dram_tpr13 & BIT(16))
-+ clrbits_le32(0x3103108, BIT(13));
-+ else
-+ setbits_le32(0x3103108, BIT(13));
-+
-+ /* Purpose ?? */
-+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR3)
-+ clrsetbits_le32(0x310307c, 0xf0000, 0x1000);
-+
-+ dram_enable_all_master();
-+ if (para->dram_tpr13 & BIT(28)) {
-+ if ((readl(0x70005d4) & BIT(16)) ||
-+ dramc_simple_wr_test(mem_size_mb, 4096))
-+ return 0;
-+ }
-+
-+ return mem_size_mb;
-+}
-+
-+unsigned long sunxi_dram_init(void)
-+{
-+ dram_para_t para = {
-+ .dram_clk = CONFIG_DRAM_CLK,
-+ .dram_type = CONFIG_SUNXI_DRAM_TYPE,
-+ .dram_zq = CONFIG_DRAM_ZQ,
-+ .dram_odt_en = CONFIG_DRAM_SUNXI_ODT_EN,
-+ .dram_para1 = 0x000010d2,
-+ .dram_para2 = 0,
-+ .dram_mr0 = 0x1c70,
-+ .dram_mr1 = 0x42,
-+ .dram_mr2 = 0x18,
-+ .dram_mr3 = 0,
-+ .dram_tpr0 = 0x004a2195,
-+ .dram_tpr1 = 0x02423190,
-+ .dram_tpr2 = 0x0008b061,
-+ .dram_tpr3 = 0xb4787896, // unused
-+ .dram_tpr4 = 0,
-+ .dram_tpr5 = 0x48484848,
-+ .dram_tpr6 = 0x00000048,
-+ .dram_tpr7 = 0x1620121e, // unused
-+ .dram_tpr8 = 0,
-+ .dram_tpr9 = 0, // clock?
-+ .dram_tpr10 = 0,
-+ .dram_tpr11 = CONFIG_DRAM_SUNXI_TPR11,
-+ .dram_tpr12 = CONFIG_DRAM_SUNXI_TPR12,
-+ .dram_tpr13 = CONFIG_DRAM_SUNXI_TPR13,
-+ };
-+
-+ return init_DRAM(0, ¶) * 1024UL * 1024;
-+};
-+
-+#ifdef CONFIG_RAM /* using the driver model */
-+struct sunxi_ram_priv {
-+ size_t size;
-+};
-+
-+static int sunxi_ram_probe(struct udevice *dev)
-+{
-+ struct sunxi_ram_priv *priv = dev_get_priv(dev);
-+ unsigned long dram_size;
-+
-+ debug("%s: %s: probing\n", __func__, dev->name);
-+
-+ dram_size = sunxi_dram_init();
-+ if (!dram_size) {
-+ printf("DRAM init failed: %d\n", ret);
-+ return -ENODEV;
-+ }
-+
-+ priv->size = dram_size;
-+
-+ return 0;
-+}
-+
-+static int sunxi_ram_get_info(struct udevice *dev, struct ram_info *info)
-+{
-+ struct sunxi_ram_priv *priv = dev_get_priv(dev);
-+
-+ debug("%s: %s: getting info\n", __func__, dev->name);
-+
-+ info->base = CFG_SYS_SDRAM_BASE;
-+ info->size = priv->size;
-+
-+ return 0;
-+}
-+
-+static struct ram_ops sunxi_ram_ops = {
-+ .get_info = sunxi_ram_get_info,
-+};
-+
-+static const struct udevice_id sunxi_ram_ids[] = {
-+ { .compatible = "allwinner,sun20i-d1-mbus" },
-+ { }
-+};
-+
-+U_BOOT_DRIVER(sunxi_ram) = {
-+ .name = "sunxi_ram",
-+ .id = UCLASS_RAM,
-+ .of_match = sunxi_ram_ids,
-+ .ops = &sunxi_ram_ops,
-+ .probe = sunxi_ram_probe,
-+ .priv_auto = sizeof(struct sunxi_ram_priv),
-+};
-+#endif /* CONFIG_RAM (using driver model) */
-diff --git a/drivers/ram/sunxi/dram_sun20i_d1.h b/drivers/ram/sunxi/dram_sun20i_d1.h
-new file mode 100644
-index 0000000000..89aac9dade
---- /dev/null
-+++ b/drivers/ram/sunxi/dram_sun20i_d1.h
-@@ -0,0 +1,70 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * D1/R528/T113 DRAM controller register and constant defines
-+ *
-+ * (C) Copyright 2022 Arm Ltd.
-+ * Based on H6 and H616 header, which are:
-+ * (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
-+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
-+ *
-+ */
-+
-+#ifndef _SUNXI_DRAM_SUN20I_D1_H
-+#define _SUNXI_DRAM_SUN20I_D1_H
-+
-+enum sunxi_dram_type {
-+ SUNXI_DRAM_TYPE_DDR2 = 2,
-+ SUNXI_DRAM_TYPE_DDR3 = 3,
-+ SUNXI_DRAM_TYPE_LPDDR2 = 6,
-+ SUNXI_DRAM_TYPE_LPDDR3 = 7,
-+};
-+
-+/*
-+ * This structure contains a mixture of fixed configuration settings,
-+ * variables that are used at runtime to communicate settings between
-+ * different stages and functions, and unused values.
-+ * This is copied from Allwinner's boot0 data structure, which can be
-+ * found at offset 0x38 in any boot0 binary. To allow matching up some
-+ * board specific settings, this struct is kept compatible, even though
-+ * we don't need all members in our code.
-+ */
-+typedef struct dram_para {
-+ /* normal configuration */
-+ u32 dram_clk;
-+ u32 dram_type;
-+ u32 dram_zq;
-+ u32 dram_odt_en;
-+
-+ /* control configuration */
-+ u32 dram_para1;
-+ u32 dram_para2;
-+
-+ /* timing configuration */
-+ u32 dram_mr0;
-+ u32 dram_mr1;
-+ u32 dram_mr2;
-+ u32 dram_mr3;
-+ u32 dram_tpr0; //DRAMTMG0
-+ u32 dram_tpr1; //DRAMTMG1
-+ u32 dram_tpr2; //DRAMTMG2
-+ u32 dram_tpr3; //DRAMTMG3
-+ u32 dram_tpr4; //DRAMTMG4
-+ u32 dram_tpr5; //DRAMTMG5
-+ u32 dram_tpr6; //DRAMTMG8
-+ u32 dram_tpr7;
-+ u32 dram_tpr8;
-+ u32 dram_tpr9;
-+ u32 dram_tpr10;
-+ u32 dram_tpr11;
-+ u32 dram_tpr12;
-+ u32 dram_tpr13; /* contains a bitfield of DRAM setup settings */
-+} dram_para_t;
-+
-+static inline int ns_to_t(int nanoseconds)
-+{
-+ const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
-+
-+ return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
-+}
-+
-+#endif /* _SUNXI_DRAM_SUN20I_D1_H */
---
-2.20.1
-
--- /dev/null
+From abdc00eee12eed6db2a5e6fb7d72aae6be1d4193 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:54 +0100
+Subject: [PATCH 4014/4044] sunxi: introduce NCAT2 generation model
+
+Allwinner seems to typically stick to a common MMIO memory map for
+several SoCs, but from time to time does some breaking changes, which
+also introduce new generations of some peripherals. The last time this
+happened with the H6, which apart from re-organising the base addresses
+also changed the clock controller significantly. We added a
+CONFIG_SUN50I_GEN_H6 symbol back then to mark SoCs sharing those traits.
+
+Now the Allwinner D1 changes the memory map again, and also extends the
+pincontroller, among other peripherals.
+To mark this generation of SoCs, add a CONFIG_SUNXI_GEN_NCAT2 symbol,
+this name is reportedly used in the Allwinner BSP code, and prevents us
+from inventing our own name.
+
+Add this new symbol to some guards that were already checking for the H6
+generation, since many features are shared between the two (like the
+renovated clock controller).
+
+This paves the way to introduce a first user of this generation.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Sam Edwards <CFSworks@gmail.com>
+Tested-by: Sam Edwards <CFSworks@gmail.com>
+---
+ arch/arm/include/asm/arch-sunxi/clock.h | 2 +-
+ arch/arm/include/asm/arch-sunxi/cpu.h | 2 +
+ .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h | 43 +++++++++++++++++++
+ arch/arm/include/asm/arch-sunxi/mmc.h | 2 +-
+ arch/arm/include/asm/arch-sunxi/prcm.h | 2 +-
+ arch/arm/include/asm/arch-sunxi/timer.h | 2 +-
+ arch/arm/mach-sunxi/Kconfig | 12 +++++-
+ arch/arm/mach-sunxi/Makefile | 1 +
+ arch/arm/mach-sunxi/board.c | 22 ++++++----
+ common/spl/Kconfig | 2 +-
+ drivers/i2c/mvtwsi.c | 3 +-
+ drivers/mmc/sunxi_mmc.c | 10 +++--
+ include/sunxi_gpio.h | 3 ++
+ 13 files changed, 87 insertions(+), 19 deletions(-)
+ create mode 100644 arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+
+diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
+index 2cfd540742..3d34261b0e 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock.h
++++ b/arch/arm/include/asm/arch-sunxi/clock.h
+@@ -16,7 +16,7 @@
+ /* clock control module regs definition */
+ #if defined(CONFIG_MACH_SUN8I_A83T)
+ #include <asm/arch/clock_sun8i_a83t.h>
+-#elif defined(CONFIG_SUN50I_GEN_H6)
++#elif defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
+ #include <asm/arch/clock_sun50i_h6.h>
+ #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
+ defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
+index b08f202374..768c6572d6 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu.h
+@@ -10,6 +10,8 @@
+ #include <asm/arch/cpu_sun9i.h>
+ #elif defined(CONFIG_SUN50I_GEN_H6)
+ #include <asm/arch/cpu_sun50i_h6.h>
++#elif defined(CONFIG_SUNXI_GEN_NCAT2)
++#include <asm/arch/cpu_sunxi_ncat2.h>
+ #else
+ #include <asm/arch/cpu_sun4i.h>
+ #endif
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+new file mode 100644
+index 0000000000..b13be2c4e8
+--- /dev/null
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+@@ -0,0 +1,43 @@
++/*
++ * (C) Copyright 2022 Arm Limited
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#ifndef _SUNXI_CPU_SUNXI_NCAT2_H
++#define _SUNXI_CPU_SUNXI_NCAT2_H
++
++#define SUNXI_CCM_BASE 0x02001000
++#define SUNXI_TIMER_BASE 0x02050000
++
++#define SUNXI_UART0_BASE 0x02500000
++#define SUNXI_UART1_BASE 0x02500400
++#define SUNXI_UART2_BASE 0x02500800
++#define SUNXI_UART3_BASE 0x02500C00
++#define SUNXI_TWI0_BASE 0x02502000
++#define SUNXI_TWI1_BASE 0x02502400
++#define SUNXI_TWI2_BASE 0x02502800
++#define SUNXI_TWI3_BASE 0x02502C00
++
++#define SUNXI_SRAMC_BASE 0x03000000
++/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
++#define SUNXI_SIDC_BASE 0x03006000
++#define SUNXI_SID_BASE 0x03006200
++#define SUNXI_GIC400_BASE 0x03020000
++
++#define SUNXI_MMC0_BASE 0x04020000
++#define SUNXI_MMC1_BASE 0x04021000
++#define SUNXI_MMC2_BASE 0x04022000
++
++#define SUNXI_R_CPUCFG_BASE 0x07000400
++
++#define SUNXI_CPUX_BASE 0x09010000
++#define SUNXI_CPUCFG_BASE 0
++
++#ifndef __ASSEMBLY__
++void sunxi_board_init(void);
++void sunxi_reset(void);
++int sunxi_get_sid(unsigned int *sid);
++#endif
++
++#endif /* _SUNXI_CPU_SUNXI_NCAT2_H */
+diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
+index 5daacf10eb..8ed3e0459c 100644
+--- a/arch/arm/include/asm/arch-sunxi/mmc.h
++++ b/arch/arm/include/asm/arch-sunxi/mmc.h
+@@ -45,7 +45,7 @@ struct sunxi_mmc {
+ u32 chda; /* 0x90 */
+ u32 cbda; /* 0x94 */
+ u32 res2[26];
+-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
++#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
+ u32 res3[17];
+ u32 samp_dl;
+ u32 res4[46];
+diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
+index 5106076f5e..c5418cfd28 100644
+--- a/arch/arm/include/asm/arch-sunxi/prcm.h
++++ b/arch/arm/include/asm/arch-sunxi/prcm.h
+@@ -9,7 +9,7 @@
+ #define _SUNXI_PRCM_H
+
+ /* prcm regs definition */
+-#if defined(CONFIG_SUN50I_GEN_H6)
++#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
+ #include <asm/arch/prcm_sun50i.h>
+ #else
+ #include <asm/arch/prcm_sun6i.h>
+diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
+index bb5626d893..e17db8588e 100644
+--- a/arch/arm/include/asm/arch-sunxi/timer.h
++++ b/arch/arm/include/asm/arch-sunxi/timer.h
+@@ -76,7 +76,7 @@ struct sunxi_timer_reg {
+ struct sunxi_tgp tgp[4];
+ u8 res5[8];
+ u32 cpu_cfg;
+-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
++#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
+ u8 res3[16];
+ struct sunxi_wdog wdog[5]; /* We have 5 watchdogs */
+ #endif
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index b328ce8960..60ca1239dd 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -102,7 +102,7 @@ config AXP_PMIC_BUS
+ config SUNXI_SRAM_ADDRESS
+ hex
+ default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
+- default 0x20000 if SUN50I_GEN_H6
++ default 0x20000 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
+ default 0x0
+ ---help---
+ Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
+@@ -144,6 +144,14 @@ config SUN50I_GEN_H6
+ Select this for sunxi SoCs which have H6 like peripherals, clocks
+ and memory map.
+
++config SUNXI_GEN_NCAT2
++ bool
++ select MMC_SUNXI_HAS_NEW_MODE
++ select SUPPORT_SPL
++ ---help---
++ Select this for sunxi SoCs which have D1 like peripherals, clocks
++ and memory map.
++
+ config SUNXI_DRAM_DW
+ bool
+ ---help---
+@@ -760,6 +768,7 @@ config VIDEO_SUNXI
+ depends on !MACH_SUN9I
+ depends on !MACH_SUN50I
+ depends on !SUN50I_GEN_H6
++ depends on !SUNXI_GEN_NCAT2
+ select VIDEO
+ select DISPLAY
+ imply VIDEO_DT_SIMPLEFB
+@@ -973,6 +982,7 @@ config SPL_STACK_R_ADDR
+ default 0x2fe00000 if MACH_SUN9I
+ default 0x4fe00000 if MACH_SUN50I
+ default 0x4fe00000 if SUN50I_GEN_H6
++ default 0x4fe00000 if SUNXI_GEN_NCAT2
+
+ config SPL_SPI_SUNXI
+ bool "Support for SPI Flash on Allwinner SoCs in SPL"
+diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
+index 671211e932..1d4c70ec35 100644
+--- a/arch/arm/mach-sunxi/Makefile
++++ b/arch/arm/mach-sunxi/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o
+ endif
+ obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o gtbus_sun9i.o
+ obj-$(CONFIG_SUN50I_GEN_H6) += clock_sun50i_h6.o
++obj-$(CONFIG_SUNXI_GEN_NCAT2) += clock_sun50i_h6.o
+ ifndef CONFIG_ARM64
+ obj-y += timer.o
+ endif
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index ec46ab9279..51b8e708b0 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -176,13 +176,19 @@ static int gpio_init(void)
+ #error Unsupported console port number. Please fix pin mux settings in board.c
+ #endif
+
+-#ifdef CONFIG_SUN50I_GEN_H6
+- /* Update PIO power bias configuration by copy hardware detected value */
+- val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+- writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+- val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+- writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+-#endif
++ /*
++ * Update PIO power bias configuration by copying the hardware
++ * detected value.
++ */
++ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
++ IS_ENABLED(CONFIG_SUN50I_GEN_NCAT2)) {
++ val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
++ writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
++ }
++ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6)) {
++ val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
++ writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
++ }
+
+ return 0;
+ }
+@@ -481,7 +487,7 @@ void reset_cpu(void)
+ /* sun5i sometimes gets stuck without this */
+ writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
+ }
+-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
++#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
+ #if defined(CONFIG_MACH_SUN50I_H6)
+ /* WDOG is broken for some H6 rev. use the R_WDOG instead */
+ static const struct sunxi_wdog *wdog =
+diff --git a/common/spl/Kconfig b/common/spl/Kconfig
+index 3c2af453ab..06bcedca7d 100644
+--- a/common/spl/Kconfig
++++ b/common/spl/Kconfig
+@@ -265,7 +265,7 @@ config SPL_TEXT_BASE
+ default 0x402F0400 if AM33XX
+ default 0x40301350 if OMAP54XX
+ default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
+- default 0x20060 if SUN50I_GEN_H6
++ default 0x20060 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
+ default 0x00060 if ARCH_SUNXI
+ default 0xfffc0000 if ARCH_ZYNQMP
+ default 0x0
+diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
+index 93bbc6916e..5c9b92ccf9 100644
+--- a/drivers/i2c/mvtwsi.c
++++ b/drivers/i2c/mvtwsi.c
+@@ -124,7 +124,8 @@ enum mvtwsi_ctrl_register_fields {
+ * on other platforms, it is a normal r/w bit, which is cleared by writing 0.
+ */
+
+-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
++#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || \
++ defined(CONFIG_SUNXI_GEN_NCAT2)
+ #define MVTWSI_CONTROL_CLEAR_IFLG 0x00000008
+ #else
+ #define MVTWSI_CONTROL_CLEAR_IFLG 0x00000000
+diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
+index 03e33753fc..a8e590561c 100644
+--- a/drivers/mmc/sunxi_mmc.c
++++ b/drivers/mmc/sunxi_mmc.c
+@@ -57,6 +57,7 @@ static bool sunxi_mmc_can_calibrate(void)
+ return IS_ENABLED(CONFIG_MACH_SUN50I) ||
+ IS_ENABLED(CONFIG_MACH_SUN50I_H5) ||
+ IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
++ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
+ IS_ENABLED(CONFIG_MACH_SUN8I_R40);
+ }
+
+@@ -191,7 +192,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc)
+ rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
+ writel(rval, &priv->reg->clkcr);
+
+-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
++#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
+ /* A64 supports calibration of delays on MMC controller and we
+ * have to set delay of zero before starting calibration.
+ * Allwinner BSP driver sets a delay only in the case of
+@@ -530,7 +531,8 @@ struct mmc *sunxi_mmc_init(int sdc_no)
+ cfg->host_caps = MMC_MODE_4BIT;
+
+ if ((IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN8I) ||
+- IS_ENABLED(CONFIG_SUN50I_GEN_H6)) && (sdc_no == 2))
++ IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
++ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) && (sdc_no == 2))
+ cfg->host_caps = MMC_MODE_8BIT;
+
+ cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+@@ -544,7 +546,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
+
+ /* config ahb clock */
+ debug("init mmc %d clock and io\n", sdc_no);
+-#if !defined(CONFIG_SUN50I_GEN_H6)
++#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
+ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
+
+ #ifdef CONFIG_SUNXI_GEN_SUN6I
+@@ -619,7 +621,7 @@ static unsigned get_mclk_offset(void)
+ if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
+ return 0x410;
+
+- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
++ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+ return 0x830;
+
+ return 0x88;
+diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
+index 61978db6db..8cf9047ff9 100644
+--- a/include/sunxi_gpio.h
++++ b/include/sunxi_gpio.h
+@@ -16,6 +16,9 @@
+ #elif defined(CONFIG_SUN50I_GEN_H6)
+ #define SUNXI_PIO_BASE 0x0300b000
+ #define SUNXI_R_PIO_BASE 0x07022000
++#elif defined(CONFIG_SUNXI_GEN_NCAT2)
++#define SUNXI_PIO_BASE 0x02000000
++#define SUNXI_R_PIO_BASE 0
+ #else
+ #define SUNXI_PIO_BASE 0x01c20800
+ #define SUNXI_R_PIO_BASE 0x01f02c00
+--
+2.20.1
+
--- /dev/null
+From 8221f71488b4fb448af0c23d2c9c56bea230584d Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:55 +0100
+Subject: [PATCH 4015/4044] pinctrl: sunxi: add Allwinner D1 pinctrl
+ description
+
+Apart from using the new pinctrl MMIO register layout, the Allwinner D1
+and related SoCs still need to usual set of mux values hardcoded in
+U-Boot's pinctrl driver.
+Add the values we need so far to this list, so that DM based drivers
+will just work without further ado.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ drivers/pinctrl/sunxi/Kconfig | 4 ++++
+ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 28 +++++++++++++++++++++++++++
+ 2 files changed, 32 insertions(+)
+
+diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
+index 77da90836b..c8f937d91e 100644
+--- a/drivers/pinctrl/sunxi/Kconfig
++++ b/drivers/pinctrl/sunxi/Kconfig
+@@ -124,4 +124,8 @@ config PINCTRL_SUN50I_H616_R
+ default MACH_SUN50I_H616
+ select PINCTRL_SUNXI
+
++config PINCTRL_SUN20I_D1
++ bool "Support for the Allwinner D1/R528 PIO"
++ select PINCTRL_SUNXI
++
+ endif
+diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+index 4c52e3fa74..614cfe6b73 100644
+--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+@@ -735,6 +735,28 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc
+ .num_banks = 1,
+ };
+
++static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
++ { "emac", 8 }, /* PE0-PE15 */
++ { "gpio_in", 0 },
++ { "gpio_out", 1 },
++ { "mmc0", 2 }, /* PF0-PF5 */
++ { "mmc2", 3 }, /* PC1-PC7 */
++ { "spi0", 2 }, /* PC2-PC7 */
++#if IS_ENABLED(CONFIG_UART0_PORT_F)
++ { "uart0", 3 }, /* PF2-PF4 */
++#else
++ { "uart0", 6 }, /* PB2-PB3 */
++#endif
++ { "uart3", 7 }, /* PB6-PB9 */
++};
++
++static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
++ .functions = sun20i_d1_pinctrl_functions,
++ .num_functions = ARRAY_SIZE(sun20i_d1_pinctrl_functions),
++ .first_bank = SUNXI_GPIO_A,
++ .num_banks = 7,
++};
++
+ static const struct udevice_id sunxi_pinctrl_ids[] = {
+ #ifdef CONFIG_PINCTRL_SUNIV_F1C100S
+ {
+@@ -891,6 +913,12 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
+ .compatible = "allwinner,sun50i-h616-r-pinctrl",
+ .data = (ulong)&sun50i_h616_r_pinctrl_desc,
+ },
++#endif
++#ifdef CONFIG_PINCTRL_SUN20I_D1
++ {
++ .compatible = "allwinner,sun20i-d1-pinctrl",
++ .data = (ulong)&sun20i_d1_pinctrl_desc,
++ },
+ #endif
+ {}
+ };
+--
+2.20.1
+
+++ /dev/null
-From bc8f569427d231f9cd0f483474af870cafa857e4 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Tue, 6 Sep 2022 15:59:57 +0100
-Subject: [PATCH 4015/4031] sunxi: add early Allwinner R528/T113 SoC support
-
-This adds the remaining code bits to teach U-Boot about Allwinner's
-newest SoC generation. This was introduced with the RISC-V based
-Allwinner D1 SoC, which actually shares a die with the ARM cores versions
-called R528 (BGA, without DRAM) and T113s (QFP, with embedded DRAM).
-
-This adds the new Kconfig stanza, using the two newly introduced symbols
-for the new SoC generation and pincontroller. It also adds the new symbols
-to the relavent code places, to set all the hardcoded bits directly.
-
-We just chicken out the DRAM controller code for now with a stub to make
-it compile. There is GPLed code out there that can be used, although that
-still looks very much like the disassembly/decompile it came from.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h | 9 +++++++--
- arch/arm/mach-sunxi/Kconfig | 10 ++++++++++
- arch/arm/mach-sunxi/board.c | 8 ++++++++
- arch/arm/mach-sunxi/clock_sun50i_h6.c | 2 ++
- arch/arm/mach-sunxi/cpu_info.c | 2 ++
- common/spl/Kconfig | 1 +
- drivers/mmc/sunxi_mmc.c | 1 +
- drivers/pinctrl/sunxi/Kconfig | 1 +
- 8 files changed, 32 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-index 8471e11aa0..a84a57e5b4 100644
---- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
-@@ -266,7 +266,7 @@ struct sunxi_ccm_reg {
- #define CCM_CPU_AXI_AXI_MASK 0x3
- #define CCM_CPU_AXI_DEFAULT_FACTORS 0x301
-
--#ifdef CONFIG_MACH_SUN50I_H6
-+#ifdef CONFIG_MACH_SUN50I_H6 /* H6 */
- #define CCM_PLL6_DEFAULT 0xa0006300
-
- /* psi_ahb1_ahb2 bit field */
-@@ -277,7 +277,7 @@ struct sunxi_ccm_reg {
-
- /* apb1 bit field */
- #define CCM_APB1_DEFAULT 0x03000102
--#elif CONFIG_MACH_SUN50I_H616
-+#elif CONFIG_MACH_SUN50I_H616 /* H616 */
- #define CCM_PLL6_DEFAULT 0xa8003100
-
- /* psi_ahb1_ahb2 bit field */
-@@ -288,6 +288,11 @@ struct sunxi_ccm_reg {
-
- /* apb1 bit field */
- #define CCM_APB1_DEFAULT 0x03000102
-+#elif CONFIG_MACH_SUN8I_R528 /* R528 */
-+#define CCM_PLL6_DEFAULT 0xe8216300
-+#define CCM_PSI_AHB1_AHB2_DEFAULT 0x03000002
-+//#define CCM_AHB3_DEFAULT 0x03000002
-+#define CCM_APB1_DEFAULT 0x03000102
- #endif
-
- /* apb2 bit field */
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index 057b0ccd33..142d86afc6 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -318,6 +318,15 @@ config MACH_SUN8I_R40
- select PHY_SUN4I_USB
- imply SPL_SYS_I2C_LEGACY
-
-+config MACH_SUN8I_R528
-+ bool "sun8i (Allwinner R528)"
-+ select CPU_V7A
-+ select SUNXI_GEN_NCAT2
-+ select SUNXI_NEW_PINCTRL
-+ select MMC_SUNXI_HAS_NEW_MODE
-+ select SUPPORT_SPL
-+ select DRAM_SUN8I_R528
-+
- config MACH_SUN8I_V3S
- bool "sun8i (Allwinner V3/V3s/S3/S3L)"
- select CPU_V7A
-@@ -622,6 +631,7 @@ config SYS_CONFIG_NAME
- default "sun6i" if MACH_SUN6I
- default "sun7i" if MACH_SUN7I
- default "sun8i" if MACH_SUN8I
-+ default "sun8i" if MACH_SUN8I_R528
- default "sun9i" if MACH_SUN9I
- default "sun50i" if MACH_SUN50I
- default "sun50i" if MACH_SUN50I_H6
-diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
-index 6d96182226..df4f32d10c 100644
---- a/arch/arm/mach-sunxi/board.c
-+++ b/arch/arm/mach-sunxi/board.c
-@@ -147,6 +147,10 @@ static int gpio_init(void)
- sunxi_gpio_set_cfgpin(SUNXI_GPH(12), SUN9I_GPH_UART0);
- sunxi_gpio_set_cfgpin(SUNXI_GPH(13), SUN9I_GPH_UART0);
- sunxi_gpio_set_pull(SUNXI_GPH(13), SUNXI_GPIO_PULL_UP);
-+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_R528)
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(2), 6);
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(3), 6);
-+ sunxi_gpio_set_pull(SUNXI_GPE(3), SUNXI_GPIO_PULL_UP);
- #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUNIV)
- sunxi_gpio_set_cfgpin(SUNXI_GPA(2), SUNIV_GPE_UART0);
- sunxi_gpio_set_cfgpin(SUNXI_GPA(3), SUNIV_GPE_UART0);
-@@ -163,6 +167,10 @@ static int gpio_init(void)
- sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_GPB_UART2);
- sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
- sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP);
-+#elif CONFIG_CONS_INDEX == 4 && defined(CONFIG_MACH_SUN8I_R528)
-+ sunxi_gpio_set_cfgpin(SUNXI_GPB(6), 7);
-+ sunxi_gpio_set_cfgpin(SUNXI_GPB(7), 7);
-+ sunxi_gpio_set_pull(SUNXI_GPB(7), SUNXI_GPIO_PULL_UP);
- #elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
- sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
- sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
-diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
-index 607efe6a9c..4d5e23a9af 100644
---- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
-+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
-@@ -38,7 +38,9 @@ void clock_init_safe(void)
- CCM_CPU_AXI_DEFAULT_FACTORS);
-
- writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
-+#ifdef CCM_AHB3_DEFAULT
- writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
-+#endif
- writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
-
- /*
-diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
-index 7eef178859..7fecc3b88d 100644
---- a/arch/arm/mach-sunxi/cpu_info.c
-+++ b/arch/arm/mach-sunxi/cpu_info.c
-@@ -93,6 +93,8 @@ int print_cpuinfo(void)
- printf("CPU: Allwinner R40 (SUN8I %04x)\n", sunxi_get_sram_id());
- #elif defined CONFIG_MACH_SUN8I_V3S
- printf("CPU: Allwinner V3s (SUN8I %04x)\n", sunxi_get_sram_id());
-+#elif defined CONFIG_MACH_SUN8I_R528
-+ puts("CPU: Allwinner R528 (SUN8I)\n");
- #elif defined CONFIG_MACH_SUN9I
- puts("CPU: Allwinner A80 (SUN9I)\n");
- #elif defined CONFIG_MACH_SUN50I
-diff --git a/common/spl/Kconfig b/common/spl/Kconfig
-index 06bcedca7d..196a250ef9 100644
---- a/common/spl/Kconfig
-+++ b/common/spl/Kconfig
-@@ -357,6 +357,7 @@ config SPL_STACK
- default 0x91ffb8 if ARCH_MX6 && !MX6_OCRAM_256KB
- default 0x118000 if MACH_SUN50I_H6
- default 0x58000 if MACH_SUN50I_H616
-+ default 0x40000 if MACH_SUN8I_R528
- default 0x54000 if MACH_SUN50I || MACH_SUN50I_H5
- default 0x18000 if MACH_SUN9I
- default 0x8000 if ARCH_SUNXI
-diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
-index a8e590561c..0837e8bb30 100644
---- a/drivers/mmc/sunxi_mmc.c
-+++ b/drivers/mmc/sunxi_mmc.c
-@@ -708,6 +708,7 @@ static const struct udevice_id sunxi_mmc_ids[] = {
- { .compatible = "allwinner,sun50i-h6-emmc" },
- { .compatible = "allwinner,sun50i-a100-mmc" },
- { .compatible = "allwinner,sun50i-a100-emmc" },
-+ { .compatible = "allwinner,sun20i-d1-mmc" },
- { /* sentinel */ }
- };
-
-diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
-index c8f937d91e..cbd6179598 100644
---- a/drivers/pinctrl/sunxi/Kconfig
-+++ b/drivers/pinctrl/sunxi/Kconfig
-@@ -126,6 +126,7 @@ config PINCTRL_SUN50I_H616_R
-
- config PINCTRL_SUN20I_D1
- bool "Support for the Allwinner D1/R528 PIO"
-+ default MACH_SUN8I_R528
- select PINCTRL_SUNXI
-
- endif
---
-2.20.1
-
--- /dev/null
+From 716a59d3d21ebb997f345b28b972d8f6e627fe34 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Fri, 21 Jul 2023 14:45:56 +0100
+Subject: [PATCH 4016/4044] clk: sunxi: Add support for the D1 CCU
+
+Since the D1 CCU binding is defined, we can add support for its
+gates/resets, following the pattern of the existing drivers.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Andre Przywara <andre.przywara@arm.com>
+Acked-by: Sean Anderson <seanga2@gmail.com>
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ drivers/clk/sunxi/Kconfig | 6 +
+ drivers/clk/sunxi/Makefile | 1 +
+ drivers/clk/sunxi/clk_d1.c | 84 ++++++++++++
+ drivers/clk/sunxi/clk_sunxi.c | 5 +
+ include/dt-bindings/clock/sun20i-d1-ccu.h | 158 ++++++++++++++++++++++
+ include/dt-bindings/reset/sun20i-d1-ccu.h | 79 +++++++++++
+ 6 files changed, 333 insertions(+)
+ create mode 100644 drivers/clk/sunxi/clk_d1.c
+ create mode 100644 include/dt-bindings/clock/sun20i-d1-ccu.h
+ create mode 100644 include/dt-bindings/reset/sun20i-d1-ccu.h
+
+diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
+index bf11fad6ee..f65e482ba4 100644
+--- a/drivers/clk/sunxi/Kconfig
++++ b/drivers/clk/sunxi/Kconfig
+@@ -87,6 +87,12 @@ config CLK_SUN8I_H3
+ This enables common clock driver support for platforms based
+ on Allwinner H3/H5 SoC.
+
++config CLK_SUN20I_D1
++ bool "Clock driver for Allwinner D1"
++ help
++ This enables common clock driver support for platforms based
++ on Allwinner D1 SoC.
++
+ config CLK_SUN50I_H6
+ bool "Clock driver for Allwinner H6"
+ default MACH_SUN50I_H6
+diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
+index 895da02ebe..90a277489d 100644
+--- a/drivers/clk/sunxi/Makefile
++++ b/drivers/clk/sunxi/Makefile
+@@ -19,6 +19,7 @@ obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
+ obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
+ obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
+ obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
++obj-$(CONFIG_CLK_SUN20I_D1) += clk_d1.o
+ obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
+ obj-$(CONFIG_CLK_SUN50I_H6_R) += clk_h6_r.o
+ obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
+diff --git a/drivers/clk/sunxi/clk_d1.c b/drivers/clk/sunxi/clk_d1.c
+new file mode 100644
+index 0000000000..9dae761de8
+--- /dev/null
++++ b/drivers/clk/sunxi/clk_d1.c
+@@ -0,0 +1,84 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
++ */
++
++#include <common.h>
++#include <clk-uclass.h>
++#include <dm.h>
++#include <errno.h>
++#include <clk/sunxi.h>
++#include <dt-bindings/clock/sun20i-d1-ccu.h>
++#include <dt-bindings/reset/sun20i-d1-ccu.h>
++#include <linux/bitops.h>
++
++static struct ccu_clk_gate d1_gates[] = {
++ [CLK_APB0] = GATE_DUMMY,
++
++ [CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
++ [CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
++ [CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
++ [CLK_BUS_UART0] = GATE(0x90c, BIT(0)),
++ [CLK_BUS_UART1] = GATE(0x90c, BIT(1)),
++ [CLK_BUS_UART2] = GATE(0x90c, BIT(2)),
++ [CLK_BUS_UART3] = GATE(0x90c, BIT(3)),
++ [CLK_BUS_UART4] = GATE(0x90c, BIT(4)),
++ [CLK_BUS_UART5] = GATE(0x90c, BIT(5)),
++ [CLK_BUS_I2C0] = GATE(0x91c, BIT(0)),
++ [CLK_BUS_I2C1] = GATE(0x91c, BIT(1)),
++ [CLK_BUS_I2C2] = GATE(0x91c, BIT(2)),
++ [CLK_BUS_I2C3] = GATE(0x91c, BIT(3)),
++ [CLK_SPI0] = GATE(0x940, BIT(31)),
++ [CLK_SPI1] = GATE(0x944, BIT(31)),
++ [CLK_BUS_SPI0] = GATE(0x96c, BIT(0)),
++ [CLK_BUS_SPI1] = GATE(0x96c, BIT(1)),
++
++ [CLK_BUS_EMAC] = GATE(0x97c, BIT(0)),
++
++ [CLK_USB_OHCI0] = GATE(0xa70, BIT(31)),
++ [CLK_USB_OHCI1] = GATE(0xa74, BIT(31)),
++ [CLK_BUS_OHCI0] = GATE(0xa8c, BIT(0)),
++ [CLK_BUS_OHCI1] = GATE(0xa8c, BIT(1)),
++ [CLK_BUS_EHCI0] = GATE(0xa8c, BIT(4)),
++ [CLK_BUS_EHCI1] = GATE(0xa8c, BIT(5)),
++ [CLK_BUS_OTG] = GATE(0xa8c, BIT(8)),
++ [CLK_BUS_LRADC] = GATE(0xa9c, BIT(0)),
++
++ [CLK_RISCV] = GATE(0xd04, BIT(31)),
++};
++
++static struct ccu_reset d1_resets[] = {
++ [RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
++ [RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
++ [RST_BUS_MMC2] = RESET(0x84c, BIT(18)),
++ [RST_BUS_UART0] = RESET(0x90c, BIT(16)),
++ [RST_BUS_UART1] = RESET(0x90c, BIT(17)),
++ [RST_BUS_UART2] = RESET(0x90c, BIT(18)),
++ [RST_BUS_UART3] = RESET(0x90c, BIT(19)),
++ [RST_BUS_UART4] = RESET(0x90c, BIT(20)),
++ [RST_BUS_UART5] = RESET(0x90c, BIT(21)),
++ [RST_BUS_I2C0] = RESET(0x91c, BIT(16)),
++ [RST_BUS_I2C1] = RESET(0x91c, BIT(17)),
++ [RST_BUS_I2C2] = RESET(0x91c, BIT(18)),
++ [RST_BUS_I2C3] = RESET(0x91c, BIT(19)),
++ [RST_BUS_SPI0] = RESET(0x96c, BIT(16)),
++ [RST_BUS_SPI1] = RESET(0x96c, BIT(17)),
++
++ [RST_BUS_EMAC] = RESET(0x97c, BIT(16)),
++
++ [RST_USB_PHY0] = RESET(0xa70, BIT(30)),
++ [RST_USB_PHY1] = RESET(0xa74, BIT(30)),
++ [RST_BUS_OHCI0] = RESET(0xa8c, BIT(16)),
++ [RST_BUS_OHCI1] = RESET(0xa8c, BIT(17)),
++ [RST_BUS_EHCI0] = RESET(0xa8c, BIT(20)),
++ [RST_BUS_EHCI1] = RESET(0xa8c, BIT(21)),
++ [RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
++ [RST_BUS_LRADC] = RESET(0xa9c, BIT(16)),
++};
++
++const struct ccu_desc d1_ccu_desc = {
++ .gates = d1_gates,
++ .resets = d1_resets,
++ .num_gates = ARRAY_SIZE(d1_gates),
++ .num_resets = ARRAY_SIZE(d1_resets),
++};
+diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
+index ec02a2d037..a0011a35d9 100644
+--- a/drivers/clk/sunxi/clk_sunxi.c
++++ b/drivers/clk/sunxi/clk_sunxi.c
+@@ -118,6 +118,7 @@ extern const struct ccu_desc a64_ccu_desc;
+ extern const struct ccu_desc a80_ccu_desc;
+ extern const struct ccu_desc a80_mmc_clk_desc;
+ extern const struct ccu_desc a83t_ccu_desc;
++extern const struct ccu_desc d1_ccu_desc;
+ extern const struct ccu_desc f1c100s_ccu_desc;
+ extern const struct ccu_desc h3_ccu_desc;
+ extern const struct ccu_desc h6_ccu_desc;
+@@ -214,6 +215,10 @@ static const struct udevice_id sunxi_clk_ids[] = {
+ #ifdef CONFIG_CLK_SUNIV_F1C100S
+ { .compatible = "allwinner,suniv-f1c100s-ccu",
+ .data = (ulong)&f1c100s_ccu_desc },
++#endif
++#ifdef CONFIG_CLK_SUN20I_D1
++ { .compatible = "allwinner,sun20i-d1-ccu",
++ .data = (ulong)&d1_ccu_desc },
+ #endif
+ { }
+ };
+diff --git a/include/dt-bindings/clock/sun20i-d1-ccu.h b/include/dt-bindings/clock/sun20i-d1-ccu.h
+new file mode 100644
+index 0000000000..e143b99297
+--- /dev/null
++++ b/include/dt-bindings/clock/sun20i-d1-ccu.h
+@@ -0,0 +1,158 @@
++/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
++/*
++ * Copyright (C) 2020 huangzhenwei@allwinnertech.com
++ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
++ */
++
++#ifndef _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
++#define _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
++
++#define CLK_PLL_CPUX 0
++#define CLK_PLL_DDR0 1
++#define CLK_PLL_PERIPH0_4X 2
++#define CLK_PLL_PERIPH0_2X 3
++#define CLK_PLL_PERIPH0_800M 4
++#define CLK_PLL_PERIPH0 5
++#define CLK_PLL_PERIPH0_DIV3 6
++#define CLK_PLL_VIDEO0_4X 7
++#define CLK_PLL_VIDEO0_2X 8
++#define CLK_PLL_VIDEO0 9
++#define CLK_PLL_VIDEO1_4X 10
++#define CLK_PLL_VIDEO1_2X 11
++#define CLK_PLL_VIDEO1 12
++#define CLK_PLL_VE 13
++#define CLK_PLL_AUDIO0_4X 14
++#define CLK_PLL_AUDIO0_2X 15
++#define CLK_PLL_AUDIO0 16
++#define CLK_PLL_AUDIO1 17
++#define CLK_PLL_AUDIO1_DIV2 18
++#define CLK_PLL_AUDIO1_DIV5 19
++#define CLK_CPUX 20
++#define CLK_CPUX_AXI 21
++#define CLK_CPUX_APB 22
++#define CLK_PSI_AHB 23
++#define CLK_APB0 24
++#define CLK_APB1 25
++#define CLK_MBUS 26
++#define CLK_DE 27
++#define CLK_BUS_DE 28
++#define CLK_DI 29
++#define CLK_BUS_DI 30
++#define CLK_G2D 31
++#define CLK_BUS_G2D 32
++#define CLK_CE 33
++#define CLK_BUS_CE 34
++#define CLK_VE 35
++#define CLK_BUS_VE 36
++#define CLK_BUS_DMA 37
++#define CLK_BUS_MSGBOX0 38
++#define CLK_BUS_MSGBOX1 39
++#define CLK_BUS_MSGBOX2 40
++#define CLK_BUS_SPINLOCK 41
++#define CLK_BUS_HSTIMER 42
++#define CLK_AVS 43
++#define CLK_BUS_DBG 44
++#define CLK_BUS_PWM 45
++#define CLK_BUS_IOMMU 46
++#define CLK_DRAM 47
++#define CLK_MBUS_DMA 48
++#define CLK_MBUS_VE 49
++#define CLK_MBUS_CE 50
++#define CLK_MBUS_TVIN 51
++#define CLK_MBUS_CSI 52
++#define CLK_MBUS_G2D 53
++#define CLK_MBUS_RISCV 54
++#define CLK_BUS_DRAM 55
++#define CLK_MMC0 56
++#define CLK_MMC1 57
++#define CLK_MMC2 58
++#define CLK_BUS_MMC0 59
++#define CLK_BUS_MMC1 60
++#define CLK_BUS_MMC2 61
++#define CLK_BUS_UART0 62
++#define CLK_BUS_UART1 63
++#define CLK_BUS_UART2 64
++#define CLK_BUS_UART3 65
++#define CLK_BUS_UART4 66
++#define CLK_BUS_UART5 67
++#define CLK_BUS_I2C0 68
++#define CLK_BUS_I2C1 69
++#define CLK_BUS_I2C2 70
++#define CLK_BUS_I2C3 71
++#define CLK_SPI0 72
++#define CLK_SPI1 73
++#define CLK_BUS_SPI0 74
++#define CLK_BUS_SPI1 75
++#define CLK_EMAC_25M 76
++#define CLK_BUS_EMAC 77
++#define CLK_IR_TX 78
++#define CLK_BUS_IR_TX 79
++#define CLK_BUS_GPADC 80
++#define CLK_BUS_THS 81
++#define CLK_I2S0 82
++#define CLK_I2S1 83
++#define CLK_I2S2 84
++#define CLK_I2S2_ASRC 85
++#define CLK_BUS_I2S0 86
++#define CLK_BUS_I2S1 87
++#define CLK_BUS_I2S2 88
++#define CLK_SPDIF_TX 89
++#define CLK_SPDIF_RX 90
++#define CLK_BUS_SPDIF 91
++#define CLK_DMIC 92
++#define CLK_BUS_DMIC 93
++#define CLK_AUDIO_DAC 94
++#define CLK_AUDIO_ADC 95
++#define CLK_BUS_AUDIO 96
++#define CLK_USB_OHCI0 97
++#define CLK_USB_OHCI1 98
++#define CLK_BUS_OHCI0 99
++#define CLK_BUS_OHCI1 100
++#define CLK_BUS_EHCI0 101
++#define CLK_BUS_EHCI1 102
++#define CLK_BUS_OTG 103
++#define CLK_BUS_LRADC 104
++#define CLK_BUS_DPSS_TOP 105
++#define CLK_HDMI_24M 106
++#define CLK_HDMI_CEC_32K 107
++#define CLK_HDMI_CEC 108
++#define CLK_BUS_HDMI 109
++#define CLK_MIPI_DSI 110
++#define CLK_BUS_MIPI_DSI 111
++#define CLK_TCON_LCD0 112
++#define CLK_BUS_TCON_LCD0 113
++#define CLK_TCON_TV 114
++#define CLK_BUS_TCON_TV 115
++#define CLK_TVE 116
++#define CLK_BUS_TVE_TOP 117
++#define CLK_BUS_TVE 118
++#define CLK_TVD 119
++#define CLK_BUS_TVD_TOP 120
++#define CLK_BUS_TVD 121
++#define CLK_LEDC 122
++#define CLK_BUS_LEDC 123
++#define CLK_CSI_TOP 124
++#define CLK_CSI_MCLK 125
++#define CLK_BUS_CSI 126
++#define CLK_TPADC 127
++#define CLK_BUS_TPADC 128
++#define CLK_BUS_TZMA 129
++#define CLK_DSP 130
++#define CLK_BUS_DSP_CFG 131
++#define CLK_RISCV 132
++#define CLK_RISCV_AXI 133
++#define CLK_BUS_RISCV_CFG 134
++#define CLK_FANOUT_24M 135
++#define CLK_FANOUT_12M 136
++#define CLK_FANOUT_16M 137
++#define CLK_FANOUT_25M 138
++#define CLK_FANOUT_32K 139
++#define CLK_FANOUT_27M 140
++#define CLK_FANOUT_PCLK 141
++#define CLK_FANOUT0 142
++#define CLK_FANOUT1 143
++#define CLK_FANOUT2 144
++#define CLK_BUS_CAN0 145
++#define CLK_BUS_CAN1 146
++
++#endif /* _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ */
+diff --git a/include/dt-bindings/reset/sun20i-d1-ccu.h b/include/dt-bindings/reset/sun20i-d1-ccu.h
+new file mode 100644
+index 0000000000..f8001cf50b
+--- /dev/null
++++ b/include/dt-bindings/reset/sun20i-d1-ccu.h
+@@ -0,0 +1,79 @@
++/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
++/*
++ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
++ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
++ */
++
++#ifndef _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
++#define _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
++
++#define RST_MBUS 0
++#define RST_BUS_DE 1
++#define RST_BUS_DI 2
++#define RST_BUS_G2D 3
++#define RST_BUS_CE 4
++#define RST_BUS_VE 5
++#define RST_BUS_DMA 6
++#define RST_BUS_MSGBOX0 7
++#define RST_BUS_MSGBOX1 8
++#define RST_BUS_MSGBOX2 9
++#define RST_BUS_SPINLOCK 10
++#define RST_BUS_HSTIMER 11
++#define RST_BUS_DBG 12
++#define RST_BUS_PWM 13
++#define RST_BUS_DRAM 14
++#define RST_BUS_MMC0 15
++#define RST_BUS_MMC1 16
++#define RST_BUS_MMC2 17
++#define RST_BUS_UART0 18
++#define RST_BUS_UART1 19
++#define RST_BUS_UART2 20
++#define RST_BUS_UART3 21
++#define RST_BUS_UART4 22
++#define RST_BUS_UART5 23
++#define RST_BUS_I2C0 24
++#define RST_BUS_I2C1 25
++#define RST_BUS_I2C2 26
++#define RST_BUS_I2C3 27
++#define RST_BUS_SPI0 28
++#define RST_BUS_SPI1 29
++#define RST_BUS_EMAC 30
++#define RST_BUS_IR_TX 31
++#define RST_BUS_GPADC 32
++#define RST_BUS_THS 33
++#define RST_BUS_I2S0 34
++#define RST_BUS_I2S1 35
++#define RST_BUS_I2S2 36
++#define RST_BUS_SPDIF 37
++#define RST_BUS_DMIC 38
++#define RST_BUS_AUDIO 39
++#define RST_USB_PHY0 40
++#define RST_USB_PHY1 41
++#define RST_BUS_OHCI0 42
++#define RST_BUS_OHCI1 43
++#define RST_BUS_EHCI0 44
++#define RST_BUS_EHCI1 45
++#define RST_BUS_OTG 46
++#define RST_BUS_LRADC 47
++#define RST_BUS_DPSS_TOP 48
++#define RST_BUS_HDMI_SUB 49
++#define RST_BUS_HDMI_MAIN 50
++#define RST_BUS_MIPI_DSI 51
++#define RST_BUS_TCON_LCD0 52
++#define RST_BUS_TCON_TV 53
++#define RST_BUS_LVDS0 54
++#define RST_BUS_TVE 55
++#define RST_BUS_TVE_TOP 56
++#define RST_BUS_TVD 57
++#define RST_BUS_TVD_TOP 58
++#define RST_BUS_LEDC 59
++#define RST_BUS_CSI 60
++#define RST_BUS_TPADC 61
++#define RST_DSP 62
++#define RST_BUS_DSP_CFG 63
++#define RST_BUS_DSP_DBG 64
++#define RST_BUS_RISCV_CFG 65
++#define RST_BUS_CAN0 66
++#define RST_BUS_CAN1 67
++
++#endif /* _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ */
+--
+2.20.1
+
+++ /dev/null
-From 733d8e8ac84a4936cdd55a688f41dd8de10d870c Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Sun, 3 Jul 2022 00:14:24 +0100
-Subject: [PATCH 4016/4031] sunxi: refactor serial base addresses to avoid
- asm/arch/cpu.h
-
-At the moment we have each SoC's memory map defined in its own cpu.h,
-which is included in include/configs/sunxi_common.h. This will be a
-problem with the introduction of Allwinner RISC-V support.
-
-Remove the inclusion of that header file from the common config header,
-instead move the required serial base addresses (for the SPL) into a
-separate header file. Then include the original cpu.h file only where
-we really need it, which is only under arch/arm now.
-
-This disentangles the architecture specific header files from the
-generic code.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/cpu/armv7/sunxi/sram.c | 1 +
- arch/arm/cpu/armv8/fel_utils.S | 1 +
- arch/arm/include/asm/arch-sunxi/clock.h | 1 +
- arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 15 ---------
- .../include/asm/arch-sunxi/cpu_sun50i_h6.h | 5 ---
- arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 7 ----
- .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h | 5 ---
- arch/arm/include/asm/arch-sunxi/serial.h | 32 +++++++++++++++++++
- arch/arm/mach-sunxi/gtbus_sun9i.c | 1 +
- arch/arm/mach-sunxi/timer.c | 1 +
- include/configs/sunxi-common.h | 2 +-
- 11 files changed, 38 insertions(+), 33 deletions(-)
- create mode 100644 arch/arm/include/asm/arch-sunxi/serial.h
-
-diff --git a/arch/arm/cpu/armv7/sunxi/sram.c b/arch/arm/cpu/armv7/sunxi/sram.c
-index 28564c2846..28ff6a1b7c 100644
---- a/arch/arm/cpu/armv7/sunxi/sram.c
-+++ b/arch/arm/cpu/armv7/sunxi/sram.c
-@@ -12,6 +12,7 @@
- #include <common.h>
- #include <init.h>
- #include <asm/io.h>
-+#include <asm/arch/cpu.h>
-
- void sunxi_sram_init(void)
- {
-diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
-index 2fe38a1a04..939869b9ff 100644
---- a/arch/arm/cpu/armv8/fel_utils.S
-+++ b/arch/arm/cpu/armv8/fel_utils.S
-@@ -10,6 +10,7 @@
- #include <config.h>
- #include <asm/system.h>
- #include <linux/linkage.h>
-+#include <asm/arch/cpu.h>
-
- /*
- * We don't overwrite save_boot_params() here, to save the FEL state upon
-diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
-index 3d34261b0e..fcc8966cb0 100644
---- a/arch/arm/include/asm/arch-sunxi/clock.h
-+++ b/arch/arm/include/asm/arch-sunxi/clock.h
-@@ -9,6 +9,7 @@
- #define _SUNXI_CLOCK_H
-
- #include <linux/types.h>
-+#include <asm/arch/cpu.h>
-
- #define CLK_GATE_OPEN 0x1
- #define CLK_GATE_CLOSE 0x0
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
-index d6fe51f24b..3daee2f574 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
-@@ -128,20 +128,6 @@ defined(CONFIG_MACH_SUN50I)
- #define SUNXI_CPUCFG_BASE 0x01c25c00
- #endif
-
--#ifdef CONFIG_MACH_SUNIV
--#define SUNXI_UART0_BASE 0x01c25000
--#define SUNXI_UART1_BASE 0x01c25400
--#define SUNXI_UART2_BASE 0x01c25800
--#else
--#define SUNXI_UART0_BASE 0x01c28000
--#define SUNXI_UART1_BASE 0x01c28400
--#define SUNXI_UART2_BASE 0x01c28800
--#endif
--#define SUNXI_UART3_BASE 0x01c28c00
--#define SUNXI_UART4_BASE 0x01c29000
--#define SUNXI_UART5_BASE 0x01c29400
--#define SUNXI_UART6_BASE 0x01c29800
--#define SUNXI_UART7_BASE 0x01c29c00
- #define SUNXI_PS2_0_BASE 0x01c2a000
- #define SUNXI_PS2_1_BASE 0x01c2a400
-
-@@ -208,7 +194,6 @@ defined(CONFIG_MACH_SUN50I)
- #endif
-
- #define SUNXI_R_TWI_BASE 0x01f02400
--#define SUNXI_R_UART_BASE 0x01f02800
- #define SUN6I_P2WI_BASE 0x01f03400
- #define SUNXI_RSB_BASE 0x01f03400
-
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
-index 9b6bf84360..15ee092d35 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
-@@ -42,10 +42,6 @@
- #define SUNXI_DRAM_PHY0_BASE 0x04800000
- #endif
-
--#define SUNXI_UART0_BASE 0x05000000
--#define SUNXI_UART1_BASE 0x05000400
--#define SUNXI_UART2_BASE 0x05000800
--#define SUNXI_UART3_BASE 0x05000C00
- #define SUNXI_TWI0_BASE 0x05002000
- #define SUNXI_TWI1_BASE 0x05002400
- #define SUNXI_TWI2_BASE 0x05002800
-@@ -67,7 +63,6 @@
- #define SUNXI_R_CPUCFG_BASE 0x07000400
- #define SUNXI_PRCM_BASE 0x07010000
- #define SUNXI_R_WDOG_BASE 0x07020400
--#define SUNXI_R_UART_BASE 0x07080000
- #define SUNXI_R_TWI_BASE 0x07081400
-
- #ifndef __ASSEMBLY__
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
-index 20025be231..2bf2675d5c 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
-@@ -86,12 +86,6 @@
- #define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800)
-
- /* APB1 Module */
--#define SUNXI_UART0_BASE (REGS_APB1_BASE + 0x0000)
--#define SUNXI_UART1_BASE (REGS_APB1_BASE + 0x0400)
--#define SUNXI_UART2_BASE (REGS_APB1_BASE + 0x0800)
--#define SUNXI_UART3_BASE (REGS_APB1_BASE + 0x0C00)
--#define SUNXI_UART4_BASE (REGS_APB1_BASE + 0x1000)
--#define SUNXI_UART5_BASE (REGS_APB1_BASE + 0x1400)
- #define SUNXI_TWI0_BASE (REGS_APB1_BASE + 0x2800)
- #define SUNXI_TWI1_BASE (REGS_APB1_BASE + 0x2C00)
- #define SUNXI_TWI2_BASE (REGS_APB1_BASE + 0x3000)
-@@ -100,7 +94,6 @@
-
- /* RCPUS Module */
- #define SUNXI_PRCM_BASE (REGS_RCPUS_BASE + 0x1400)
--#define SUNXI_R_UART_BASE (REGS_RCPUS_BASE + 0x2800)
- #define SUNXI_RSB_BASE (REGS_RCPUS_BASE + 0x3400)
-
- /* Misc. */
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-index 13093085a5..d01508517c 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-@@ -27,10 +27,6 @@
- #define SUNXI_MMC1_BASE 0x04021000
- #define SUNXI_MMC2_BASE 0x04022000
-
--#define SUNXI_UART0_BASE 0x02500000
--#define SUNXI_UART1_BASE 0x02500400
--#define SUNXI_UART2_BASE 0x02500800
--#define SUNXI_UART3_BASE 0x02500C00
- #define SUNXI_TWI0_BASE 0x02502000
- #define SUNXI_TWI1_BASE 0x02502400
- #define SUNXI_TWI2_BASE 0x02502800
-@@ -42,7 +38,6 @@
- #define SUNXI_R_CPUCFG_BASE 0x07000400
- #define SUNXI_PRCM_BASE 0x07010000
- #define SUNXI_R_WDOG_BASE 0x07020400
--#define SUNXI_R_UART_BASE 0x07080000
- #define SUNXI_R_TWI_BASE 0x07081400
-
- #ifndef __ASSEMBLY__
-diff --git a/arch/arm/include/asm/arch-sunxi/serial.h b/arch/arm/include/asm/arch-sunxi/serial.h
-new file mode 100644
-index 0000000000..9386287b65
---- /dev/null
-+++ b/arch/arm/include/asm/arch-sunxi/serial.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0+ */
-+/*
-+ * hardcoded UART base addresses for early SPL use
-+ *
-+ * Copyright (c) 2022 Arm Ltd.
-+ */
-+
-+#ifndef SUNXI_SERIAL_MEMMAP_H
-+#define SUNXI_SERIAL_MEMMAP_H
-+
-+#if defined(CONFIG_MACH_SUN9I)
-+#define SUNXI_UART0_BASE 0x07000000
-+#define SUNXI_R_UART_BASE 0x08002800
-+#elif defined(CONFIG_SUN50I_GEN_H6)
-+#define SUNXI_UART0_BASE 0x05000000
-+#define SUNXI_R_UART_BASE 0x07080000
-+#elif defined(CONFIG_MACH_SUNIV)
-+#define SUNXI_UART0_BASE 0x01c25000
-+#define SUNXI_R_UART_BASE 0
-+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
-+#define SUNXI_UART0_BASE 0x02500000
-+#define SUNXI_R_UART_BASE 0 // 0x07080000 (?>
-+#else
-+#define SUNXI_UART0_BASE 0x01c28000
-+#define SUNXI_R_UART_BASE 0x01f02800
-+#endif
-+
-+#define SUNXI_UART1_BASE (SUNXI_UART0_BASE + 0x400)
-+#define SUNXI_UART2_BASE (SUNXI_UART0_BASE + 0x800)
-+#define SUNXI_UART3_BASE (SUNXI_UART0_BASE + 0xc00)
-+
-+#endif /* SUNXI_SERIAL_MEMMAP_H */
-diff --git a/arch/arm/mach-sunxi/gtbus_sun9i.c b/arch/arm/mach-sunxi/gtbus_sun9i.c
-index cf011c4cfa..5624621b50 100644
---- a/arch/arm/mach-sunxi/gtbus_sun9i.c
-+++ b/arch/arm/mach-sunxi/gtbus_sun9i.c
-@@ -8,6 +8,7 @@
-
- #include <common.h>
- #include <asm/io.h>
-+#include <asm/arch/cpu.h>
- #include <asm/arch/gtbus_sun9i.h>
- #include <asm/arch/sys_proto.h>
-
-diff --git a/arch/arm/mach-sunxi/timer.c b/arch/arm/mach-sunxi/timer.c
-index fc9d419a25..9a6f6c06d8 100644
---- a/arch/arm/mach-sunxi/timer.c
-+++ b/arch/arm/mach-sunxi/timer.c
-@@ -10,6 +10,7 @@
- #include <time.h>
- #include <asm/global_data.h>
- #include <asm/io.h>
-+#include <asm/arch/cpu.h>
- #include <asm/arch/timer.h>
- #include <linux/delay.h>
-
-diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
-index d2d70f0fc2..b8ca77d031 100644
---- a/include/configs/sunxi-common.h
-+++ b/include/configs/sunxi-common.h
-@@ -12,7 +12,6 @@
- #ifndef _SUNXI_COMMON_CONFIG_H
- #define _SUNXI_COMMON_CONFIG_H
-
--#include <asm/arch/cpu.h>
- #include <linux/stringify.h>
-
- /* Serial & console */
-@@ -24,6 +23,7 @@
- #define CFG_SYS_NS16550_CLK 24000000
- #endif
- #if !CONFIG_IS_ENABLED(DM_SERIAL)
-+#include <asm/arch/serial.h>
- # define CFG_SYS_NS16550_COM1 SUNXI_UART0_BASE
- # define CFG_SYS_NS16550_COM2 SUNXI_UART1_BASE
- # define CFG_SYS_NS16550_COM3 SUNXI_UART2_BASE
---
-2.20.1
-
+++ /dev/null
-From d25ac8934d210132b1df15bd63301646eb43d57e Mon Sep 17 00:00:00 2001
-From: Samuel Holland <samuel@sholland.org>
-Date: Wed, 25 Jan 2023 22:57:31 -0600
-Subject: [PATCH 4017/4031] riscv: dts: allwinner: Add the D1/D1s SoC
- devicetree
-
-D1 (aka D1-H), D1s (aka F133), R528, and T113 are a family of SoCs based
-on a single die, or at a pair of dies derived from the same design.
-
-D1 and D1s contain a single T-HEAD Xuantie C906 CPU, whereas R528 and
-T113 contain a pair of Cortex-A7's. D1 and R528 are the full version of
-the chip with a BGA package, whereas D1s and T113 are low-pin-count QFP
-variants.
-
-Because the original design supported both ARM and RISC-V CPUs, some
-peripherals are duplicated. In addition, all variants except D1s contain
-a HiFi 4 DSP with its own set of peripherals.
-
-The devicetrees are organized to minimize duplication:
- - Common perhiperals are described in sunxi-d1s-t113.dtsi
- - DSP-related peripherals are described in sunxi-d1-t113.dtsi
- - RISC-V specific hardware is described in sun20i-d1s.dtsi
- - Functionality unique to the D1 variant is described in sun20i-d1.dtsi
-
-The SOC_PERIPHERAL_IRQ macro handles the different #interrupt-cells
-values between the ARM (GIC) and RISC-V (PLIC) versions of the SoC.
-
-Signed-off-by: Samuel Holland <samuel@sholland.org>
----
- arch/riscv/dts/sun20i-common-regulators.dtsi | 28 +
- arch/riscv/dts/sun20i-d1.dtsi | 66 ++
- arch/riscv/dts/sun20i-d1s.dtsi | 76 ++
- arch/riscv/dts/sunxi-d1-t113.dtsi | 15 +
- arch/riscv/dts/sunxi-d1s-t113.dtsi | 834 +++++++++++++++++++
- include/dt-bindings/clock/sun20i-d1-r-ccu.h | 19 +
- include/dt-bindings/reset/sun20i-d1-r-ccu.h | 16 +
- 7 files changed, 1054 insertions(+)
- create mode 100644 arch/riscv/dts/sun20i-common-regulators.dtsi
- create mode 100644 arch/riscv/dts/sun20i-d1.dtsi
- create mode 100644 arch/riscv/dts/sun20i-d1s.dtsi
- create mode 100644 arch/riscv/dts/sunxi-d1-t113.dtsi
- create mode 100644 arch/riscv/dts/sunxi-d1s-t113.dtsi
- create mode 100644 include/dt-bindings/clock/sun20i-d1-r-ccu.h
- create mode 100644 include/dt-bindings/reset/sun20i-d1-r-ccu.h
-
-diff --git a/arch/riscv/dts/sun20i-common-regulators.dtsi b/arch/riscv/dts/sun20i-common-regulators.dtsi
-new file mode 100644
-index 0000000000..9b03fca244
---- /dev/null
-+++ b/arch/riscv/dts/sun20i-common-regulators.dtsi
-@@ -0,0 +1,28 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
-+
-+/ {
-+ reg_vcc: vcc {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ };
-+
-+ reg_vcc_3v3: vcc-3v3 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc-3v3";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ vin-supply = <®_vcc>;
-+ };
-+};
-+
-+&pio {
-+ vcc-pb-supply = <®_vcc_3v3>;
-+ vcc-pc-supply = <®_vcc_3v3>;
-+ vcc-pd-supply = <®_vcc_3v3>;
-+ vcc-pe-supply = <®_vcc_3v3>;
-+ vcc-pf-supply = <®_vcc_3v3>;
-+ vcc-pg-supply = <®_vcc_3v3>;
-+};
-diff --git a/arch/riscv/dts/sun20i-d1.dtsi b/arch/riscv/dts/sun20i-d1.dtsi
-new file mode 100644
-index 0000000000..97e7cbb325
---- /dev/null
-+++ b/arch/riscv/dts/sun20i-d1.dtsi
-@@ -0,0 +1,66 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
-+
-+#include "sun20i-d1s.dtsi"
-+#include "sunxi-d1-t113.dtsi"
-+
-+/ {
-+ soc {
-+ lradc: keys@2009800 {
-+ compatible = "allwinner,sun20i-d1-lradc",
-+ "allwinner,sun50i-r329-lradc";
-+ reg = <0x2009800 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(61) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_LRADC>;
-+ resets = <&ccu RST_BUS_LRADC>;
-+ status = "disabled";
-+ };
-+
-+ i2s0: i2s@2032000 {
-+ compatible = "allwinner,sun20i-d1-i2s",
-+ "allwinner,sun50i-r329-i2s";
-+ reg = <0x2032000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(26) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_I2S0>,
-+ <&ccu CLK_I2S0>;
-+ clock-names = "apb", "mod";
-+ resets = <&ccu RST_BUS_I2S0>;
-+ dmas = <&dma 3>, <&dma 3>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #sound-dai-cells = <0>;
-+ };
-+ };
-+};
-+
-+&pio {
-+ /omit-if-no-ref/
-+ dmic_pb11_d0_pin: dmic-pb11-d0-pin {
-+ pins = "PB11";
-+ function = "dmic";
-+ };
-+
-+ /omit-if-no-ref/
-+ dmic_pe17_clk_pin: dmic-pe17-clk-pin {
-+ pins = "PE17";
-+ function = "dmic";
-+ };
-+
-+ /omit-if-no-ref/
-+ i2c0_pb10_pins: i2c0-pb10-pins {
-+ pins = "PB10", "PB11";
-+ function = "i2c0";
-+ };
-+
-+ /omit-if-no-ref/
-+ i2c2_pb0_pins: i2c2-pb0-pins {
-+ pins = "PB0", "PB1";
-+ function = "i2c2";
-+ };
-+
-+ /omit-if-no-ref/
-+ uart0_pb8_pins: uart0-pb8-pins {
-+ pins = "PB8", "PB9";
-+ function = "uart0";
-+ };
-+};
-diff --git a/arch/riscv/dts/sun20i-d1s.dtsi b/arch/riscv/dts/sun20i-d1s.dtsi
-new file mode 100644
-index 0000000000..8275630af9
---- /dev/null
-+++ b/arch/riscv/dts/sun20i-d1s.dtsi
-@@ -0,0 +1,76 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
-+
-+#define SOC_PERIPHERAL_IRQ(nr) (nr + 16)
-+
-+#include "sunxi-d1s-t113.dtsi"
-+
-+/ {
-+ cpus {
-+ timebase-frequency = <24000000>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ cpu0: cpu@0 {
-+ compatible = "thead,c906", "riscv";
-+ device_type = "cpu";
-+ reg = <0>;
-+ clocks = <&ccu CLK_RISCV>;
-+ d-cache-block-size = <64>;
-+ d-cache-sets = <256>;
-+ d-cache-size = <32768>;
-+ i-cache-block-size = <64>;
-+ i-cache-sets = <128>;
-+ i-cache-size = <32768>;
-+ mmu-type = "riscv,sv39";
-+ operating-points-v2 = <&opp_table_cpu>;
-+ riscv,isa = "rv64imafdc";
-+ #cooling-cells = <2>;
-+
-+ cpu0_intc: interrupt-controller {
-+ compatible = "riscv,cpu-intc";
-+ interrupt-controller;
-+ #address-cells = <0>;
-+ #interrupt-cells = <1>;
-+ };
-+ };
-+ };
-+
-+ opp_table_cpu: opp-table-cpu {
-+ compatible = "operating-points-v2";
-+
-+ opp-408000000 {
-+ opp-hz = /bits/ 64 <408000000>;
-+ opp-microvolt = <900000 900000 1100000>;
-+ };
-+
-+ opp-1080000000 {
-+ opp-hz = /bits/ 64 <1008000000>;
-+ opp-microvolt = <900000 900000 1100000>;
-+ };
-+ };
-+
-+ soc {
-+ interrupt-parent = <&plic>;
-+
-+ riscv_wdt: watchdog@6011000 {
-+ compatible = "allwinner,sun20i-d1-wdt";
-+ reg = <0x6011000 0x20>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(131) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
-+ clock-names = "hosc", "losc";
-+ };
-+
-+ plic: interrupt-controller@10000000 {
-+ compatible = "allwinner,sun20i-d1-plic",
-+ "thead,c900-plic";
-+ reg = <0x10000000 0x4000000>;
-+ interrupts-extended = <&cpu0_intc 11>,
-+ <&cpu0_intc 9>;
-+ interrupt-controller;
-+ riscv,ndev = <175>;
-+ #address-cells = <0>;
-+ #interrupt-cells = <2>;
-+ };
-+ };
-+};
-diff --git a/arch/riscv/dts/sunxi-d1-t113.dtsi b/arch/riscv/dts/sunxi-d1-t113.dtsi
-new file mode 100644
-index 0000000000..b7156123df
---- /dev/null
-+++ b/arch/riscv/dts/sunxi-d1-t113.dtsi
-@@ -0,0 +1,15 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
-+
-+/ {
-+ soc {
-+ dsp_wdt: watchdog@1700400 {
-+ compatible = "allwinner,sun20i-d1-wdt";
-+ reg = <0x1700400 0x20>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(122) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
-+ clock-names = "hosc", "losc";
-+ status = "reserved";
-+ };
-+ };
-+};
-diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-new file mode 100644
-index 0000000000..6fadcee780
---- /dev/null
-+++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-@@ -0,0 +1,834 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
-+
-+#include <dt-bindings/clock/sun6i-rtc.h>
-+#include <dt-bindings/clock/sun8i-de2.h>
-+#include <dt-bindings/clock/sun8i-tcon-top.h>
-+#include <dt-bindings/clock/sun20i-d1-ccu.h>
-+#include <dt-bindings/clock/sun20i-d1-r-ccu.h>
-+#include <dt-bindings/interrupt-controller/irq.h>
-+#include <dt-bindings/reset/sun8i-de2.h>
-+#include <dt-bindings/reset/sun20i-d1-ccu.h>
-+#include <dt-bindings/reset/sun20i-d1-r-ccu.h>
-+
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ dcxo: dcxo-clk {
-+ compatible = "fixed-clock";
-+ clock-output-names = "dcxo";
-+ #clock-cells = <0>;
-+ };
-+
-+ de: display-engine {
-+ compatible = "allwinner,sun20i-d1-display-engine";
-+ allwinner,pipelines = <&mixer0>, <&mixer1>;
-+ status = "disabled";
-+ };
-+
-+ soc {
-+ compatible = "simple-bus";
-+ ranges;
-+ dma-noncoherent;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ pio: pinctrl@2000000 {
-+ compatible = "allwinner,sun20i-d1-pinctrl";
-+ reg = <0x2000000 0x800>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(69) IRQ_TYPE_LEVEL_HIGH>,
-+ <SOC_PERIPHERAL_IRQ(71) IRQ_TYPE_LEVEL_HIGH>,
-+ <SOC_PERIPHERAL_IRQ(73) IRQ_TYPE_LEVEL_HIGH>,
-+ <SOC_PERIPHERAL_IRQ(75) IRQ_TYPE_LEVEL_HIGH>,
-+ <SOC_PERIPHERAL_IRQ(77) IRQ_TYPE_LEVEL_HIGH>,
-+ <SOC_PERIPHERAL_IRQ(79) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_APB0>,
-+ <&dcxo>,
-+ <&rtc CLK_OSC32K>;
-+ clock-names = "apb", "hosc", "losc";
-+ gpio-controller;
-+ interrupt-controller;
-+ #gpio-cells = <3>;
-+ #interrupt-cells = <3>;
-+
-+ /omit-if-no-ref/
-+ clk_pg11_pin: clk-pg11-pin {
-+ pins = "PG11";
-+ function = "clk";
-+ };
-+
-+ /omit-if-no-ref/
-+ dsi_4lane_pins: dsi-4lane-pins {
-+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
-+ "PD6", "PD7", "PD8", "PD9";
-+ drive-strength = <30>;
-+ function = "dsi";
-+ };
-+
-+ /omit-if-no-ref/
-+ lcd_rgb666_pins: lcd-rgb666-pins {
-+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
-+ "PD6", "PD7", "PD8", "PD9", "PD10", "PD11",
-+ "PD12", "PD13", "PD14", "PD15", "PD16", "PD17",
-+ "PD18", "PD19", "PD20", "PD21";
-+ function = "lcd0";
-+ };
-+
-+ /omit-if-no-ref/
-+ mmc0_pins: mmc0-pins {
-+ pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
-+ function = "mmc0";
-+ };
-+
-+ /omit-if-no-ref/
-+ mmc1_pins: mmc1-pins {
-+ pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5";
-+ function = "mmc1";
-+ };
-+
-+ /omit-if-no-ref/
-+ mmc2_pins: mmc2-pins {
-+ pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7";
-+ function = "mmc2";
-+ };
-+
-+ /omit-if-no-ref/
-+ rgmii_pe_pins: rgmii-pe-pins {
-+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
-+ "PE5", "PE6", "PE7", "PE8", "PE9",
-+ "PE11", "PE12", "PE13", "PE14", "PE15";
-+ function = "emac";
-+ };
-+
-+ /omit-if-no-ref/
-+ rmii_pe_pins: rmii-pe-pins {
-+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
-+ "PE5", "PE6", "PE7", "PE8", "PE9";
-+ function = "emac";
-+ };
-+
-+ /omit-if-no-ref/
-+ uart1_pg6_pins: uart1-pg6-pins {
-+ pins = "PG6", "PG7";
-+ function = "uart1";
-+ };
-+
-+ /omit-if-no-ref/
-+ uart1_pg8_rts_cts_pins: uart1-pg8-rts-cts-pins {
-+ pins = "PG8", "PG9";
-+ function = "uart1";
-+ };
-+
-+ /omit-if-no-ref/
-+ uart3_pb_pins: uart3-pb-pins {
-+ pins = "PB6", "PB7";
-+ function = "uart3";
-+ };
-+ };
-+
-+ ccu: clock-controller@2001000 {
-+ compatible = "allwinner,sun20i-d1-ccu";
-+ reg = <0x2001000 0x1000>;
-+ clocks = <&dcxo>,
-+ <&rtc CLK_OSC32K>,
-+ <&rtc CLK_IOSC>;
-+ clock-names = "hosc", "losc", "iosc";
-+ #clock-cells = <1>;
-+ #reset-cells = <1>;
-+ };
-+
-+ dmic: dmic@2031000 {
-+ compatible = "allwinner,sun20i-d1-dmic",
-+ "allwinner,sun50i-h6-dmic";
-+ reg = <0x2031000 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(24) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_DMIC>,
-+ <&ccu CLK_DMIC>;
-+ clock-names = "bus", "mod";
-+ resets = <&ccu RST_BUS_DMIC>;
-+ dmas = <&dma 8>;
-+ dma-names = "rx";
-+ status = "disabled";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ i2s1: i2s@2033000 {
-+ compatible = "allwinner,sun20i-d1-i2s",
-+ "allwinner,sun50i-r329-i2s";
-+ reg = <0x2033000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(27) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_I2S1>,
-+ <&ccu CLK_I2S1>;
-+ clock-names = "apb", "mod";
-+ resets = <&ccu RST_BUS_I2S1>;
-+ dmas = <&dma 4>, <&dma 4>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ i2s2: i2s@2034000 {
-+ compatible = "allwinner,sun20i-d1-i2s",
-+ "allwinner,sun50i-r329-i2s";
-+ reg = <0x2034000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(28) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_I2S2>,
-+ <&ccu CLK_I2S2>;
-+ clock-names = "apb", "mod";
-+ resets = <&ccu RST_BUS_I2S2>;
-+ dmas = <&dma 5>, <&dma 5>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ timer: timer@2050000 {
-+ compatible = "allwinner,sun20i-d1-timer",
-+ "allwinner,sun8i-a23-timer";
-+ reg = <0x2050000 0xa0>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(59) IRQ_TYPE_LEVEL_HIGH>,
-+ <SOC_PERIPHERAL_IRQ(60) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&dcxo>;
-+ };
-+
-+ wdt: watchdog@20500a0 {
-+ compatible = "allwinner,sun20i-d1-wdt-reset",
-+ "allwinner,sun20i-d1-wdt";
-+ reg = <0x20500a0 0x20>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(63) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
-+ clock-names = "hosc", "losc";
-+ status = "reserved";
-+ };
-+
-+ uart0: serial@2500000 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x2500000 0x400>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(2) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_UART0>;
-+ resets = <&ccu RST_BUS_UART0>;
-+ dmas = <&dma 14>, <&dma 14>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ };
-+
-+ uart1: serial@2500400 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x2500400 0x400>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(3) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_UART1>;
-+ resets = <&ccu RST_BUS_UART1>;
-+ dmas = <&dma 15>, <&dma 15>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ };
-+
-+ uart2: serial@2500800 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x2500800 0x400>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(4) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_UART2>;
-+ resets = <&ccu RST_BUS_UART2>;
-+ dmas = <&dma 16>, <&dma 16>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ };
-+
-+ uart3: serial@2500c00 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x2500c00 0x400>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(5) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_UART3>;
-+ resets = <&ccu RST_BUS_UART3>;
-+ dmas = <&dma 17>, <&dma 17>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ };
-+
-+ uart4: serial@2501000 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x2501000 0x400>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(6) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_UART4>;
-+ resets = <&ccu RST_BUS_UART4>;
-+ dmas = <&dma 18>, <&dma 18>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ };
-+
-+ uart5: serial@2501400 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x2501400 0x400>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(7) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_UART5>;
-+ resets = <&ccu RST_BUS_UART5>;
-+ dmas = <&dma 19>, <&dma 19>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ };
-+
-+ i2c0: i2c@2502000 {
-+ compatible = "allwinner,sun20i-d1-i2c",
-+ "allwinner,sun8i-v536-i2c",
-+ "allwinner,sun6i-a31-i2c";
-+ reg = <0x2502000 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(9) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_I2C0>;
-+ resets = <&ccu RST_BUS_I2C0>;
-+ dmas = <&dma 43>, <&dma 43>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ i2c1: i2c@2502400 {
-+ compatible = "allwinner,sun20i-d1-i2c",
-+ "allwinner,sun8i-v536-i2c",
-+ "allwinner,sun6i-a31-i2c";
-+ reg = <0x2502400 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_I2C1>;
-+ resets = <&ccu RST_BUS_I2C1>;
-+ dmas = <&dma 44>, <&dma 44>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ i2c2: i2c@2502800 {
-+ compatible = "allwinner,sun20i-d1-i2c",
-+ "allwinner,sun8i-v536-i2c",
-+ "allwinner,sun6i-a31-i2c";
-+ reg = <0x2502800 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(11) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_I2C2>;
-+ resets = <&ccu RST_BUS_I2C2>;
-+ dmas = <&dma 45>, <&dma 45>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ i2c3: i2c@2502c00 {
-+ compatible = "allwinner,sun20i-d1-i2c",
-+ "allwinner,sun8i-v536-i2c",
-+ "allwinner,sun6i-a31-i2c";
-+ reg = <0x2502c00 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(12) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_I2C3>;
-+ resets = <&ccu RST_BUS_I2C3>;
-+ dmas = <&dma 46>, <&dma 46>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ syscon: syscon@3000000 {
-+ compatible = "allwinner,sun20i-d1-system-control";
-+ reg = <0x3000000 0x1000>;
-+ ranges;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ };
-+
-+ dma: dma-controller@3002000 {
-+ compatible = "allwinner,sun20i-d1-dma";
-+ reg = <0x3002000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(50) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
-+ clock-names = "bus", "mbus";
-+ resets = <&ccu RST_BUS_DMA>;
-+ dma-channels = <16>;
-+ dma-requests = <48>;
-+ #dma-cells = <1>;
-+ };
-+
-+ sid: efuse@3006000 {
-+ compatible = "allwinner,sun20i-d1-sid";
-+ reg = <0x3006000 0x1000>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ };
-+
-+ mbus: dram-controller@3102000 {
-+ compatible = "allwinner,sun20i-d1-mbus";
-+ reg = <0x3102000 0x1000>,
-+ <0x3103000 0x1000>;
-+ reg-names = "mbus", "dram";
-+ interrupts = <SOC_PERIPHERAL_IRQ(43) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_MBUS>,
-+ <&ccu CLK_DRAM>,
-+ <&ccu CLK_BUS_DRAM>;
-+ clock-names = "mbus", "dram", "bus";
-+ dma-ranges = <0 0x40000000 0x80000000>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ #interconnect-cells = <1>;
-+ };
-+
-+ mmc0: mmc@4020000 {
-+ compatible = "allwinner,sun20i-d1-mmc";
-+ reg = <0x4020000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(40) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
-+ clock-names = "ahb", "mmc";
-+ resets = <&ccu RST_BUS_MMC0>;
-+ reset-names = "ahb";
-+ cap-sd-highspeed;
-+ max-frequency = <150000000>;
-+ no-mmc;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ mmc1: mmc@4021000 {
-+ compatible = "allwinner,sun20i-d1-mmc";
-+ reg = <0x4021000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(41) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
-+ clock-names = "ahb", "mmc";
-+ resets = <&ccu RST_BUS_MMC1>;
-+ reset-names = "ahb";
-+ cap-sd-highspeed;
-+ max-frequency = <150000000>;
-+ no-mmc;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ mmc2: mmc@4022000 {
-+ compatible = "allwinner,sun20i-d1-emmc",
-+ "allwinner,sun50i-a100-emmc";
-+ reg = <0x4022000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(42) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
-+ clock-names = "ahb", "mmc";
-+ resets = <&ccu RST_BUS_MMC2>;
-+ reset-names = "ahb";
-+ cap-mmc-highspeed;
-+ max-frequency = <150000000>;
-+ mmc-ddr-1_8v;
-+ mmc-ddr-3_3v;
-+ no-sd;
-+ no-sdio;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ usb_otg: usb@4100000 {
-+ compatible = "allwinner,sun20i-d1-musb",
-+ "allwinner,sun8i-a33-musb";
-+ reg = <0x4100000 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(29) IRQ_TYPE_LEVEL_HIGH>;
-+ interrupt-names = "mc";
-+ clocks = <&ccu CLK_BUS_OTG>;
-+ resets = <&ccu RST_BUS_OTG>;
-+ extcon = <&usbphy 0>;
-+ phys = <&usbphy 0>;
-+ phy-names = "usb";
-+ status = "disabled";
-+ };
-+
-+ usbphy: phy@4100400 {
-+ compatible = "allwinner,sun20i-d1-usb-phy";
-+ reg = <0x4100400 0x100>,
-+ <0x4101800 0x100>,
-+ <0x4200800 0x100>;
-+ reg-names = "phy_ctrl",
-+ "pmu0",
-+ "pmu1";
-+ clocks = <&dcxo>,
-+ <&dcxo>;
-+ clock-names = "usb0_phy",
-+ "usb1_phy";
-+ resets = <&ccu RST_USB_PHY0>,
-+ <&ccu RST_USB_PHY1>;
-+ reset-names = "usb0_reset",
-+ "usb1_reset";
-+ status = "disabled";
-+ #phy-cells = <1>;
-+ };
-+
-+ ehci0: usb@4101000 {
-+ compatible = "allwinner,sun20i-d1-ehci",
-+ "generic-ehci";
-+ reg = <0x4101000 0x100>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(30) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_OHCI0>,
-+ <&ccu CLK_BUS_EHCI0>,
-+ <&ccu CLK_USB_OHCI0>;
-+ resets = <&ccu RST_BUS_OHCI0>,
-+ <&ccu RST_BUS_EHCI0>;
-+ phys = <&usbphy 0>;
-+ phy-names = "usb";
-+ status = "disabled";
-+ };
-+
-+ ohci0: usb@4101400 {
-+ compatible = "allwinner,sun20i-d1-ohci",
-+ "generic-ohci";
-+ reg = <0x4101400 0x100>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(31) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_OHCI0>,
-+ <&ccu CLK_USB_OHCI0>;
-+ resets = <&ccu RST_BUS_OHCI0>;
-+ phys = <&usbphy 0>;
-+ phy-names = "usb";
-+ status = "disabled";
-+ };
-+
-+ ehci1: usb@4200000 {
-+ compatible = "allwinner,sun20i-d1-ehci",
-+ "generic-ehci";
-+ reg = <0x4200000 0x100>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(33) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_OHCI1>,
-+ <&ccu CLK_BUS_EHCI1>,
-+ <&ccu CLK_USB_OHCI1>;
-+ resets = <&ccu RST_BUS_OHCI1>,
-+ <&ccu RST_BUS_EHCI1>;
-+ phys = <&usbphy 1>;
-+ phy-names = "usb";
-+ status = "disabled";
-+ };
-+
-+ ohci1: usb@4200400 {
-+ compatible = "allwinner,sun20i-d1-ohci",
-+ "generic-ohci";
-+ reg = <0x4200400 0x100>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(34) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_OHCI1>,
-+ <&ccu CLK_USB_OHCI1>;
-+ resets = <&ccu RST_BUS_OHCI1>;
-+ phys = <&usbphy 1>;
-+ phy-names = "usb";
-+ status = "disabled";
-+ };
-+
-+ emac: ethernet@4500000 {
-+ compatible = "allwinner,sun20i-d1-emac",
-+ "allwinner,sun50i-a64-emac";
-+ reg = <0x4500000 0x10000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(46) IRQ_TYPE_LEVEL_HIGH>;
-+ interrupt-names = "macirq";
-+ clocks = <&ccu CLK_BUS_EMAC>;
-+ clock-names = "stmmaceth";
-+ resets = <&ccu RST_BUS_EMAC>;
-+ reset-names = "stmmaceth";
-+ syscon = <&syscon>;
-+ status = "disabled";
-+
-+ mdio: mdio {
-+ compatible = "snps,dwmac-mdio";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+ };
-+
-+ display_clocks: clock-controller@5000000 {
-+ compatible = "allwinner,sun20i-d1-de2-clk",
-+ "allwinner,sun50i-h5-de2-clk";
-+ reg = <0x5000000 0x10000>;
-+ clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>;
-+ clock-names = "bus", "mod";
-+ resets = <&ccu RST_BUS_DE>;
-+ #clock-cells = <1>;
-+ #reset-cells = <1>;
-+ };
-+
-+ mixer0: mixer@5100000 {
-+ compatible = "allwinner,sun20i-d1-de2-mixer-0";
-+ reg = <0x5100000 0x100000>;
-+ clocks = <&display_clocks CLK_BUS_MIXER0>,
-+ <&display_clocks CLK_MIXER0>;
-+ clock-names = "bus", "mod";
-+ resets = <&display_clocks RST_MIXER0>;
-+
-+ ports {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ mixer0_out: port@1 {
-+ reg = <1>;
-+
-+ mixer0_out_tcon_top_mixer0: endpoint {
-+ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
-+ };
-+ };
-+ };
-+ };
-+
-+ mixer1: mixer@5200000 {
-+ compatible = "allwinner,sun20i-d1-de2-mixer-1";
-+ reg = <0x5200000 0x100000>;
-+ clocks = <&display_clocks CLK_BUS_MIXER1>,
-+ <&display_clocks CLK_MIXER1>;
-+ clock-names = "bus", "mod";
-+ resets = <&display_clocks RST_MIXER1>;
-+
-+ ports {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ mixer1_out: port@1 {
-+ reg = <1>;
-+
-+ mixer1_out_tcon_top_mixer1: endpoint {
-+ remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
-+ };
-+ };
-+ };
-+ };
-+
-+ dsi: dsi@5450000 {
-+ compatible = "allwinner,sun20i-d1-mipi-dsi",
-+ "allwinner,sun50i-a100-mipi-dsi";
-+ reg = <0x5450000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
-+ <&tcon_top CLK_TCON_TOP_DSI>;
-+ clock-names = "bus", "mod";
-+ resets = <&ccu RST_BUS_MIPI_DSI>;
-+ phys = <&dphy>;
-+ phy-names = "dphy";
-+ status = "disabled";
-+
-+ port {
-+ dsi_in_tcon_lcd0: endpoint {
-+ remote-endpoint = <&tcon_lcd0_out_dsi>;
-+ };
-+ };
-+ };
-+
-+ dphy: phy@5451000 {
-+ compatible = "allwinner,sun20i-d1-mipi-dphy",
-+ "allwinner,sun50i-a100-mipi-dphy";
-+ reg = <0x5451000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
-+ <&ccu CLK_MIPI_DSI>;
-+ clock-names = "bus", "mod";
-+ resets = <&ccu RST_BUS_MIPI_DSI>;
-+ #phy-cells = <0>;
-+ };
-+
-+ tcon_top: tcon-top@5460000 {
-+ compatible = "allwinner,sun20i-d1-tcon-top";
-+ reg = <0x5460000 0x1000>;
-+ clocks = <&ccu CLK_BUS_DPSS_TOP>,
-+ <&ccu CLK_TCON_TV>,
-+ <&ccu CLK_TVE>,
-+ <&ccu CLK_TCON_LCD0>;
-+ clock-names = "bus", "tcon-tv0", "tve0", "dsi";
-+ clock-output-names = "tcon-top-tv0", "tcon-top-dsi";
-+ resets = <&ccu RST_BUS_DPSS_TOP>;
-+ #clock-cells = <1>;
-+
-+ ports {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_top_mixer0_in: port@0 {
-+ reg = <0>;
-+
-+ tcon_top_mixer0_in_mixer0: endpoint {
-+ remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
-+ };
-+ };
-+
-+ tcon_top_mixer0_out: port@1 {
-+ reg = <1>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
-+ reg = <0>;
-+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer0>;
-+ };
-+
-+ tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
-+ reg = <2>;
-+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
-+ };
-+ };
-+
-+ tcon_top_mixer1_in: port@2 {
-+ reg = <2>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_top_mixer1_in_mixer1: endpoint@1 {
-+ reg = <1>;
-+ remote-endpoint = <&mixer1_out_tcon_top_mixer1>;
-+ };
-+ };
-+
-+ tcon_top_mixer1_out: port@3 {
-+ reg = <3>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
-+ reg = <0>;
-+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer1>;
-+ };
-+
-+ tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
-+ reg = <2>;
-+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
-+ };
-+ };
-+
-+ tcon_top_hdmi_in: port@4 {
-+ reg = <4>;
-+
-+ tcon_top_hdmi_in_tcon_tv0: endpoint {
-+ remote-endpoint = <&tcon_tv0_out_tcon_top_hdmi>;
-+ };
-+ };
-+
-+ tcon_top_hdmi_out: port@5 {
-+ reg = <5>;
-+ };
-+ };
-+ };
-+
-+ tcon_lcd0: lcd-controller@5461000 {
-+ compatible = "allwinner,sun20i-d1-tcon-lcd";
-+ reg = <0x5461000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(90) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_TCON_LCD0>,
-+ <&ccu CLK_TCON_LCD0>;
-+ clock-names = "ahb", "tcon-ch0";
-+ clock-output-names = "tcon-pixel-clock";
-+ resets = <&ccu RST_BUS_TCON_LCD0>,
-+ <&ccu RST_BUS_LVDS0>;
-+ reset-names = "lcd", "lvds";
-+ #clock-cells = <0>;
-+
-+ ports {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_lcd0_in: port@0 {
-+ reg = <0>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_lcd0_in_tcon_top_mixer0: endpoint@0 {
-+ reg = <0>;
-+ remote-endpoint = <&tcon_top_mixer0_out_tcon_lcd0>;
-+ };
-+
-+ tcon_lcd0_in_tcon_top_mixer1: endpoint@1 {
-+ reg = <1>;
-+ remote-endpoint = <&tcon_top_mixer1_out_tcon_lcd0>;
-+ };
-+ };
-+
-+ tcon_lcd0_out: port@1 {
-+ reg = <1>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_lcd0_out_dsi: endpoint@1 {
-+ reg = <1>;
-+ remote-endpoint = <&dsi_in_tcon_lcd0>;
-+ };
-+ };
-+ };
-+ };
-+
-+ tcon_tv0: lcd-controller@5470000 {
-+ compatible = "allwinner,sun20i-d1-tcon-tv";
-+ reg = <0x5470000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(91) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_TCON_TV>,
-+ <&tcon_top CLK_TCON_TOP_TV0>;
-+ clock-names = "ahb", "tcon-ch1";
-+ resets = <&ccu RST_BUS_TCON_TV>;
-+ reset-names = "lcd";
-+
-+ ports {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_tv0_in: port@0 {
-+ reg = <0>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
-+ reg = <0>;
-+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
-+ };
-+
-+ tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
-+ reg = <1>;
-+ remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
-+ };
-+ };
-+
-+ tcon_tv0_out: port@1 {
-+ reg = <1>;
-+
-+ tcon_tv0_out_tcon_top_hdmi: endpoint {
-+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
-+ };
-+ };
-+ };
-+ };
-+
-+ ppu: power-controller@7001000 {
-+ compatible = "allwinner,sun20i-d1-ppu";
-+ reg = <0x7001000 0x1000>;
-+ clocks = <&r_ccu CLK_BUS_R_PPU>;
-+ resets = <&r_ccu RST_BUS_R_PPU>;
-+ #power-domain-cells = <1>;
-+ };
-+
-+ r_ccu: clock-controller@7010000 {
-+ compatible = "allwinner,sun20i-d1-r-ccu";
-+ reg = <0x7010000 0x400>;
-+ clocks = <&dcxo>,
-+ <&rtc CLK_OSC32K>,
-+ <&rtc CLK_IOSC>,
-+ <&ccu CLK_PLL_PERIPH0_DIV3>;
-+ clock-names = "hosc", "losc", "iosc", "pll-periph";
-+ #clock-cells = <1>;
-+ #reset-cells = <1>;
-+ };
-+
-+ rtc: rtc@7090000 {
-+ compatible = "allwinner,sun20i-d1-rtc",
-+ "allwinner,sun50i-r329-rtc";
-+ reg = <0x7090000 0x400>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(144) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&r_ccu CLK_BUS_R_RTC>,
-+ <&dcxo>,
-+ <&r_ccu CLK_R_AHB>;
-+ clock-names = "bus", "hosc", "ahb";
-+ #clock-cells = <1>;
-+ };
-+ };
-+};
-diff --git a/include/dt-bindings/clock/sun20i-d1-r-ccu.h b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
-new file mode 100644
-index 0000000000..4c2697fd32
---- /dev/null
-+++ b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
-@@ -0,0 +1,19 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
-+/*
-+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
-+ */
-+
-+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
-+#define _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
-+
-+#define CLK_R_AHB 0
-+
-+#define CLK_BUS_R_TIMER 2
-+#define CLK_BUS_R_TWD 3
-+#define CLK_BUS_R_PPU 4
-+#define CLK_R_IR_RX 5
-+#define CLK_BUS_R_IR_RX 6
-+#define CLK_BUS_R_RTC 7
-+#define CLK_BUS_R_CPUCFG 8
-+
-+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ */
-diff --git a/include/dt-bindings/reset/sun20i-d1-r-ccu.h b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
-new file mode 100644
-index 0000000000..d93d6423d2
---- /dev/null
-+++ b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
-@@ -0,0 +1,16 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
-+/*
-+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
-+ */
-+
-+#ifndef _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
-+#define _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
-+
-+#define RST_BUS_R_TIMER 0
-+#define RST_BUS_R_TWD 1
-+#define RST_BUS_R_PPU 2
-+#define RST_BUS_R_IR_RX 3
-+#define RST_BUS_R_RTC 4
-+#define RST_BUS_R_CPUCFG 5
-+
-+#endif /* _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ */
---
-2.20.1
-
--- /dev/null
+From 8cd51196fec0b7544cb5842dac9f7209542a6a61 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:57 +0100
+Subject: [PATCH 4017/4044] sunxi: clock: D1/R528: Enable PLL LDO during PLL1
+ setup
+
+The D1/R528/T113s SoCs introduce a new "LDO enable" bit in the CPUX_PLL.
+Just enable that when we program that PLL.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h | 1 +
+ arch/arm/mach-sunxi/clock_sun50i_h6.c | 12 +++++++-----
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+index 37df4410ea..9895c2c220 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+@@ -228,6 +228,7 @@ struct sunxi_ccm_reg {
+
+ /* pll1 bit field */
+ #define CCM_PLL1_CTRL_EN BIT(31)
++#define CCM_PLL1_LDO_EN BIT(30)
+ #define CCM_PLL1_LOCK_EN BIT(29)
+ #define CCM_PLL1_LOCK BIT(28)
+ #define CCM_PLL1_OUT_EN BIT(27)
+diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+index 7926394cf7..90110eab10 100644
+--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
++++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+@@ -86,11 +86,13 @@ void clock_set_pll1(unsigned int clk)
+ writel(val, &ccm->cpu_axi_cfg);
+
+ /* clk = 24*n/p, p is ignored if clock is >288MHz */
+- writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
+-#ifdef CONFIG_MACH_SUN50I_H616
+- CCM_PLL1_OUT_EN |
+-#endif
+- CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
++ val = CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2;
++ val |= CCM_PLL1_CTRL_N(clk / 24000000);
++ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
++ val |= CCM_PLL1_OUT_EN;
++ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
++ val |= CCM_PLL1_OUT_EN | CCM_PLL1_LDO_EN;
++ writel(val, &ccm->pll1_cfg);
+ while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
+
+ /* Switch CPU to PLL1 */
+--
+2.20.1
+
+++ /dev/null
-From 3db4754246274bc530d008f54fc686db8425479f Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Tue, 3 Jan 2023 16:04:47 +0000
-Subject: [PATCH 4018/4031] ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi
-
-The Allwinner T113-s SoC is apparently using the same (or at least a very
-similar) die as the D1/D1s, but replaces the single RISC-V core with
-two Arm Cortex-A7 cores.
-Since the D1 core .dtsi already describes all common peripherals, we
-just need a DT describing the ARM specific peripherals: the CPU cores,
-the Generic Timer, the GIC and the PMU.
-We include the core .dtsi directly from the riscv DT directory.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/dts/sun8i-t113s.dtsi | 59 +++++++++++++++++++++++++++++++++++
- 1 file changed, 59 insertions(+)
- create mode 100644 arch/arm/dts/sun8i-t113s.dtsi
-
-diff --git a/arch/arm/dts/sun8i-t113s.dtsi b/arch/arm/dts/sun8i-t113s.dtsi
-new file mode 100644
-index 0000000000..ce00883130
---- /dev/null
-+++ b/arch/arm/dts/sun8i-t113s.dtsi
-@@ -0,0 +1,59 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2022 Arm Ltd.
-+
-+#define SOC_PERIPHERAL_IRQ(nr) GIC_SPI nr
-+
-+#include <dt-bindings/interrupt-controller/arm-gic.h>
-+#include <../../riscv/dts/sunxi-d1s-t113.dtsi>
-+#include <../../riscv/dts/sunxi-d1-t113.dtsi>
-+
-+/ {
-+ interrupt-parent = <&gic>;
-+
-+ cpus {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ cpu0: cpu@0 {
-+ compatible = "arm,cortex-a7";
-+ device_type = "cpu";
-+ reg = <0>;
-+ clocks = <&ccu CLK_CPUX>;
-+ clock-names = "cpu";
-+ };
-+
-+ cpu1: cpu@1 {
-+ compatible = "arm,cortex-a7";
-+ device_type = "cpu";
-+ reg = <1>;
-+ clocks = <&ccu CLK_CPUX>;
-+ clock-names = "cpu";
-+ };
-+ };
-+
-+ gic: interrupt-controller@1c81000 {
-+ compatible = "arm,gic-400";
-+ reg = <0x03021000 0x1000>,
-+ <0x03022000 0x2000>,
-+ <0x03024000 0x2000>,
-+ <0x03026000 0x2000>;
-+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
-+ interrupt-controller;
-+ #interrupt-cells = <3>;
-+ };
-+
-+ timer {
-+ compatible = "arm,armv7-timer";
-+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
-+ };
-+
-+ pmu {
-+ compatible = "arm,cortex-a7-pmu";
-+ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
-+ interrupt-affinity = <&cpu0>, <&cpu1>;
-+ };
-+};
---
-2.20.1
-
--- /dev/null
+From 18b787a4cb4edc9b6aa38b55830c9f9f17716000 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:58 +0100
+Subject: [PATCH 4018/4044] sunxi: clock: support D1/R528 PLL6 clock
+
+The PLL_PERIPH0 clock changed a bit in the D1/R528/T113s SoCs: there is
+new P0 divider at bits [18:16], and the M divider is 1.
+
+Add code to support this version of "PLL6".
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ .../include/asm/arch-sunxi/clock_sun50i_h6.h | 2 ++
+ arch/arm/mach-sunxi/clock_sun50i_h6.c | 24 +++++++++++++------
+ 2 files changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+index 9895c2c220..8471e11aa0 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+@@ -249,6 +249,8 @@ struct sunxi_ccm_reg {
+ #define CCM_PLL6_CTRL_EN BIT(31)
+ #define CCM_PLL6_LOCK_EN BIT(29)
+ #define CCM_PLL6_LOCK BIT(28)
++#define CCM_PLL6_CTRL_P0_SHIFT 16
++#define CCM_PLL6_CTRL_P0_MASK (0x7 << CCM_PLL6_CTRL_P0_SHIFT)
+ #define CCM_PLL6_CTRL_N_SHIFT 8
+ #define CCM_PLL6_CTRL_N_MASK (0xff << CCM_PLL6_CTRL_N_SHIFT)
+ #define CCM_PLL6_CTRL_DIV1_SHIFT 0
+diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+index 90110eab10..607efe6a9c 100644
+--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
++++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+@@ -107,16 +107,26 @@ unsigned int clock_get_pll6(void)
+ {
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+- int m = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ? 4 : 2;
+-
+ uint32_t rval = readl(&ccm->pll6_cfg);
+ int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
+- int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
+- CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
+ int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
+- CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
+- /* The register defines PLL6-2X or PLL6-4X, not plain PLL6 */
+- return 24000000 / m * n / div1 / div2;
++ CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
++ int div1, m;
++
++ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
++ div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
++ CCM_PLL6_CTRL_P0_SHIFT) + 1;
++ m = 1;
++ } else {
++ div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
++ CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
++ if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
++ m = 4;
++ else
++ m = 2;
++ }
++
++ return 24000000U * n / m / div1 / div2;
+ }
+
+ int clock_twi_onoff(int port, int state)
+--
+2.20.1
+
+++ /dev/null
-From 61b9b6b87af8e7eed501155803620083f6dff849 Mon Sep 17 00:00:00 2001
-From: Andre Przywara <andre.przywara@arm.com>
-Date: Fri, 2 Dec 2022 16:11:36 +0000
-Subject: [PATCH 4019/4031] sunxi: add preliminary MangoPi MQ-R board support
-
-This includes a preliminary basic DT and a defconfig to get the board
-booted.
-
-Signed-off-by: Andre Przywara <andre.przywara@arm.com>
----
- arch/arm/dts/Makefile | 2 +
- .../arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts | 35 +++++
- arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi | 126 ++++++++++++++++++
- configs/mangopi_mq_r_defconfig | 17 +++
- 4 files changed, 180 insertions(+)
- create mode 100644 arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
- create mode 100644 arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
- create mode 100644 configs/mangopi_mq_r_defconfig
-
-diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
-index c160e884bf..41ee9c4c65 100644
---- a/arch/arm/dts/Makefile
-+++ b/arch/arm/dts/Makefile
-@@ -710,6 +710,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
- sun8i-s3-pinecube.dtb \
- sun8i-v3-sl631-imx179.dtb \
- sun8i-v3s-licheepi-zero.dtb
-+dtb-$(CONFIG_MACH_SUN8I_R528) += \
-+ sun8i-t113s-mangopi-mq-r-t113.dtb
- dtb-$(CONFIG_MACH_SUN50I_H5) += \
- sun50i-h5-bananapi-m2-plus.dtb \
- sun50i-h5-emlid-neutis-n5-devboard.dtb \
-diff --git a/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
-new file mode 100644
-index 0000000000..94e24b5926
---- /dev/null
-+++ b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
-@@ -0,0 +1,35 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2022 Arm Ltd.
-+
-+#include <dt-bindings/interrupt-controller/irq.h>
-+
-+/dts-v1/;
-+
-+#include "sun8i-t113s.dtsi"
-+#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
-+
-+/ {
-+ model = "MangoPi MQ-R-T113";
-+ compatible = "widora,mangopi-mq-r-t113", "allwinner,sun8i-t113s";
-+
-+ aliases {
-+ ethernet0 = &rtl8189ftv;
-+ };
-+};
-+
-+&cpu0 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&cpu1 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&mmc1 {
-+ rtl8189ftv: wifi@1 {
-+ reg = <1>;
-+ interrupt-parent = <&pio>;
-+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 = WL_WAKE_AP */
-+ interrupt-names = "host-wake";
-+ };
-+};
-diff --git a/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
-new file mode 100644
-index 0000000000..e9bc749488
---- /dev/null
-+++ b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
-@@ -0,0 +1,126 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2022 Arm Ltd.
-+/*
-+ * Common peripherals and configurations for MangoPi MQ-R boards.
-+ */
-+
-+#include <dt-bindings/gpio/gpio.h>
-+#include <dt-bindings/leds/common.h>
-+
-+/ {
-+ aliases {
-+ serial3 = &uart3;
-+ };
-+
-+ chosen {
-+ stdout-path = "serial3:115200n8";
-+ };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ led-0 {
-+ color = <LED_COLOR_ID_BLUE>;
-+ function = LED_FUNCTION_STATUS;
-+ gpios = <&pio 3 22 GPIO_ACTIVE_LOW>; /* PD22 */
-+ };
-+ };
-+
-+ /* board wide 5V supply directly from the USB-C socket */
-+ reg_vcc5v: regulator-5v {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc-5v";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ regulator-always-on;
-+ };
-+
-+ /* SY8008 DC/DC regulator on the board */
-+ reg_3v3: regulator-3v3 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc-3v3";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ vin-supply = <®_vcc5v>;
-+ };
-+
-+ /* SY8008 DC/DC regulator on the board, also supplying VDD-SYS */
-+ reg_vcc_core: regulator-core {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc-core";
-+ regulator-min-microvolt = <880000>;
-+ regulator-max-microvolt = <880000>;
-+ vin-supply = <®_vcc5v>;
-+ };
-+
-+ /* XC6206 LDO on the board */
-+ reg_avdd2v8: regulator-avdd {
-+ compatible = "regulator-fixed";
-+ regulator-name = "avdd2v8";
-+ regulator-min-microvolt = <2800000>;
-+ regulator-max-microvolt = <2800000>;
-+ vin-supply = <®_3v3>;
-+ };
-+
-+ wifi_pwrseq: wifi-pwrseq {
-+ compatible = "mmc-pwrseq-simple";
-+ reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
-+ };
-+};
-+
-+&dcxo {
-+ clock-frequency = <24000000>;
-+};
-+
-+&ehci1 {
-+ status = "okay";
-+};
-+
-+&mmc0 {
-+ pinctrl-0 = <&mmc0_pins>;
-+ pinctrl-names = "default";
-+ vmmc-supply = <®_3v3>;
-+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
-+ disable-wp;
-+ bus-width = <4>;
-+ status = "okay";
-+};
-+
-+&mmc1 {
-+ pinctrl-0 = <&mmc1_pins>;
-+ pinctrl-names = "default";
-+ vmmc-supply = <®_3v3>;
-+ non-removable;
-+ bus-width = <4>;
-+ mmc-pwrseq = <&wifi_pwrseq>;
-+ status = "okay";
-+};
-+
-+&ohci1 {
-+ status = "okay";
-+};
-+
-+&pio {
-+ vcc-pb-supply = <®_3v3>;
-+ vcc-pd-supply = <®_3v3>;
-+ vcc-pe-supply = <®_avdd2v8>;
-+ vcc-pf-supply = <®_3v3>;
-+ vcc-pg-supply = <®_3v3>;
-+};
-+
-+&uart3 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart3_pb_pins>;
-+ status = "okay";
-+};
-+
-+/* The USB-C socket has its CC pins pulled to GND, so is hardwired as a UFP. */
-+&usb_otg {
-+ dr_mode = "peripheral";
-+ status = "okay";
-+};
-+
-+&usbphy {
-+ usb1_vbus-supply = <®_vcc5v>;
-+ status = "okay";
-+};
-diff --git a/configs/mangopi_mq_r_defconfig b/configs/mangopi_mq_r_defconfig
-new file mode 100644
-index 0000000000..28bbfde602
---- /dev/null
-+++ b/configs/mangopi_mq_r_defconfig
-@@ -0,0 +1,17 @@
-+CONFIG_ARM=y
-+CONFIG_ARCH_SUNXI=y
-+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-mangopi-mq-r-t113"
-+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
-+CONFIG_SPL=y
-+CONFIG_MACH_SUN8I_R528=y
-+CONFIG_CONS_INDEX=4
-+CONFIG_MMC0_CD_PIN="PF6"
-+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-+CONFIG_SYS_MONITOR_LEN=786432
-+CONFIG_DRAM_CLK=792
-+CONFIG_DRAM_ZQ=8092667
-+CONFIG_DRAM_SUNXI_ODT_EN=0
-+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
-+CONFIG_DRAM_SUNXI_TPR11=0x340000
-+CONFIG_DRAM_SUNXI_TPR12=0x46
-+CONFIG_DRAM_SUNXI_TPR13=0x34000100
---
-2.20.1
-
--- /dev/null
+From c691eece56bd26a66aeebe435dd5179c60073e43 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:59 +0100
+Subject: [PATCH 4019/4044] sunxi: clock: h6: prepare for PRCM less SoCs
+
+The Allwinner D1/R528/T113 SoCs have a very minimal separate
+"management" power plane, with almost no device attached to it (so
+no r_i2c or r_uart). This means we don't need to flip any clock gates in
+the PRCM block, which in fact those SoCs do not have.
+
+Prepare the code for those SoCs by making the PRCM block optional in the
+H6 SPL clock code, which we otherwise share to this new family of SoCs.
+If the memory map (cpu.h) does not define the PRCM address, we simply
+skip any attempt to program gates there.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/mach-sunxi/clock_sun50i_h6.c | 22 +++++++++++++++++++---
+ 1 file changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+index 607efe6a9c..c3a4623d34 100644
+--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
++++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+@@ -4,14 +4,20 @@
+ #include <asm/arch/clock.h>
+ #include <asm/arch/prcm.h>
+
++#ifndef SUNXI_PRCM_BASE
++#define SUNXI_PRCM_BASE 0
++#endif
++
+ #ifdef CONFIG_SPL_BUILD
+-void clock_init_safe(void)
++
++static void clock_init_safe_prcm(void)
+ {
+- struct sunxi_ccm_reg *const ccm =
+- (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ struct sunxi_prcm_reg *const prcm =
+ (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+
++ if (!prcm)
++ return;
++
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616)) {
+ /* this seems to enable PLLs on H616 */
+ setbits_le32(&prcm->sys_pwroff_gating, 0x10);
+@@ -27,6 +33,14 @@ void clock_init_safe(void)
+ /* set PLL VDD LDO output to 1.14 V */
+ setbits_le32(&prcm->pll_ldo_cfg, 0x60000);
+ }
++}
++
++void clock_init_safe(void)
++{
++ struct sunxi_ccm_reg *const ccm =
++ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
++
++ clock_init_safe_prcm();
+
+ clock_set_pll1(408000000);
+
+@@ -141,6 +155,8 @@ int clock_twi_onoff(int port, int state)
+ value = BIT(GATE_SHIFT) | BIT (RESET_SHIFT);
+
+ if (port == 5) {
++ if (!prcm)
++ return -ENODEV;
+ shift = 0;
+ ptr = &prcm->twi_gate_reset;
+ } else {
+--
+2.20.1
+
--- /dev/null
+From b3afb64d19f297a9bddddaf75e67a88b1be96f90 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Sat, 26 Aug 2023 16:56:03 +0200
+Subject: [PATCH 4020/4044] Kconfig: sunxi: prepare for using drivers/ram/sunxi
+
+At the moment all Allwinner DRAM initialisation routines are stored in
+arch/arm/mach-sunxi, even though those "drivers" are just a giant
+collection of writel's, without any architectural dependency.
+
+The R528/T113-s SoC (with ARM cores) and the D1/D1s Soc (with RISC-V
+cores) share the same die, so should share the same DRAM init routines as
+well.
+
+To prepare for this, add a new sunxi directory inside drivers/ram, and
+add some stub entries to prepare for the addition of the share DRAM code
+for those SoCs.
+
+The RISC-V D1(s) SoCs will probably use SPL_DM, so make this entry
+depend on that already.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ drivers/ram/Kconfig | 1 +
+ drivers/ram/sunxi/Kconfig | 13 +++++++++++++
+ 2 files changed, 14 insertions(+)
+ create mode 100644 drivers/ram/sunxi/Kconfig
+
+diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
+index e085119963..636374be59 100644
+--- a/drivers/ram/Kconfig
++++ b/drivers/ram/Kconfig
+@@ -112,3 +112,4 @@ source "drivers/ram/rockchip/Kconfig"
+ source "drivers/ram/sifive/Kconfig"
+ source "drivers/ram/stm32mp1/Kconfig"
+ source "drivers/ram/octeon/Kconfig"
++source "drivers/ram/sunxi/Kconfig"
+diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
+new file mode 100644
+index 0000000000..97e261de54
+--- /dev/null
++++ b/drivers/ram/sunxi/Kconfig
+@@ -0,0 +1,13 @@
++config DRAM_SUN20I_D1
++ bool "DM DRAM driver support for Allwinner D1"
++ depends on RAM && ARCH_SUNXI
++ default y
++ help
++ This enables support for DRAM drivers using the driver model
++ for Allwinner SoCs.
++
++config DRAM_SUN8I_R528
++ bool "DRAM driver support for Allwinner R528/T113s"
++ default y if MACH_SUN8I_R528
++ help
++ Select this DRAM controller driver for the R528/T113s SoCs.
+--
+2.20.1
+
+++ /dev/null
-From c20401da0fe90a790f47e70cf79f43551adf76b9 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sat, 3 Jun 2023 00:52:04 +0200
-Subject: [PATCH 4020/4031] sunxi: add uart0_pins on Port E PE2/PE3 on D1s/T133
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/riscv/dts/sunxi-d1s-t113.dtsi | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-index 6fadcee780..2b7d54aab4 100644
---- a/arch/riscv/dts/sunxi-d1s-t113.dtsi
-+++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-@@ -125,6 +125,12 @@
- pins = "PB6", "PB7";
- function = "uart3";
- };
-+
-+ /omit-if-no-ref/
-+ uart0_pins: uart0-pins {
-+ pins = "PE2", "PE3";
-+ function = "uart0";
-+ };
- };
-
- ccu: clock-controller@2001000 {
---
-2.20.1
-
--- /dev/null
+From 96e17af5ca374af5e45422ca56d11f523437d2d2 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:46:01 +0100
+Subject: [PATCH 4021/4044] sunxi: add R528/T113-s3/D1(s) DRAM initialisation
+ code
+
+The Allwinner R528/T113-s/D1/D1s SoCs all share the same die, so use the
+same DRAM initialisation code.
+Make use of prior art here and lift some code from awboot[1], which
+carried init code based on earlier decompilation efforts, but with a
+GPL2 license tag.
+This code has been heavily reworked and cleaned up, to match previous
+DRAM routines for other SoCs, and also to be closer to U-Boot's coding
+style and support routines.
+The actual DRAM chip timing parameters are included in the main file,
+since they cover all DRAM types, and are protected by a new Kconfig
+CONFIG_SUNXI_DRAM_TYPE symbol, which allows the compiler to pick only
+the relevant settings, at build time.
+
+The relevant DRAM chips/board specific configuration parameters are
+delivered via Kconfig, so this code here should work for all supported
+SoCs and DRAM chips combinations.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Tested-by: Sam Edwards <CFSworks@gmail.com>
+---
+ drivers/Makefile | 1 +
+ drivers/ram/Makefile | 3 +
+ drivers/ram/sunxi/Kconfig | 59 ++
+ drivers/ram/sunxi/Makefile | 4 +
+ drivers/ram/sunxi/dram_sun20i_d1.c | 1432 ++++++++++++++++++++++++++++
+ drivers/ram/sunxi/dram_sun20i_d1.h | 73 ++
+ 6 files changed, 1572 insertions(+)
+ create mode 100644 drivers/ram/sunxi/Makefile
+ create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.c
+ create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.h
+
+diff --git a/drivers/Makefile b/drivers/Makefile
+index 15d19d0c8a..1542ce7caf 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -52,6 +52,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
+ obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
+ obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
+ obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
++obj-$(CONFIG_DRAM_SUN8I_R528) += ram/
+ obj-$(CONFIG_SPL_DM_RESET) += reset/
+ obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
+ obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
+diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
+index 83948e2c43..ae3cf65fa4 100644
+--- a/drivers/ram/Makefile
++++ b/drivers/ram/Makefile
+@@ -10,6 +10,9 @@ obj-$(CONFIG_STM32MP1_DDR) += stm32mp1/
+ obj-$(CONFIG_STM32_SDRAM) += stm32_sdram.o
+ obj-$(CONFIG_ARCH_BMIPS) += bmips_ram.o
+
++obj-$(CONFIG_DRAM_SUN8I_R528) += sunxi/
++
++
+ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
+
+ obj-$(CONFIG_K3_AM654_DDRSS) += k3-am654-ddrss.o
+diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
+index 97e261de54..657f47a870 100644
+--- a/drivers/ram/sunxi/Kconfig
++++ b/drivers/ram/sunxi/Kconfig
+@@ -11,3 +11,62 @@ config DRAM_SUN8I_R528
+ default y if MACH_SUN8I_R528
+ help
+ Select this DRAM controller driver for the R528/T113s SoCs.
++
++if DRAM_SUN20I_D1 || DRAM_SUN8I_R528
++
++config DRAM_SUNXI_ODT_EN
++ hex "DRAM ODT EN parameter"
++ default 0x1
++ help
++ ODT EN value from vendor DRAM settings.
++
++config DRAM_SUNXI_TPR0
++ hex "DRAM TPR0 parameter"
++ default 0x0
++ help
++ TPR0 value from vendor DRAM settings.
++
++config DRAM_SUNXI_TPR11
++ hex "DRAM TPR11 parameter"
++ default 0x0
++ help
++ TPR11 value from vendor DRAM settings.
++
++config DRAM_SUNXI_TPR12
++ hex "DRAM TPR12 parameter"
++ default 0x0
++ help
++ TPR12 value from vendor DRAM settings.
++
++config DRAM_SUNXI_TPR13
++ hex "DRAM TPR13 parameter"
++ default 0x0
++ help
++ TPR13 value from vendor DRAM settings. It tells which features
++ should be configured.
++
++choice
++ prompt "DRAM chip type"
++ default SUNXI_DRAM_TYPE_DDR3 if DRAM_SUN8I_R528 || DRAM_SUN20I_D1
++
++config SUNXI_DRAM_TYPE_DDR2
++ bool "DDR2 chips"
++
++config SUNXI_DRAM_TYPE_DDR3
++ bool "DDR3 chips"
++
++config SUNXI_DRAM_TYPE_LPDDR2
++ bool "LPDDR2 chips"
++
++config SUNXI_DRAM_TYPE_LPDDR3
++ bool "LPDDR3 chips"
++endchoice
++
++config SUNXI_DRAM_TYPE
++ int
++ default 2 if SUNXI_DRAM_TYPE_DDR2
++ default 3 if SUNXI_DRAM_TYPE_DDR3
++ default 6 if SUNXI_DRAM_TYPE_LPDDR2
++ default 7 if SUNXI_DRAM_TYPE_LPDDR3
++
++endif
+diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
+new file mode 100644
+index 0000000000..d6fb2cf0b6
+--- /dev/null
++++ b/drivers/ram/sunxi/Makefile
+@@ -0,0 +1,4 @@
++# SPDX-License-Identifier: GPL-2.0+
++
++obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
++obj-$(CONFIG_DRAM_SUN8I_R528) += dram_sun20i_d1.o
+diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
+new file mode 100644
+index 0000000000..c766fc2406
+--- /dev/null
++++ b/drivers/ram/sunxi/dram_sun20i_d1.c
+@@ -0,0 +1,1432 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Allwinner D1/D1s/R528/T113-sx DRAM initialisation
++ *
++ * As usual there is no documentation for the memory controller or PHY IP
++ * used here. The baseline of this code was lifted from awboot[1], which
++ * seems to be based on some form of de-compilation of some original Allwinner
++ * code bits (with a GPL2 license tag from the very beginning).
++ * This version here is a reworked version, to match the U-Boot coding style
++ * and style of the other Allwinner DRAM drivers.
++ *
++ * [1] https://github.com/szemzoa/awboot.git
++ */
++
++#include <asm/io.h>
++#include <common.h>
++#ifdef CONFIG_RAM
++ #include <dm.h>
++ #include <ram.h>
++#endif
++#include <linux/delay.h>
++
++#include "dram_sun20i_d1.h"
++
++#ifndef SUNXI_SID_BASE
++#define SUNXI_SID_BASE 0x3006200
++#endif
++
++#ifndef SUNXI_CCM_BASE
++#define SUNXI_CCM_BASE 0x2001000
++#endif
++
++static void sid_read_ldoB_cal(const dram_para_t *para)
++{
++ uint32_t reg;
++
++ reg = (readl(SUNXI_SID_BASE + 0x1c) & 0xff00) >> 8;
++
++ if (reg == 0)
++ return;
++
++ switch (para->dram_type) {
++ case SUNXI_DRAM_TYPE_DDR2:
++ break;
++ case SUNXI_DRAM_TYPE_DDR3:
++ if (reg > 0x20)
++ reg -= 0x16;
++ break;
++ default:
++ reg = 0;
++ break;
++ }
++
++ clrsetbits_le32(0x3000150, 0xff00, reg << 8);
++}
++
++static void dram_voltage_set(const dram_para_t *para)
++{
++ int vol;
++
++ switch (para->dram_type) {
++ case SUNXI_DRAM_TYPE_DDR2:
++ vol = 47;
++ break;
++ case SUNXI_DRAM_TYPE_DDR3:
++ vol = 25;
++ break;
++ default:
++ vol = 0;
++ break;
++ }
++
++ clrsetbits_le32(0x3000150, 0x20ff00, vol << 8);
++
++ udelay(1);
++
++ sid_read_ldoB_cal(para);
++}
++
++static void dram_enable_all_master(void)
++{
++ writel(~0, 0x3102020);
++ writel(0xff, 0x3102024);
++ writel(0xffff, 0x3102028);
++ udelay(10);
++}
++
++static void dram_disable_all_master(void)
++{
++ writel(1, 0x3102020);
++ writel(0, 0x3102024);
++ writel(0, 0x3102028);
++ udelay(10);
++}
++
++static void eye_delay_compensation(const dram_para_t *para)
++{
++ uint32_t delay;
++ unsigned long ptr;
++
++ // DATn0IOCR, n = 0...7
++ delay = (para->dram_tpr11 & 0xf) << 9;
++ delay |= (para->dram_tpr12 & 0xf) << 1;
++ for (ptr = 0x3103310; ptr < 0x3103334; ptr += 4)
++ setbits_le32(ptr, delay);
++
++ // DATn1IOCR, n = 0...7
++ delay = (para->dram_tpr11 & 0xf0) << 5;
++ delay |= (para->dram_tpr12 & 0xf0) >> 3;
++ for (ptr = 0x3103390; ptr != 0x31033b4; ptr += 4)
++ setbits_le32(ptr, delay);
++
++ // PGCR0: assert AC loopback FIFO reset
++ clrbits_le32(0x3103100, 0x04000000);
++
++ // ??
++
++ delay = (para->dram_tpr11 & 0xf0000) >> 7;
++ delay |= (para->dram_tpr12 & 0xf0000) >> 15;
++ setbits_le32(0x3103334, delay);
++ setbits_le32(0x3103338, delay);
++
++ delay = (para->dram_tpr11 & 0xf00000) >> 11;
++ delay |= (para->dram_tpr12 & 0xf00000) >> 19;
++ setbits_le32(0x31033b4, delay);
++ setbits_le32(0x31033b8, delay);
++
++ setbits_le32(0x310333c, (para->dram_tpr11 & 0xf0000) << 9);
++ setbits_le32(0x31033bc, (para->dram_tpr11 & 0xf00000) << 5);
++
++ // PGCR0: release AC loopback FIFO reset
++ setbits_le32(0x3103100, BIT(26));
++
++ udelay(1);
++
++ delay = (para->dram_tpr10 & 0xf0) << 4;
++ for (ptr = 0x3103240; ptr != 0x310327c; ptr += 4)
++ setbits_le32(ptr, delay);
++ for (ptr = 0x3103228; ptr != 0x3103240; ptr += 4)
++ setbits_le32(ptr, delay);
++
++ setbits_le32(0x3103218, (para->dram_tpr10 & 0x0f) << 8);
++ setbits_le32(0x310321c, (para->dram_tpr10 & 0x0f) << 8);
++
++ setbits_le32(0x3103280, (para->dram_tpr10 & 0xf00) >> 4);
++}
++
++/*
++ * Main purpose of the auto_set_timing routine seems to be to calculate all
++ * timing settings for the specific type of sdram used. Read together with
++ * an sdram datasheet for context on the various variables.
++ */
++static void mctl_set_timing_params(const dram_para_t *para,
++ const dram_config_t *config)
++{
++ /* DRAM_TPR0 */
++ u8 tccd = 2;
++ u8 tfaw;
++ u8 trrd;
++ u8 trcd;
++ u8 trc;
++
++ /* DRAM_TPR1 */
++ u8 txp;
++ u8 twtr;
++ u8 trtp = 4;
++ u8 twr;
++ u8 trp;
++ u8 tras;
++
++ /* DRAM_TPR2 */
++ u16 trefi;
++ u16 trfc;
++
++ u8 tcksrx;
++ u8 tckesr;
++ u8 trd2wr;
++ u8 twr2rd;
++ u8 trasmax;
++ u8 twtp;
++ u8 tcke;
++ u8 tmod;
++ u8 tmrd;
++ u8 tmrw;
++
++ u8 tcl;
++ u8 tcwl;
++ u8 t_rdata_en;
++ u8 wr_latency;
++
++ u32 mr0;
++ u32 mr1;
++ u32 mr2;
++ u32 mr3;
++
++ u32 tdinit0;
++ u32 tdinit1;
++ u32 tdinit2;
++ u32 tdinit3;
++
++ switch (para->dram_type) {
++ case SUNXI_DRAM_TYPE_DDR2:
++ /* DRAM_TPR0 */
++ tfaw = ns_to_t(50);
++ trrd = ns_to_t(10);
++ trcd = ns_to_t(20);
++ trc = ns_to_t(65);
++
++ /* DRAM_TPR1 */
++ txp = 2;
++ twtr = ns_to_t(8);
++ twr = ns_to_t(15);
++ trp = ns_to_t(15);
++ tras = ns_to_t(45);
++
++ /* DRAM_TRP2 */
++ trfc = ns_to_t(328);
++ trefi = ns_to_t(7800) / 32;
++
++ trasmax = CONFIG_DRAM_CLK / 30;
++ if (CONFIG_DRAM_CLK < 409) {
++ t_rdata_en = 1;
++ tcl = 3;
++ mr0 = 0x06a3;
++ } else {
++ t_rdata_en = 2;
++ tcl = 4;
++ mr0 = 0x0e73;
++ }
++ tmrd = 2;
++ twtp = twr + 5;
++ tcksrx = 5;
++ tckesr = 4;
++ trd2wr = 4;
++ tcke = 3;
++ tmod = 12;
++ wr_latency = 1;
++ tmrw = 0;
++ twr2rd = twtr + 5;
++ tcwl = 0;
++
++ mr1 = para->dram_mr1;
++ mr2 = 0;
++ mr3 = 0;
++
++ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
++ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
++ tdinit2 = 200 * CONFIG_DRAM_CLK + 1;
++ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
++
++ break;
++ case SUNXI_DRAM_TYPE_DDR3:
++ trfc = ns_to_t(350);
++ trefi = ns_to_t(7800) / 32 + 1; // XXX
++
++ twtr = ns_to_t(8) + 2; // + 2 ? XXX
++ /* Only used by trd2wr calculation, which gets discard below */
++// twr = max(ns_to_t(15), 2);
++ trrd = max(ns_to_t(10), 2);
++ txp = max(ns_to_t(10), 2);
++
++ if (CONFIG_DRAM_CLK <= 800) {
++ tfaw = ns_to_t(50);
++ trcd = ns_to_t(15);
++ trp = ns_to_t(15);
++ trc = ns_to_t(53);
++ tras = ns_to_t(38);
++
++ mr0 = 0x1c70;
++ mr2 = 0x18;
++ tcl = 6;
++ wr_latency = 2;
++ tcwl = 4;
++ t_rdata_en = 4;
++ } else {
++ tfaw = ns_to_t(35);
++ trcd = ns_to_t(14);
++ trp = ns_to_t(14);
++ trc = ns_to_t(48);
++ tras = ns_to_t(34);
++
++ mr0 = 0x1e14;
++ mr2 = 0x20;
++ tcl = 7;
++ wr_latency = 3;
++ tcwl = 5;
++ t_rdata_en = 5;
++ }
++
++ trasmax = CONFIG_DRAM_CLK / 30;
++ twtp = tcwl + 2 + twtr; // WL+BL/2+tWTR
++ /* Gets overwritten below */
++// trd2wr = tcwl + 2 + twr; // WL+BL/2+tWR
++ twr2rd = tcwl + twtr; // WL+tWTR
++
++ tdinit0 = 500 * CONFIG_DRAM_CLK + 1; // 500 us
++ tdinit1 = 360 * CONFIG_DRAM_CLK / 1000 + 1; // 360 ns
++ tdinit2 = 200 * CONFIG_DRAM_CLK + 1; // 200 us
++ tdinit3 = 1 * CONFIG_DRAM_CLK + 1; // 1 us
++
++ mr1 = para->dram_mr1;
++ mr3 = 0;
++ tcke = 3;
++ tcksrx = 5;
++ tckesr = 4;
++ if (((config->dram_tpr13 & 0xc) == 0x04) || CONFIG_DRAM_CLK < 912)
++ trd2wr = 5;
++ else
++ trd2wr = 6;
++
++ tmod = 12;
++ tmrd = 4;
++ tmrw = 0;
++
++ break;
++ case SUNXI_DRAM_TYPE_LPDDR2:
++ tfaw = max(ns_to_t(50), 4);
++ trrd = max(ns_to_t(10), 1);
++ trcd = max(ns_to_t(24), 2);
++ trc = ns_to_t(70);
++ txp = ns_to_t(8);
++ if (txp < 2) {
++ txp++;
++ twtr = 2;
++ } else {
++ twtr = txp;
++ }
++ twr = max(ns_to_t(15), 2);
++ trp = ns_to_t(17);
++ tras = ns_to_t(42);
++ trefi = ns_to_t(3900) / 32;
++ trfc = ns_to_t(210);
++
++ trasmax = CONFIG_DRAM_CLK / 60;
++ mr3 = para->dram_mr3;
++ twtp = twr + 5;
++ mr2 = 6;
++ mr1 = 5;
++ tcksrx = 5;
++ tckesr = 5;
++ trd2wr = 10;
++ tcke = 2;
++ tmod = 5;
++ tmrd = 5;
++ tmrw = 3;
++ tcl = 4;
++ wr_latency = 1;
++ t_rdata_en = 1;
++
++ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
++ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
++ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
++ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
++ twr2rd = twtr + 5;
++ tcwl = 2;
++ mr1 = 195;
++ mr0 = 0;
++
++ break;
++ case SUNXI_DRAM_TYPE_LPDDR3:
++ tfaw = max(ns_to_t(50), 4);
++ trrd = max(ns_to_t(10), 1);
++ trcd = max(ns_to_t(24), 2);
++ trc = ns_to_t(70);
++ twtr = max(ns_to_t(8), 2);
++ twr = max(ns_to_t(15), 2);
++ trp = ns_to_t(17);
++ tras = ns_to_t(42);
++ trefi = ns_to_t(3900) / 32;
++ trfc = ns_to_t(210);
++ txp = twtr;
++
++ trasmax = CONFIG_DRAM_CLK / 60;
++ if (CONFIG_DRAM_CLK < 800) {
++ tcwl = 4;
++ wr_latency = 3;
++ t_rdata_en = 6;
++ mr2 = 12;
++ } else {
++ tcwl = 3;
++ tcke = 6;
++ wr_latency = 2;
++ t_rdata_en = 5;
++ mr2 = 10;
++ }
++ twtp = tcwl + 5;
++ tcl = 7;
++ mr3 = para->dram_mr3;
++ tcksrx = 5;
++ tckesr = 5;
++ trd2wr = 13;
++ tcke = 3;
++ tmod = 12;
++ tdinit0 = 400 * CONFIG_DRAM_CLK + 1;
++ tdinit1 = 500 * CONFIG_DRAM_CLK / 1000 + 1;
++ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
++ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
++ tmrd = 5;
++ tmrw = 5;
++ twr2rd = tcwl + twtr + 5;
++ mr1 = 195;
++ mr0 = 0;
++
++ break;
++ default:
++ trfc = 128;
++ trp = 6;
++ trefi = 98;
++ txp = 10;
++ twr = 8;
++ twtr = 3;
++ tras = 14;
++ tfaw = 16;
++ trc = 20;
++ trcd = 6;
++ trrd = 3;
++
++ twr2rd = 8;
++ tcksrx = 4;
++ tckesr = 3;
++ trd2wr = 4;
++ trasmax = 27;
++ twtp = 12;
++ tcke = 2;
++ tmod = 6;
++ tmrd = 2;
++ tmrw = 0;
++ tcwl = 3;
++ tcl = 3;
++ wr_latency = 1;
++ t_rdata_en = 1;
++ mr3 = 0;
++ mr2 = 0;
++ mr1 = 0;
++ mr0 = 0;
++ tdinit3 = 0;
++ tdinit2 = 0;
++ tdinit1 = 0;
++ tdinit0 = 0;
++
++ break;
++ }
++
++ /* Set mode registers */
++ writel(mr0, 0x3103030);
++ writel(mr1, 0x3103034);
++ writel(mr2, 0x3103038);
++ writel(mr3, 0x310303c);
++ /* TODO: dram_odt_en is either 0x0 or 0x1, so right shift looks weird */
++ writel((para->dram_odt_en >> 4) & 0x3, 0x310302c);
++
++ /* Set dram timing DRAMTMG0 - DRAMTMG5 */
++ writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0),
++ 0x3103058);
++ writel((txp << 16) | (trtp << 8) | (trc << 0),
++ 0x310305c);
++ writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0),
++ 0x3103060);
++ writel((tmrw << 16) | (tmrd << 12) | (tmod << 0),
++ 0x3103064);
++ writel((trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0),
++ 0x3103068);
++ writel((tcksrx << 24) | (tcksrx << 16) | (tckesr << 8) | (tcke << 0),
++ 0x310306c);
++
++ /* Set dual rank timing */
++ clrsetbits_le32(0x3103078, 0xf000ffff,
++ (CONFIG_DRAM_CLK < 800) ? 0xf0006610 : 0xf0007610);
++
++ /* Set phy interface time PITMG0, PTR3, PTR4 */
++ writel((0x2 << 24) | (t_rdata_en << 16) | BIT(8) | (wr_latency << 0),
++ 0x3103080);
++ writel(((tdinit0 << 0) | (tdinit1 << 20)), 0x3103050);
++ writel(((tdinit2 << 0) | (tdinit3 << 20)), 0x3103054);
++
++ /* Set refresh timing and mode */
++ writel((trefi << 16) | (trfc << 0), 0x3103090);
++ writel((trefi << 15) & 0x0fff0000, 0x3103094);
++}
++
++// Purpose of this routine seems to be to initialize the PLL driving
++// the MBUS and sdram.
++//
++static int ccu_set_pll_ddr_clk(int index, const dram_para_t *para,
++ const dram_config_t *config)
++{
++ unsigned int val, clk, n;
++
++ if (config->dram_tpr13 & BIT(6))
++ clk = para->dram_tpr9;
++ else
++ clk = para->dram_clk;
++
++ // set VCO clock divider
++ n = (clk * 2) / 24;
++
++ val = readl(SUNXI_CCM_BASE + 0x10);
++ val &= ~0x0007ff03; // clear dividers
++ val |= (n - 1) << 8; // set PLL division
++ val |= BIT(31) | BIT(30); // enable PLL and LDO
++ writel(val | BIT(29), SUNXI_CCM_BASE + 0x10);
++
++ // wait for PLL to lock
++ while ((readl(SUNXI_CCM_BASE + 0x10) & BIT(28)) == 0)
++ ;
++
++ udelay(20);
++
++ // enable PLL output
++ setbits_le32(SUNXI_CCM_BASE + 0x0, BIT(27));
++
++ // turn clock gate on
++ val = readl(SUNXI_CCM_BASE + 0x800);
++ val &= ~0x03000303; // select DDR clk source, n=1, m=1
++ val |= BIT(31); // turn clock on
++ writel(val, SUNXI_CCM_BASE + 0x800);
++
++ return n * 24;
++}
++
++/* Set up the PLL and clock gates for the DRAM controller and MBUS clocks. */
++static void mctl_sys_init(const dram_para_t *para, const dram_config_t *config)
++{
++ // assert MBUS reset
++ clrbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
++
++ // turn off sdram clock gate, assert sdram reset
++ clrbits_le32(SUNXI_CCM_BASE + 0x80c, 0x10001);
++ clrsetbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(30), BIT(27));
++ udelay(10);
++
++ // set ddr pll clock
++ ccu_set_pll_ddr_clk(0, para, config);
++ udelay(100);
++ dram_disable_all_master();
++
++ // release sdram reset
++ setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(16));
++
++ // release MBUS reset
++ setbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
++ setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(30));
++
++ udelay(5);
++
++ // turn on sdram clock gate
++ setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(0));
++
++ // turn dram clock gate on, trigger sdr clock update
++ setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(27));
++ udelay(5);
++
++ // mCTL clock enable
++ writel(0x8000, 0x310300c);
++ udelay(10);
++}
++
++// The main purpose of this routine seems to be to copy an address configuration
++// from the dram_para1 and dram_para2 fields to the PHY configuration registers
++// (0x3102000, 0x3102004).
++//
++static void mctl_com_init(const dram_para_t *para, const dram_config_t *config)
++{
++ uint32_t val, width;
++ unsigned long ptr;
++ int i;
++
++ // purpose ??
++ clrsetbits_le32(0x3102008, 0x3f00, 0x2000);
++
++ // set SDRAM type and word width
++ val = readl(0x3102000) & ~0x00fff000;
++ val |= (para->dram_type & 0x7) << 16; // DRAM type
++ val |= (~config->dram_para2 & 0x1) << 12; // DQ width
++ val |= BIT(22); // ??
++ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
++ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
++ val |= BIT(19); // type 6 and 7 must use 1T
++ } else {
++ if (config->dram_tpr13 & BIT(5))
++ val |= BIT(19);
++ }
++ writel(val, 0x3102000);
++
++ // init rank / bank / row for single/dual or two different ranks
++ if ((config->dram_para2 & BIT(8)) &&
++ ((config->dram_para2 & 0xf000) != 0x1000))
++ width = 32;
++ else
++ width = 16;
++
++ ptr = 0x3102000;
++ for (i = 0; i < width; i += 16) {
++ val = readl(ptr) & 0xfffff000;
++
++ val |= (config->dram_para2 >> 12) & 0x3; // rank
++ val |= ((config->dram_para1 >> (i + 12)) << 2) & 0x4; // bank - 2
++ val |= (((config->dram_para1 >> (i + 4)) - 1) << 4) & 0xff; // row - 1
++
++ // convert from page size to column addr width - 3
++ switch ((config->dram_para1 >> i) & 0xf) {
++ case 8: val |= 0xa00; break;
++ case 4: val |= 0x900; break;
++ case 2: val |= 0x800; break;
++ case 1: val |= 0x700; break;
++ default: val |= 0x600; break;
++ }
++ writel(val, ptr);
++ ptr += 4;
++ }
++
++ // set ODTMAP based on number of ranks in use
++ val = (readl(0x3102000) & 0x1) ? 0x303 : 0x201;
++ writel(val, 0x3103120);
++
++ // set mctl reg 3c4 to zero when using half DQ
++ if (config->dram_para2 & BIT(0))
++ writel(0, 0x31033c4);
++
++ // purpose ??
++ if (para->dram_tpr4) {
++ setbits_le32(0x3102000, (para->dram_tpr4 & 0x3) << 25);
++ setbits_le32(0x3102004, (para->dram_tpr4 & 0x7fc) << 10);
++ }
++}
++
++static const uint8_t ac_remapping_tables[][22] = {
++ [0] = { 0 },
++ [1] = { 1, 9, 3, 7, 8, 18, 4, 13, 5, 6, 10,
++ 2, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
++ [2] = { 4, 9, 3, 7, 8, 18, 1, 13, 2, 6, 10,
++ 5, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
++ [3] = { 1, 7, 8, 12, 10, 18, 4, 13, 5, 6, 3,
++ 2, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
++ [4] = { 4, 12, 10, 7, 8, 18, 1, 13, 2, 6, 3,
++ 5, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
++ [5] = { 13, 2, 7, 9, 12, 19, 5, 1, 6, 3, 4,
++ 8, 10, 0, 0, 0, 21, 22, 18, 17, 11, 20 },
++ [6] = { 3, 10, 7, 13, 9, 11, 1, 2, 4, 6, 8,
++ 5, 12, 0, 0, 0, 20, 1, 0, 21, 22, 17 },
++ [7] = { 3, 2, 4, 7, 9, 1, 17, 12, 18, 14, 13,
++ 8, 15, 6, 10, 5, 19, 22, 16, 21, 20, 11 },
++};
++
++/*
++ * This routine chooses one of several remapping tables for 22 lines.
++ * It is unclear which lines are being remapped. It seems to pick
++ * table cfg7 for the Nezha board.
++ */
++static void mctl_phy_ac_remapping(const dram_para_t *para,
++ const dram_config_t *config)
++{
++ const uint8_t *cfg;
++ uint32_t fuse, val;
++
++ /*
++ * It is unclear whether the LPDDRx types don't need any remapping,
++ * or whether the original code just didn't provide tables.
++ */
++ if (para->dram_type != SUNXI_DRAM_TYPE_DDR2 &&
++ para->dram_type != SUNXI_DRAM_TYPE_DDR3)
++ return;
++
++ fuse = (readl(SUNXI_SID_BASE + 0x28) & 0xf00) >> 8;
++ debug("DDR efuse: 0x%x\n", fuse);
++
++ if (para->dram_type == SUNXI_DRAM_TYPE_DDR2) {
++ if (fuse == 15)
++ return;
++ cfg = ac_remapping_tables[6];
++ } else {
++ if (config->dram_tpr13 & 0xc0000) {
++ cfg = ac_remapping_tables[7];
++ } else {
++ switch (fuse) {
++ case 8: cfg = ac_remapping_tables[2]; break;
++ case 9: cfg = ac_remapping_tables[3]; break;
++ case 10: cfg = ac_remapping_tables[5]; break;
++ case 11: cfg = ac_remapping_tables[4]; break;
++ default:
++ case 12: cfg = ac_remapping_tables[1]; break;
++ case 13:
++ case 14: cfg = ac_remapping_tables[0]; break;
++ }
++ }
++ }
++
++ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
++ (cfg[1] << 10) | (cfg[0] << 5);
++ writel(val, 0x3102500);
++
++ val = (cfg[10] << 25) | (cfg[9] << 20) | (cfg[8] << 15) |
++ (cfg[ 7] << 10) | (cfg[6] << 5) | cfg[5];
++ writel(val, 0x3102504);
++
++ val = (cfg[15] << 20) | (cfg[14] << 15) | (cfg[13] << 10) |
++ (cfg[12] << 5) | cfg[11];
++ writel(val, 0x3102508);
++
++ val = (cfg[21] << 25) | (cfg[20] << 20) | (cfg[19] << 15) |
++ (cfg[18] << 10) | (cfg[17] << 5) | cfg[16];
++ writel(val, 0x310250c);
++
++ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
++ (cfg[1] << 10) | (cfg[0] << 5) | 1;
++ writel(val, 0x3102500);
++}
++
++// Init the controller channel. The key part is placing commands in the main
++// command register (PIR, 0x3103000) and checking command status (PGSR0, 0x3103010).
++//
++static unsigned int mctl_channel_init(unsigned int ch_index,
++ const dram_para_t *para,
++ const dram_config_t *config)
++{
++ unsigned int val, dqs_gating_mode;
++
++ dqs_gating_mode = (config->dram_tpr13 & 0xc) >> 2;
++
++ // set DDR clock to half of CPU clock
++ clrsetbits_le32(0x310200c, 0xfff, (para->dram_clk / 2) - 1);
++
++ // MRCTRL0 nibble 3 undocumented
++ clrsetbits_le32(0x3103108, 0xf00, 0x300);
++
++ if (para->dram_odt_en)
++ val = 0;
++ else
++ val = BIT(5);
++
++ // DX0GCR0
++ if (para->dram_clk > 672)
++ clrsetbits_le32(0x3103344, 0xf63e, val);
++ else
++ clrsetbits_le32(0x3103344, 0xf03e, val);
++
++ // DX1GCR0
++ if (para->dram_clk > 672) {
++ setbits_le32(0x3103344, 0x400);
++ clrsetbits_le32(0x31033c4, 0xf63e, val);
++ } else {
++ clrsetbits_le32(0x31033c4, 0xf03e, val);
++ }
++
++ // 0x3103208 undocumented
++ setbits_le32(0x3103208, BIT(1));
++
++ eye_delay_compensation(para);
++
++ // set PLL SSCG ?
++ val = readl(0x3103108);
++ if (dqs_gating_mode == 1) {
++ clrsetbits_le32(0x3103108, 0xc0, 0);
++ clrbits_le32(0x31030bc, 0x107);
++ } else if (dqs_gating_mode == 2) {
++ clrsetbits_le32(0x3103108, 0xc0, 0x80);
++
++ clrsetbits_le32(0x31030bc, 0x107,
++ (((config->dram_tpr13 >> 16) & 0x1f) - 2) | 0x100);
++ clrsetbits_le32(0x310311c, BIT(31), BIT(27));
++ } else {
++ clrbits_le32(0x3103108, 0x40);
++ udelay(10);
++ setbits_le32(0x3103108, 0xc0);
++ }
++
++ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
++ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
++ if (dqs_gating_mode == 1)
++ clrsetbits_le32(0x310311c, 0x080000c0, 0x80000000);
++ else
++ clrsetbits_le32(0x310311c, 0x77000000, 0x22000000);
++ }
++
++ clrsetbits_le32(0x31030c0, 0x0fffffff,
++ (config->dram_para2 & BIT(12)) ? 0x03000001 : 0x01000007);
++
++ if (readl(0x70005d4) & BIT(16)) {
++ clrbits_le32(0x7010250, 0x2);
++ udelay(10);
++ }
++
++ // Set ZQ config
++ clrsetbits_le32(0x3103140, 0x3ffffff,
++ (para->dram_zq & 0x00ffffff) | BIT(25));
++
++ // Initialise DRAM controller
++ if (dqs_gating_mode == 1) {
++ //writel(0x52, 0x3103000); // prep PHY reset + PLL init + z-cal
++ writel(0x53, 0x3103000); // Go
++
++ while ((readl(0x3103010) & 0x1) == 0) {
++ } // wait for IDONE
++ udelay(10);
++
++ // 0x520 = prep DQS gating + DRAM init + d-cal
++ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
++ writel(0x5a0, 0x3103000); // + DRAM reset
++ else
++ writel(0x520, 0x3103000);
++ } else {
++ if ((readl(0x70005d4) & (1 << 16)) == 0) {
++ // prep DRAM init + PHY reset + d-cal + PLL init + z-cal
++ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
++ writel(0x1f2, 0x3103000); // + DRAM reset
++ else
++ writel(0x172, 0x3103000);
++ } else {
++ // prep PHY reset + d-cal + z-cal
++ writel(0x62, 0x3103000);
++ }
++ }
++
++ setbits_le32(0x3103000, 0x1); // GO
++
++ udelay(10);
++ while ((readl(0x3103010) & 0x1) == 0) {
++ } // wait for IDONE
++
++ if (readl(0x70005d4) & BIT(16)) {
++ clrsetbits_le32(0x310310c, 0x06000000, 0x04000000);
++ udelay(10);
++
++ setbits_le32(0x3103004, 0x1);
++
++ while ((readl(0x3103018) & 0x7) != 0x3) {
++ }
++
++ clrbits_le32(0x7010250, 0x1);
++ udelay(10);
++
++ clrbits_le32(0x3103004, 0x1);
++
++ while ((readl(0x3103018) & 0x7) != 0x1) {
++ }
++
++ udelay(15);
++
++ if (dqs_gating_mode == 1) {
++ clrbits_le32(0x3103108, 0xc0);
++ clrsetbits_le32(0x310310c, 0x06000000, 0x02000000);
++ udelay(1);
++ writel(0x401, 0x3103000);
++
++ while ((readl(0x3103010) & 0x1) == 0) {
++ }
++ }
++ }
++
++ // Check for training error
++ if (readl(0x3103010) & BIT(20)) {
++ printf("ZQ calibration error, check external 240 ohm resistor\n");
++ return 0;
++ }
++
++ // STATR = Zynq STAT? Wait for status 'normal'?
++ while ((readl(0x3103018) & 0x1) == 0) {
++ }
++
++ setbits_le32(0x310308c, BIT(31));
++ udelay(10);
++ clrbits_le32(0x310308c, BIT(31));
++ udelay(10);
++ setbits_le32(0x3102014, BIT(31));
++ udelay(10);
++
++ clrbits_le32(0x310310c, 0x06000000);
++
++ if (dqs_gating_mode == 1)
++ clrsetbits_le32(0x310311c, 0xc0, 0x40);
++
++ return 1;
++}
++
++static unsigned int calculate_rank_size(uint32_t regval)
++{
++ unsigned int bits;
++
++ bits = (regval >> 8) & 0xf; /* page size - 3 */
++ bits += (regval >> 4) & 0xf; /* row width - 1 */
++ bits += (regval >> 2) & 0x3; /* bank count - 2 */
++ bits -= 14; /* 1MB = 20 bits, minus above 6 = 14 */
++
++ return 1U << bits;
++}
++
++/*
++ * The below routine reads the dram config registers and extracts
++ * the number of address bits in each rank available. It then calculates
++ * total memory size in MB.
++ */
++static unsigned int DRAMC_get_dram_size(void)
++{
++ uint32_t val;
++ unsigned int size;
++
++ val = readl(0x3102000); /* MC_WORK_MODE0 */
++ size = calculate_rank_size(val);
++ if ((val & 0x3) == 0) /* single rank? */
++ return size;
++
++ val = readl(0x3102004); /* MC_WORK_MODE1 */
++ if ((val & 0x3) == 0) /* two identical ranks? */
++ return size * 2;
++
++ /* add sizes of both ranks */
++ return size + calculate_rank_size(val);
++}
++
++/*
++ * The below routine reads the command status register to extract
++ * DQ width and rank count. This follows the DQS training command in
++ * channel_init. If error bit 22 is reset, we have two ranks and full DQ.
++ * If there was an error, figure out whether it was half DQ, single rank,
++ * or both. Set bit 12 and 0 in dram_para2 with the results.
++ */
++static int dqs_gate_detect(dram_config_t *config)
++{
++ uint32_t dx0, dx1;
++
++ if ((readl(0x3103010) & BIT(22)) == 0) {
++ config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
++ debug("dual rank and full DQ\n");
++
++ return 1;
++ }
++
++ dx0 = (readl(0x3103348) & 0x3000000) >> 24;
++ if (dx0 == 0) {
++ config->dram_para2 = (config->dram_para2 & ~0xf) | 0x1001;
++ debug("dual rank and half DQ\n");
++
++ return 1;
++ }
++
++ if (dx0 == 2) {
++ dx1 = (readl(0x31033c8) & 0x3000000) >> 24;
++ if (dx1 == 2) {
++ config->dram_para2 = config->dram_para2 & ~0xf00f;
++ debug("single rank and full DQ\n");
++ } else {
++ config->dram_para2 = (config->dram_para2 & ~0xf00f) | BIT(0);
++ debug("single rank and half DQ\n");
++ }
++
++ return 1;
++ }
++
++ if ((config->dram_tpr13 & BIT(29)) == 0)
++ return 0;
++
++ debug("DX0 state: %d\n", dx0);
++ debug("DX1 state: %d\n", dx1);
++
++ return 0;
++}
++
++static int dramc_simple_wr_test(unsigned int mem_mb, int len)
++{
++ unsigned int offs = (mem_mb / 2) << 18; // half of memory size
++ unsigned int patt1 = 0x01234567;
++ unsigned int patt2 = 0xfedcba98;
++ unsigned int *addr, v1, v2, i;
++
++ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
++ for (i = 0; i != len; i++, addr++) {
++ writel(patt1 + i, (unsigned long)addr);
++ writel(patt2 + i, (unsigned long)(addr + offs));
++ }
++
++ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
++ for (i = 0; i != len; i++) {
++ v1 = readl((unsigned long)(addr + i));
++ v2 = patt1 + i;
++ if (v1 != v2) {
++ printf("DRAM: simple test FAIL\n");
++ printf("%x != %x at address %p\n", v1, v2, addr + i);
++ return 1;
++ }
++ v1 = readl((unsigned long)(addr + offs + i));
++ v2 = patt2 + i;
++ if (v1 != v2) {
++ printf("DRAM: simple test FAIL\n");
++ printf("%x != %x at address %p\n", v1, v2, addr + offs + i);
++ return 1;
++ }
++ }
++
++ debug("DRAM: simple test OK\n");
++ return 0;
++}
++
++// Set the Vref mode for the controller
++//
++static void mctl_vrefzq_init(const dram_para_t *para, const dram_config_t *config)
++{
++ if (config->dram_tpr13 & BIT(17))
++ return;
++
++ clrsetbits_le32(0x3103110, 0x7f7f7f7f, para->dram_tpr5);
++
++ // IOCVR1
++ if ((config->dram_tpr13 & BIT(16)) == 0)
++ clrsetbits_le32(0x3103114, 0x7f, para->dram_tpr6 & 0x7f);
++}
++
++// Perform an init of the controller. This is actually done 3 times. The first
++// time to establish the number of ranks and DQ width. The second time to
++// establish the actual ram size. The third time is final one, with the final
++// settings.
++//
++static int mctl_core_init(const dram_para_t *para, const dram_config_t *config)
++{
++ mctl_sys_init(para, config);
++
++ mctl_vrefzq_init(para, config);
++
++ mctl_com_init(para, config);
++
++ mctl_phy_ac_remapping(para, config);
++
++ mctl_set_timing_params(para, config);
++
++ return mctl_channel_init(0, para, config);
++}
++
++/*
++ * This routine sizes a DRAM device by cycling through address lines and
++ * figuring out if they are connected to a real address line, or if the
++ * address is a mirror.
++ * First the column and bank bit allocations are set to low values (2 and 9
++ * address lines). Then a maximum allocation (16 lines) is set for rows and
++ * this is tested.
++ * Next the BA2 line is checked. This seems to be placed above the column,
++ * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
++ * and these are tested. The results are placed in dram_para1 and dram_para2.
++ */
++static int auto_scan_dram_size(const dram_para_t *para, dram_config_t *config)
++{
++ unsigned int rval, i, j, rank, maxrank, offs;
++ unsigned int shft;
++ unsigned long ptr, mc_work_mode, chk;
++
++ if (mctl_core_init(para, config) == 0) {
++ printf("DRAM initialisation error : 0\n");
++ return 0;
++ }
++
++ maxrank = (config->dram_para2 & 0xf000) ? 2 : 1;
++ mc_work_mode = 0x3102000;
++ offs = 0;
++
++ /* write test pattern */
++ for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
++ writel((i & 0x1) ? ptr : ~ptr, ptr);
++
++ for (rank = 0; rank < maxrank;) {
++ /* set row mode */
++ clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
++ udelay(1);
++
++ // Scan per address line, until address wraps (i.e. see shadow)
++ for (i = 11; i < 17; i++) {
++ chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
++ ptr = CFG_SYS_SDRAM_BASE;
++ for (j = 0; j < 64; j++) {
++ if (readl(chk) != ((j & 1) ? ptr : ~ptr))
++ break;
++ ptr += 4;
++ chk += 4;
++ }
++ if (j == 64)
++ break;
++ }
++ if (i > 16)
++ i = 16;
++ debug("rank %d row = %d\n", rank, i);
++
++ /* Store rows in para 1 */
++ shft = offs + 4;
++ rval = config->dram_para1;
++ rval &= ~(0xff << shft);
++ rval |= i << shft;
++ config->dram_para1 = rval;
++
++ if (rank == 1) /* Set bank mode for rank0 */
++ clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
++
++ /* Set bank mode for current rank */
++ clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
++ udelay(1);
++
++ // Test if bit A23 is BA2 or mirror XXX A22?
++ chk = CFG_SYS_SDRAM_BASE + (1U << 22);
++ ptr = CFG_SYS_SDRAM_BASE;
++ for (i = 0, j = 0; i < 64; i++) {
++ if (readl(chk) != ((i & 1) ? ptr : ~ptr)) {
++ j = 1;
++ break;
++ }
++ ptr += 4;
++ chk += 4;
++ }
++
++ debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
++
++ /* Store banks in para 1 */
++ shft = 12 + offs;
++ rval = config->dram_para1;
++ rval &= ~(0xf << shft);
++ rval |= j << shft;
++ config->dram_para1 = rval;
++
++ if (rank == 1) /* Set page mode for rank0 */
++ clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
++
++ /* Set page mode for current rank */
++ clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
++ udelay(1);
++
++ // Scan per address line, until address wraps (i.e. see shadow)
++ for (i = 9; i < 14; i++) {
++ chk = CFG_SYS_SDRAM_BASE + (1U << i);
++ ptr = CFG_SYS_SDRAM_BASE;
++ for (j = 0; j < 64; j++) {
++ if (readl(chk) != ((j & 1) ? ptr : ~ptr))
++ break;
++ ptr += 4;
++ chk += 4;
++ }
++ if (j == 64)
++ break;
++ }
++ if (i > 13)
++ i = 13;
++
++ unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
++ debug("rank %d page size = %d KB\n", rank, pgsize);
++
++ /* Store page size */
++ shft = offs;
++ rval = config->dram_para1;
++ rval &= ~(0xf << shft);
++ rval |= pgsize << shft;
++ config->dram_para1 = rval;
++
++ // Move to next rank
++ rank++;
++ if (rank != maxrank) {
++ if (rank == 1) {
++ /* MC_WORK_MODE */
++ clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
++
++ /* MC_WORK_MODE2 */
++ clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
++ }
++ /* store rank1 config in upper half of para1 */
++ offs += 16;
++ mc_work_mode += 4; /* move to MC_WORK_MODE2 */
++ }
++ }
++ if (maxrank == 2) {
++ config->dram_para2 &= 0xfffff0ff;
++ /* note: rval is equal to para->dram_para1 here */
++ if ((rval & 0xffff) == (rval >> 16)) {
++ debug("rank1 config same as rank0\n");
++ } else {
++ config->dram_para2 |= BIT(8);
++ debug("rank1 config different from rank0\n");
++ }
++ }
++
++ return 1;
++}
++
++/*
++ * This routine sets up parameters with dqs_gating_mode equal to 1 and two
++ * ranks enabled. It then configures the core and tests for 1 or 2 ranks and
++ * full or half DQ width. It then resets the parameters to the original values.
++ * dram_para2 is updated with the rank and width findings.
++ */
++static int auto_scan_dram_rank_width(const dram_para_t *para,
++ dram_config_t *config)
++{
++ unsigned int s1 = config->dram_tpr13;
++ unsigned int s2 = config->dram_para1;
++
++ config->dram_para1 = 0x00b000b0;
++ config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
++
++ /* set DQS probe mode */
++ config->dram_tpr13 = (config->dram_tpr13 & ~0x8) | BIT(2) | BIT(0);
++
++ mctl_core_init(para, config);
++
++ if (readl(0x3103010) & BIT(20))
++ return 0;
++
++ if (dqs_gate_detect(config) == 0)
++ return 0;
++
++ config->dram_tpr13 = s1;
++ config->dram_para1 = s2;
++
++ return 1;
++}
++
++/*
++ * This routine determines the SDRAM topology. It first establishes the number
++ * of ranks and the DQ width. Then it scans the SDRAM address lines to establish
++ * the size of each rank. It then updates dram_tpr13 to reflect that the sizes
++ * are now known: a re-init will not repeat the autoscan.
++ */
++static int auto_scan_dram_config(const dram_para_t *para,
++ dram_config_t *config)
++{
++ if (((config->dram_tpr13 & BIT(14)) == 0) &&
++ (auto_scan_dram_rank_width(para, config) == 0)) {
++ printf("ERROR: auto scan dram rank & width failed\n");
++ return 0;
++ }
++
++ if (((config->dram_tpr13 & BIT(0)) == 0) &&
++ (auto_scan_dram_size(para, config) == 0)) {
++ printf("ERROR: auto scan dram size failed\n");
++ return 0;
++ }
++
++ if ((config->dram_tpr13 & BIT(15)) == 0)
++ config->dram_tpr13 |= BIT(14) | BIT(13) | BIT(1) | BIT(0);
++
++ return 1;
++}
++
++static int init_DRAM(int type, const dram_para_t *para)
++{
++ dram_config_t config = {
++ .dram_para1 = 0x000010d2,
++ .dram_para2 = 0,
++ .dram_tpr13 = CONFIG_DRAM_SUNXI_TPR13,
++ };
++ u32 rc, mem_size_mb;
++
++ debug("DRAM BOOT DRIVE INFO: %s\n", "V0.24");
++ debug("DRAM CLK = %d MHz\n", para->dram_clk);
++ debug("DRAM Type = %d (2:DDR2,3:DDR3)\n", para->dram_type);
++ if ((para->dram_odt_en & 0x1) == 0)
++ debug("DRAMC read ODT off\n");
++ else
++ debug("DRAMC ZQ value: 0x%x\n", para->dram_zq);
++
++ /* Test ZQ status */
++ if (config.dram_tpr13 & BIT(16)) {
++ debug("DRAM only have internal ZQ\n");
++ setbits_le32(0x3000160, BIT(8));
++ writel(0, 0x3000168);
++ udelay(10);
++ } else {
++ clrbits_le32(0x3000160, 0x3);
++ writel(config.dram_tpr13 & BIT(16), 0x7010254);
++ udelay(10);
++ clrsetbits_le32(0x3000160, 0x108, BIT(1));
++ udelay(10);
++ setbits_le32(0x3000160, BIT(0));
++ udelay(20);
++ debug("ZQ value = 0x%x\n", readl(0x300016c));
++ }
++
++ dram_voltage_set(para);
++
++ /* Set SDRAM controller auto config */
++ if ((config.dram_tpr13 & BIT(0)) == 0) {
++ if (auto_scan_dram_config(para, &config) == 0) {
++ printf("auto_scan_dram_config() FAILED\n");
++ return 0;
++ }
++ }
++
++ /* report ODT */
++ rc = para->dram_mr1;
++ if ((rc & 0x44) == 0)
++ debug("DRAM ODT off\n");
++ else
++ debug("DRAM ODT value: 0x%x\n", rc);
++
++ /* Init core, final run */
++ if (mctl_core_init(para, &config) == 0) {
++ printf("DRAM initialisation error: 1\n");
++ return 0;
++ }
++
++ /* Get SDRAM size */
++ /* TODO: who ever puts a negative number in the top half? */
++ rc = config.dram_para2;
++ if (rc & BIT(31)) {
++ rc = (rc >> 16) & ~BIT(15);
++ } else {
++ rc = DRAMC_get_dram_size();
++ debug("DRAM: size = %dMB\n", rc);
++ config.dram_para2 = (config.dram_para2 & 0xffffU) | rc << 16;
++ }
++ mem_size_mb = rc;
++
++ /* Purpose ?? */
++ if (config.dram_tpr13 & BIT(30)) {
++ rc = para->dram_tpr8;
++ if (rc == 0)
++ rc = 0x10000200;
++ writel(rc, 0x31030a0);
++ writel(0x40a, 0x310309c);
++ setbits_le32(0x3103004, BIT(0));
++ debug("Enable Auto SR\n");
++ } else {
++ clrbits_le32(0x31030a0, 0xffff);
++ clrbits_le32(0x3103004, 0x1);
++ }
++
++ /* Purpose ?? */
++ if (config.dram_tpr13 & BIT(9)) {
++ clrsetbits_le32(0x3103100, 0xf000, 0x5000);
++ } else {
++ if (para->dram_type != SUNXI_DRAM_TYPE_LPDDR2)
++ clrbits_le32(0x3103100, 0xf000);
++ }
++
++ setbits_le32(0x3103140, BIT(31));
++
++ /* CHECK: is that really writing to a different register? */
++ if (config.dram_tpr13 & BIT(8))
++ writel(readl(0x3103140) | 0x300, 0x31030b8);
++
++ if (config.dram_tpr13 & BIT(16))
++ clrbits_le32(0x3103108, BIT(13));
++ else
++ setbits_le32(0x3103108, BIT(13));
++
++ /* Purpose ?? */
++ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR3)
++ clrsetbits_le32(0x310307c, 0xf0000, 0x1000);
++
++ dram_enable_all_master();
++ if (config.dram_tpr13 & BIT(28)) {
++ if ((readl(0x70005d4) & BIT(16)) ||
++ dramc_simple_wr_test(mem_size_mb, 4096))
++ return 0;
++ }
++
++ return mem_size_mb;
++}
++
++ static const dram_para_t para = {
++ .dram_clk = CONFIG_DRAM_CLK,
++ .dram_type = CONFIG_SUNXI_DRAM_TYPE,
++ .dram_zq = CONFIG_DRAM_ZQ,
++ .dram_odt_en = CONFIG_DRAM_SUNXI_ODT_EN,
++ .dram_mr0 = 0x1c70,
++ .dram_mr1 = 0x42,
++ .dram_mr2 = 0x18,
++ .dram_mr3 = 0,
++ .dram_tpr0 = 0x004a2195,
++ .dram_tpr1 = 0x02423190,
++ .dram_tpr2 = 0x0008b061,
++ .dram_tpr3 = 0xb4787896, // unused
++ .dram_tpr4 = 0,
++ .dram_tpr5 = 0x48484848,
++ .dram_tpr6 = 0x00000048,
++ .dram_tpr7 = 0x1620121e, // unused
++ .dram_tpr8 = 0,
++ .dram_tpr9 = 0, // clock?
++ .dram_tpr10 = 0,
++ .dram_tpr11 = CONFIG_DRAM_SUNXI_TPR11,
++ .dram_tpr12 = CONFIG_DRAM_SUNXI_TPR12,
++ };
++
++unsigned long sunxi_dram_init(void)
++{
++ return init_DRAM(0, ¶) * 1024UL * 1024;
++};
++
++#ifdef CONFIG_RAM /* using the driver model */
++struct sunxi_ram_priv {
++ size_t size;
++};
++
++static int sunxi_ram_probe(struct udevice *dev)
++{
++ struct sunxi_ram_priv *priv = dev_get_priv(dev);
++ unsigned long dram_size;
++
++ debug("%s: %s: probing\n", __func__, dev->name);
++
++ dram_size = sunxi_dram_init();
++ if (!dram_size) {
++ printf("DRAM init failed: %d\n", ret);
++ return -ENODEV;
++ }
++
++ priv->size = dram_size;
++
++ return 0;
++}
++
++static int sunxi_ram_get_info(struct udevice *dev, struct ram_info *info)
++{
++ struct sunxi_ram_priv *priv = dev_get_priv(dev);
++
++ debug("%s: %s: getting info\n", __func__, dev->name);
++
++ info->base = CFG_SYS_SDRAM_BASE;
++ info->size = priv->size;
++
++ return 0;
++}
++
++static struct ram_ops sunxi_ram_ops = {
++ .get_info = sunxi_ram_get_info,
++};
++
++static const struct udevice_id sunxi_ram_ids[] = {
++ { .compatible = "allwinner,sun20i-d1-mbus" },
++ { }
++};
++
++U_BOOT_DRIVER(sunxi_ram) = {
++ .name = "sunxi_ram",
++ .id = UCLASS_RAM,
++ .of_match = sunxi_ram_ids,
++ .ops = &sunxi_ram_ops,
++ .probe = sunxi_ram_probe,
++ .priv_auto = sizeof(struct sunxi_ram_priv),
++};
++#endif /* CONFIG_RAM (using driver model) */
+diff --git a/drivers/ram/sunxi/dram_sun20i_d1.h b/drivers/ram/sunxi/dram_sun20i_d1.h
+new file mode 100644
+index 0000000000..91383f6cf1
+--- /dev/null
++++ b/drivers/ram/sunxi/dram_sun20i_d1.h
+@@ -0,0 +1,73 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * D1/R528/T113 DRAM controller register and constant defines
++ *
++ * (C) Copyright 2022 Arm Ltd.
++ * Based on H6 and H616 header, which are:
++ * (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
++ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
++ *
++ */
++
++#ifndef _SUNXI_DRAM_SUN20I_D1_H
++#define _SUNXI_DRAM_SUN20I_D1_H
++
++enum sunxi_dram_type {
++ SUNXI_DRAM_TYPE_DDR2 = 2,
++ SUNXI_DRAM_TYPE_DDR3 = 3,
++ SUNXI_DRAM_TYPE_LPDDR2 = 6,
++ SUNXI_DRAM_TYPE_LPDDR3 = 7,
++};
++
++/*
++ * This structure contains a mixture of fixed configuration settings,
++ * variables that are used at runtime to communicate settings between
++ * different stages and functions, and unused values.
++ * This is copied from Allwinner's boot0 data structure, which can be
++ * found at offset 0x38 in any boot0 binary. To allow matching up some
++ * board specific settings, this struct is kept compatible, even though
++ * we don't need all members in our code.
++ */
++typedef struct dram_para {
++ /* normal configuration */
++ const u32 dram_clk;
++ const u32 dram_type;
++ const u32 dram_zq;
++ const u32 dram_odt_en;
++
++ /* timing configuration */
++ const u32 dram_mr0;
++ const u32 dram_mr1;
++ const u32 dram_mr2;
++ const u32 dram_mr3;
++ const u32 dram_tpr0; //DRAMTMG0
++ const u32 dram_tpr1; //DRAMTMG1
++ const u32 dram_tpr2; //DRAMTMG2
++ const u32 dram_tpr3; //DRAMTMG3
++ const u32 dram_tpr4; //DRAMTMG4
++ const u32 dram_tpr5; //DRAMTMG5
++ const u32 dram_tpr6; //DRAMTMG8
++ const u32 dram_tpr7;
++ const u32 dram_tpr8;
++ const u32 dram_tpr9;
++ const u32 dram_tpr10;
++ const u32 dram_tpr11;
++ const u32 dram_tpr12;
++} dram_para_t;
++
++typedef struct dram_config {
++ /* control configuration */
++ u32 dram_para1;
++ u32 dram_para2;
++ /* contains a bitfield of DRAM setup settings */
++ u32 dram_tpr13;
++} dram_config_t;
++
++static inline int ns_to_t(int nanoseconds)
++{
++ const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
++
++ return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
++}
++
++#endif /* _SUNXI_DRAM_SUN20I_D1_H */
+--
+2.20.1
+
+++ /dev/null
-From 9c4f13ffba3c53b1d4beb8cdb71f658b80692b15 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sat, 3 Jun 2023 00:52:40 +0200
-Subject: [PATCH 4021/4031] sunxi: add support for MangoPI MQDual T113 variant
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/arm/dts/Makefile | 3 +-
- .../dts/sun8i-t113s-mangopi-mqdual-t113.dts | 50 +++++++++++++++++++
- configs/mangopi_mqdual_t113_defconfig | 17 +++++++
- 3 files changed, 69 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts
- create mode 100644 configs/mangopi_mqdual_t113_defconfig
-
-diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
-index 41ee9c4c65..4207f17601 100644
---- a/arch/arm/dts/Makefile
-+++ b/arch/arm/dts/Makefile
-@@ -711,7 +711,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
- sun8i-v3-sl631-imx179.dtb \
- sun8i-v3s-licheepi-zero.dtb
- dtb-$(CONFIG_MACH_SUN8I_R528) += \
-- sun8i-t113s-mangopi-mq-r-t113.dtb
-+ sun8i-t113s-mangopi-mq-r-t113.dtb \
-+ sun8i-t113s-mangopi-mqdual-t113.dtb
- dtb-$(CONFIG_MACH_SUN50I_H5) += \
- sun50i-h5-bananapi-m2-plus.dtb \
- sun50i-h5-emlid-neutis-n5-devboard.dtb \
-diff --git a/arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts b/arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts
-new file mode 100644
-index 0000000000..7de3ddb92f
---- /dev/null
-+++ b/arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts
-@@ -0,0 +1,50 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2022 Arm Ltd.
-+
-+#include <dt-bindings/interrupt-controller/irq.h>
-+
-+/dts-v1/;
-+
-+#include "sun8i-t113s.dtsi"
-+#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
-+
-+/ {
-+ model = "MangoPi MQDual T113";
-+ compatible = "widora,mangopi-mqdual-t113", "allwinner,sun8i-t113s";
-+
-+ aliases {
-+ serial0 = &uart0;
-+ ethernet0 = &rtl8189ftv;
-+ };
-+
-+ chosen {
-+ stdout-path = "serial0:115200n8";
-+ };
-+};
-+
-+&cpu0 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&cpu1 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&mmc1 {
-+ rtl8189ftv: wifi@1 {
-+ reg = <1>;
-+ interrupt-parent = <&pio>;
-+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 = WL_WAKE_AP */
-+ interrupt-names = "host-wake";
-+ };
-+};
-+
-+&uart0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_pins>;
-+ status = "okay";
-+};
-+
-+&uart3 {
-+ status = "disabled";
-+};
-diff --git a/configs/mangopi_mqdual_t113_defconfig b/configs/mangopi_mqdual_t113_defconfig
-new file mode 100644
-index 0000000000..98b90c55f4
---- /dev/null
-+++ b/configs/mangopi_mqdual_t113_defconfig
-@@ -0,0 +1,17 @@
-+CONFIG_ARM=y
-+CONFIG_ARCH_SUNXI=y
-+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-mangopi-mqdual-t113"
-+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
-+CONFIG_SPL=y
-+CONFIG_MACH_SUN8I_R528=y
-+CONFIG_CONS_INDEX=1
-+CONFIG_MMC0_CD_PIN="PF6"
-+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-+CONFIG_SYS_MONITOR_LEN=786432
-+CONFIG_DRAM_CLK=792
-+CONFIG_DRAM_ZQ=8092667
-+CONFIG_DRAM_SUNXI_ODT_EN=0
-+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
-+CONFIG_DRAM_SUNXI_TPR11=0x340000
-+CONFIG_DRAM_SUNXI_TPR12=0x46
-+CONFIG_DRAM_SUNXI_TPR13=0x34000100
---
-2.20.1
-
--- /dev/null
+From 2caf5cf5bb2d34f07d4920eb5e4eacd07f66a27b Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:46:02 +0100
+Subject: [PATCH 4022/4044] sunxi: add Allwinner R528/T113 SoC support
+
+This adds the remaining code bits to teach U-Boot about Allwinner's
+newest SoC generation. This was introduced with the RISC-V based
+Allwinner D1 SoC, which actually shares a die with the ARM cores versions
+called R528 (BGA, without DRAM) and T113s (QFP, with embedded DRAM).
+
+This adds the new Kconfig stanza, using the two newly introduced symbols
+for the new SoC generation and pincontroller. It also adds the new symbols
+to the relavent code places, to set all the hardcoded bits directly.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Tested-by: Maksim Kiselev <bigunclemax@gmail.com>
+---
+ arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h | 9 +++++++--
+ arch/arm/mach-sunxi/Kconfig | 11 +++++++++++
+ arch/arm/mach-sunxi/board.c | 8 ++++++++
+ arch/arm/mach-sunxi/clock_sun50i_h6.c | 2 ++
+ arch/arm/mach-sunxi/cpu_info.c | 2 ++
+ common/spl/Kconfig | 1 +
+ drivers/clk/sunxi/Kconfig | 1 +
+ drivers/mmc/sunxi_mmc.c | 1 +
+ drivers/pinctrl/sunxi/Kconfig | 1 +
+ 9 files changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+index 8471e11aa0..a84a57e5b4 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+@@ -266,7 +266,7 @@ struct sunxi_ccm_reg {
+ #define CCM_CPU_AXI_AXI_MASK 0x3
+ #define CCM_CPU_AXI_DEFAULT_FACTORS 0x301
+
+-#ifdef CONFIG_MACH_SUN50I_H6
++#ifdef CONFIG_MACH_SUN50I_H6 /* H6 */
+ #define CCM_PLL6_DEFAULT 0xa0006300
+
+ /* psi_ahb1_ahb2 bit field */
+@@ -277,7 +277,7 @@ struct sunxi_ccm_reg {
+
+ /* apb1 bit field */
+ #define CCM_APB1_DEFAULT 0x03000102
+-#elif CONFIG_MACH_SUN50I_H616
++#elif CONFIG_MACH_SUN50I_H616 /* H616 */
+ #define CCM_PLL6_DEFAULT 0xa8003100
+
+ /* psi_ahb1_ahb2 bit field */
+@@ -288,6 +288,11 @@ struct sunxi_ccm_reg {
+
+ /* apb1 bit field */
+ #define CCM_APB1_DEFAULT 0x03000102
++#elif CONFIG_MACH_SUN8I_R528 /* R528 */
++#define CCM_PLL6_DEFAULT 0xe8216300
++#define CCM_PSI_AHB1_AHB2_DEFAULT 0x03000002
++//#define CCM_AHB3_DEFAULT 0x03000002
++#define CCM_APB1_DEFAULT 0x03000102
+ #endif
+
+ /* apb2 bit field */
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index 60ca1239dd..77b510cdfe 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -316,6 +316,15 @@ config MACH_SUN8I_R40
+ select PHY_SUN4I_USB
+ imply SPL_SYS_I2C_LEGACY
+
++config MACH_SUN8I_R528
++ bool "sun8i (Allwinner R528)"
++ select CPU_V7A
++ select SUNXI_GEN_NCAT2
++ select SUNXI_NEW_PINCTRL
++ select MMC_SUNXI_HAS_NEW_MODE
++ select SUPPORT_SPL
++ select DRAM_SUN8I_R528
++
+ config MACH_SUN8I_V3S
+ bool "sun8i (Allwinner V3/V3s/S3/S3L)"
+ select CPU_V7A
+@@ -612,6 +621,7 @@ config SYS_CLK_FREQ
+ default 1008000000 if MACH_SUN9I
+ default 888000000 if MACH_SUN50I_H6
+ default 1008000000 if MACH_SUN50I_H616
++ default 1008000000 if MACH_SUN8I_R528
+
+ config SYS_CONFIG_NAME
+ default "suniv" if MACH_SUNIV
+@@ -620,6 +630,7 @@ config SYS_CONFIG_NAME
+ default "sun6i" if MACH_SUN6I
+ default "sun7i" if MACH_SUN7I
+ default "sun8i" if MACH_SUN8I
++ default "sun8i" if MACH_SUN8I_R528
+ default "sun9i" if MACH_SUN9I
+ default "sun50i" if MACH_SUN50I
+ default "sun50i" if MACH_SUN50I_H6
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index 51b8e708b0..8980ffb509 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -147,6 +147,10 @@ static int gpio_init(void)
+ sunxi_gpio_set_cfgpin(SUNXI_GPH(12), SUN9I_GPH_UART0);
+ sunxi_gpio_set_cfgpin(SUNXI_GPH(13), SUN9I_GPH_UART0);
+ sunxi_gpio_set_pull(SUNXI_GPH(13), SUNXI_GPIO_PULL_UP);
++#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_R528)
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(2), 6);
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(3), 6);
++ sunxi_gpio_set_pull(SUNXI_GPE(3), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUNIV)
+ sunxi_gpio_set_cfgpin(SUNXI_GPA(2), SUNIV_GPE_UART0);
+ sunxi_gpio_set_cfgpin(SUNXI_GPA(3), SUNIV_GPE_UART0);
+@@ -163,6 +167,10 @@ static int gpio_init(void)
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_GPB_UART2);
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
+ sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP);
++#elif CONFIG_CONS_INDEX == 4 && defined(CONFIG_MACH_SUN8I_R528)
++ sunxi_gpio_set_cfgpin(SUNXI_GPB(6), 7);
++ sunxi_gpio_set_cfgpin(SUNXI_GPB(7), 7);
++ sunxi_gpio_set_pull(SUNXI_GPB(7), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
+diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+index c3a4623d34..bf21a71542 100644
+--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
++++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
+@@ -52,7 +52,9 @@ void clock_init_safe(void)
+ CCM_CPU_AXI_DEFAULT_FACTORS);
+
+ writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
++#ifdef CCM_AHB3_DEFAULT
+ writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
++#endif
+ writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
+
+ /*
+diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
+index 7eef178859..7fecc3b88d 100644
+--- a/arch/arm/mach-sunxi/cpu_info.c
++++ b/arch/arm/mach-sunxi/cpu_info.c
+@@ -93,6 +93,8 @@ int print_cpuinfo(void)
+ printf("CPU: Allwinner R40 (SUN8I %04x)\n", sunxi_get_sram_id());
+ #elif defined CONFIG_MACH_SUN8I_V3S
+ printf("CPU: Allwinner V3s (SUN8I %04x)\n", sunxi_get_sram_id());
++#elif defined CONFIG_MACH_SUN8I_R528
++ puts("CPU: Allwinner R528 (SUN8I)\n");
+ #elif defined CONFIG_MACH_SUN9I
+ puts("CPU: Allwinner A80 (SUN9I)\n");
+ #elif defined CONFIG_MACH_SUN50I
+diff --git a/common/spl/Kconfig b/common/spl/Kconfig
+index 06bcedca7d..196a250ef9 100644
+--- a/common/spl/Kconfig
++++ b/common/spl/Kconfig
+@@ -357,6 +357,7 @@ config SPL_STACK
+ default 0x91ffb8 if ARCH_MX6 && !MX6_OCRAM_256KB
+ default 0x118000 if MACH_SUN50I_H6
+ default 0x58000 if MACH_SUN50I_H616
++ default 0x40000 if MACH_SUN8I_R528
+ default 0x54000 if MACH_SUN50I || MACH_SUN50I_H5
+ default 0x18000 if MACH_SUN9I
+ default 0x8000 if ARCH_SUNXI
+diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
+index f65e482ba4..8bdc094489 100644
+--- a/drivers/clk/sunxi/Kconfig
++++ b/drivers/clk/sunxi/Kconfig
+@@ -89,6 +89,7 @@ config CLK_SUN8I_H3
+
+ config CLK_SUN20I_D1
+ bool "Clock driver for Allwinner D1"
++ default MACH_SUN8I_R528
+ help
+ This enables common clock driver support for platforms based
+ on Allwinner D1 SoC.
+diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
+index a8e590561c..0837e8bb30 100644
+--- a/drivers/mmc/sunxi_mmc.c
++++ b/drivers/mmc/sunxi_mmc.c
+@@ -708,6 +708,7 @@ static const struct udevice_id sunxi_mmc_ids[] = {
+ { .compatible = "allwinner,sun50i-h6-emmc" },
+ { .compatible = "allwinner,sun50i-a100-mmc" },
+ { .compatible = "allwinner,sun50i-a100-emmc" },
++ { .compatible = "allwinner,sun20i-d1-mmc" },
+ { /* sentinel */ }
+ };
+
+diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
+index c8f937d91e..cbd6179598 100644
+--- a/drivers/pinctrl/sunxi/Kconfig
++++ b/drivers/pinctrl/sunxi/Kconfig
+@@ -126,6 +126,7 @@ config PINCTRL_SUN50I_H616_R
+
+ config PINCTRL_SUN20I_D1
+ bool "Support for the Allwinner D1/R528 PIO"
++ default MACH_SUN8I_R528
+ select PINCTRL_SUNXI
+
+ endif
+--
+2.20.1
+
+++ /dev/null
-From 34ee938e52f219912dd9c2333ce2174860201290 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sat, 3 Jun 2023 23:41:31 +0200
-Subject: [PATCH 4022/4031] sunxi: add support for UART5 in Port E group on
- T133
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/arm/include/asm/arch-sunxi/serial.h | 1 +
- arch/arm/mach-sunxi/board.c | 4 ++++
- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 1 +
- include/configs/sunxi-common.h | 3 +++
- 4 files changed, 9 insertions(+)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/serial.h b/arch/arm/include/asm/arch-sunxi/serial.h
-index 9386287b65..48d0f42a3b 100644
---- a/arch/arm/include/asm/arch-sunxi/serial.h
-+++ b/arch/arm/include/asm/arch-sunxi/serial.h
-@@ -20,6 +20,7 @@
- #elif defined(CONFIG_SUNXI_GEN_NCAT2)
- #define SUNXI_UART0_BASE 0x02500000
- #define SUNXI_R_UART_BASE 0 // 0x07080000 (?>
-+#define SUNXI_UART5_BASE (SUNXI_UART0_BASE + 0x1400)
- #else
- #define SUNXI_UART0_BASE 0x01c28000
- #define SUNXI_R_UART_BASE 0x01f02800
-diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
-index df4f32d10c..6a37b33767 100644
---- a/arch/arm/mach-sunxi/board.c
-+++ b/arch/arm/mach-sunxi/board.c
-@@ -175,6 +175,10 @@ static int gpio_init(void)
- sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
- sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
- sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP);
-+#elif CONFIG_CONS_INDEX == 6 && defined(CONFIG_MACH_SUN8I_R528)
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(6), 9);
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(7), 9);
-+ sunxi_gpio_set_pull(SUNXI_GPE(7), SUNXI_GPIO_PULL_UP);
- #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN8I) && \
- !defined(CONFIG_MACH_SUN8I_R40)
- sunxi_gpio_set_cfgpin(SUNXI_GPG(6), SUN8I_GPG_UART1);
-diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-index 614cfe6b73..2717d79bc3 100644
---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-@@ -748,6 +748,7 @@ static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
- { "uart0", 6 }, /* PB2-PB3 */
- #endif
- { "uart3", 7 }, /* PB6-PB9 */
-+ { "uart5", 3 }, /* PE6-PE7 */
- };
-
- static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
-diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
-index b8ca77d031..bdb568af4b 100644
---- a/include/configs/sunxi-common.h
-+++ b/include/configs/sunxi-common.h
-@@ -29,6 +29,9 @@
- # define CFG_SYS_NS16550_COM3 SUNXI_UART2_BASE
- # define CFG_SYS_NS16550_COM4 SUNXI_UART3_BASE
- # define CFG_SYS_NS16550_COM5 SUNXI_R_UART_BASE
-+#if defined(CONFIG_SUNXI_GEN_NCAT2)
-+# define CFG_SYS_NS16550_COM6 SUNXI_UART5_BASE
-+#endif
- #endif
-
- /* CPU */
---
-2.20.1
-
+++ /dev/null
-From 8e178708d913eb1f4b40661519944db779d0476b Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sun, 4 Jun 2023 00:13:45 +0200
-Subject: [PATCH 4023/4031] sunxi: add MYIR MYD-YT113X board
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/arm/dts/Makefile | 3 +-
- arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts | 48 ++++++++++++++++++++
- configs/myir_myd_t113x_defconfig | 17 +++++++
- 3 files changed, 67 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts
- create mode 100644 configs/myir_myd_t113x_defconfig
-
-diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
-index 4207f17601..6fb49de59a 100644
---- a/arch/arm/dts/Makefile
-+++ b/arch/arm/dts/Makefile
-@@ -712,7 +712,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
- sun8i-v3s-licheepi-zero.dtb
- dtb-$(CONFIG_MACH_SUN8I_R528) += \
- sun8i-t113s-mangopi-mq-r-t113.dtb \
-- sun8i-t113s-mangopi-mqdual-t113.dtb
-+ sun8i-t113s-mangopi-mqdual-t113.dtb \
-+ sun8i-t113s-myir-myd-yt113x.dtb
- dtb-$(CONFIG_MACH_SUN50I_H5) += \
- sun50i-h5-bananapi-m2-plus.dtb \
- sun50i-h5-emlid-neutis-n5-devboard.dtb \
-diff --git a/arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts
-new file mode 100644
-index 0000000000..1c568b4cee
---- /dev/null
-+++ b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts
-@@ -0,0 +1,48 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2022 Arm Ltd.
-+
-+#include <dt-bindings/interrupt-controller/irq.h>
-+
-+/dts-v1/;
-+
-+#include "sun8i-t113s.dtsi"
-+#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
-+
-+/ {
-+ model = "MYIR MYD-YT113X";
-+ compatible = "myir,myd-yt113x", "myir,myc-yt113x", "allwinner,sun8i-t113s";
-+
-+ aliases {
-+ serial5 = &uart5;
-+ };
-+
-+ chosen {
-+ stdout-path = "serial5:115200n8";
-+ };
-+};
-+
-+&cpu0 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&cpu1 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&pio {
-+ /omit-if-no-ref/
-+ uart5_pins: uart5-pins {
-+ pins = "PE6", "PE7";
-+ function = "uart5";
-+ };
-+};
-+
-+&uart5 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart5_pins>;
-+ status = "okay";
-+};
-+
-+&uart3 {
-+ status = "disabled";
-+};
-diff --git a/configs/myir_myd_t113x_defconfig b/configs/myir_myd_t113x_defconfig
-new file mode 100644
-index 0000000000..dc652732e3
---- /dev/null
-+++ b/configs/myir_myd_t113x_defconfig
-@@ -0,0 +1,17 @@
-+CONFIG_ARM=y
-+CONFIG_ARCH_SUNXI=y
-+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-myir-myd-yt113x"
-+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
-+CONFIG_SPL=y
-+CONFIG_MACH_SUN8I_R528=y
-+CONFIG_CONS_INDEX=6
-+CONFIG_MMC0_CD_PIN="PF6"
-+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-+CONFIG_SYS_MONITOR_LEN=786432
-+CONFIG_DRAM_CLK=792
-+CONFIG_DRAM_ZQ=8092667
-+CONFIG_DRAM_SUNXI_ODT_EN=0
-+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
-+CONFIG_DRAM_SUNXI_TPR11=0x340000
-+CONFIG_DRAM_SUNXI_TPR12=0x46
-+CONFIG_DRAM_SUNXI_TPR13=0x34000100
---
-2.20.1
-
--- /dev/null
+From 3322934ace5532df9a783c138471abd479ed2737 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:46:03 +0100
+Subject: [PATCH 4023/4044] sunxi: refactor serial base addresses to avoid
+ asm/arch/cpu.h
+
+At the moment we have each SoC's memory map defined in its own cpu.h,
+which is included in include/configs/sunxi_common.h. This will be a
+problem with the introduction of Allwinner RISC-V support.
+
+Remove the inclusion of that header file from the common config header,
+instead move the required serial base addresses (for the SPL) into a
+separate header file. Then include the original cpu.h file only where
+we really need it, which is only under arch/arm now.
+
+This disentangles the architecture specific header files from the
+generic code.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/cpu/armv7/sunxi/sram.c | 1 +
+ arch/arm/cpu/armv8/fel_utils.S | 1 +
+ arch/arm/include/asm/arch-sunxi/boot0.h | 2 ++
+ arch/arm/include/asm/arch-sunxi/clock.h | 1 +
+ arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 15 ---------
+ .../include/asm/arch-sunxi/cpu_sun50i_h6.h | 5 ---
+ arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 7 ----
+ .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h | 4 ---
+ arch/arm/include/asm/arch-sunxi/serial.h | 32 +++++++++++++++++++
+ arch/arm/mach-sunxi/gtbus_sun9i.c | 1 +
+ arch/arm/mach-sunxi/timer.c | 1 +
+ include/configs/sunxi-common.h | 2 +-
+ 12 files changed, 40 insertions(+), 32 deletions(-)
+ create mode 100644 arch/arm/include/asm/arch-sunxi/serial.h
+
+diff --git a/arch/arm/cpu/armv7/sunxi/sram.c b/arch/arm/cpu/armv7/sunxi/sram.c
+index 28564c2846..28ff6a1b7c 100644
+--- a/arch/arm/cpu/armv7/sunxi/sram.c
++++ b/arch/arm/cpu/armv7/sunxi/sram.c
+@@ -12,6 +12,7 @@
+ #include <common.h>
+ #include <init.h>
+ #include <asm/io.h>
++#include <asm/arch/cpu.h>
+
+ void sunxi_sram_init(void)
+ {
+diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
+index 2fe38a1a04..939869b9ff 100644
+--- a/arch/arm/cpu/armv8/fel_utils.S
++++ b/arch/arm/cpu/armv8/fel_utils.S
+@@ -10,6 +10,7 @@
+ #include <config.h>
+ #include <asm/system.h>
+ #include <linux/linkage.h>
++#include <asm/arch/cpu.h>
+
+ /*
+ * We don't overwrite save_boot_params() here, to save the FEL state upon
+diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
+index 46b7e073b5..8ff7ca9b20 100644
+--- a/arch/arm/include/asm/arch-sunxi/boot0.h
++++ b/arch/arm/include/asm/arch-sunxi/boot0.h
+@@ -3,6 +3,8 @@
+ * Configuration settings for the Allwinner A64 (sun50i) CPU
+ */
+
++#include <asm/arch/cpu.h>
++
+ #if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
+ /* reserve space for BOOT0 header information */
+ b reset
+diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
+index 3d34261b0e..fcc8966cb0 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock.h
++++ b/arch/arm/include/asm/arch-sunxi/clock.h
+@@ -9,6 +9,7 @@
+ #define _SUNXI_CLOCK_H
+
+ #include <linux/types.h>
++#include <asm/arch/cpu.h>
+
+ #define CLK_GATE_OPEN 0x1
+ #define CLK_GATE_CLOSE 0x0
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+index d6fe51f24b..3daee2f574 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+@@ -128,20 +128,6 @@ defined(CONFIG_MACH_SUN50I)
+ #define SUNXI_CPUCFG_BASE 0x01c25c00
+ #endif
+
+-#ifdef CONFIG_MACH_SUNIV
+-#define SUNXI_UART0_BASE 0x01c25000
+-#define SUNXI_UART1_BASE 0x01c25400
+-#define SUNXI_UART2_BASE 0x01c25800
+-#else
+-#define SUNXI_UART0_BASE 0x01c28000
+-#define SUNXI_UART1_BASE 0x01c28400
+-#define SUNXI_UART2_BASE 0x01c28800
+-#endif
+-#define SUNXI_UART3_BASE 0x01c28c00
+-#define SUNXI_UART4_BASE 0x01c29000
+-#define SUNXI_UART5_BASE 0x01c29400
+-#define SUNXI_UART6_BASE 0x01c29800
+-#define SUNXI_UART7_BASE 0x01c29c00
+ #define SUNXI_PS2_0_BASE 0x01c2a000
+ #define SUNXI_PS2_1_BASE 0x01c2a400
+
+@@ -208,7 +194,6 @@ defined(CONFIG_MACH_SUN50I)
+ #endif
+
+ #define SUNXI_R_TWI_BASE 0x01f02400
+-#define SUNXI_R_UART_BASE 0x01f02800
+ #define SUN6I_P2WI_BASE 0x01f03400
+ #define SUNXI_RSB_BASE 0x01f03400
+
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+index 9b6bf84360..15ee092d35 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+@@ -42,10 +42,6 @@
+ #define SUNXI_DRAM_PHY0_BASE 0x04800000
+ #endif
+
+-#define SUNXI_UART0_BASE 0x05000000
+-#define SUNXI_UART1_BASE 0x05000400
+-#define SUNXI_UART2_BASE 0x05000800
+-#define SUNXI_UART3_BASE 0x05000C00
+ #define SUNXI_TWI0_BASE 0x05002000
+ #define SUNXI_TWI1_BASE 0x05002400
+ #define SUNXI_TWI2_BASE 0x05002800
+@@ -67,7 +63,6 @@
+ #define SUNXI_R_CPUCFG_BASE 0x07000400
+ #define SUNXI_PRCM_BASE 0x07010000
+ #define SUNXI_R_WDOG_BASE 0x07020400
+-#define SUNXI_R_UART_BASE 0x07080000
+ #define SUNXI_R_TWI_BASE 0x07081400
+
+ #ifndef __ASSEMBLY__
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+index 20025be231..2bf2675d5c 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+@@ -86,12 +86,6 @@
+ #define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800)
+
+ /* APB1 Module */
+-#define SUNXI_UART0_BASE (REGS_APB1_BASE + 0x0000)
+-#define SUNXI_UART1_BASE (REGS_APB1_BASE + 0x0400)
+-#define SUNXI_UART2_BASE (REGS_APB1_BASE + 0x0800)
+-#define SUNXI_UART3_BASE (REGS_APB1_BASE + 0x0C00)
+-#define SUNXI_UART4_BASE (REGS_APB1_BASE + 0x1000)
+-#define SUNXI_UART5_BASE (REGS_APB1_BASE + 0x1400)
+ #define SUNXI_TWI0_BASE (REGS_APB1_BASE + 0x2800)
+ #define SUNXI_TWI1_BASE (REGS_APB1_BASE + 0x2C00)
+ #define SUNXI_TWI2_BASE (REGS_APB1_BASE + 0x3000)
+@@ -100,7 +94,6 @@
+
+ /* RCPUS Module */
+ #define SUNXI_PRCM_BASE (REGS_RCPUS_BASE + 0x1400)
+-#define SUNXI_R_UART_BASE (REGS_RCPUS_BASE + 0x2800)
+ #define SUNXI_RSB_BASE (REGS_RCPUS_BASE + 0x3400)
+
+ /* Misc. */
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+index b13be2c4e8..961a3b37c9 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+@@ -10,10 +10,6 @@
+ #define SUNXI_CCM_BASE 0x02001000
+ #define SUNXI_TIMER_BASE 0x02050000
+
+-#define SUNXI_UART0_BASE 0x02500000
+-#define SUNXI_UART1_BASE 0x02500400
+-#define SUNXI_UART2_BASE 0x02500800
+-#define SUNXI_UART3_BASE 0x02500C00
+ #define SUNXI_TWI0_BASE 0x02502000
+ #define SUNXI_TWI1_BASE 0x02502400
+ #define SUNXI_TWI2_BASE 0x02502800
+diff --git a/arch/arm/include/asm/arch-sunxi/serial.h b/arch/arm/include/asm/arch-sunxi/serial.h
+new file mode 100644
+index 0000000000..9386287b65
+--- /dev/null
++++ b/arch/arm/include/asm/arch-sunxi/serial.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * hardcoded UART base addresses for early SPL use
++ *
++ * Copyright (c) 2022 Arm Ltd.
++ */
++
++#ifndef SUNXI_SERIAL_MEMMAP_H
++#define SUNXI_SERIAL_MEMMAP_H
++
++#if defined(CONFIG_MACH_SUN9I)
++#define SUNXI_UART0_BASE 0x07000000
++#define SUNXI_R_UART_BASE 0x08002800
++#elif defined(CONFIG_SUN50I_GEN_H6)
++#define SUNXI_UART0_BASE 0x05000000
++#define SUNXI_R_UART_BASE 0x07080000
++#elif defined(CONFIG_MACH_SUNIV)
++#define SUNXI_UART0_BASE 0x01c25000
++#define SUNXI_R_UART_BASE 0
++#elif defined(CONFIG_SUNXI_GEN_NCAT2)
++#define SUNXI_UART0_BASE 0x02500000
++#define SUNXI_R_UART_BASE 0 // 0x07080000 (?>
++#else
++#define SUNXI_UART0_BASE 0x01c28000
++#define SUNXI_R_UART_BASE 0x01f02800
++#endif
++
++#define SUNXI_UART1_BASE (SUNXI_UART0_BASE + 0x400)
++#define SUNXI_UART2_BASE (SUNXI_UART0_BASE + 0x800)
++#define SUNXI_UART3_BASE (SUNXI_UART0_BASE + 0xc00)
++
++#endif /* SUNXI_SERIAL_MEMMAP_H */
+diff --git a/arch/arm/mach-sunxi/gtbus_sun9i.c b/arch/arm/mach-sunxi/gtbus_sun9i.c
+index cf011c4cfa..5624621b50 100644
+--- a/arch/arm/mach-sunxi/gtbus_sun9i.c
++++ b/arch/arm/mach-sunxi/gtbus_sun9i.c
+@@ -8,6 +8,7 @@
+
+ #include <common.h>
+ #include <asm/io.h>
++#include <asm/arch/cpu.h>
+ #include <asm/arch/gtbus_sun9i.h>
+ #include <asm/arch/sys_proto.h>
+
+diff --git a/arch/arm/mach-sunxi/timer.c b/arch/arm/mach-sunxi/timer.c
+index fc9d419a25..9a6f6c06d8 100644
+--- a/arch/arm/mach-sunxi/timer.c
++++ b/arch/arm/mach-sunxi/timer.c
+@@ -10,6 +10,7 @@
+ #include <time.h>
+ #include <asm/global_data.h>
+ #include <asm/io.h>
++#include <asm/arch/cpu.h>
+ #include <asm/arch/timer.h>
+ #include <linux/delay.h>
+
+diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
+index d2d70f0fc2..b8ca77d031 100644
+--- a/include/configs/sunxi-common.h
++++ b/include/configs/sunxi-common.h
+@@ -12,7 +12,6 @@
+ #ifndef _SUNXI_COMMON_CONFIG_H
+ #define _SUNXI_COMMON_CONFIG_H
+
+-#include <asm/arch/cpu.h>
+ #include <linux/stringify.h>
+
+ /* Serial & console */
+@@ -24,6 +23,7 @@
+ #define CFG_SYS_NS16550_CLK 24000000
+ #endif
+ #if !CONFIG_IS_ENABLED(DM_SERIAL)
++#include <asm/arch/serial.h>
+ # define CFG_SYS_NS16550_COM1 SUNXI_UART0_BASE
+ # define CFG_SYS_NS16550_COM2 SUNXI_UART1_BASE
+ # define CFG_SYS_NS16550_COM3 SUNXI_UART2_BASE
+--
+2.20.1
+
--- /dev/null
+From ebd383f6a25566c6a0e72f702eb826182929cd2b Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Fri, 21 Jul 2023 14:46:04 +0100
+Subject: [PATCH 4024/4044] riscv: dts: allwinner: Add the D1/D1s SoC
+ devicetree
+
+D1 (aka D1-H), D1s (aka F133), R528, and T113 are a family of SoCs based
+on a single die, or at a pair of dies derived from the same design.
+
+D1 and D1s contain a single T-HEAD Xuantie C906 CPU, whereas R528 and
+T113 contain a pair of Cortex-A7's. D1 and R528 are the full version of
+the chip with a BGA package, whereas D1s and T113 are low-pin-count QFP
+variants.
+
+Because the original design supported both ARM and RISC-V CPUs, some
+peripherals are duplicated. In addition, all variants except D1s contain
+a HiFi 4 DSP with its own set of peripherals.
+
+The devicetrees are organized to minimize duplication:
+ - Common perhiperals are described in sunxi-d1s-t113.dtsi
+ - DSP-related peripherals are described in sunxi-d1-t113.dtsi
+ - RISC-V specific hardware is described in sun20i-d1s.dtsi
+ - Functionality unique to the D1 variant is described in sun20i-d1.dtsi
+
+The SOC_PERIPHERAL_IRQ macro handles the different #interrupt-cells
+values between the ARM (GIC) and RISC-V (PLIC) versions of the SoC.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+---
+ arch/riscv/dts/sun20i-common-regulators.dtsi | 28 +
+ arch/riscv/dts/sun20i-d1.dtsi | 66 ++
+ arch/riscv/dts/sun20i-d1s.dtsi | 76 ++
+ arch/riscv/dts/sunxi-d1-t113.dtsi | 15 +
+ arch/riscv/dts/sunxi-d1s-t113.dtsi | 846 +++++++++++++++++++
+ include/dt-bindings/clock/sun20i-d1-r-ccu.h | 19 +
+ include/dt-bindings/reset/sun20i-d1-r-ccu.h | 16 +
+ 7 files changed, 1066 insertions(+)
+ create mode 100644 arch/riscv/dts/sun20i-common-regulators.dtsi
+ create mode 100644 arch/riscv/dts/sun20i-d1.dtsi
+ create mode 100644 arch/riscv/dts/sun20i-d1s.dtsi
+ create mode 100644 arch/riscv/dts/sunxi-d1-t113.dtsi
+ create mode 100644 arch/riscv/dts/sunxi-d1s-t113.dtsi
+ create mode 100644 include/dt-bindings/clock/sun20i-d1-r-ccu.h
+ create mode 100644 include/dt-bindings/reset/sun20i-d1-r-ccu.h
+
+diff --git a/arch/riscv/dts/sun20i-common-regulators.dtsi b/arch/riscv/dts/sun20i-common-regulators.dtsi
+new file mode 100644
+index 0000000000..9b03fca244
+--- /dev/null
++++ b/arch/riscv/dts/sun20i-common-regulators.dtsi
+@@ -0,0 +1,28 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
++
++/ {
++ reg_vcc: vcc {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ };
++
++ reg_vcc_3v3: vcc-3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <®_vcc>;
++ };
++};
++
++&pio {
++ vcc-pb-supply = <®_vcc_3v3>;
++ vcc-pc-supply = <®_vcc_3v3>;
++ vcc-pd-supply = <®_vcc_3v3>;
++ vcc-pe-supply = <®_vcc_3v3>;
++ vcc-pf-supply = <®_vcc_3v3>;
++ vcc-pg-supply = <®_vcc_3v3>;
++};
+diff --git a/arch/riscv/dts/sun20i-d1.dtsi b/arch/riscv/dts/sun20i-d1.dtsi
+new file mode 100644
+index 0000000000..97e7cbb325
+--- /dev/null
++++ b/arch/riscv/dts/sun20i-d1.dtsi
+@@ -0,0 +1,66 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
++
++#include "sun20i-d1s.dtsi"
++#include "sunxi-d1-t113.dtsi"
++
++/ {
++ soc {
++ lradc: keys@2009800 {
++ compatible = "allwinner,sun20i-d1-lradc",
++ "allwinner,sun50i-r329-lradc";
++ reg = <0x2009800 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(61) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_LRADC>;
++ resets = <&ccu RST_BUS_LRADC>;
++ status = "disabled";
++ };
++
++ i2s0: i2s@2032000 {
++ compatible = "allwinner,sun20i-d1-i2s",
++ "allwinner,sun50i-r329-i2s";
++ reg = <0x2032000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(26) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_I2S0>,
++ <&ccu CLK_I2S0>;
++ clock-names = "apb", "mod";
++ resets = <&ccu RST_BUS_I2S0>;
++ dmas = <&dma 3>, <&dma 3>;
++ dma-names = "rx", "tx";
++ status = "disabled";
++ #sound-dai-cells = <0>;
++ };
++ };
++};
++
++&pio {
++ /omit-if-no-ref/
++ dmic_pb11_d0_pin: dmic-pb11-d0-pin {
++ pins = "PB11";
++ function = "dmic";
++ };
++
++ /omit-if-no-ref/
++ dmic_pe17_clk_pin: dmic-pe17-clk-pin {
++ pins = "PE17";
++ function = "dmic";
++ };
++
++ /omit-if-no-ref/
++ i2c0_pb10_pins: i2c0-pb10-pins {
++ pins = "PB10", "PB11";
++ function = "i2c0";
++ };
++
++ /omit-if-no-ref/
++ i2c2_pb0_pins: i2c2-pb0-pins {
++ pins = "PB0", "PB1";
++ function = "i2c2";
++ };
++
++ /omit-if-no-ref/
++ uart0_pb8_pins: uart0-pb8-pins {
++ pins = "PB8", "PB9";
++ function = "uart0";
++ };
++};
+diff --git a/arch/riscv/dts/sun20i-d1s.dtsi b/arch/riscv/dts/sun20i-d1s.dtsi
+new file mode 100644
+index 0000000000..8275630af9
+--- /dev/null
++++ b/arch/riscv/dts/sun20i-d1s.dtsi
+@@ -0,0 +1,76 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
++
++#define SOC_PERIPHERAL_IRQ(nr) (nr + 16)
++
++#include "sunxi-d1s-t113.dtsi"
++
++/ {
++ cpus {
++ timebase-frequency = <24000000>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu0: cpu@0 {
++ compatible = "thead,c906", "riscv";
++ device_type = "cpu";
++ reg = <0>;
++ clocks = <&ccu CLK_RISCV>;
++ d-cache-block-size = <64>;
++ d-cache-sets = <256>;
++ d-cache-size = <32768>;
++ i-cache-block-size = <64>;
++ i-cache-sets = <128>;
++ i-cache-size = <32768>;
++ mmu-type = "riscv,sv39";
++ operating-points-v2 = <&opp_table_cpu>;
++ riscv,isa = "rv64imafdc";
++ #cooling-cells = <2>;
++
++ cpu0_intc: interrupt-controller {
++ compatible = "riscv,cpu-intc";
++ interrupt-controller;
++ #address-cells = <0>;
++ #interrupt-cells = <1>;
++ };
++ };
++ };
++
++ opp_table_cpu: opp-table-cpu {
++ compatible = "operating-points-v2";
++
++ opp-408000000 {
++ opp-hz = /bits/ 64 <408000000>;
++ opp-microvolt = <900000 900000 1100000>;
++ };
++
++ opp-1080000000 {
++ opp-hz = /bits/ 64 <1008000000>;
++ opp-microvolt = <900000 900000 1100000>;
++ };
++ };
++
++ soc {
++ interrupt-parent = <&plic>;
++
++ riscv_wdt: watchdog@6011000 {
++ compatible = "allwinner,sun20i-d1-wdt";
++ reg = <0x6011000 0x20>;
++ interrupts = <SOC_PERIPHERAL_IRQ(131) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
++ clock-names = "hosc", "losc";
++ };
++
++ plic: interrupt-controller@10000000 {
++ compatible = "allwinner,sun20i-d1-plic",
++ "thead,c900-plic";
++ reg = <0x10000000 0x4000000>;
++ interrupts-extended = <&cpu0_intc 11>,
++ <&cpu0_intc 9>;
++ interrupt-controller;
++ riscv,ndev = <175>;
++ #address-cells = <0>;
++ #interrupt-cells = <2>;
++ };
++ };
++};
+diff --git a/arch/riscv/dts/sunxi-d1-t113.dtsi b/arch/riscv/dts/sunxi-d1-t113.dtsi
+new file mode 100644
+index 0000000000..b7156123df
+--- /dev/null
++++ b/arch/riscv/dts/sunxi-d1-t113.dtsi
+@@ -0,0 +1,15 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
++
++/ {
++ soc {
++ dsp_wdt: watchdog@1700400 {
++ compatible = "allwinner,sun20i-d1-wdt";
++ reg = <0x1700400 0x20>;
++ interrupts = <SOC_PERIPHERAL_IRQ(122) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
++ clock-names = "hosc", "losc";
++ status = "reserved";
++ };
++ };
++};
+diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+new file mode 100644
+index 0000000000..922e8e0e2c
+--- /dev/null
++++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+@@ -0,0 +1,846 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
++
++#include <dt-bindings/clock/sun6i-rtc.h>
++#include <dt-bindings/clock/sun8i-de2.h>
++#include <dt-bindings/clock/sun8i-tcon-top.h>
++#include <dt-bindings/clock/sun20i-d1-ccu.h>
++#include <dt-bindings/clock/sun20i-d1-r-ccu.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/reset/sun8i-de2.h>
++#include <dt-bindings/reset/sun20i-d1-ccu.h>
++#include <dt-bindings/reset/sun20i-d1-r-ccu.h>
++
++/ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ dcxo: dcxo-clk {
++ compatible = "fixed-clock";
++ clock-output-names = "dcxo";
++ #clock-cells = <0>;
++ };
++
++ de: display-engine {
++ compatible = "allwinner,sun20i-d1-display-engine";
++ allwinner,pipelines = <&mixer0>, <&mixer1>;
++ status = "disabled";
++ };
++
++ soc {
++ compatible = "simple-bus";
++ ranges;
++ dma-noncoherent;
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ pio: pinctrl@2000000 {
++ compatible = "allwinner,sun20i-d1-pinctrl";
++ reg = <0x2000000 0x800>;
++ interrupts = <SOC_PERIPHERAL_IRQ(69) IRQ_TYPE_LEVEL_HIGH>,
++ <SOC_PERIPHERAL_IRQ(71) IRQ_TYPE_LEVEL_HIGH>,
++ <SOC_PERIPHERAL_IRQ(73) IRQ_TYPE_LEVEL_HIGH>,
++ <SOC_PERIPHERAL_IRQ(75) IRQ_TYPE_LEVEL_HIGH>,
++ <SOC_PERIPHERAL_IRQ(77) IRQ_TYPE_LEVEL_HIGH>,
++ <SOC_PERIPHERAL_IRQ(79) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_APB0>,
++ <&dcxo>,
++ <&rtc CLK_OSC32K>;
++ clock-names = "apb", "hosc", "losc";
++ gpio-controller;
++ interrupt-controller;
++ #gpio-cells = <3>;
++ #interrupt-cells = <3>;
++
++ /omit-if-no-ref/
++ clk_pg11_pin: clk-pg11-pin {
++ pins = "PG11";
++ function = "clk";
++ };
++
++ /omit-if-no-ref/
++ dsi_4lane_pins: dsi-4lane-pins {
++ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
++ "PD6", "PD7", "PD8", "PD9";
++ drive-strength = <30>;
++ function = "dsi";
++ };
++
++ /omit-if-no-ref/
++ lcd_rgb666_pins: lcd-rgb666-pins {
++ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
++ "PD6", "PD7", "PD8", "PD9", "PD10", "PD11",
++ "PD12", "PD13", "PD14", "PD15", "PD16", "PD17",
++ "PD18", "PD19", "PD20", "PD21";
++ function = "lcd0";
++ };
++
++ /omit-if-no-ref/
++ mmc0_pins: mmc0-pins {
++ pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
++ function = "mmc0";
++ };
++
++ /omit-if-no-ref/
++ mmc1_pins: mmc1-pins {
++ pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5";
++ function = "mmc1";
++ };
++
++ /omit-if-no-ref/
++ mmc2_pins: mmc2-pins {
++ pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7";
++ function = "mmc2";
++ };
++
++ /omit-if-no-ref/
++ rgmii_pe_pins: rgmii-pe-pins {
++ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
++ "PE5", "PE6", "PE7", "PE8", "PE9",
++ "PE11", "PE12", "PE13", "PE14", "PE15";
++ function = "emac";
++ };
++
++ /omit-if-no-ref/
++ rmii_pe_pins: rmii-pe-pins {
++ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
++ "PE5", "PE6", "PE7", "PE8", "PE9";
++ function = "emac";
++ };
++
++ /omit-if-no-ref/
++ uart1_pg6_pins: uart1-pg6-pins {
++ pins = "PG6", "PG7";
++ function = "uart1";
++ };
++
++ /omit-if-no-ref/
++ uart1_pg8_rts_cts_pins: uart1-pg8-rts-cts-pins {
++ pins = "PG8", "PG9";
++ function = "uart1";
++ };
++
++ /omit-if-no-ref/
++ uart3_pb_pins: uart3-pb-pins {
++ pins = "PB6", "PB7";
++ function = "uart3";
++ };
++ };
++
++ ccu: clock-controller@2001000 {
++ compatible = "allwinner,sun20i-d1-ccu";
++ reg = <0x2001000 0x1000>;
++ clocks = <&dcxo>,
++ <&rtc CLK_OSC32K>,
++ <&rtc CLK_IOSC>;
++ clock-names = "hosc", "losc", "iosc";
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ };
++
++ dmic: dmic@2031000 {
++ compatible = "allwinner,sun20i-d1-dmic",
++ "allwinner,sun50i-h6-dmic";
++ reg = <0x2031000 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(24) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_DMIC>,
++ <&ccu CLK_DMIC>;
++ clock-names = "bus", "mod";
++ resets = <&ccu RST_BUS_DMIC>;
++ dmas = <&dma 8>;
++ dma-names = "rx";
++ status = "disabled";
++ #sound-dai-cells = <0>;
++ };
++
++ i2s1: i2s@2033000 {
++ compatible = "allwinner,sun20i-d1-i2s",
++ "allwinner,sun50i-r329-i2s";
++ reg = <0x2033000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(27) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_I2S1>,
++ <&ccu CLK_I2S1>;
++ clock-names = "apb", "mod";
++ resets = <&ccu RST_BUS_I2S1>;
++ dmas = <&dma 4>, <&dma 4>;
++ dma-names = "rx", "tx";
++ status = "disabled";
++ #sound-dai-cells = <0>;
++ };
++
++ i2s2: i2s@2034000 {
++ compatible = "allwinner,sun20i-d1-i2s",
++ "allwinner,sun50i-r329-i2s";
++ reg = <0x2034000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(28) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_I2S2>,
++ <&ccu CLK_I2S2>;
++ clock-names = "apb", "mod";
++ resets = <&ccu RST_BUS_I2S2>;
++ dmas = <&dma 5>, <&dma 5>;
++ dma-names = "rx", "tx";
++ status = "disabled";
++ #sound-dai-cells = <0>;
++ };
++
++ timer: timer@2050000 {
++ compatible = "allwinner,sun20i-d1-timer",
++ "allwinner,sun8i-a23-timer";
++ reg = <0x2050000 0xa0>;
++ interrupts = <SOC_PERIPHERAL_IRQ(59) IRQ_TYPE_LEVEL_HIGH>,
++ <SOC_PERIPHERAL_IRQ(60) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&dcxo>;
++ };
++
++ wdt: watchdog@20500a0 {
++ compatible = "allwinner,sun20i-d1-wdt-reset",
++ "allwinner,sun20i-d1-wdt";
++ reg = <0x20500a0 0x20>;
++ interrupts = <SOC_PERIPHERAL_IRQ(63) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
++ clock-names = "hosc", "losc";
++ status = "reserved";
++ };
++
++ uart0: serial@2500000 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x2500000 0x400>;
++ reg-io-width = <4>;
++ reg-shift = <2>;
++ interrupts = <SOC_PERIPHERAL_IRQ(2) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_UART0>;
++ resets = <&ccu RST_BUS_UART0>;
++ dmas = <&dma 14>, <&dma 14>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ uart1: serial@2500400 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x2500400 0x400>;
++ reg-io-width = <4>;
++ reg-shift = <2>;
++ interrupts = <SOC_PERIPHERAL_IRQ(3) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_UART1>;
++ resets = <&ccu RST_BUS_UART1>;
++ dmas = <&dma 15>, <&dma 15>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ uart2: serial@2500800 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x2500800 0x400>;
++ reg-io-width = <4>;
++ reg-shift = <2>;
++ interrupts = <SOC_PERIPHERAL_IRQ(4) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_UART2>;
++ resets = <&ccu RST_BUS_UART2>;
++ dmas = <&dma 16>, <&dma 16>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ uart3: serial@2500c00 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x2500c00 0x400>;
++ reg-io-width = <4>;
++ reg-shift = <2>;
++ interrupts = <SOC_PERIPHERAL_IRQ(5) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_UART3>;
++ resets = <&ccu RST_BUS_UART3>;
++ dmas = <&dma 17>, <&dma 17>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ uart4: serial@2501000 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x2501000 0x400>;
++ reg-io-width = <4>;
++ reg-shift = <2>;
++ interrupts = <SOC_PERIPHERAL_IRQ(6) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_UART4>;
++ resets = <&ccu RST_BUS_UART4>;
++ dmas = <&dma 18>, <&dma 18>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ uart5: serial@2501400 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x2501400 0x400>;
++ reg-io-width = <4>;
++ reg-shift = <2>;
++ interrupts = <SOC_PERIPHERAL_IRQ(7) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_UART5>;
++ resets = <&ccu RST_BUS_UART5>;
++ dmas = <&dma 19>, <&dma 19>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ i2c0: i2c@2502000 {
++ compatible = "allwinner,sun20i-d1-i2c",
++ "allwinner,sun8i-v536-i2c",
++ "allwinner,sun6i-a31-i2c";
++ reg = <0x2502000 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(9) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_I2C0>;
++ resets = <&ccu RST_BUS_I2C0>;
++ dmas = <&dma 43>, <&dma 43>;
++ dma-names = "rx", "tx";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ i2c1: i2c@2502400 {
++ compatible = "allwinner,sun20i-d1-i2c",
++ "allwinner,sun8i-v536-i2c",
++ "allwinner,sun6i-a31-i2c";
++ reg = <0x2502400 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_I2C1>;
++ resets = <&ccu RST_BUS_I2C1>;
++ dmas = <&dma 44>, <&dma 44>;
++ dma-names = "rx", "tx";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ i2c2: i2c@2502800 {
++ compatible = "allwinner,sun20i-d1-i2c",
++ "allwinner,sun8i-v536-i2c",
++ "allwinner,sun6i-a31-i2c";
++ reg = <0x2502800 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(11) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_I2C2>;
++ resets = <&ccu RST_BUS_I2C2>;
++ dmas = <&dma 45>, <&dma 45>;
++ dma-names = "rx", "tx";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ i2c3: i2c@2502c00 {
++ compatible = "allwinner,sun20i-d1-i2c",
++ "allwinner,sun8i-v536-i2c",
++ "allwinner,sun6i-a31-i2c";
++ reg = <0x2502c00 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(12) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_I2C3>;
++ resets = <&ccu RST_BUS_I2C3>;
++ dmas = <&dma 46>, <&dma 46>;
++ dma-names = "rx", "tx";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ syscon: syscon@3000000 {
++ compatible = "allwinner,sun20i-d1-system-control";
++ reg = <0x3000000 0x1000>;
++ ranges;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ };
++
++ dma: dma-controller@3002000 {
++ compatible = "allwinner,sun20i-d1-dma";
++ reg = <0x3002000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(50) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
++ clock-names = "bus", "mbus";
++ resets = <&ccu RST_BUS_DMA>;
++ dma-channels = <16>;
++ dma-requests = <48>;
++ #dma-cells = <1>;
++ };
++
++ sid: efuse@3006000 {
++ compatible = "allwinner,sun20i-d1-sid";
++ reg = <0x3006000 0x1000>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ };
++
++ crypto: crypto@3040000 {
++ compatible = "allwinner,sun20i-d1-crypto";
++ reg = <0x3040000 0x800>;
++ interrupts = <SOC_PERIPHERAL_IRQ(52) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_CE>,
++ <&ccu CLK_CE>,
++ <&ccu CLK_MBUS_CE>,
++ <&rtc CLK_IOSC>;
++ clock-names = "bus", "mod", "ram", "trng";
++ resets = <&ccu RST_BUS_CE>;
++ };
++
++ mbus: dram-controller@3102000 {
++ compatible = "allwinner,sun20i-d1-mbus";
++ reg = <0x3102000 0x1000>,
++ <0x3103000 0x1000>;
++ reg-names = "mbus", "dram";
++ interrupts = <SOC_PERIPHERAL_IRQ(43) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_MBUS>,
++ <&ccu CLK_DRAM>,
++ <&ccu CLK_BUS_DRAM>;
++ clock-names = "mbus", "dram", "bus";
++ dma-ranges = <0 0x40000000 0x80000000>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ #interconnect-cells = <1>;
++ };
++
++ mmc0: mmc@4020000 {
++ compatible = "allwinner,sun20i-d1-mmc";
++ reg = <0x4020000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(40) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
++ clock-names = "ahb", "mmc";
++ resets = <&ccu RST_BUS_MMC0>;
++ reset-names = "ahb";
++ cap-sd-highspeed;
++ max-frequency = <150000000>;
++ no-mmc;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ mmc1: mmc@4021000 {
++ compatible = "allwinner,sun20i-d1-mmc";
++ reg = <0x4021000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(41) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
++ clock-names = "ahb", "mmc";
++ resets = <&ccu RST_BUS_MMC1>;
++ reset-names = "ahb";
++ cap-sd-highspeed;
++ max-frequency = <150000000>;
++ no-mmc;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ mmc2: mmc@4022000 {
++ compatible = "allwinner,sun20i-d1-emmc",
++ "allwinner,sun50i-a100-emmc";
++ reg = <0x4022000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(42) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
++ clock-names = "ahb", "mmc";
++ resets = <&ccu RST_BUS_MMC2>;
++ reset-names = "ahb";
++ cap-mmc-highspeed;
++ max-frequency = <150000000>;
++ mmc-ddr-1_8v;
++ mmc-ddr-3_3v;
++ no-sd;
++ no-sdio;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ usb_otg: usb@4100000 {
++ compatible = "allwinner,sun20i-d1-musb",
++ "allwinner,sun8i-a33-musb";
++ reg = <0x4100000 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(29) IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "mc";
++ clocks = <&ccu CLK_BUS_OTG>;
++ resets = <&ccu RST_BUS_OTG>;
++ extcon = <&usbphy 0>;
++ phys = <&usbphy 0>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ usbphy: phy@4100400 {
++ compatible = "allwinner,sun20i-d1-usb-phy";
++ reg = <0x4100400 0x100>,
++ <0x4101800 0x100>,
++ <0x4200800 0x100>;
++ reg-names = "phy_ctrl",
++ "pmu0",
++ "pmu1";
++ clocks = <&dcxo>,
++ <&dcxo>;
++ clock-names = "usb0_phy",
++ "usb1_phy";
++ resets = <&ccu RST_USB_PHY0>,
++ <&ccu RST_USB_PHY1>;
++ reset-names = "usb0_reset",
++ "usb1_reset";
++ status = "disabled";
++ #phy-cells = <1>;
++ };
++
++ ehci0: usb@4101000 {
++ compatible = "allwinner,sun20i-d1-ehci",
++ "generic-ehci";
++ reg = <0x4101000 0x100>;
++ interrupts = <SOC_PERIPHERAL_IRQ(30) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_OHCI0>,
++ <&ccu CLK_BUS_EHCI0>,
++ <&ccu CLK_USB_OHCI0>;
++ resets = <&ccu RST_BUS_OHCI0>,
++ <&ccu RST_BUS_EHCI0>;
++ phys = <&usbphy 0>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci0: usb@4101400 {
++ compatible = "allwinner,sun20i-d1-ohci",
++ "generic-ohci";
++ reg = <0x4101400 0x100>;
++ interrupts = <SOC_PERIPHERAL_IRQ(31) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_OHCI0>,
++ <&ccu CLK_USB_OHCI0>;
++ resets = <&ccu RST_BUS_OHCI0>;
++ phys = <&usbphy 0>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ehci1: usb@4200000 {
++ compatible = "allwinner,sun20i-d1-ehci",
++ "generic-ehci";
++ reg = <0x4200000 0x100>;
++ interrupts = <SOC_PERIPHERAL_IRQ(33) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_OHCI1>,
++ <&ccu CLK_BUS_EHCI1>,
++ <&ccu CLK_USB_OHCI1>;
++ resets = <&ccu RST_BUS_OHCI1>,
++ <&ccu RST_BUS_EHCI1>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci1: usb@4200400 {
++ compatible = "allwinner,sun20i-d1-ohci",
++ "generic-ohci";
++ reg = <0x4200400 0x100>;
++ interrupts = <SOC_PERIPHERAL_IRQ(34) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_OHCI1>,
++ <&ccu CLK_USB_OHCI1>;
++ resets = <&ccu RST_BUS_OHCI1>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ emac: ethernet@4500000 {
++ compatible = "allwinner,sun20i-d1-emac",
++ "allwinner,sun50i-a64-emac";
++ reg = <0x4500000 0x10000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(46) IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "macirq";
++ clocks = <&ccu CLK_BUS_EMAC>;
++ clock-names = "stmmaceth";
++ resets = <&ccu RST_BUS_EMAC>;
++ reset-names = "stmmaceth";
++ syscon = <&syscon>;
++ status = "disabled";
++
++ mdio: mdio {
++ compatible = "snps,dwmac-mdio";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++ };
++
++ display_clocks: clock-controller@5000000 {
++ compatible = "allwinner,sun20i-d1-de2-clk",
++ "allwinner,sun50i-h5-de2-clk";
++ reg = <0x5000000 0x10000>;
++ clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>;
++ clock-names = "bus", "mod";
++ resets = <&ccu RST_BUS_DE>;
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ };
++
++ mixer0: mixer@5100000 {
++ compatible = "allwinner,sun20i-d1-de2-mixer-0";
++ reg = <0x5100000 0x100000>;
++ clocks = <&display_clocks CLK_BUS_MIXER0>,
++ <&display_clocks CLK_MIXER0>;
++ clock-names = "bus", "mod";
++ resets = <&display_clocks RST_MIXER0>;
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ mixer0_out: port@1 {
++ reg = <1>;
++
++ mixer0_out_tcon_top_mixer0: endpoint {
++ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
++ };
++ };
++ };
++ };
++
++ mixer1: mixer@5200000 {
++ compatible = "allwinner,sun20i-d1-de2-mixer-1";
++ reg = <0x5200000 0x100000>;
++ clocks = <&display_clocks CLK_BUS_MIXER1>,
++ <&display_clocks CLK_MIXER1>;
++ clock-names = "bus", "mod";
++ resets = <&display_clocks RST_MIXER1>;
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ mixer1_out: port@1 {
++ reg = <1>;
++
++ mixer1_out_tcon_top_mixer1: endpoint {
++ remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
++ };
++ };
++ };
++ };
++
++ dsi: dsi@5450000 {
++ compatible = "allwinner,sun20i-d1-mipi-dsi",
++ "allwinner,sun50i-a100-mipi-dsi";
++ reg = <0x5450000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_MIPI_DSI>,
++ <&tcon_top CLK_TCON_TOP_DSI>;
++ clock-names = "bus", "mod";
++ resets = <&ccu RST_BUS_MIPI_DSI>;
++ phys = <&dphy>;
++ phy-names = "dphy";
++ status = "disabled";
++
++ port {
++ dsi_in_tcon_lcd0: endpoint {
++ remote-endpoint = <&tcon_lcd0_out_dsi>;
++ };
++ };
++ };
++
++ dphy: phy@5451000 {
++ compatible = "allwinner,sun20i-d1-mipi-dphy",
++ "allwinner,sun50i-a100-mipi-dphy";
++ reg = <0x5451000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_MIPI_DSI>,
++ <&ccu CLK_MIPI_DSI>;
++ clock-names = "bus", "mod";
++ resets = <&ccu RST_BUS_MIPI_DSI>;
++ #phy-cells = <0>;
++ };
++
++ tcon_top: tcon-top@5460000 {
++ compatible = "allwinner,sun20i-d1-tcon-top";
++ reg = <0x5460000 0x1000>;
++ clocks = <&ccu CLK_BUS_DPSS_TOP>,
++ <&ccu CLK_TCON_TV>,
++ <&ccu CLK_TVE>,
++ <&ccu CLK_TCON_LCD0>;
++ clock-names = "bus", "tcon-tv0", "tve0", "dsi";
++ clock-output-names = "tcon-top-tv0", "tcon-top-dsi";
++ resets = <&ccu RST_BUS_DPSS_TOP>;
++ #clock-cells = <1>;
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_top_mixer0_in: port@0 {
++ reg = <0>;
++
++ tcon_top_mixer0_in_mixer0: endpoint {
++ remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
++ };
++ };
++
++ tcon_top_mixer0_out: port@1 {
++ reg = <1>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
++ reg = <0>;
++ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer0>;
++ };
++
++ tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
++ reg = <2>;
++ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
++ };
++ };
++
++ tcon_top_mixer1_in: port@2 {
++ reg = <2>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_top_mixer1_in_mixer1: endpoint@1 {
++ reg = <1>;
++ remote-endpoint = <&mixer1_out_tcon_top_mixer1>;
++ };
++ };
++
++ tcon_top_mixer1_out: port@3 {
++ reg = <3>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
++ reg = <0>;
++ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer1>;
++ };
++
++ tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
++ reg = <2>;
++ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
++ };
++ };
++
++ tcon_top_hdmi_in: port@4 {
++ reg = <4>;
++
++ tcon_top_hdmi_in_tcon_tv0: endpoint {
++ remote-endpoint = <&tcon_tv0_out_tcon_top_hdmi>;
++ };
++ };
++
++ tcon_top_hdmi_out: port@5 {
++ reg = <5>;
++ };
++ };
++ };
++
++ tcon_lcd0: lcd-controller@5461000 {
++ compatible = "allwinner,sun20i-d1-tcon-lcd";
++ reg = <0x5461000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(90) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_TCON_LCD0>,
++ <&ccu CLK_TCON_LCD0>;
++ clock-names = "ahb", "tcon-ch0";
++ clock-output-names = "tcon-pixel-clock";
++ resets = <&ccu RST_BUS_TCON_LCD0>,
++ <&ccu RST_BUS_LVDS0>;
++ reset-names = "lcd", "lvds";
++ #clock-cells = <0>;
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_lcd0_in: port@0 {
++ reg = <0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_lcd0_in_tcon_top_mixer0: endpoint@0 {
++ reg = <0>;
++ remote-endpoint = <&tcon_top_mixer0_out_tcon_lcd0>;
++ };
++
++ tcon_lcd0_in_tcon_top_mixer1: endpoint@1 {
++ reg = <1>;
++ remote-endpoint = <&tcon_top_mixer1_out_tcon_lcd0>;
++ };
++ };
++
++ tcon_lcd0_out: port@1 {
++ reg = <1>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_lcd0_out_dsi: endpoint@1 {
++ reg = <1>;
++ remote-endpoint = <&dsi_in_tcon_lcd0>;
++ };
++ };
++ };
++ };
++
++ tcon_tv0: lcd-controller@5470000 {
++ compatible = "allwinner,sun20i-d1-tcon-tv";
++ reg = <0x5470000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(91) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_TCON_TV>,
++ <&tcon_top CLK_TCON_TOP_TV0>;
++ clock-names = "ahb", "tcon-ch1";
++ resets = <&ccu RST_BUS_TCON_TV>;
++ reset-names = "lcd";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_tv0_in: port@0 {
++ reg = <0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
++ reg = <0>;
++ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
++ };
++
++ tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
++ reg = <1>;
++ remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
++ };
++ };
++
++ tcon_tv0_out: port@1 {
++ reg = <1>;
++
++ tcon_tv0_out_tcon_top_hdmi: endpoint {
++ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
++ };
++ };
++ };
++ };
++
++ ppu: power-controller@7001000 {
++ compatible = "allwinner,sun20i-d1-ppu";
++ reg = <0x7001000 0x1000>;
++ clocks = <&r_ccu CLK_BUS_R_PPU>;
++ resets = <&r_ccu RST_BUS_R_PPU>;
++ #power-domain-cells = <1>;
++ };
++
++ r_ccu: clock-controller@7010000 {
++ compatible = "allwinner,sun20i-d1-r-ccu";
++ reg = <0x7010000 0x400>;
++ clocks = <&dcxo>,
++ <&rtc CLK_OSC32K>,
++ <&rtc CLK_IOSC>,
++ <&ccu CLK_PLL_PERIPH0_DIV3>;
++ clock-names = "hosc", "losc", "iosc", "pll-periph";
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ };
++
++ rtc: rtc@7090000 {
++ compatible = "allwinner,sun20i-d1-rtc",
++ "allwinner,sun50i-r329-rtc";
++ reg = <0x7090000 0x400>;
++ interrupts = <SOC_PERIPHERAL_IRQ(144) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&r_ccu CLK_BUS_R_RTC>,
++ <&dcxo>,
++ <&r_ccu CLK_R_AHB>;
++ clock-names = "bus", "hosc", "ahb";
++ #clock-cells = <1>;
++ };
++ };
++};
+diff --git a/include/dt-bindings/clock/sun20i-d1-r-ccu.h b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
+new file mode 100644
+index 0000000000..4c2697fd32
+--- /dev/null
++++ b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
+@@ -0,0 +1,19 @@
++/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
++/*
++ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
++ */
++
++#ifndef _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
++#define _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
++
++#define CLK_R_AHB 0
++
++#define CLK_BUS_R_TIMER 2
++#define CLK_BUS_R_TWD 3
++#define CLK_BUS_R_PPU 4
++#define CLK_R_IR_RX 5
++#define CLK_BUS_R_IR_RX 6
++#define CLK_BUS_R_RTC 7
++#define CLK_BUS_R_CPUCFG 8
++
++#endif /* _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ */
+diff --git a/include/dt-bindings/reset/sun20i-d1-r-ccu.h b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
+new file mode 100644
+index 0000000000..d93d6423d2
+--- /dev/null
++++ b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
+@@ -0,0 +1,16 @@
++/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
++/*
++ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
++ */
++
++#ifndef _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
++#define _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
++
++#define RST_BUS_R_TIMER 0
++#define RST_BUS_R_TWD 1
++#define RST_BUS_R_PPU 2
++#define RST_BUS_R_IR_RX 3
++#define RST_BUS_R_RTC 4
++#define RST_BUS_R_CPUCFG 5
++
++#endif /* _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ */
+--
+2.20.1
+
+++ /dev/null
-From 9dd404ee6108f09894d5ff60feedb713284ca617 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sat, 3 Jun 2023 23:57:46 +0200
-Subject: [PATCH 4024/4031] sunxi: add support for UART3 on PE pins
-
-Some boards use Port E pins for muxing the UART3 as console. Add a new
-Kconfig option allowing to select this (mimicking MMC_PINS_PH).
-
-Pinmux taken from https://bbs.aw-ol.com/assets/uploads/files/1648883311844-t113-s3_datasheet_v1.2.pdf
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/arm/mach-sunxi/Kconfig | 6 ++++++
- arch/arm/mach-sunxi/board.c | 10 ++++++++--
- arch/riscv/dts/sunxi-d1s-t113.dtsi | 6 ++++++
- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 4 ++++
- 4 files changed, 24 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index 142d86afc6..59fa62c8d5 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -665,6 +665,12 @@ config UART0_PORT_F
- at the same time, the system can be only booted in the FEL mode.
- Only enable this if you really know what you are doing.
-
-+config UART3_PINS_PE
-+ bool "Pins for uart3 are on Port E"
-+ ---help---
-+ Select this option for boards where uart3 uses the Port E pinmux.
-+ (Some T113-S3 boards use uart3 as console.)
-+
- config OLD_SUNXI_KERNEL_COMPAT
- bool "Enable workarounds for booting old kernels"
- ---help---
-diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
-index 6a37b33767..5de490feda 100644
---- a/arch/arm/mach-sunxi/board.c
-+++ b/arch/arm/mach-sunxi/board.c
-@@ -168,16 +168,22 @@ static int gpio_init(void)
- sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
- sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP);
- #elif CONFIG_CONS_INDEX == 4 && defined(CONFIG_MACH_SUN8I_R528)
-+#if defined(CONFIG_UART3_PINS_PE)
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(8), 5);
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(9), 5);
-+ sunxi_gpio_set_pull(SUNXI_GPE(9), SUNXI_GPIO_PULL_UP);
-+#else
- sunxi_gpio_set_cfgpin(SUNXI_GPB(6), 7);
- sunxi_gpio_set_cfgpin(SUNXI_GPB(7), 7);
- sunxi_gpio_set_pull(SUNXI_GPB(7), SUNXI_GPIO_PULL_UP);
-+#endif
- #elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
- sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
- sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
- sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP);
- #elif CONFIG_CONS_INDEX == 6 && defined(CONFIG_MACH_SUN8I_R528)
-- sunxi_gpio_set_cfgpin(SUNXI_GPE(6), 9);
-- sunxi_gpio_set_cfgpin(SUNXI_GPE(7), 9);
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(6), 3);
-+ sunxi_gpio_set_cfgpin(SUNXI_GPE(7), 3);
- sunxi_gpio_set_pull(SUNXI_GPE(7), SUNXI_GPIO_PULL_UP);
- #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN8I) && \
- !defined(CONFIG_MACH_SUN8I_R40)
-diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-index 2b7d54aab4..d858f21fd2 100644
---- a/arch/riscv/dts/sunxi-d1s-t113.dtsi
-+++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-@@ -126,6 +126,12 @@
- function = "uart3";
- };
-
-+ /omit-if-no-ref/
-+ uart3_pe_pins: uart3-pe-pins {
-+ pins = "PE8", "PE9";
-+ function = "uart3";
-+ };
-+
- /omit-if-no-ref/
- uart0_pins: uart0-pins {
- pins = "PE2", "PE3";
-diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-index 2717d79bc3..e466808e4e 100644
---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
-@@ -747,7 +747,11 @@ static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
- #else
- { "uart0", 6 }, /* PB2-PB3 */
- #endif
-+#if IS_ENABLED(CONFIG_UART3_PINS_E)
-+ { "uart3", 5 }, /* PE8-PE9 */
-+else
- { "uart3", 7 }, /* PB6-PB9 */
-+#endif
- { "uart5", 3 }, /* PE6-PE7 */
- };
-
---
-2.20.1
-
--- /dev/null
+From 32020fad9d2fc6ce8f6e67af2ac7c9c6e7c47dec Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:46:05 +0100
+Subject: [PATCH 4025/4044] ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi
+
+The Allwinner T113-s SoC is apparently using the same (or at least a very
+similar) die as the D1/D1s, but replaces the single RISC-V core with
+two Arm Cortex-A7 cores.
+Since the D1 core .dtsi already describes all common peripherals, we
+just need a DT describing the ARM specific peripherals: the CPU cores,
+the Generic Timer, the GIC and the PMU.
+We include the core .dtsi directly from the riscv DT directory.
+
+The ARM core version of the DT specifies the CPUX watchdog as
+"reserved", which means it won't be recognised by U-Boot. Override this
+in our generic sunxi-u-boot.dtsi, to let U-Boot pick up this watchdog,
+so that the generic reset driver will work.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Sam Edwards <CFSworks@gmail.com>
+Tested-by: Sam Edwards <CFSworks@gmail.com>
+---
+ arch/arm/dts/sun8i-t113s.dtsi | 59 ++++++++++++++++++++++++++++++++++
+ arch/arm/dts/sunxi-u-boot.dtsi | 7 ++++
+ 2 files changed, 66 insertions(+)
+ create mode 100644 arch/arm/dts/sun8i-t113s.dtsi
+
+diff --git a/arch/arm/dts/sun8i-t113s.dtsi b/arch/arm/dts/sun8i-t113s.dtsi
+new file mode 100644
+index 0000000000..ce00883130
+--- /dev/null
++++ b/arch/arm/dts/sun8i-t113s.dtsi
+@@ -0,0 +1,59 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2022 Arm Ltd.
++
++#define SOC_PERIPHERAL_IRQ(nr) GIC_SPI nr
++
++#include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <../../riscv/dts/sunxi-d1s-t113.dtsi>
++#include <../../riscv/dts/sunxi-d1-t113.dtsi>
++
++/ {
++ interrupt-parent = <&gic>;
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu0: cpu@0 {
++ compatible = "arm,cortex-a7";
++ device_type = "cpu";
++ reg = <0>;
++ clocks = <&ccu CLK_CPUX>;
++ clock-names = "cpu";
++ };
++
++ cpu1: cpu@1 {
++ compatible = "arm,cortex-a7";
++ device_type = "cpu";
++ reg = <1>;
++ clocks = <&ccu CLK_CPUX>;
++ clock-names = "cpu";
++ };
++ };
++
++ gic: interrupt-controller@1c81000 {
++ compatible = "arm,gic-400";
++ reg = <0x03021000 0x1000>,
++ <0x03022000 0x2000>,
++ <0x03024000 0x2000>,
++ <0x03026000 0x2000>;
++ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
++ interrupt-controller;
++ #interrupt-cells = <3>;
++ };
++
++ timer {
++ compatible = "arm,armv7-timer";
++ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
++ };
++
++ pmu {
++ compatible = "arm,cortex-a7-pmu";
++ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-affinity = <&cpu0>, <&cpu1>;
++ };
++};
+diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
+index e959eb2a40..27de5b8eac 100644
+--- a/arch/arm/dts/sunxi-u-boot.dtsi
++++ b/arch/arm/dts/sunxi-u-boot.dtsi
+@@ -23,6 +23,13 @@
+ };
+ };
+
++/* Let U-Boot be the firmware layer that controls the watchdog. */
++#ifdef CONFIG_MACH_SUN8I_R528
++&wdt {
++ status = "okay";
++};
++#endif
++
+ &binman {
+ u-boot-sunxi-with-spl {
+ filename = "u-boot-sunxi-with-spl.bin";
+--
+2.20.1
+
+++ /dev/null
-From d3a69c14de1b3b2e61bfeb421f0f0f4ecec1207e Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sat, 3 Jun 2023 23:42:33 +0200
-Subject: [PATCH 4025/4031] sunxi: add support for Rongpin RP-T113 board
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/arm/dts/Makefile | 3 +-
- arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts | 98 ++++++++++++++++++++
- configs/rongpin_rp_t113_defconfig | 18 ++++
- 3 files changed, 118 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
- create mode 100644 configs/rongpin_rp_t113_defconfig
-
-diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
-index 6fb49de59a..be89021657 100644
---- a/arch/arm/dts/Makefile
-+++ b/arch/arm/dts/Makefile
-@@ -713,7 +713,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
- dtb-$(CONFIG_MACH_SUN8I_R528) += \
- sun8i-t113s-mangopi-mq-r-t113.dtb \
- sun8i-t113s-mangopi-mqdual-t113.dtb \
-- sun8i-t113s-myir-myd-yt113x.dtb
-+ sun8i-t113s-myir-myd-yt113x.dtb \
-+ sun8i-t113s-rongpin-rp-t113.dtb
- dtb-$(CONFIG_MACH_SUN50I_H5) += \
- sun50i-h5-bananapi-m2-plus.dtb \
- sun50i-h5-emlid-neutis-n5-devboard.dtb \
-diff --git a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-new file mode 100644
-index 0000000000..6ac2c065c4
---- /dev/null
-+++ b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-@@ -0,0 +1,98 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2022 Arm Ltd.
-+
-+#include <dt-bindings/interrupt-controller/irq.h>
-+
-+/dts-v1/;
-+
-+#include "sun8i-t113s.dtsi"
-+
-+/ {
-+ model = "Rongpin RP-T113";
-+ compatible = "rongpin,rp-t113", "allwinner,sun8i-t113s";
-+
-+ aliases {
-+ serial3 = &uart3;
-+ };
-+
-+ chosen {
-+ stdout-path = "serial3:115200n8";
-+ };
-+
-+ /* board wide 5V supply directly from the USB-C socket */
-+ reg_vcc5v: regulator-5v {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc-5v";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ regulator-always-on;
-+ };
-+
-+ /* SY8008 DC/DC regulator on the board */
-+ reg_3v3: regulator-3v3 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc-3v3";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ vin-supply = <®_vcc5v>;
-+ };
-+
-+ /* SY8008 DC/DC regulator on the board, also supplying VDD-SYS */
-+ reg_vcc_core: regulator-core {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc-core";
-+ regulator-min-microvolt = <880000>;
-+ regulator-max-microvolt = <880000>;
-+ vin-supply = <®_vcc5v>;
-+ };
-+
-+ /* XC6206 LDO on the board */
-+ reg_avdd2v8: regulator-avdd {
-+ compatible = "regulator-fixed";
-+ regulator-name = "avdd2v8";
-+ regulator-min-microvolt = <2800000>;
-+ regulator-max-microvolt = <2800000>;
-+ vin-supply = <®_3v3>;
-+ };
-+};
-+
-+&cpu0 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&cpu1 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&pio {
-+ vcc-pb-supply = <®_3v3>;
-+ vcc-pd-supply = <®_3v3>;
-+ vcc-pe-supply = <®_avdd2v8>;
-+ vcc-pf-supply = <®_3v3>;
-+ vcc-pg-supply = <®_3v3>;
-+};
-+
-+&uart3 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart3_pe_pins>;
-+ status = "okay";
-+};
-+
-+&mmc0 {
-+ pinctrl-0 = <&mmc0_pins>;
-+ pinctrl-names = "default";
-+ vmmc-supply = <®_3v3>;
-+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
-+ disable-wp;
-+ bus-width = <4>;
-+ status = "okay";
-+};
-+
-+&mmc2 {
-+ pinctrl-0 = <&mmc2_pins>;
-+ pinctrl-names = "default";
-+ vmmc-supply = <®_3v3>;
-+ non-removable;
-+ bus-width = <4>;
-+ status = "okay";
-+};
-diff --git a/configs/rongpin_rp_t113_defconfig b/configs/rongpin_rp_t113_defconfig
-new file mode 100644
-index 0000000000..9b5a5bcd65
---- /dev/null
-+++ b/configs/rongpin_rp_t113_defconfig
-@@ -0,0 +1,18 @@
-+CONFIG_ARM=y
-+CONFIG_ARCH_SUNXI=y
-+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-rongpin-rp-t113"
-+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
-+CONFIG_SPL=y
-+CONFIG_MACH_SUN8I_R528=y
-+CONFIG_CONS_INDEX=4
-+CONFIG_MMC0_CD_PIN="PF6"
-+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-+CONFIG_SYS_MONITOR_LEN=786432
-+CONFIG_DRAM_CLK=792
-+CONFIG_DRAM_ZQ=8092667
-+CONFIG_DRAM_SUNXI_ODT_EN=0
-+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
-+CONFIG_DRAM_SUNXI_TPR11=0x340000
-+CONFIG_DRAM_SUNXI_TPR12=0x46
-+CONFIG_DRAM_SUNXI_TPR13=0x34000100
-+CONFIG_UART3_PINS_PE=y
---
-2.20.1
-
+++ /dev/null
-From 7dbc707b5911c28724c2f5a220315513bf9ce3f3 Mon Sep 17 00:00:00 2001
-From: Yegor Yefremov <yegorslists@googlemail.com>
-Date: Wed, 28 Nov 2012 11:15:18 +0100
-Subject: [PATCH 4026/4031] net: add ICPlus PHY driver
-
-The driver code was taken from Linux kernel source:
-drivers/net/phy/icplus.c
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
-Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
----
- drivers/net/phy/Kconfig | 3 ++
- drivers/net/phy/Makefile | 1 +
- drivers/net/phy/icplus.c | 94 ++++++++++++++++++++++++++++++++++++++++
- drivers/net/phy/phy.c | 3 ++
- include/phy.h | 1 +
- 5 files changed, 102 insertions(+)
- create mode 100644 drivers/net/phy/icplus.c
-
-diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
-index 5eaff053a0..93980398f1 100644
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -165,6 +165,9 @@ config PHY_DAVICOM
- config PHY_ET1011C
- bool "LSI TruePHY ET1011C support"
-
-+config PHY_ICPLUS
-+ bool "IC+ IP101 Ethernet PHY support"
-+
- config PHY_LXT
- bool "LXT971 Ethernet PHY support"
-
-diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
-index d38e99e717..5b6b78631d 100644
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -18,6 +18,7 @@ obj-$(CONFIG_PHY_CORTINA) += cortina.o
- obj-$(CONFIG_PHY_CORTINA_ACCESS) += ca_phy.o
- obj-$(CONFIG_PHY_DAVICOM) += davicom.o
- obj-$(CONFIG_PHY_ET1011C) += et1011c.o
-+obj-$(CONFIG_PHY_ICPLUS) += icplus.o
- obj-$(CONFIG_PHY_LXT) += lxt.o
- obj-$(CONFIG_PHY_MARVELL) += marvell.o
- obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
-diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
-new file mode 100644
-index 0000000000..dd5c59259d
---- /dev/null
-+++ b/drivers/net/phy/icplus.c
-@@ -0,0 +1,94 @@
-+/*
-+ * ICPlus PHY drivers
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ *
-+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
-+ *
-+ */
-+#include <phy.h>
-+
-+/* IP101A/G - IP1001 */
-+#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
-+#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
-+#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */
-+#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
-+#define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */
-+#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
-+#define IP101A_G_IRQ_PIN_USED (1<<15) /* INTR pin used */
-+#define IP101A_G_IRQ_DEFAULT IP101A_G_IRQ_PIN_USED
-+
-+static int ip1001_config(struct phy_device *phydev)
-+{
-+ int c;
-+
-+ /* Enable Auto Power Saving mode */
-+ c = phy_read(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2);
-+ if (c < 0)
-+ return c;
-+ c |= IP1001_APS_ON;
-+ c = phy_write(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2, c);
-+ if (c < 0)
-+ return c;
-+
-+ /* INTR pin used: speed/link/duplex will cause an interrupt */
-+ c = phy_write(phydev, MDIO_DEVAD_NONE, IP101A_G_IRQ_CONF_STATUS,
-+ IP101A_G_IRQ_DEFAULT);
-+ if (c < 0)
-+ return c;
-+
-+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
-+ /*
-+ * Additional delay (2ns) used to adjust RX clock phase
-+ * at RGMII interface
-+ */
-+ c = phy_read(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS);
-+ if (c < 0)
-+ return c;
-+
-+ c |= IP1001_PHASE_SEL_MASK;
-+ c = phy_write(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS,
-+ c);
-+ if (c < 0)
-+ return c;
-+ }
-+
-+ return 0;
-+}
-+
-+static int ip1001_startup(struct phy_device *phydev)
-+{
-+ genphy_update_link(phydev);
-+ genphy_parse_link(phydev);
-+
-+ return 0;
-+}
-+static struct phy_driver IP1001_driver = {
-+ .name = "ICPlus IP1001",
-+ .uid = 0x02430d90,
-+ .mask = 0x0ffffff0,
-+ .features = PHY_GBIT_FEATURES,
-+ .config = &ip1001_config,
-+ .startup = &ip1001_startup,
-+ .shutdown = &genphy_shutdown,
-+};
-+
-+int phy_icplus_init(void)
-+{
-+ phy_register(&IP1001_driver);
-+
-+ return 0;
-+}
-diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
-index 80230b907c..9e22db3fc8 100644
---- a/drivers/net/phy/phy.c
-+++ b/drivers/net/phy/phy.c
-@@ -514,6 +514,9 @@ int phy_init(void)
- #ifdef CONFIG_PHY_ET1011C
- phy_et1011c_init();
- #endif
-+#ifdef CONFIG_PHY_ICPLUS
-+ phy_icplus_init();
-+#endif
- #ifdef CONFIG_PHY_LXT
- phy_lxt_init();
- #endif
-diff --git a/include/phy.h b/include/phy.h
-index 87aa86c2e7..749285f15e 100644
---- a/include/phy.h
-+++ b/include/phy.h
-@@ -325,6 +325,7 @@ int phy_cortina_init(void);
- int phy_cortina_access_init(void);
- int phy_davicom_init(void);
- int phy_et1011c_init(void);
-+int phy_icplus_init(void);
- int phy_lxt_init(void);
- int phy_marvell_init(void);
- int phy_micrel_ksz8xxx_init(void);
---
-2.20.1
-
--- /dev/null
+From 3cab8f3bd34a0d16fca67ad10ec2ad413fdc99da Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:46:06 +0100
+Subject: [PATCH 4026/4044] sunxi: add MangoPi MQ-R board support
+
+This copies the T113s specific DTs from the Linux kernel tree
+(v6.4-rc1), and adds a defconfig to get the board booted.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/dts/Makefile | 2 +
+ .../arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts | 35 +++++
+ arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi | 126 ++++++++++++++++++
+ configs/mangopi_mq_r_defconfig | 15 +++
+ 4 files changed, 178 insertions(+)
+ create mode 100644 arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
+ create mode 100644 arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
+ create mode 100644 configs/mangopi_mq_r_defconfig
+
+diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+index c160e884bf..41ee9c4c65 100644
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -710,6 +710,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
+ sun8i-s3-pinecube.dtb \
+ sun8i-v3-sl631-imx179.dtb \
+ sun8i-v3s-licheepi-zero.dtb
++dtb-$(CONFIG_MACH_SUN8I_R528) += \
++ sun8i-t113s-mangopi-mq-r-t113.dtb
+ dtb-$(CONFIG_MACH_SUN50I_H5) += \
+ sun50i-h5-bananapi-m2-plus.dtb \
+ sun50i-h5-emlid-neutis-n5-devboard.dtb \
+diff --git a/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
+new file mode 100644
+index 0000000000..94e24b5926
+--- /dev/null
++++ b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
+@@ -0,0 +1,35 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2022 Arm Ltd.
++
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/dts-v1/;
++
++#include "sun8i-t113s.dtsi"
++#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
++
++/ {
++ model = "MangoPi MQ-R-T113";
++ compatible = "widora,mangopi-mq-r-t113", "allwinner,sun8i-t113s";
++
++ aliases {
++ ethernet0 = &rtl8189ftv;
++ };
++};
++
++&cpu0 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&cpu1 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&mmc1 {
++ rtl8189ftv: wifi@1 {
++ reg = <1>;
++ interrupt-parent = <&pio>;
++ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 = WL_WAKE_AP */
++ interrupt-names = "host-wake";
++ };
++};
+diff --git a/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
+new file mode 100644
+index 0000000000..e9bc749488
+--- /dev/null
++++ b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
+@@ -0,0 +1,126 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2022 Arm Ltd.
++/*
++ * Common peripherals and configurations for MangoPi MQ-R boards.
++ */
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++ aliases {
++ serial3 = &uart3;
++ };
++
++ chosen {
++ stdout-path = "serial3:115200n8";
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led-0 {
++ color = <LED_COLOR_ID_BLUE>;
++ function = LED_FUNCTION_STATUS;
++ gpios = <&pio 3 22 GPIO_ACTIVE_LOW>; /* PD22 */
++ };
++ };
++
++ /* board wide 5V supply directly from the USB-C socket */
++ reg_vcc5v: regulator-5v {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-5v";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
++
++ /* SY8008 DC/DC regulator on the board */
++ reg_3v3: regulator-3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <®_vcc5v>;
++ };
++
++ /* SY8008 DC/DC regulator on the board, also supplying VDD-SYS */
++ reg_vcc_core: regulator-core {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-core";
++ regulator-min-microvolt = <880000>;
++ regulator-max-microvolt = <880000>;
++ vin-supply = <®_vcc5v>;
++ };
++
++ /* XC6206 LDO on the board */
++ reg_avdd2v8: regulator-avdd {
++ compatible = "regulator-fixed";
++ regulator-name = "avdd2v8";
++ regulator-min-microvolt = <2800000>;
++ regulator-max-microvolt = <2800000>;
++ vin-supply = <®_3v3>;
++ };
++
++ wifi_pwrseq: wifi-pwrseq {
++ compatible = "mmc-pwrseq-simple";
++ reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
++ };
++};
++
++&dcxo {
++ clock-frequency = <24000000>;
++};
++
++&ehci1 {
++ status = "okay";
++};
++
++&mmc0 {
++ pinctrl-0 = <&mmc0_pins>;
++ pinctrl-names = "default";
++ vmmc-supply = <®_3v3>;
++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
++ disable-wp;
++ bus-width = <4>;
++ status = "okay";
++};
++
++&mmc1 {
++ pinctrl-0 = <&mmc1_pins>;
++ pinctrl-names = "default";
++ vmmc-supply = <®_3v3>;
++ non-removable;
++ bus-width = <4>;
++ mmc-pwrseq = <&wifi_pwrseq>;
++ status = "okay";
++};
++
++&ohci1 {
++ status = "okay";
++};
++
++&pio {
++ vcc-pb-supply = <®_3v3>;
++ vcc-pd-supply = <®_3v3>;
++ vcc-pe-supply = <®_avdd2v8>;
++ vcc-pf-supply = <®_3v3>;
++ vcc-pg-supply = <®_3v3>;
++};
++
++&uart3 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart3_pb_pins>;
++ status = "okay";
++};
++
++/* The USB-C socket has its CC pins pulled to GND, so is hardwired as a UFP. */
++&usb_otg {
++ dr_mode = "peripheral";
++ status = "okay";
++};
++
++&usbphy {
++ usb1_vbus-supply = <®_vcc5v>;
++ status = "okay";
++};
+diff --git a/configs/mangopi_mq_r_defconfig b/configs/mangopi_mq_r_defconfig
+new file mode 100644
+index 0000000000..66ae639326
+--- /dev/null
++++ b/configs/mangopi_mq_r_defconfig
+@@ -0,0 +1,15 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-mangopi-mq-r-t113"
++CONFIG_SPL=y
++CONFIG_MACH_SUN8I_R528=y
++CONFIG_DRAM_CLK=792
++CONFIG_DRAM_ZQ=8092667
++CONFIG_SUNXI_MINIMUM_DRAM_MB=128
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_DRAM_SUNXI_ODT_EN=0
++CONFIG_DRAM_SUNXI_TPR0=0x004a2195
++CONFIG_DRAM_SUNXI_TPR11=0x340000
++CONFIG_DRAM_SUNXI_TPR12=0x46
++CONFIG_DRAM_SUNXI_TPR13=0x34000100
++CONFIG_CONS_INDEX=4
+--
+2.20.1
+
--- /dev/null
+From f9950a4c4cbabde0c07f4b2e3fdeee52b0c1f788 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 3 Jun 2023 00:52:04 +0200
+Subject: [PATCH 4027/4044] sunxi: add uart0_pins on Port E PE2/PE3 on D1s/T133
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/riscv/dts/sunxi-d1s-t113.dtsi | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+index 922e8e0e2c..b1f97bd0bc 100644
+--- a/arch/riscv/dts/sunxi-d1s-t113.dtsi
++++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+@@ -125,6 +125,12 @@
+ pins = "PB6", "PB7";
+ function = "uart3";
+ };
++
++ /omit-if-no-ref/
++ uart0_pins: uart0-pins {
++ pins = "PE2", "PE3";
++ function = "uart0";
++ };
+ };
+
+ ccu: clock-controller@2001000 {
+--
+2.20.1
+
+++ /dev/null
-From 789c1062934120dcbf4f88a867638f23dcfc1c39 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sun, 4 Jun 2023 15:40:42 +0200
-Subject: [PATCH 4027/4031] sunxi: enable emac on Rongpin RP-T113
-
-The emac is connected to an IC+ IP101 PHY, for which the driver
-has been re-added (it was removed in 2014).
-
-Currently the driver init fails with the below, so further tweaking
-will be required.
-
-CPU: Allwinner R528 (SUN8I)
-Model: Rongpin RP-T113
-DRAM: 128 MiB
-Core: 36 devices, 15 uclasses, devicetree: separate
-MMC: mmc@4020000: 0, mmc@4022000: 1
-Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1...
-In: serial@2500c00
-Out: serial@2500c00
-Err: serial@2500c00
-Net: eth_sun8i_emac ethernet@4500000: failed to get TX clock
-No ethernet found.
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts | 28 ++++++++++++++++++++
- configs/rongpin_rp_t113_defconfig | 3 +++
- 2 files changed, 31 insertions(+)
-
-diff --git a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-index 6ac2c065c4..f2521438fb 100644
---- a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-+++ b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-@@ -54,6 +54,16 @@
- regulator-max-microvolt = <2800000>;
- vin-supply = <®_3v3>;
- };
-+
-+ reg_gmac_3v3: gmac-3v3 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "gmac-3v3";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ startup-delay-us = <100000>;
-+ enable-active-high;
-+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */
-+ };
- };
-
- &cpu0 {
-@@ -78,6 +88,17 @@
- status = "okay";
- };
-
-+&emac {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&rmii_pe_pins>;
-+
-+ phy-supply = <®_3v3>;
-+ phy-handle = <&ext_rgmii_phy>;
-+ phy-mode = "rmii";
-+
-+ status = "okay";
-+};
-+
- &mmc0 {
- pinctrl-0 = <&mmc0_pins>;
- pinctrl-names = "default";
-@@ -96,3 +117,10 @@
- bus-width = <4>;
- status = "okay";
- };
-+
-+&mdio {
-+ ext_rgmii_phy: ethernet-phy@1 {
-+ compatible = "ethernet-phy-ieee802.3-c22";
-+ reg = <1>;
-+ };
-+};
-diff --git a/configs/rongpin_rp_t113_defconfig b/configs/rongpin_rp_t113_defconfig
-index 9b5a5bcd65..e234934f50 100644
---- a/configs/rongpin_rp_t113_defconfig
-+++ b/configs/rongpin_rp_t113_defconfig
-@@ -16,3 +16,6 @@ CONFIG_DRAM_SUNXI_TPR11=0x340000
- CONFIG_DRAM_SUNXI_TPR12=0x46
- CONFIG_DRAM_SUNXI_TPR13=0x34000100
- CONFIG_UART3_PINS_PE=y
-+CONFIG_SUN8I_EMAC=y
-+CONFIG_PHY_ICPLUS=y
-+CONFIG_RMII=y
---
-2.20.1
-
+++ /dev/null
-From 9dd54fb43abdb66b42679eb668612b9e055a962e Mon Sep 17 00:00:00 2001
-From: Yanhong Wang <yanhong.wang@starfivetech.com>
-Date: Thu, 25 May 2023 17:36:27 +0800
-Subject: [PATCH 4028/4031] net: phy: Add driver for Motorcomm yt8531 gigabit
- ethernet phy
-
-Add a driver for the motorcomm yt8531 gigabit ethernet phy. We have
-verified the driver on StarFive VisionFive2 board.
-
-Signed-off-by: Yanhong Wang <yanhong.wang@starfivetech.com>
-Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
----
- drivers/net/phy/Kconfig | 6 +
- drivers/net/phy/Makefile | 1 +
- drivers/net/phy/motorcomm.c | 437 ++++++++++++++++++++++++++++++++++++
- 3 files changed, 444 insertions(+)
- create mode 100644 drivers/net/phy/motorcomm.c
-
-diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
-index 93980398f1..0a99682c27 100644
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -215,6 +215,12 @@ config PHY_MICREL_KSZ8XXX
-
- endif # PHY_MICREL
-
-+config PHY_MOTORCOMM
-+ tristate "Motorcomm PHYs"
-+ help
-+ Enables support for Motorcomm network PHYs.
-+ Currently supports the YT8531 Gigabit Ethernet PHYs.
-+
- config PHY_MSCC
- bool "Microsemi Corp Ethernet PHYs support"
-
-diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
-index 5b6b78631d..9637a138f8 100644
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -24,6 +24,7 @@ obj-$(CONFIG_PHY_MARVELL) += marvell.o
- obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
- obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
- obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
-+obj-$(CONFIG_PHY_MOTORCOMM) += motorcomm.o
- obj-$(CONFIG_PHY_NATSEMI) += natsemi.o
- obj-$(CONFIG_PHY_NXP_C45_TJA11XX) += nxp-c45-tja11xx.o
- obj-$(CONFIG_PHY_NXP_TJA11XX) += nxp-tja11xx.o
-diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
-new file mode 100644
-index 0000000000..e822fd76f2
---- /dev/null
-+++ b/drivers/net/phy/motorcomm.c
-@@ -0,0 +1,437 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * Motorcomm 8531 PHY driver.
-+ *
-+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <config.h>
-+#include <common.h>
-+#include <malloc.h>
-+#include <phy.h>
-+#include <linux/bitfield.h>
-+
-+#define PHY_ID_YT8531 0x4f51e91b
-+#define PHY_ID_MASK GENMASK(31, 0)
-+
-+/* Extended Register's Address Offset Register */
-+#define YTPHY_PAGE_SELECT 0x1E
-+
-+/* Extended Register's Data Register */
-+#define YTPHY_PAGE_DATA 0x1F
-+
-+#define YTPHY_SYNCE_CFG_REG 0xA012
-+
-+#define YTPHY_DTS_OUTPUT_CLK_DIS 0
-+#define YTPHY_DTS_OUTPUT_CLK_25M 25000000
-+#define YTPHY_DTS_OUTPUT_CLK_125M 125000000
-+
-+#define YT8531_SCR_SYNCE_ENABLE BIT(6)
-+/* 1b0 output 25m clock *default*
-+ * 1b1 output 125m clock
-+ */
-+#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4)
-+#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1)
-+#define YT8531_SCR_CLK_SRC_PLL_125M 0
-+#define YT8531_SCR_CLK_SRC_UTP_RX 1
-+#define YT8531_SCR_CLK_SRC_SDS_RX 2
-+#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3
-+#define YT8531_SCR_CLK_SRC_REF_25M 4
-+#define YT8531_SCR_CLK_SRC_SSC_25M 5
-+
-+/* 1b0 use original tx_clk_rgmii *default*
-+ * 1b1 use inverted tx_clk_rgmii.
-+ */
-+#define YT8531_RC1R_TX_CLK_SEL_INVERTED BIT(14)
-+#define YT8531_RC1R_RX_DELAY_MASK GENMASK(13, 10)
-+#define YT8531_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4)
-+#define YT8531_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0)
-+#define YT8531_RC1R_RGMII_0_000_NS 0
-+#define YT8531_RC1R_RGMII_0_150_NS 1
-+#define YT8531_RC1R_RGMII_0_300_NS 2
-+#define YT8531_RC1R_RGMII_0_450_NS 3
-+#define YT8531_RC1R_RGMII_0_600_NS 4
-+#define YT8531_RC1R_RGMII_0_750_NS 5
-+#define YT8531_RC1R_RGMII_0_900_NS 6
-+#define YT8531_RC1R_RGMII_1_050_NS 7
-+#define YT8531_RC1R_RGMII_1_200_NS 8
-+#define YT8531_RC1R_RGMII_1_350_NS 9
-+#define YT8531_RC1R_RGMII_1_500_NS 10
-+#define YT8531_RC1R_RGMII_1_650_NS 11
-+#define YT8531_RC1R_RGMII_1_800_NS 12
-+#define YT8531_RC1R_RGMII_1_950_NS 13
-+#define YT8531_RC1R_RGMII_2_100_NS 14
-+#define YT8531_RC1R_RGMII_2_250_NS 15
-+
-+/* Phy gmii clock gating Register */
-+#define YT8531_CLOCK_GATING_REG 0xC
-+#define YT8531_CGR_RX_CLK_EN BIT(12)
-+
-+/* Specific Status Register */
-+#define YTPHY_SPECIFIC_STATUS_REG 0x11
-+#define YTPHY_DUPLEX_MASK BIT(13)
-+#define YTPHY_DUPLEX_SHIFT 13
-+#define YTPHY_SPEED_MODE_MASK GENMASK(15, 14)
-+#define YTPHY_SPEED_MODE_SHIFT 14
-+
-+#define YT8531_EXTREG_SLEEP_CONTROL1_REG 0x27
-+#define YT8531_ESC1R_SLEEP_SW BIT(15)
-+#define YT8531_ESC1R_PLLON_SLP BIT(14)
-+
-+#define YT8531_RGMII_CONFIG1_REG 0xA003
-+
-+#define YT8531_CHIP_CONFIG_REG 0xA001
-+#define YT8531_CCR_SW_RST BIT(15)
-+/* 1b0 disable 1.9ns rxc clock delay *default*
-+ * 1b1 enable 1.9ns rxc clock delay
-+ */
-+#define YT8531_CCR_RXC_DLY_EN BIT(8)
-+#define YT8531_CCR_RXC_DLY_1_900_NS 1900
-+
-+/* bits in struct ytphy_plat_priv->flag */
-+#define TX_CLK_ADJ_ENABLED BIT(0)
-+#define AUTO_SLEEP_DISABLED BIT(1)
-+#define KEEP_PLL_ENABLED BIT(2)
-+#define TX_CLK_10_INVERTED BIT(3)
-+#define TX_CLK_100_INVERTED BIT(4)
-+#define TX_CLK_1000_INVERTED BIT(5)
-+
-+struct ytphy_plat_priv {
-+ u32 rx_delay_ps;
-+ u32 tx_delay_ps;
-+ u32 clk_out_frequency;
-+ u32 flag;
-+};
-+
-+/**
-+ * struct ytphy_cfg_reg_map - map a config value to a register value
-+ * @cfg: value in device configuration
-+ * @reg: value in the register
-+ */
-+struct ytphy_cfg_reg_map {
-+ u32 cfg;
-+ u32 reg;
-+};
-+
-+static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = {
-+ /* for tx delay / rx delay with YT8531_CCR_RXC_DLY_EN is not set. */
-+ { 0, YT8531_RC1R_RGMII_0_000_NS },
-+ { 150, YT8531_RC1R_RGMII_0_150_NS },
-+ { 300, YT8531_RC1R_RGMII_0_300_NS },
-+ { 450, YT8531_RC1R_RGMII_0_450_NS },
-+ { 600, YT8531_RC1R_RGMII_0_600_NS },
-+ { 750, YT8531_RC1R_RGMII_0_750_NS },
-+ { 900, YT8531_RC1R_RGMII_0_900_NS },
-+ { 1050, YT8531_RC1R_RGMII_1_050_NS },
-+ { 1200, YT8531_RC1R_RGMII_1_200_NS },
-+ { 1350, YT8531_RC1R_RGMII_1_350_NS },
-+ { 1500, YT8531_RC1R_RGMII_1_500_NS },
-+ { 1650, YT8531_RC1R_RGMII_1_650_NS },
-+ { 1800, YT8531_RC1R_RGMII_1_800_NS },
-+ { 1950, YT8531_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */
-+ { 2100, YT8531_RC1R_RGMII_2_100_NS },
-+ { 2250, YT8531_RC1R_RGMII_2_250_NS },
-+
-+ /* only for rx delay with YT8531_CCR_RXC_DLY_EN is set. */
-+ { 0 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_000_NS },
-+ { 150 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_150_NS },
-+ { 300 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_300_NS },
-+ { 450 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_450_NS },
-+ { 600 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_600_NS },
-+ { 750 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_750_NS },
-+ { 900 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_900_NS },
-+ { 1050 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_050_NS },
-+ { 1200 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_200_NS },
-+ { 1350 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_350_NS },
-+ { 1500 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_500_NS },
-+ { 1650 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_650_NS },
-+ { 1800 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_800_NS },
-+ { 1950 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_950_NS },
-+ { 2100 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_100_NS },
-+ { 2250 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_250_NS }
-+};
-+
-+static u32 ytphy_get_delay_reg_value(struct phy_device *phydev,
-+ u32 val,
-+ u16 *rxc_dly_en)
-+{
-+ int tb_size = ARRAY_SIZE(ytphy_rgmii_delays);
-+ int tb_size_half = tb_size / 2;
-+ int i;
-+
-+ /* when rxc_dly_en is NULL, it is get the delay for tx, only half of
-+ * tb_size is valid.
-+ */
-+ if (!rxc_dly_en)
-+ tb_size = tb_size_half;
-+
-+ for (i = 0; i < tb_size; i++) {
-+ if (ytphy_rgmii_delays[i].cfg == val) {
-+ if (rxc_dly_en && i < tb_size_half)
-+ *rxc_dly_en = 0;
-+ return ytphy_rgmii_delays[i].reg;
-+ }
-+ }
-+
-+ pr_warn("Unsupported value %d, using default (%u)\n",
-+ val, YT8531_RC1R_RGMII_1_950_NS);
-+
-+ /* when rxc_dly_en is not NULL, it is get the delay for rx.
-+ * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps,
-+ * so YT8531_CCR_RXC_DLY_EN should not be set.
-+ */
-+ if (rxc_dly_en)
-+ *rxc_dly_en = 0;
-+
-+ return YT8531_RC1R_RGMII_1_950_NS;
-+}
-+
-+static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask,
-+ u16 set)
-+{
-+ int ret;
-+
-+ ret = phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_SELECT, regnum);
-+ if (ret < 0)
-+ return ret;
-+
-+ return phy_modify(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA, mask, set);
-+}
-+
-+static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev)
-+{
-+ struct ytphy_plat_priv *priv = phydev->priv;
-+ u16 rxc_dly_en = YT8531_CCR_RXC_DLY_EN;
-+ u32 rx_reg, tx_reg;
-+ u16 mask, val = 0;
-+ int ret;
-+
-+ rx_reg = ytphy_get_delay_reg_value(phydev, priv->rx_delay_ps,
-+ &rxc_dly_en);
-+ tx_reg = ytphy_get_delay_reg_value(phydev, priv->tx_delay_ps,
-+ NULL);
-+
-+ switch (phydev->interface) {
-+ case PHY_INTERFACE_MODE_RGMII:
-+ rxc_dly_en = 0;
-+ break;
-+ case PHY_INTERFACE_MODE_RGMII_RXID:
-+ val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg);
-+ break;
-+ case PHY_INTERFACE_MODE_RGMII_TXID:
-+ rxc_dly_en = 0;
-+ val |= FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
-+ break;
-+ case PHY_INTERFACE_MODE_RGMII_ID:
-+ val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg) |
-+ FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
-+ break;
-+ default: /* do not support other modes */
-+ return -EOPNOTSUPP;
-+ }
-+
-+ ret = ytphy_modify_ext(phydev, YT8531_CHIP_CONFIG_REG,
-+ YT8531_CCR_RXC_DLY_EN, rxc_dly_en);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* Generally, it is not necessary to adjust YT8531_RC1R_FE_TX_DELAY */
-+ mask = YT8531_RC1R_RX_DELAY_MASK | YT8531_RC1R_GE_TX_DELAY_MASK;
-+ return ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG, mask, val);
-+}
-+
-+static int yt8531_parse_status(struct phy_device *phydev)
-+{
-+ int val;
-+ int speed, speed_mode;
-+
-+ val = phy_read(phydev, MDIO_DEVAD_NONE, YTPHY_SPECIFIC_STATUS_REG);
-+ if (val < 0)
-+ return val;
-+
-+ speed_mode = (val & YTPHY_SPEED_MODE_MASK) >> YTPHY_SPEED_MODE_SHIFT;
-+ switch (speed_mode) {
-+ case 2:
-+ speed = SPEED_1000;
-+ break;
-+ case 1:
-+ speed = SPEED_100;
-+ break;
-+ default:
-+ speed = SPEED_10;
-+ break;
-+ }
-+
-+ phydev->speed = speed;
-+ phydev->duplex = (val & YTPHY_DUPLEX_MASK) >> YTPHY_DUPLEX_SHIFT;
-+
-+ return 0;
-+}
-+
-+static int yt8531_startup(struct phy_device *phydev)
-+{
-+ struct ytphy_plat_priv *priv = phydev->priv;
-+ u16 val = 0;
-+ int ret;
-+
-+ ret = genphy_update_link(phydev);
-+ if (ret)
-+ return ret;
-+
-+ ret = yt8531_parse_status(phydev);
-+ if (ret)
-+ return ret;
-+
-+ if (phydev->speed < 0)
-+ return -EINVAL;
-+
-+ if (!(priv->flag & TX_CLK_ADJ_ENABLED))
-+ return 0;
-+
-+ switch (phydev->speed) {
-+ case SPEED_1000:
-+ if (priv->flag & TX_CLK_1000_INVERTED)
-+ val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
-+ break;
-+ case SPEED_100:
-+ if (priv->flag & TX_CLK_100_INVERTED)
-+ val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
-+ break;
-+ case SPEED_10:
-+ if (priv->flag & TX_CLK_10_INVERTED)
-+ val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
-+ break;
-+ default:
-+ printf("UNKNOWN SPEED\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG,
-+ YT8531_RC1R_TX_CLK_SEL_INVERTED, val);
-+ if (ret < 0)
-+ pr_warn("Modify TX_CLK_SEL err:%d\n", ret);
-+
-+ return 0;
-+}
-+
-+static void ytphy_dt_parse(struct phy_device *phydev)
-+{
-+ struct ytphy_plat_priv *priv = phydev->priv;
-+
-+ priv->clk_out_frequency = ofnode_read_u32_default(phydev->node,
-+ "motorcomm,clk-out-frequency-hz",
-+ YTPHY_DTS_OUTPUT_CLK_DIS);
-+ priv->rx_delay_ps = ofnode_read_u32_default(phydev->node,
-+ "rx-internal-delay-ps",
-+ YT8531_RC1R_RGMII_1_950_NS);
-+ priv->tx_delay_ps = ofnode_read_u32_default(phydev->node,
-+ "tx-internal-delay-ps",
-+ YT8531_RC1R_RGMII_1_950_NS);
-+
-+ if (ofnode_read_bool(phydev->node, "motorcomm,auto-sleep-disabled"))
-+ priv->flag |= AUTO_SLEEP_DISABLED;
-+
-+ if (ofnode_read_bool(phydev->node, "motorcomm,keep-pll-enabled"))
-+ priv->flag |= KEEP_PLL_ENABLED;
-+
-+ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-adj-enabled"))
-+ priv->flag |= TX_CLK_ADJ_ENABLED;
-+
-+ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-10-inverted"))
-+ priv->flag |= TX_CLK_10_INVERTED;
-+
-+ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-100-inverted"))
-+ priv->flag |= TX_CLK_100_INVERTED;
-+
-+ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-1000-inverted"))
-+ priv->flag |= TX_CLK_1000_INVERTED;
-+}
-+
-+static int yt8531_config(struct phy_device *phydev)
-+{
-+ struct ytphy_plat_priv *priv = phydev->priv;
-+ u16 mask, val;
-+ int ret;
-+
-+ ret = genphy_config_aneg(phydev);
-+ if (ret < 0)
-+ return ret;
-+
-+ ytphy_dt_parse(phydev);
-+ switch (priv->clk_out_frequency) {
-+ case YTPHY_DTS_OUTPUT_CLK_DIS:
-+ mask = YT8531_SCR_SYNCE_ENABLE;
-+ val = 0;
-+ break;
-+ case YTPHY_DTS_OUTPUT_CLK_25M:
-+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
-+ YT8531_SCR_CLK_FRE_SEL_125M;
-+ val = YT8531_SCR_SYNCE_ENABLE |
-+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
-+ YT8531_SCR_CLK_SRC_REF_25M);
-+ break;
-+ case YTPHY_DTS_OUTPUT_CLK_125M:
-+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
-+ YT8531_SCR_CLK_FRE_SEL_125M;
-+ val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M |
-+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
-+ YT8531_SCR_CLK_SRC_PLL_125M);
-+ break;
-+ default:
-+ pr_warn("Freq err:%u\n", priv->clk_out_frequency);
-+ return -EINVAL;
-+ }
-+
-+ ret = ytphy_modify_ext(phydev, YTPHY_SYNCE_CFG_REG, mask,
-+ val);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = ytphy_rgmii_clk_delay_config(phydev);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (priv->flag & AUTO_SLEEP_DISABLED) {
-+ /* disable auto sleep */
-+ ret = ytphy_modify_ext(phydev,
-+ YT8531_EXTREG_SLEEP_CONTROL1_REG,
-+ YT8531_ESC1R_SLEEP_SW, 0);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ if (priv->flag & KEEP_PLL_ENABLED) {
-+ /* enable RXC clock when no wire plug */
-+ ret = ytphy_modify_ext(phydev,
-+ YT8531_CLOCK_GATING_REG,
-+ YT8531_CGR_RX_CLK_EN, 0);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static int yt8531_probe(struct phy_device *phydev)
-+{
-+ struct ytphy_plat_priv *priv;
-+
-+ priv = calloc(1, sizeof(struct ytphy_plat_priv));
-+ if (!priv)
-+ return -ENOMEM;
-+
-+ phydev->priv = priv;
-+
-+ return 0;
-+}
-+
-+U_BOOT_PHY_DRIVER(motorcomm8531) = {
-+ .name = "YT8531 Gigabit Ethernet",
-+ .uid = PHY_ID_YT8531,
-+ .mask = PHY_ID_MASK,
-+ .features = PHY_GBIT_FEATURES,
-+ .probe = &yt8531_probe,
-+ .config = &yt8531_config,
-+ .startup = &yt8531_startup,
-+ .shutdown = &genphy_shutdown,
-+};
---
-2.20.1
-
--- /dev/null
+From b4f63d64a10847dc64c456ddcf262ac5c5eea616 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 3 Jun 2023 00:52:40 +0200
+Subject: [PATCH 4028/4044] sunxi: add support for MangoPI MQDual T113 variant
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/dts/Makefile | 3 +-
+ .../dts/sun8i-t113s-mangopi-mqdual-t113.dts | 50 +++++++++++++++++++
+ configs/mangopi_mqdual_t113_defconfig | 17 +++++++
+ 3 files changed, 69 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts
+ create mode 100644 configs/mangopi_mqdual_t113_defconfig
+
+diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+index 41ee9c4c65..4207f17601 100644
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -711,7 +711,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
+ sun8i-v3-sl631-imx179.dtb \
+ sun8i-v3s-licheepi-zero.dtb
+ dtb-$(CONFIG_MACH_SUN8I_R528) += \
+- sun8i-t113s-mangopi-mq-r-t113.dtb
++ sun8i-t113s-mangopi-mq-r-t113.dtb \
++ sun8i-t113s-mangopi-mqdual-t113.dtb
+ dtb-$(CONFIG_MACH_SUN50I_H5) += \
+ sun50i-h5-bananapi-m2-plus.dtb \
+ sun50i-h5-emlid-neutis-n5-devboard.dtb \
+diff --git a/arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts b/arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts
+new file mode 100644
+index 0000000000..7de3ddb92f
+--- /dev/null
++++ b/arch/arm/dts/sun8i-t113s-mangopi-mqdual-t113.dts
+@@ -0,0 +1,50 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2022 Arm Ltd.
++
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/dts-v1/;
++
++#include "sun8i-t113s.dtsi"
++#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
++
++/ {
++ model = "MangoPi MQDual T113";
++ compatible = "widora,mangopi-mqdual-t113", "allwinner,sun8i-t113s";
++
++ aliases {
++ serial0 = &uart0;
++ ethernet0 = &rtl8189ftv;
++ };
++
++ chosen {
++ stdout-path = "serial0:115200n8";
++ };
++};
++
++&cpu0 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&cpu1 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&mmc1 {
++ rtl8189ftv: wifi@1 {
++ reg = <1>;
++ interrupt-parent = <&pio>;
++ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 = WL_WAKE_AP */
++ interrupt-names = "host-wake";
++ };
++};
++
++&uart0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pins>;
++ status = "okay";
++};
++
++&uart3 {
++ status = "disabled";
++};
+diff --git a/configs/mangopi_mqdual_t113_defconfig b/configs/mangopi_mqdual_t113_defconfig
+new file mode 100644
+index 0000000000..98b90c55f4
+--- /dev/null
++++ b/configs/mangopi_mqdual_t113_defconfig
+@@ -0,0 +1,17 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-mangopi-mqdual-t113"
++CONFIG_SUNXI_MINIMUM_DRAM_MB=128
++CONFIG_SPL=y
++CONFIG_MACH_SUN8I_R528=y
++CONFIG_CONS_INDEX=1
++CONFIG_MMC0_CD_PIN="PF6"
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_SYS_MONITOR_LEN=786432
++CONFIG_DRAM_CLK=792
++CONFIG_DRAM_ZQ=8092667
++CONFIG_DRAM_SUNXI_ODT_EN=0
++CONFIG_DRAM_SUNXI_TPR0=0x004a2195
++CONFIG_DRAM_SUNXI_TPR11=0x340000
++CONFIG_DRAM_SUNXI_TPR12=0x46
++CONFIG_DRAM_SUNXI_TPR13=0x34000100
+--
+2.20.1
+
--- /dev/null
+From c58e825d57bff0f9124f3afbcbad4a5c06d3670f Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 3 Jun 2023 23:41:31 +0200
+Subject: [PATCH 4029/4044] sunxi: add support for UART5 in Port E group on
+ T133
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/include/asm/arch-sunxi/serial.h | 1 +
+ arch/arm/mach-sunxi/board.c | 4 ++++
+ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 1 +
+ include/configs/sunxi-common.h | 3 +++
+ 4 files changed, 9 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/serial.h b/arch/arm/include/asm/arch-sunxi/serial.h
+index 9386287b65..48d0f42a3b 100644
+--- a/arch/arm/include/asm/arch-sunxi/serial.h
++++ b/arch/arm/include/asm/arch-sunxi/serial.h
+@@ -20,6 +20,7 @@
+ #elif defined(CONFIG_SUNXI_GEN_NCAT2)
+ #define SUNXI_UART0_BASE 0x02500000
+ #define SUNXI_R_UART_BASE 0 // 0x07080000 (?>
++#define SUNXI_UART5_BASE (SUNXI_UART0_BASE + 0x1400)
+ #else
+ #define SUNXI_UART0_BASE 0x01c28000
+ #define SUNXI_R_UART_BASE 0x01f02800
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index 8980ffb509..50693d216b 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -175,6 +175,10 @@ static int gpio_init(void)
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
+ sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP);
++#elif CONFIG_CONS_INDEX == 6 && defined(CONFIG_MACH_SUN8I_R528)
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(6), 9);
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(7), 9);
++ sunxi_gpio_set_pull(SUNXI_GPE(7), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN8I) && \
+ !defined(CONFIG_MACH_SUN8I_R40)
+ sunxi_gpio_set_cfgpin(SUNXI_GPG(6), SUN8I_GPG_UART1);
+diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+index 614cfe6b73..2717d79bc3 100644
+--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+@@ -748,6 +748,7 @@ static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
+ { "uart0", 6 }, /* PB2-PB3 */
+ #endif
+ { "uart3", 7 }, /* PB6-PB9 */
++ { "uart5", 3 }, /* PE6-PE7 */
+ };
+
+ static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
+diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
+index b8ca77d031..bdb568af4b 100644
+--- a/include/configs/sunxi-common.h
++++ b/include/configs/sunxi-common.h
+@@ -29,6 +29,9 @@
+ # define CFG_SYS_NS16550_COM3 SUNXI_UART2_BASE
+ # define CFG_SYS_NS16550_COM4 SUNXI_UART3_BASE
+ # define CFG_SYS_NS16550_COM5 SUNXI_R_UART_BASE
++#if defined(CONFIG_SUNXI_GEN_NCAT2)
++# define CFG_SYS_NS16550_COM6 SUNXI_UART5_BASE
++#endif
+ #endif
+
+ /* CPU */
+--
+2.20.1
+
+++ /dev/null
-From 98a8ab5c4b9695d806f5e0d0d8db9935fe7ed6f8 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Mon, 5 Jun 2023 17:57:15 +0200
-Subject: [PATCH 4029/4031] sunxi: enable gmac on MYIR MYD-YT113X with the
- YT8531 PHY
-
-The gmac is connected to a Motorcomm YT8531, for which the driver
-has been picked from Starfive and ported over.
-
-Support is not yet added in DTS, only for compile testing.
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- configs/myir_myd_t113x_defconfig | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/configs/myir_myd_t113x_defconfig b/configs/myir_myd_t113x_defconfig
-index dc652732e3..ad2b59ed70 100644
---- a/configs/myir_myd_t113x_defconfig
-+++ b/configs/myir_myd_t113x_defconfig
-@@ -15,3 +15,7 @@ CONFIG_DRAM_SUNXI_TPR0=0x004a2195
- CONFIG_DRAM_SUNXI_TPR11=0x340000
- CONFIG_DRAM_SUNXI_TPR12=0x46
- CONFIG_DRAM_SUNXI_TPR13=0x34000100
-+CONFIG_PHY_MOTORCOMM=y
-+CONFIG_SUN8I_EMAC=y
-+CONFIG_RGMII=y
-+CONFIG_RMII=y
---
-2.20.1
-
+++ /dev/null
-From 099cca9ab11daf77d1b8e5864ebb3b08a41b94fb Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Mon, 5 Jun 2023 18:15:15 +0200
-Subject: [PATCH 4030/4031] net: phy: backport and update driver for Motorcomm
- yt8531 phy
-
-Don't use U_BOOT_PHY_DRIVER yet.
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- drivers/net/phy/motorcomm.c | 9 ++++++++-
- drivers/net/phy/phy.c | 3 +++
- include/phy.h | 1 +
- 3 files changed, 12 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
-index e822fd76f2..eb2dd65c4a 100644
---- a/drivers/net/phy/motorcomm.c
-+++ b/drivers/net/phy/motorcomm.c
-@@ -425,7 +425,7 @@ static int yt8531_probe(struct phy_device *phydev)
- return 0;
- }
-
--U_BOOT_PHY_DRIVER(motorcomm8531) = {
-+static struct phy_driver YT8531_driver = {
- .name = "YT8531 Gigabit Ethernet",
- .uid = PHY_ID_YT8531,
- .mask = PHY_ID_MASK,
-@@ -435,3 +435,10 @@ U_BOOT_PHY_DRIVER(motorcomm8531) = {
- .startup = &yt8531_startup,
- .shutdown = &genphy_shutdown,
- };
-+
-+int phy_motorcomm_init(void)
-+{
-+ phy_register(&YT8531_driver);
-+
-+ return 0;
-+}
-diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
-index 9e22db3fc8..3613c3dd17 100644
---- a/drivers/net/phy/phy.c
-+++ b/drivers/net/phy/phy.c
-@@ -532,6 +532,9 @@ int phy_init(void)
- #ifdef CONFIG_PHY_MESON_GXL
- phy_meson_gxl_init();
- #endif
-+#ifdef CONFIG_PHY_MOTORCOMM
-+ phy_motorcomm_init();
-+#endif
- #ifdef CONFIG_PHY_NATSEMI
- phy_natsemi_init();
- #endif
-diff --git a/include/phy.h b/include/phy.h
-index 749285f15e..05208d7f3d 100644
---- a/include/phy.h
-+++ b/include/phy.h
-@@ -331,6 +331,7 @@ int phy_marvell_init(void);
- int phy_micrel_ksz8xxx_init(void);
- int phy_micrel_ksz90x1_init(void);
- int phy_meson_gxl_init(void);
-+int phy_motorcomm_init(void);
- int phy_natsemi_init(void);
- int phy_nxp_c45_tja11xx_init(void);
- int phy_nxp_tja11xx_init(void);
---
-2.20.1
-
--- /dev/null
+From 542c6069f64d4e97c68007bb7e22c030ab7f9526 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sun, 4 Jun 2023 00:13:45 +0200
+Subject: [PATCH 4030/4044] sunxi: add MYIR MYD-YT113X board
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/dts/Makefile | 3 +-
+ arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts | 68 ++++++++++++++++++++
+ configs/myir_myd_t113x_defconfig | 19 ++++++
+ 3 files changed, 89 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts
+ create mode 100644 configs/myir_myd_t113x_defconfig
+
+diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+index 4207f17601..6fb49de59a 100644
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -712,7 +712,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
+ sun8i-v3s-licheepi-zero.dtb
+ dtb-$(CONFIG_MACH_SUN8I_R528) += \
+ sun8i-t113s-mangopi-mq-r-t113.dtb \
+- sun8i-t113s-mangopi-mqdual-t113.dtb
++ sun8i-t113s-mangopi-mqdual-t113.dtb \
++ sun8i-t113s-myir-myd-yt113x.dtb
+ dtb-$(CONFIG_MACH_SUN50I_H5) += \
+ sun50i-h5-bananapi-m2-plus.dtb \
+ sun50i-h5-emlid-neutis-n5-devboard.dtb \
+diff --git a/arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts
+new file mode 100644
+index 0000000000..afd0d8f532
+--- /dev/null
++++ b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x.dts
+@@ -0,0 +1,68 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2022 Arm Ltd.
++
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/dts-v1/;
++
++#include "sun8i-t113s.dtsi"
++#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
++
++/ {
++ model = "MYIR MYD-YT113X";
++ compatible = "myir,myd-yt113x", "myir,myc-yt113x", "allwinner,sun8i-t113s";
++
++ aliases {
++ serial5 = &uart5;
++ };
++
++ chosen {
++ stdout-path = "serial5:115200n8";
++ };
++};
++
++&cpu0 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&cpu1 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&mmc2_pins {
++ bias-pull-up;
++ drive-strength = <40>;
++};
++
++&mmc2 {
++ pinctrl-0 = <&mmc2_pins>;
++ pinctrl-names = "default";
++ vmmc-supply = <®_3v3>;
++ non-removable;
++ bus-width = <4>;
++ status = "okay";
++
++ emmc: emmc@0 {
++ reg = <0>;
++ compatible = "mmc-card";
++ broken-hpi;
++ };
++};
++
++&pio {
++ /omit-if-no-ref/
++ uart5_pins: uart5-pins {
++ pins = "PE6", "PE7";
++ function = "uart5";
++ };
++};
++
++&uart5 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart5_pins>;
++ status = "okay";
++};
++
++&uart3 {
++ status = "disabled";
++};
+diff --git a/configs/myir_myd_t113x_defconfig b/configs/myir_myd_t113x_defconfig
+new file mode 100644
+index 0000000000..21f939272a
+--- /dev/null
++++ b/configs/myir_myd_t113x_defconfig
+@@ -0,0 +1,20 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-myir-myd-yt113x"
++CONFIG_SUNXI_MINIMUM_DRAM_MB=128
++CONFIG_SPL=y
++CONFIG_MACH_SUN8I_R528=y
++CONFIG_CONS_INDEX=6
++CONFIG_MMC0_CD_PIN="PF6"
++CONFIG_MMC_SUNXI_SLOT_EXTRA=2
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_SYS_MONITOR_LEN=786432
++CONFIG_DRAM_CLK=792
++CONFIG_DRAM_ZQ=8092667
++CONFIG_DRAM_SUNXI_ODT_EN=0
++CONFIG_DRAM_SUNXI_TPR0=0x004a2195
++CONFIG_DRAM_SUNXI_TPR11=0x340000
++CONFIG_DRAM_SUNXI_TPR12=0x46
++CONFIG_DRAM_SUNXI_TPR13=0x34000100
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_OHCI_HCD=y
+--
+2.20.1
+
--- /dev/null
+From 0c47a295e3d6f4611a152485fac63bb2b64369e8 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 3 Jun 2023 23:57:46 +0200
+Subject: [PATCH 4031/4044] sunxi: add support for UART3 on PE pins
+
+Some boards use Port E pins for muxing the UART3 as console. Add a new
+Kconfig option allowing to select this (mimicking MMC_PINS_PH).
+
+Pinmux taken from https://bbs.aw-ol.com/assets/uploads/files/1648883311844-t113-s3_datasheet_v1.2.pdf
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/mach-sunxi/Kconfig | 6 ++++++
+ arch/arm/mach-sunxi/board.c | 10 ++++++++--
+ arch/riscv/dts/sunxi-d1s-t113.dtsi | 6 ++++++
+ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 4 ++++
+ 4 files changed, 24 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index 77b510cdfe..1ddf496a55 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -664,6 +664,12 @@ config UART0_PORT_F
+ at the same time, the system can be only booted in the FEL mode.
+ Only enable this if you really know what you are doing.
+
++config UART3_PINS_PE
++ bool "Pins for uart3 are on Port E"
++ ---help---
++ Select this option for boards where uart3 uses the Port E pinmux.
++ (Some T113-S3 boards use uart3 as console.)
++
+ config OLD_SUNXI_KERNEL_COMPAT
+ bool "Enable workarounds for booting old kernels"
+ ---help---
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index 50693d216b..85dbad0552 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -168,16 +168,22 @@ static int gpio_init(void)
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
+ sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 4 && defined(CONFIG_MACH_SUN8I_R528)
++#if defined(CONFIG_UART3_PINS_PE)
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(8), 5);
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(9), 5);
++ sunxi_gpio_set_pull(SUNXI_GPE(9), SUNXI_GPIO_PULL_UP);
++#else
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(6), 7);
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(7), 7);
+ sunxi_gpio_set_pull(SUNXI_GPB(7), SUNXI_GPIO_PULL_UP);
++#endif
+ #elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
+ sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 6 && defined(CONFIG_MACH_SUN8I_R528)
+- sunxi_gpio_set_cfgpin(SUNXI_GPE(6), 9);
+- sunxi_gpio_set_cfgpin(SUNXI_GPE(7), 9);
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(6), 3);
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(7), 3);
+ sunxi_gpio_set_pull(SUNXI_GPE(7), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN8I) && \
+ !defined(CONFIG_MACH_SUN8I_R40)
+diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+index b1f97bd0bc..b72bbc5e43 100644
+--- a/arch/riscv/dts/sunxi-d1s-t113.dtsi
++++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+@@ -126,6 +126,12 @@
+ function = "uart3";
+ };
+
++ /omit-if-no-ref/
++ uart3_pe_pins: uart3-pe-pins {
++ pins = "PE8", "PE9";
++ function = "uart3";
++ };
++
+ /omit-if-no-ref/
+ uart0_pins: uart0-pins {
+ pins = "PE2", "PE3";
+diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+index 2717d79bc3..e466808e4e 100644
+--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+@@ -747,7 +747,11 @@ static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
+ #else
+ { "uart0", 6 }, /* PB2-PB3 */
+ #endif
++#if IS_ENABLED(CONFIG_UART3_PINS_E)
++ { "uart3", 5 }, /* PE8-PE9 */
++else
+ { "uart3", 7 }, /* PB6-PB9 */
++#endif
+ { "uart5", 3 }, /* PE6-PE7 */
+ };
+
+--
+2.20.1
+
+++ /dev/null
-From 4481a2790ed667a206203ecf3fd8f8bbcf35d062 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Mon, 5 Jun 2023 18:29:41 +0200
-Subject: [PATCH 4031/4031] sunxi: rongpin-rp-t113: add missing gpio.h include
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-index f2521438fb..348ae5eec6 100644
---- a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-+++ b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
-@@ -2,6 +2,7 @@
- // Copyright (C) 2022 Arm Ltd.
-
- #include <dt-bindings/interrupt-controller/irq.h>
-+#include <dt-bindings/gpio/gpio.h>
-
- /dts-v1/;
-
---
-2.20.1
-
--- /dev/null
+From 11fe7200d693e88d1f648fd000c327dcc529fa28 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 3 Jun 2023 23:42:33 +0200
+Subject: [PATCH 4032/4044] sunxi: add support for Rongpin RP-T113 board
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/dts/Makefile | 3 +-
+ arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts | 98 ++++++++++++++++++++
+ configs/rongpin_rp_t113_defconfig | 18 ++++
+ 3 files changed, 118 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
+ create mode 100644 configs/rongpin_rp_t113_defconfig
+
+diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+index 6fb49de59a..be89021657 100644
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -713,7 +713,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
+ dtb-$(CONFIG_MACH_SUN8I_R528) += \
+ sun8i-t113s-mangopi-mq-r-t113.dtb \
+ sun8i-t113s-mangopi-mqdual-t113.dtb \
+- sun8i-t113s-myir-myd-yt113x.dtb
++ sun8i-t113s-myir-myd-yt113x.dtb \
++ sun8i-t113s-rongpin-rp-t113.dtb
+ dtb-$(CONFIG_MACH_SUN50I_H5) += \
+ sun50i-h5-bananapi-m2-plus.dtb \
+ sun50i-h5-emlid-neutis-n5-devboard.dtb \
+diff --git a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
+new file mode 100644
+index 0000000000..6ac2c065c4
+--- /dev/null
++++ b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
+@@ -0,0 +1,98 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2022 Arm Ltd.
++
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/dts-v1/;
++
++#include "sun8i-t113s.dtsi"
++
++/ {
++ model = "Rongpin RP-T113";
++ compatible = "rongpin,rp-t113", "allwinner,sun8i-t113s";
++
++ aliases {
++ serial3 = &uart3;
++ };
++
++ chosen {
++ stdout-path = "serial3:115200n8";
++ };
++
++ /* board wide 5V supply directly from the USB-C socket */
++ reg_vcc5v: regulator-5v {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-5v";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
++
++ /* SY8008 DC/DC regulator on the board */
++ reg_3v3: regulator-3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <®_vcc5v>;
++ };
++
++ /* SY8008 DC/DC regulator on the board, also supplying VDD-SYS */
++ reg_vcc_core: regulator-core {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-core";
++ regulator-min-microvolt = <880000>;
++ regulator-max-microvolt = <880000>;
++ vin-supply = <®_vcc5v>;
++ };
++
++ /* XC6206 LDO on the board */
++ reg_avdd2v8: regulator-avdd {
++ compatible = "regulator-fixed";
++ regulator-name = "avdd2v8";
++ regulator-min-microvolt = <2800000>;
++ regulator-max-microvolt = <2800000>;
++ vin-supply = <®_3v3>;
++ };
++};
++
++&cpu0 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&cpu1 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&pio {
++ vcc-pb-supply = <®_3v3>;
++ vcc-pd-supply = <®_3v3>;
++ vcc-pe-supply = <®_avdd2v8>;
++ vcc-pf-supply = <®_3v3>;
++ vcc-pg-supply = <®_3v3>;
++};
++
++&uart3 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart3_pe_pins>;
++ status = "okay";
++};
++
++&mmc0 {
++ pinctrl-0 = <&mmc0_pins>;
++ pinctrl-names = "default";
++ vmmc-supply = <®_3v3>;
++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
++ disable-wp;
++ bus-width = <4>;
++ status = "okay";
++};
++
++&mmc2 {
++ pinctrl-0 = <&mmc2_pins>;
++ pinctrl-names = "default";
++ vmmc-supply = <®_3v3>;
++ non-removable;
++ bus-width = <4>;
++ status = "okay";
++};
+diff --git a/configs/rongpin_rp_t113_defconfig b/configs/rongpin_rp_t113_defconfig
+new file mode 100644
+index 0000000000..9b5a5bcd65
+--- /dev/null
++++ b/configs/rongpin_rp_t113_defconfig
+@@ -0,0 +1,18 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-rongpin-rp-t113"
++CONFIG_SUNXI_MINIMUM_DRAM_MB=128
++CONFIG_SPL=y
++CONFIG_MACH_SUN8I_R528=y
++CONFIG_CONS_INDEX=4
++CONFIG_MMC0_CD_PIN="PF6"
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_SYS_MONITOR_LEN=786432
++CONFIG_DRAM_CLK=792
++CONFIG_DRAM_ZQ=8092667
++CONFIG_DRAM_SUNXI_ODT_EN=0
++CONFIG_DRAM_SUNXI_TPR0=0x004a2195
++CONFIG_DRAM_SUNXI_TPR11=0x340000
++CONFIG_DRAM_SUNXI_TPR12=0x46
++CONFIG_DRAM_SUNXI_TPR13=0x34000100
++CONFIG_UART3_PINS_PE=y
+--
+2.20.1
+
--- /dev/null
+From daa5621013e06419c90bf27b5c88b8036af2b3da Mon Sep 17 00:00:00 2001
+From: Yegor Yefremov <yegorslists@googlemail.com>
+Date: Wed, 28 Nov 2012 11:15:18 +0100
+Subject: [PATCH 4033/4044] net: add ICPlus PHY driver
+
+The driver code was taken from Linux kernel source:
+drivers/net/phy/icplus.c
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
+---
+ drivers/net/phy/Kconfig | 3 ++
+ drivers/net/phy/Makefile | 1 +
+ drivers/net/phy/icplus.c | 94 ++++++++++++++++++++++++++++++++++++++++
+ drivers/net/phy/phy.c | 3 ++
+ include/phy.h | 1 +
+ 5 files changed, 102 insertions(+)
+ create mode 100644 drivers/net/phy/icplus.c
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 5eaff053a0..93980398f1 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -165,6 +165,9 @@ config PHY_DAVICOM
+ config PHY_ET1011C
+ bool "LSI TruePHY ET1011C support"
+
++config PHY_ICPLUS
++ bool "IC+ IP101 Ethernet PHY support"
++
+ config PHY_LXT
+ bool "LXT971 Ethernet PHY support"
+
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index d38e99e717..5b6b78631d 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -18,6 +18,7 @@ obj-$(CONFIG_PHY_CORTINA) += cortina.o
+ obj-$(CONFIG_PHY_CORTINA_ACCESS) += ca_phy.o
+ obj-$(CONFIG_PHY_DAVICOM) += davicom.o
+ obj-$(CONFIG_PHY_ET1011C) += et1011c.o
++obj-$(CONFIG_PHY_ICPLUS) += icplus.o
+ obj-$(CONFIG_PHY_LXT) += lxt.o
+ obj-$(CONFIG_PHY_MARVELL) += marvell.o
+ obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
+diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
+new file mode 100644
+index 0000000000..dd5c59259d
+--- /dev/null
++++ b/drivers/net/phy/icplus.c
+@@ -0,0 +1,94 @@
++/*
++ * ICPlus PHY drivers
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ * Copyright (c) 2007 Freescale Semiconductor, Inc.
++ *
++ */
++#include <phy.h>
++
++/* IP101A/G - IP1001 */
++#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
++#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
++#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */
++#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
++#define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */
++#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
++#define IP101A_G_IRQ_PIN_USED (1<<15) /* INTR pin used */
++#define IP101A_G_IRQ_DEFAULT IP101A_G_IRQ_PIN_USED
++
++static int ip1001_config(struct phy_device *phydev)
++{
++ int c;
++
++ /* Enable Auto Power Saving mode */
++ c = phy_read(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2);
++ if (c < 0)
++ return c;
++ c |= IP1001_APS_ON;
++ c = phy_write(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2, c);
++ if (c < 0)
++ return c;
++
++ /* INTR pin used: speed/link/duplex will cause an interrupt */
++ c = phy_write(phydev, MDIO_DEVAD_NONE, IP101A_G_IRQ_CONF_STATUS,
++ IP101A_G_IRQ_DEFAULT);
++ if (c < 0)
++ return c;
++
++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
++ /*
++ * Additional delay (2ns) used to adjust RX clock phase
++ * at RGMII interface
++ */
++ c = phy_read(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS);
++ if (c < 0)
++ return c;
++
++ c |= IP1001_PHASE_SEL_MASK;
++ c = phy_write(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS,
++ c);
++ if (c < 0)
++ return c;
++ }
++
++ return 0;
++}
++
++static int ip1001_startup(struct phy_device *phydev)
++{
++ genphy_update_link(phydev);
++ genphy_parse_link(phydev);
++
++ return 0;
++}
++static struct phy_driver IP1001_driver = {
++ .name = "ICPlus IP1001",
++ .uid = 0x02430d90,
++ .mask = 0x0ffffff0,
++ .features = PHY_GBIT_FEATURES,
++ .config = &ip1001_config,
++ .startup = &ip1001_startup,
++ .shutdown = &genphy_shutdown,
++};
++
++int phy_icplus_init(void)
++{
++ phy_register(&IP1001_driver);
++
++ return 0;
++}
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 80230b907c..9e22db3fc8 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -514,6 +514,9 @@ int phy_init(void)
+ #ifdef CONFIG_PHY_ET1011C
+ phy_et1011c_init();
+ #endif
++#ifdef CONFIG_PHY_ICPLUS
++ phy_icplus_init();
++#endif
+ #ifdef CONFIG_PHY_LXT
+ phy_lxt_init();
+ #endif
+diff --git a/include/phy.h b/include/phy.h
+index 87aa86c2e7..749285f15e 100644
+--- a/include/phy.h
++++ b/include/phy.h
+@@ -325,6 +325,7 @@ int phy_cortina_init(void);
+ int phy_cortina_access_init(void);
+ int phy_davicom_init(void);
+ int phy_et1011c_init(void);
++int phy_icplus_init(void);
+ int phy_lxt_init(void);
+ int phy_marvell_init(void);
+ int phy_micrel_ksz8xxx_init(void);
+--
+2.20.1
+
--- /dev/null
+From 7d987c1284c883d31090e940dbec78fb2a66ea60 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sun, 4 Jun 2023 15:40:42 +0200
+Subject: [PATCH 4034/4044] sunxi: enable emac on Rongpin RP-T113
+
+The emac is connected to an IC+ IP101 PHY, for which the driver
+has been re-added (it was removed in 2014).
+
+Currently the driver init fails with the below, so further tweaking
+will be required.
+
+CPU: Allwinner R528 (SUN8I)
+Model: Rongpin RP-T113
+DRAM: 128 MiB
+Core: 36 devices, 15 uclasses, devicetree: separate
+MMC: mmc@4020000: 0, mmc@4022000: 1
+Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1...
+In: serial@2500c00
+Out: serial@2500c00
+Err: serial@2500c00
+Net: eth_sun8i_emac ethernet@4500000: failed to get TX clock
+No ethernet found.
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts | 28 ++++++++++++++++++++
+ configs/rongpin_rp_t113_defconfig | 3 +++
+ 2 files changed, 31 insertions(+)
+
+diff --git a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
+index 6ac2c065c4..f2521438fb 100644
+--- a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
++++ b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
+@@ -54,6 +54,16 @@
+ regulator-max-microvolt = <2800000>;
+ vin-supply = <®_3v3>;
+ };
++
++ reg_gmac_3v3: gmac-3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "gmac-3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ startup-delay-us = <100000>;
++ enable-active-high;
++ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */
++ };
+ };
+
+ &cpu0 {
+@@ -78,6 +88,17 @@
+ status = "okay";
+ };
+
++&emac {
++ pinctrl-names = "default";
++ pinctrl-0 = <&rmii_pe_pins>;
++
++ phy-supply = <®_3v3>;
++ phy-handle = <&ext_rgmii_phy>;
++ phy-mode = "rmii";
++
++ status = "okay";
++};
++
+ &mmc0 {
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+@@ -96,3 +117,10 @@
+ bus-width = <4>;
+ status = "okay";
+ };
++
++&mdio {
++ ext_rgmii_phy: ethernet-phy@1 {
++ compatible = "ethernet-phy-ieee802.3-c22";
++ reg = <1>;
++ };
++};
+diff --git a/configs/rongpin_rp_t113_defconfig b/configs/rongpin_rp_t113_defconfig
+index 9b5a5bcd65..e234934f50 100644
+--- a/configs/rongpin_rp_t113_defconfig
++++ b/configs/rongpin_rp_t113_defconfig
+@@ -16,3 +16,6 @@ CONFIG_DRAM_SUNXI_TPR11=0x340000
+ CONFIG_DRAM_SUNXI_TPR12=0x46
+ CONFIG_DRAM_SUNXI_TPR13=0x34000100
+ CONFIG_UART3_PINS_PE=y
++CONFIG_SUN8I_EMAC=y
++CONFIG_PHY_ICPLUS=y
++CONFIG_RMII=y
+--
+2.20.1
+
--- /dev/null
+From 1b83ab458f7e8971576c9f1ac884eb9e6de4d0cd Mon Sep 17 00:00:00 2001
+From: Yanhong Wang <yanhong.wang@starfivetech.com>
+Date: Thu, 25 May 2023 17:36:27 +0800
+Subject: [PATCH 4035/4044] net: phy: Add driver for Motorcomm yt8531 gigabit
+ ethernet phy
+
+Add a driver for the motorcomm yt8531 gigabit ethernet phy. We have
+verified the driver on StarFive VisionFive2 board.
+
+Signed-off-by: Yanhong Wang <yanhong.wang@starfivetech.com>
+Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
+---
+ drivers/net/phy/Kconfig | 6 +
+ drivers/net/phy/Makefile | 1 +
+ drivers/net/phy/motorcomm.c | 437 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 444 insertions(+)
+ create mode 100644 drivers/net/phy/motorcomm.c
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 93980398f1..0a99682c27 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -215,6 +215,12 @@ config PHY_MICREL_KSZ8XXX
+
+ endif # PHY_MICREL
+
++config PHY_MOTORCOMM
++ tristate "Motorcomm PHYs"
++ help
++ Enables support for Motorcomm network PHYs.
++ Currently supports the YT8531 Gigabit Ethernet PHYs.
++
+ config PHY_MSCC
+ bool "Microsemi Corp Ethernet PHYs support"
+
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index 5b6b78631d..9637a138f8 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -24,6 +24,7 @@ obj-$(CONFIG_PHY_MARVELL) += marvell.o
+ obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
+ obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
+ obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
++obj-$(CONFIG_PHY_MOTORCOMM) += motorcomm.o
+ obj-$(CONFIG_PHY_NATSEMI) += natsemi.o
+ obj-$(CONFIG_PHY_NXP_C45_TJA11XX) += nxp-c45-tja11xx.o
+ obj-$(CONFIG_PHY_NXP_TJA11XX) += nxp-tja11xx.o
+diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
+new file mode 100644
+index 0000000000..e822fd76f2
+--- /dev/null
++++ b/drivers/net/phy/motorcomm.c
+@@ -0,0 +1,437 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Motorcomm 8531 PHY driver.
++ *
++ * Copyright (C) 2023 StarFive Technology Co., Ltd.
++ */
++
++#include <config.h>
++#include <common.h>
++#include <malloc.h>
++#include <phy.h>
++#include <linux/bitfield.h>
++
++#define PHY_ID_YT8531 0x4f51e91b
++#define PHY_ID_MASK GENMASK(31, 0)
++
++/* Extended Register's Address Offset Register */
++#define YTPHY_PAGE_SELECT 0x1E
++
++/* Extended Register's Data Register */
++#define YTPHY_PAGE_DATA 0x1F
++
++#define YTPHY_SYNCE_CFG_REG 0xA012
++
++#define YTPHY_DTS_OUTPUT_CLK_DIS 0
++#define YTPHY_DTS_OUTPUT_CLK_25M 25000000
++#define YTPHY_DTS_OUTPUT_CLK_125M 125000000
++
++#define YT8531_SCR_SYNCE_ENABLE BIT(6)
++/* 1b0 output 25m clock *default*
++ * 1b1 output 125m clock
++ */
++#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4)
++#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1)
++#define YT8531_SCR_CLK_SRC_PLL_125M 0
++#define YT8531_SCR_CLK_SRC_UTP_RX 1
++#define YT8531_SCR_CLK_SRC_SDS_RX 2
++#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3
++#define YT8531_SCR_CLK_SRC_REF_25M 4
++#define YT8531_SCR_CLK_SRC_SSC_25M 5
++
++/* 1b0 use original tx_clk_rgmii *default*
++ * 1b1 use inverted tx_clk_rgmii.
++ */
++#define YT8531_RC1R_TX_CLK_SEL_INVERTED BIT(14)
++#define YT8531_RC1R_RX_DELAY_MASK GENMASK(13, 10)
++#define YT8531_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4)
++#define YT8531_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0)
++#define YT8531_RC1R_RGMII_0_000_NS 0
++#define YT8531_RC1R_RGMII_0_150_NS 1
++#define YT8531_RC1R_RGMII_0_300_NS 2
++#define YT8531_RC1R_RGMII_0_450_NS 3
++#define YT8531_RC1R_RGMII_0_600_NS 4
++#define YT8531_RC1R_RGMII_0_750_NS 5
++#define YT8531_RC1R_RGMII_0_900_NS 6
++#define YT8531_RC1R_RGMII_1_050_NS 7
++#define YT8531_RC1R_RGMII_1_200_NS 8
++#define YT8531_RC1R_RGMII_1_350_NS 9
++#define YT8531_RC1R_RGMII_1_500_NS 10
++#define YT8531_RC1R_RGMII_1_650_NS 11
++#define YT8531_RC1R_RGMII_1_800_NS 12
++#define YT8531_RC1R_RGMII_1_950_NS 13
++#define YT8531_RC1R_RGMII_2_100_NS 14
++#define YT8531_RC1R_RGMII_2_250_NS 15
++
++/* Phy gmii clock gating Register */
++#define YT8531_CLOCK_GATING_REG 0xC
++#define YT8531_CGR_RX_CLK_EN BIT(12)
++
++/* Specific Status Register */
++#define YTPHY_SPECIFIC_STATUS_REG 0x11
++#define YTPHY_DUPLEX_MASK BIT(13)
++#define YTPHY_DUPLEX_SHIFT 13
++#define YTPHY_SPEED_MODE_MASK GENMASK(15, 14)
++#define YTPHY_SPEED_MODE_SHIFT 14
++
++#define YT8531_EXTREG_SLEEP_CONTROL1_REG 0x27
++#define YT8531_ESC1R_SLEEP_SW BIT(15)
++#define YT8531_ESC1R_PLLON_SLP BIT(14)
++
++#define YT8531_RGMII_CONFIG1_REG 0xA003
++
++#define YT8531_CHIP_CONFIG_REG 0xA001
++#define YT8531_CCR_SW_RST BIT(15)
++/* 1b0 disable 1.9ns rxc clock delay *default*
++ * 1b1 enable 1.9ns rxc clock delay
++ */
++#define YT8531_CCR_RXC_DLY_EN BIT(8)
++#define YT8531_CCR_RXC_DLY_1_900_NS 1900
++
++/* bits in struct ytphy_plat_priv->flag */
++#define TX_CLK_ADJ_ENABLED BIT(0)
++#define AUTO_SLEEP_DISABLED BIT(1)
++#define KEEP_PLL_ENABLED BIT(2)
++#define TX_CLK_10_INVERTED BIT(3)
++#define TX_CLK_100_INVERTED BIT(4)
++#define TX_CLK_1000_INVERTED BIT(5)
++
++struct ytphy_plat_priv {
++ u32 rx_delay_ps;
++ u32 tx_delay_ps;
++ u32 clk_out_frequency;
++ u32 flag;
++};
++
++/**
++ * struct ytphy_cfg_reg_map - map a config value to a register value
++ * @cfg: value in device configuration
++ * @reg: value in the register
++ */
++struct ytphy_cfg_reg_map {
++ u32 cfg;
++ u32 reg;
++};
++
++static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = {
++ /* for tx delay / rx delay with YT8531_CCR_RXC_DLY_EN is not set. */
++ { 0, YT8531_RC1R_RGMII_0_000_NS },
++ { 150, YT8531_RC1R_RGMII_0_150_NS },
++ { 300, YT8531_RC1R_RGMII_0_300_NS },
++ { 450, YT8531_RC1R_RGMII_0_450_NS },
++ { 600, YT8531_RC1R_RGMII_0_600_NS },
++ { 750, YT8531_RC1R_RGMII_0_750_NS },
++ { 900, YT8531_RC1R_RGMII_0_900_NS },
++ { 1050, YT8531_RC1R_RGMII_1_050_NS },
++ { 1200, YT8531_RC1R_RGMII_1_200_NS },
++ { 1350, YT8531_RC1R_RGMII_1_350_NS },
++ { 1500, YT8531_RC1R_RGMII_1_500_NS },
++ { 1650, YT8531_RC1R_RGMII_1_650_NS },
++ { 1800, YT8531_RC1R_RGMII_1_800_NS },
++ { 1950, YT8531_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */
++ { 2100, YT8531_RC1R_RGMII_2_100_NS },
++ { 2250, YT8531_RC1R_RGMII_2_250_NS },
++
++ /* only for rx delay with YT8531_CCR_RXC_DLY_EN is set. */
++ { 0 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_000_NS },
++ { 150 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_150_NS },
++ { 300 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_300_NS },
++ { 450 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_450_NS },
++ { 600 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_600_NS },
++ { 750 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_750_NS },
++ { 900 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_900_NS },
++ { 1050 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_050_NS },
++ { 1200 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_200_NS },
++ { 1350 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_350_NS },
++ { 1500 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_500_NS },
++ { 1650 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_650_NS },
++ { 1800 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_800_NS },
++ { 1950 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_950_NS },
++ { 2100 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_100_NS },
++ { 2250 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_250_NS }
++};
++
++static u32 ytphy_get_delay_reg_value(struct phy_device *phydev,
++ u32 val,
++ u16 *rxc_dly_en)
++{
++ int tb_size = ARRAY_SIZE(ytphy_rgmii_delays);
++ int tb_size_half = tb_size / 2;
++ int i;
++
++ /* when rxc_dly_en is NULL, it is get the delay for tx, only half of
++ * tb_size is valid.
++ */
++ if (!rxc_dly_en)
++ tb_size = tb_size_half;
++
++ for (i = 0; i < tb_size; i++) {
++ if (ytphy_rgmii_delays[i].cfg == val) {
++ if (rxc_dly_en && i < tb_size_half)
++ *rxc_dly_en = 0;
++ return ytphy_rgmii_delays[i].reg;
++ }
++ }
++
++ pr_warn("Unsupported value %d, using default (%u)\n",
++ val, YT8531_RC1R_RGMII_1_950_NS);
++
++ /* when rxc_dly_en is not NULL, it is get the delay for rx.
++ * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps,
++ * so YT8531_CCR_RXC_DLY_EN should not be set.
++ */
++ if (rxc_dly_en)
++ *rxc_dly_en = 0;
++
++ return YT8531_RC1R_RGMII_1_950_NS;
++}
++
++static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask,
++ u16 set)
++{
++ int ret;
++
++ ret = phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_SELECT, regnum);
++ if (ret < 0)
++ return ret;
++
++ return phy_modify(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA, mask, set);
++}
++
++static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev)
++{
++ struct ytphy_plat_priv *priv = phydev->priv;
++ u16 rxc_dly_en = YT8531_CCR_RXC_DLY_EN;
++ u32 rx_reg, tx_reg;
++ u16 mask, val = 0;
++ int ret;
++
++ rx_reg = ytphy_get_delay_reg_value(phydev, priv->rx_delay_ps,
++ &rxc_dly_en);
++ tx_reg = ytphy_get_delay_reg_value(phydev, priv->tx_delay_ps,
++ NULL);
++
++ switch (phydev->interface) {
++ case PHY_INTERFACE_MODE_RGMII:
++ rxc_dly_en = 0;
++ break;
++ case PHY_INTERFACE_MODE_RGMII_RXID:
++ val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg);
++ break;
++ case PHY_INTERFACE_MODE_RGMII_TXID:
++ rxc_dly_en = 0;
++ val |= FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
++ break;
++ case PHY_INTERFACE_MODE_RGMII_ID:
++ val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg) |
++ FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
++ break;
++ default: /* do not support other modes */
++ return -EOPNOTSUPP;
++ }
++
++ ret = ytphy_modify_ext(phydev, YT8531_CHIP_CONFIG_REG,
++ YT8531_CCR_RXC_DLY_EN, rxc_dly_en);
++ if (ret < 0)
++ return ret;
++
++ /* Generally, it is not necessary to adjust YT8531_RC1R_FE_TX_DELAY */
++ mask = YT8531_RC1R_RX_DELAY_MASK | YT8531_RC1R_GE_TX_DELAY_MASK;
++ return ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG, mask, val);
++}
++
++static int yt8531_parse_status(struct phy_device *phydev)
++{
++ int val;
++ int speed, speed_mode;
++
++ val = phy_read(phydev, MDIO_DEVAD_NONE, YTPHY_SPECIFIC_STATUS_REG);
++ if (val < 0)
++ return val;
++
++ speed_mode = (val & YTPHY_SPEED_MODE_MASK) >> YTPHY_SPEED_MODE_SHIFT;
++ switch (speed_mode) {
++ case 2:
++ speed = SPEED_1000;
++ break;
++ case 1:
++ speed = SPEED_100;
++ break;
++ default:
++ speed = SPEED_10;
++ break;
++ }
++
++ phydev->speed = speed;
++ phydev->duplex = (val & YTPHY_DUPLEX_MASK) >> YTPHY_DUPLEX_SHIFT;
++
++ return 0;
++}
++
++static int yt8531_startup(struct phy_device *phydev)
++{
++ struct ytphy_plat_priv *priv = phydev->priv;
++ u16 val = 0;
++ int ret;
++
++ ret = genphy_update_link(phydev);
++ if (ret)
++ return ret;
++
++ ret = yt8531_parse_status(phydev);
++ if (ret)
++ return ret;
++
++ if (phydev->speed < 0)
++ return -EINVAL;
++
++ if (!(priv->flag & TX_CLK_ADJ_ENABLED))
++ return 0;
++
++ switch (phydev->speed) {
++ case SPEED_1000:
++ if (priv->flag & TX_CLK_1000_INVERTED)
++ val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
++ break;
++ case SPEED_100:
++ if (priv->flag & TX_CLK_100_INVERTED)
++ val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
++ break;
++ case SPEED_10:
++ if (priv->flag & TX_CLK_10_INVERTED)
++ val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
++ break;
++ default:
++ printf("UNKNOWN SPEED\n");
++ return -EINVAL;
++ }
++
++ ret = ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG,
++ YT8531_RC1R_TX_CLK_SEL_INVERTED, val);
++ if (ret < 0)
++ pr_warn("Modify TX_CLK_SEL err:%d\n", ret);
++
++ return 0;
++}
++
++static void ytphy_dt_parse(struct phy_device *phydev)
++{
++ struct ytphy_plat_priv *priv = phydev->priv;
++
++ priv->clk_out_frequency = ofnode_read_u32_default(phydev->node,
++ "motorcomm,clk-out-frequency-hz",
++ YTPHY_DTS_OUTPUT_CLK_DIS);
++ priv->rx_delay_ps = ofnode_read_u32_default(phydev->node,
++ "rx-internal-delay-ps",
++ YT8531_RC1R_RGMII_1_950_NS);
++ priv->tx_delay_ps = ofnode_read_u32_default(phydev->node,
++ "tx-internal-delay-ps",
++ YT8531_RC1R_RGMII_1_950_NS);
++
++ if (ofnode_read_bool(phydev->node, "motorcomm,auto-sleep-disabled"))
++ priv->flag |= AUTO_SLEEP_DISABLED;
++
++ if (ofnode_read_bool(phydev->node, "motorcomm,keep-pll-enabled"))
++ priv->flag |= KEEP_PLL_ENABLED;
++
++ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-adj-enabled"))
++ priv->flag |= TX_CLK_ADJ_ENABLED;
++
++ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-10-inverted"))
++ priv->flag |= TX_CLK_10_INVERTED;
++
++ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-100-inverted"))
++ priv->flag |= TX_CLK_100_INVERTED;
++
++ if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-1000-inverted"))
++ priv->flag |= TX_CLK_1000_INVERTED;
++}
++
++static int yt8531_config(struct phy_device *phydev)
++{
++ struct ytphy_plat_priv *priv = phydev->priv;
++ u16 mask, val;
++ int ret;
++
++ ret = genphy_config_aneg(phydev);
++ if (ret < 0)
++ return ret;
++
++ ytphy_dt_parse(phydev);
++ switch (priv->clk_out_frequency) {
++ case YTPHY_DTS_OUTPUT_CLK_DIS:
++ mask = YT8531_SCR_SYNCE_ENABLE;
++ val = 0;
++ break;
++ case YTPHY_DTS_OUTPUT_CLK_25M:
++ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
++ YT8531_SCR_CLK_FRE_SEL_125M;
++ val = YT8531_SCR_SYNCE_ENABLE |
++ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
++ YT8531_SCR_CLK_SRC_REF_25M);
++ break;
++ case YTPHY_DTS_OUTPUT_CLK_125M:
++ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
++ YT8531_SCR_CLK_FRE_SEL_125M;
++ val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M |
++ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
++ YT8531_SCR_CLK_SRC_PLL_125M);
++ break;
++ default:
++ pr_warn("Freq err:%u\n", priv->clk_out_frequency);
++ return -EINVAL;
++ }
++
++ ret = ytphy_modify_ext(phydev, YTPHY_SYNCE_CFG_REG, mask,
++ val);
++ if (ret < 0)
++ return ret;
++
++ ret = ytphy_rgmii_clk_delay_config(phydev);
++ if (ret < 0)
++ return ret;
++
++ if (priv->flag & AUTO_SLEEP_DISABLED) {
++ /* disable auto sleep */
++ ret = ytphy_modify_ext(phydev,
++ YT8531_EXTREG_SLEEP_CONTROL1_REG,
++ YT8531_ESC1R_SLEEP_SW, 0);
++ if (ret < 0)
++ return ret;
++ }
++
++ if (priv->flag & KEEP_PLL_ENABLED) {
++ /* enable RXC clock when no wire plug */
++ ret = ytphy_modify_ext(phydev,
++ YT8531_CLOCK_GATING_REG,
++ YT8531_CGR_RX_CLK_EN, 0);
++ if (ret < 0)
++ return ret;
++ }
++
++ return 0;
++}
++
++static int yt8531_probe(struct phy_device *phydev)
++{
++ struct ytphy_plat_priv *priv;
++
++ priv = calloc(1, sizeof(struct ytphy_plat_priv));
++ if (!priv)
++ return -ENOMEM;
++
++ phydev->priv = priv;
++
++ return 0;
++}
++
++U_BOOT_PHY_DRIVER(motorcomm8531) = {
++ .name = "YT8531 Gigabit Ethernet",
++ .uid = PHY_ID_YT8531,
++ .mask = PHY_ID_MASK,
++ .features = PHY_GBIT_FEATURES,
++ .probe = &yt8531_probe,
++ .config = &yt8531_config,
++ .startup = &yt8531_startup,
++ .shutdown = &genphy_shutdown,
++};
+--
+2.20.1
+
--- /dev/null
+From 7530416165eb2a6c7378f7bb4a90fdf67439277d Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Mon, 5 Jun 2023 17:57:15 +0200
+Subject: [PATCH 4036/4044] sunxi: enable gmac on MYIR MYD-YT113X with the
+ YT8531 PHY
+
+The gmac is connected to a Motorcomm YT8531, for which the driver
+has been picked from Starfive and ported over.
+
+Support is not yet added in DTS, only for compile testing.
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ configs/myir_myd_t113x_defconfig | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/configs/myir_myd_t113x_defconfig b/configs/myir_myd_t113x_defconfig
+index 21f939272a..088196389a 100644
+--- a/configs/myir_myd_t113x_defconfig
++++ b/configs/myir_myd_t113x_defconfig
+@@ -17,3 +17,12 @@ CONFIG_DRAM_SUNXI_TPR12=0x46
+ CONFIG_DRAM_SUNXI_TPR13=0x34000100
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_USB_OHCI_HCD=y
++CONFIG_PHY_MOTORCOMM=y
++CONFIG_SUN8I_EMAC=y
++CONFIG_RGMII=y
++CONFIG_RMII=y
++CONFIG_SUPPORT_EMMC_BOOT=y
++CONFIG_MMC_IO_VOLTAGE=y
++CONFIG_SPL_MMC_IO_VOLTAGE=y
++CONFIG_MMC_HS200_SUPPORT=y
++CONFIG_SPL_MMC_HS200_SUPPORT=y
+--
+2.20.1
+
--- /dev/null
+From 05b11cc62c2c6e523636143b6db255fa98b77de3 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Mon, 5 Jun 2023 18:15:15 +0200
+Subject: [PATCH 4037/4044] net: phy: backport and update driver for Motorcomm
+ yt8531 phy
+
+Don't use U_BOOT_PHY_DRIVER yet.
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ drivers/net/phy/motorcomm.c | 9 ++++++++-
+ drivers/net/phy/phy.c | 3 +++
+ include/phy.h | 1 +
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
+index e822fd76f2..eb2dd65c4a 100644
+--- a/drivers/net/phy/motorcomm.c
++++ b/drivers/net/phy/motorcomm.c
+@@ -425,7 +425,7 @@ static int yt8531_probe(struct phy_device *phydev)
+ return 0;
+ }
+
+-U_BOOT_PHY_DRIVER(motorcomm8531) = {
++static struct phy_driver YT8531_driver = {
+ .name = "YT8531 Gigabit Ethernet",
+ .uid = PHY_ID_YT8531,
+ .mask = PHY_ID_MASK,
+@@ -435,3 +435,10 @@ U_BOOT_PHY_DRIVER(motorcomm8531) = {
+ .startup = &yt8531_startup,
+ .shutdown = &genphy_shutdown,
+ };
++
++int phy_motorcomm_init(void)
++{
++ phy_register(&YT8531_driver);
++
++ return 0;
++}
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 9e22db3fc8..3613c3dd17 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -532,6 +532,9 @@ int phy_init(void)
+ #ifdef CONFIG_PHY_MESON_GXL
+ phy_meson_gxl_init();
+ #endif
++#ifdef CONFIG_PHY_MOTORCOMM
++ phy_motorcomm_init();
++#endif
+ #ifdef CONFIG_PHY_NATSEMI
+ phy_natsemi_init();
+ #endif
+diff --git a/include/phy.h b/include/phy.h
+index 749285f15e..05208d7f3d 100644
+--- a/include/phy.h
++++ b/include/phy.h
+@@ -331,6 +331,7 @@ int phy_marvell_init(void);
+ int phy_micrel_ksz8xxx_init(void);
+ int phy_micrel_ksz90x1_init(void);
+ int phy_meson_gxl_init(void);
++int phy_motorcomm_init(void);
+ int phy_natsemi_init(void);
+ int phy_nxp_c45_tja11xx_init(void);
+ int phy_nxp_tja11xx_init(void);
+--
+2.20.1
+
--- /dev/null
+From 808463e5b8f77b2daaa9a2a7d8aefbdbbad16141 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Mon, 5 Jun 2023 18:29:41 +0200
+Subject: [PATCH 4038/4044] sunxi: rongpin-rp-t113: add missing gpio.h include
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
+index f2521438fb..348ae5eec6 100644
+--- a/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
++++ b/arch/arm/dts/sun8i-t113s-rongpin-rp-t113.dts
+@@ -2,6 +2,7 @@
+ // Copyright (C) 2022 Arm Ltd.
+
+ #include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/gpio/gpio.h>
+
+ /dts-v1/;
+
+--
+2.20.1
+
--- /dev/null
+From 2392217ef179219a41246e883a52dc64fcfede2a Mon Sep 17 00:00:00 2001
+From: Maxim Kiselev <bigunclemax@gmail.com>
+Date: Fri, 19 May 2023 16:40:07 +0300
+Subject: [PATCH 4039/4044] sunxi: SPL SPI: Add SPI boot support for the
+ Allwinner R528/T113 SoCs
+
+R528/T113 SoCs uses the same SPI IP as the H6, also have the same clocks
+and reset bits layout, but the CCU base is different. Another difference
+is that the new SoCs do not have a clock divider inside. Instead of this
+we should configure sample mode depending on input clock rate.
+
+The pin assignment is also different: the H6 uses PC0, the R528/T113 PC4
+instead. This makes for a change in spi0_pinmux_setup() routine.
+
+This patch extends the H6/H616 #ifdef guards to also cover the R528/T113,
+using the shared CONFIG_SUNXI_GEN_NCAT2 and CONFIG_MACH_SUN8I_R528
+symbols. Also use CONFIG_SUNXI_GEN_NCAT2 symbol for the Kconfig
+dependency.
+
+Signed-off-by: Maxim Kiselev <bigunclemax@gmail.com>
+Tested-by: Sam Edwards <CFSworks@gmail.com>
+---
+ arch/arm/mach-sunxi/Kconfig | 2 +-
+ arch/arm/mach-sunxi/spl_spi_sunxi.c | 78 +++++++++++++++++++++--------
+ 2 files changed, 58 insertions(+), 22 deletions(-)
+
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index 1ddf496a55..d914066298 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -1003,7 +1003,7 @@ config SPL_STACK_R_ADDR
+
+ config SPL_SPI_SUNXI
+ bool "Support for SPI Flash on Allwinner SoCs in SPL"
+- depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6 || MACH_SUNIV
++ depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6 || MACH_SUNIV || SUNXI_GEN_NCAT2
+ help
+ Enable support for SPI Flash. This option allows SPL to read from
+ sunxi SPI Flash. It uses the same method as the boot ROM, so does
+diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
+index c2410dd7bb..3cfbf56d59 100644
+--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
++++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
+@@ -73,18 +73,27 @@
+ #define SUN6I_CTL_ENABLE BIT(0)
+ #define SUN6I_CTL_MASTER BIT(1)
+ #define SUN6I_CTL_SRST BIT(31)
++#define SUN6I_TCR_SDM BIT(13)
+ #define SUN6I_TCR_XCH BIT(31)
+
+ /*****************************************************************************/
+
+-#define CCM_AHB_GATING0 (0x01C20000 + 0x60)
+-#define CCM_H6_SPI_BGR_REG (0x03001000 + 0x96c)
+-#ifdef CONFIG_SUN50I_GEN_H6
+-#define CCM_SPI0_CLK (0x03001000 + 0x940)
++#if defined(CONFIG_SUN50I_GEN_H6)
++#define CCM_BASE 0x03001000
++#elif defined(CONFIG_SUNXI_GEN_NCAT2)
++#define CCM_BASE 0x02001000
+ #else
+-#define CCM_SPI0_CLK (0x01C20000 + 0xA0)
++#define CCM_BASE 0x01C20000
+ #endif
+-#define SUN6I_BUS_SOFT_RST_REG0 (0x01C20000 + 0x2C0)
++
++#define CCM_AHB_GATING0 (CCM_BASE + 0x60)
++#define CCM_H6_SPI_BGR_REG (CCM_BASE + 0x96c)
++#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
++#define CCM_SPI0_CLK (CCM_BASE + 0x940)
++#else
++#define CCM_SPI0_CLK (CCM_BASE + 0xA0)
++#endif
++#define SUN6I_BUS_SOFT_RST_REG0 (CCM_BASE + 0x2C0)
+
+ #define AHB_RESET_SPI0_SHIFT 20
+ #define AHB_GATE_OFFSET_SPI0 20
+@@ -102,17 +111,22 @@
+ */
+ static void spi0_pinmux_setup(unsigned int pin_function)
+ {
+- /* All chips use PC0 and PC2. */
+- sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
++ /* All chips use PC2. And all chips use PC0, except R528/T113 */
++ if (!IS_ENABLED(CONFIG_MACH_SUN8I_R528))
++ sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
++
+ sunxi_gpio_set_cfgpin(SUNXI_GPC(2), pin_function);
+
+- /* All chips except H6 and H616 use PC1. */
+- if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
++ /* All chips except H6/H616/R528/T113 use PC1. */
++ if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
++ !IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ sunxi_gpio_set_cfgpin(SUNXI_GPC(1), pin_function);
+
+- if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
++ if (IS_ENABLED(CONFIG_MACH_SUN50I_H6) ||
++ IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ sunxi_gpio_set_cfgpin(SUNXI_GPC(5), pin_function);
+- if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
++ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
++ IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ sunxi_gpio_set_cfgpin(SUNXI_GPC(4), pin_function);
+
+ /* Older generations use PC23 for CS, newer ones use PC3. */
+@@ -126,7 +140,8 @@ static void spi0_pinmux_setup(unsigned int pin_function)
+ static bool is_sun6i_gen_spi(void)
+ {
+ return IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
+- IS_ENABLED(CONFIG_SUN50I_GEN_H6);
++ IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
++ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2);
+ }
+
+ static uintptr_t spi0_base_address(void)
+@@ -137,6 +152,9 @@ static uintptr_t spi0_base_address(void)
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
+ return 0x05010000;
+
++ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
++ return 0x04025000;
++
+ if (!is_sun6i_gen_spi() ||
+ IS_ENABLED(CONFIG_MACH_SUNIV))
+ return 0x01C05000;
+@@ -152,23 +170,30 @@ static void spi0_enable_clock(void)
+ uintptr_t base = spi0_base_address();
+
+ /* Deassert SPI0 reset on SUN6I */
+- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
++ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
++ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+ setbits_le32(CCM_H6_SPI_BGR_REG, (1U << 16) | 0x1);
+ else if (is_sun6i_gen_spi())
+ setbits_le32(SUN6I_BUS_SOFT_RST_REG0,
+ (1 << AHB_RESET_SPI0_SHIFT));
+
+ /* Open the SPI0 gate */
+- if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
++ if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
++ !IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+ setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
+
+ if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
+ /* Divide by 32, clock source is AHB clock 200MHz */
+ writel(SPI0_CLK_DIV_BY_32, base + SUN6I_SPI0_CCTL);
+ } else {
+- /* Divide by 4 */
+- writel(SPI0_CLK_DIV_BY_4, base + (is_sun6i_gen_spi() ?
+- SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL));
++ /* New SoCs do not have a clock divider inside */
++ if (!IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
++ /* Divide by 4 */
++ writel(SPI0_CLK_DIV_BY_4,
++ base + (is_sun6i_gen_spi() ? SUN6I_SPI0_CCTL :
++ SUN4I_SPI0_CCTL));
++ }
++
+ /* 24MHz from OSC24M */
+ writel((1 << 31), CCM_SPI0_CLK);
+ }
+@@ -180,6 +205,14 @@ static void spi0_enable_clock(void)
+ /* Wait for completion */
+ while (readl(base + SUN6I_SPI0_GCR) & SUN6I_CTL_SRST)
+ ;
++
++ /*
++ * For new SoCs we should configure sample mode depending on
++ * input clock. As 24MHz from OSC24M is used, we could use
++ * normal sample mode by setting SDM bit in the TCR register
++ */
++ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
++ setbits_le32(base + SUN6I_SPI0_TCR, SUN6I_TCR_SDM);
+ } else {
+ /* Enable SPI in the master mode and reset FIFO */
+ setbits_le32(base + SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
+@@ -206,11 +239,13 @@ static void spi0_disable_clock(void)
+ writel(0, CCM_SPI0_CLK);
+
+ /* Close the SPI0 gate */
+- if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
++ if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
++ !IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+ clrbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
+
+ /* Assert SPI0 reset on SUN6I */
+- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
++ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
++ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+ clrbits_le32(CCM_H6_SPI_BGR_REG, (1U << 16) | 0x1);
+ else if (is_sun6i_gen_spi())
+ clrbits_le32(SUN6I_BUS_SOFT_RST_REG0,
+@@ -224,7 +259,8 @@ static void spi0_init(void)
+ if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
+ IS_ENABLED(CONFIG_SUN50I_GEN_H6))
+ pin_function = SUN50I_GPC_SPI0;
+- else if (IS_ENABLED(CONFIG_MACH_SUNIV))
++ else if (IS_ENABLED(CONFIG_MACH_SUNIV) ||
++ IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ pin_function = SUNIV_GPC_SPI0;
+
+ spi0_pinmux_setup(pin_function);
+--
+2.20.1
+
--- /dev/null
+From 805c9053f77e86e442f7a76832ea259695918a8c Mon Sep 17 00:00:00 2001
+From: Maxim Kiselev <bigunclemax@gmail.com>
+Date: Fri, 19 May 2023 16:40:08 +0300
+Subject: [PATCH 4040/4044] spi: sunxi: Add support for R329/D1/R528/T113 SPI
+ controller
+
+These SoCs have two SPI controllers that are quite similar to the SPI
+on previous Allwinner SoCs. The main difference is that new SoCs
+don't have a clock divider (SPI_CCR register) inside SPI IP.
+
+Instead SPI sample mode should be configured depending on the input clock.
+
+For now SPI input clock source selection is not supported by this driver,
+and only HOSC@24MHz can be used as input clock. Therefore, according to
+the, manual we could change the SPI sample mode from delay half
+cycle(default) to normal.
+
+This patch adds a quirk for this kind of SPI controllers
+
+Signed-off-by: Maxim Kiselev <bigunclemax@gmail.com>
+Tested-by: Sam Edwards <CFSworks@gmail.com>
+---
+ drivers/spi/spi-sunxi.c | 34 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 33 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
+index c56d82d998..9ec6b359e2 100644
+--- a/drivers/spi/spi-sunxi.c
++++ b/drivers/spi/spi-sunxi.c
+@@ -117,6 +117,8 @@ enum sun4i_spi_bits {
+ SPI_TCR_XCH,
+ SPI_TCR_CS_MANUAL,
+ SPI_TCR_CS_LEVEL,
++ SPI_TCR_SDC,
++ SPI_TCR_SDM,
+ SPI_FCR_TF_RST,
+ SPI_FCR_RF_RST,
+ SPI_FSR_RF_CNT_MASK,
+@@ -128,6 +130,7 @@ struct sun4i_spi_variant {
+ u32 fifo_depth;
+ bool has_soft_reset;
+ bool has_burst_ctl;
++ bool has_clk_ctl;
+ };
+
+ struct sun4i_spi_plat {
+@@ -302,7 +305,19 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
+ setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
+ SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
+
+- sun4i_spi_set_speed_mode(dev->parent);
++ if (priv->variant->has_clk_ctl) {
++ sun4i_spi_set_speed_mode(dev->parent);
++ } else {
++ /*
++ * At this moment there is no ability to change input clock.
++ * Therefore, we can only use default HOSC@24MHz clock and
++ * set SPI sampling mode to normal
++ */
++ clrsetbits_le32(SPI_REG(priv, SPI_TCR),
++ SPI_BIT(priv, SPI_TCR_SDC) |
++ SPI_BIT(priv, SPI_TCR_SDM),
++ SPI_BIT(priv, SPI_TCR_SDM));
++ }
+
+ return 0;
+ }
+@@ -516,6 +531,8 @@ static const u32 sun6i_spi_bits[] = {
+ [SPI_TCR_CS_MASK] = 0x30,
+ [SPI_TCR_CS_MANUAL] = BIT(6),
+ [SPI_TCR_CS_LEVEL] = BIT(7),
++ [SPI_TCR_SDC] = BIT(11),
++ [SPI_TCR_SDM] = BIT(13),
+ [SPI_TCR_XCH] = BIT(31),
+ [SPI_FCR_RF_RST] = BIT(15),
+ [SPI_FCR_TF_RST] = BIT(31),
+@@ -526,6 +543,7 @@ static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
+ .regs = sun4i_spi_regs,
+ .bits = sun4i_spi_bits,
+ .fifo_depth = 64,
++ .has_clk_ctl = true,
+ };
+
+ static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
+@@ -534,6 +552,7 @@ static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
+ .fifo_depth = 128,
+ .has_soft_reset = true,
+ .has_burst_ctl = true,
++ .has_clk_ctl = true,
+ };
+
+ static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
+@@ -542,6 +561,15 @@ static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
+ .fifo_depth = 64,
+ .has_soft_reset = true,
+ .has_burst_ctl = true,
++ .has_clk_ctl = true,
++};
++
++static const struct sun4i_spi_variant sun50i_r329_spi_variant = {
++ .regs = sun6i_spi_regs,
++ .bits = sun6i_spi_bits,
++ .fifo_depth = 64,
++ .has_soft_reset = true,
++ .has_burst_ctl = true,
+ };
+
+ static const struct udevice_id sun4i_spi_ids[] = {
+@@ -557,6 +585,10 @@ static const struct udevice_id sun4i_spi_ids[] = {
+ .compatible = "allwinner,sun8i-h3-spi",
+ .data = (ulong)&sun8i_h3_spi_variant,
+ },
++ {
++ .compatible = "allwinner,sun50i-r329-spi",
++ .data = (ulong)&sun50i_r329_spi_variant,
++ },
+ { /* sentinel */ }
+ };
+
+--
+2.20.1
+
--- /dev/null
+From ae59ce94c3dd062bd6f371cef729664fea5c8c71 Mon Sep 17 00:00:00 2001
+From: Maxim Kiselev <bigunclemax@gmail.com>
+Date: Fri, 19 May 2023 16:40:09 +0300
+Subject: [PATCH 4041/4044] riscv: dts: allwinner: d1: Add SPI controllers node
+
+Some boards form the MangoPi family (MQ\MQ-Dual\MQ-R) may have
+an optional SPI flash that connects to the SPI0 controller.
+
+This controller is the same for R329/D1/R528/T113s SoCs and
+should be supported by the sun50i-r329-spi driver.
+
+So let's add its DT nodes.
+
+Signed-off-by: Maxim Kiselev <bigunclemax@gmail.com>
+Reviewed-by: Sam Edwards <CFSworks@gmail.com>
+---
+ arch/riscv/dts/sunxi-d1s-t113.dtsi | 37 ++++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+index b72bbc5e43..324353905f 100644
+--- a/arch/riscv/dts/sunxi-d1s-t113.dtsi
++++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+@@ -108,6 +108,12 @@
+ function = "emac";
+ };
+
++ /omit-if-no-ref/
++ spi0_pins: spi0-pins {
++ pins = "PC2", "PC3", "PC4", "PC5";
++ function = "spi0";
++ };
++
+ /omit-if-no-ref/
+ uart1_pg6_pins: uart1-pg6-pins {
+ pins = "PG6", "PG7";
+@@ -459,6 +465,37 @@
+ #size-cells = <0>;
+ };
+
++ spi0: spi@4025000 {
++ compatible = "allwinner,sun20i-d1-spi",
++ "allwinner,sun50i-r329-spi";
++ reg = <0x04025000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(15) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
++ clock-names = "ahb", "mod";
++ dmas = <&dma 22>, <&dma 22>;
++ dma-names = "rx", "tx";
++ resets = <&ccu RST_BUS_SPI0>;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ spi1: spi@4026000 {
++ compatible = "allwinner,sun20i-d1-spi-dbi",
++ "allwinner,sun50i-r329-spi-dbi",
++ "allwinner,sun50i-r329-spi";
++ reg = <0x04026000 0x1000>;
++ interrupts = <SOC_PERIPHERAL_IRQ(16) IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
++ clock-names = "ahb", "mod";
++ dmas = <&dma 23>, <&dma 23>;
++ dma-names = "rx", "tx";
++ resets = <&ccu RST_BUS_SPI1>;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ usb_otg: usb@4100000 {
+ compatible = "allwinner,sun20i-d1-musb",
+ "allwinner,sun8i-a33-musb";
+--
+2.20.1
+
--- /dev/null
+From 433545eafc6867a9b468bb9cd805bce36e172cda Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 29 Jul 2023 11:23:47 +0200
+Subject: [PATCH 4042/4044] sunxi: add MYIR MYD-YT113X-SPI board
+
+Instead of eMMC, this board sports a 256Mb SPI NAND flash.
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/arm/dts/Makefile | 1 +
+ .../dts/sun8i-t113s-myir-myd-yt113x-spi.dts | 59 +++++++++++++++++++
+ configs/myir_myd_t113x-spi_defconfig | 38 ++++++++++++
+ 3 files changed, 98 insertions(+)
+ create mode 100644 arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
+ create mode 100644 configs/myir_myd_t113x-spi_defconfig
+
+diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+index be89021657..267f7bc07e 100644
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -714,6 +714,7 @@ dtb-$(CONFIG_MACH_SUN8I_R528) += \
+ sun8i-t113s-mangopi-mq-r-t113.dtb \
+ sun8i-t113s-mangopi-mqdual-t113.dtb \
+ sun8i-t113s-myir-myd-yt113x.dtb \
++ sun8i-t113s-myir-myd-yt113x-spi.dtb \
+ sun8i-t113s-rongpin-rp-t113.dtb
+ dtb-$(CONFIG_MACH_SUN50I_H5) += \
+ sun50i-h5-bananapi-m2-plus.dtb \
+diff --git a/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
+new file mode 100644
+index 0000000000..f72bab29a6
+--- /dev/null
++++ b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
+@@ -0,0 +1,59 @@
++// SPDX-License-Identifier: (GPL-2.0+ or MIT)
++// Copyright (C) 2022 Arm Ltd.
++
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/dts-v1/;
++
++#include "sun8i-t113s.dtsi"
++#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
++
++/ {
++ model = "MYIR MYD-YT113X (SPI)";
++ compatible = "myir,myd-yt113x", "myir,myc-yt113x", "allwinner,sun8i-t113s";
++
++ aliases {
++ serial5 = &uart5;
++ };
++
++ chosen {
++ stdout-path = "serial5:115200n8";
++ };
++};
++
++&cpu0 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&cpu1 {
++ cpu-supply = <®_vcc_core>;
++};
++
++&pio {
++ /omit-if-no-ref/
++ uart5_pins: uart5-pins {
++ pins = "PE6", "PE7";
++ function = "uart5";
++ };
++};
++
++&uart5 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart5_pins>;
++ status = "okay";
++};
++
++&uart3 {
++ status = "disabled";
++};
++
++&spi0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi0_pins>;
++ status = "okay";
++ spi_nand@0 {
++ compatible = "spi-nand";
++ reg = <0>;
++ spi-max-frequency = <52000000>;
++ };
++};
+diff --git a/configs/myir_myd_t113x-spi_defconfig b/configs/myir_myd_t113x-spi_defconfig
+new file mode 100644
+index 0000000000..a433fe0449
+--- /dev/null
++++ b/configs/myir_myd_t113x-spi_defconfig
+@@ -0,0 +1,38 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-myir-myd-yt113x-spi"
++CONFIG_SUNXI_MINIMUM_DRAM_MB=128
++CONFIG_SPL=y
++CONFIG_SPL_SPI_SUNXI=y
++CONFIG_MTD_SPI_NAND=y
++CONFIG_MACH_SUN8I_R528=y
++CONFIG_CONS_INDEX=6
++CONFIG_MMC0_CD_PIN="PF6"
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_SYS_MONITOR_LEN=786432
++CONFIG_DRAM_CLK=792
++CONFIG_DRAM_ZQ=8092667
++CONFIG_DRAM_SUNXI_ODT_EN=0
++CONFIG_DRAM_SUNXI_TPR0=0x004a2195
++CONFIG_DRAM_SUNXI_TPR11=0x340000
++CONFIG_DRAM_SUNXI_TPR12=0x46
++CONFIG_DRAM_SUNXI_TPR13=0x34000100
++CONFIG_CLK_SUN20I_D1=y
++CONFIG_PHY_MOTORCOMM=y
++CONFIG_SUN8I_EMAC=y
++CONFIG_RGMII=y
++CONFIG_RMII=y
++CONFIG_MTD=y
++CONFIG_DM_MTD=y
++CONFIG_SYS_MTDPARTS_RUNTIME=y
++CONFIG_NAND_STM32_FMC2=y
++CONFIG_SYS_NAND_ONFI_DETECTION=y
++CONFIG_MTD_SPI_NAND=y
++CONFIG_DM_SPI_FLASH=y
++CONFIG_SPI_FLASH_MACRONIX=y
++CONFIG_SPI_FLASH_SPANSION=y
++CONFIG_SPI_FLASH_STMICRO=y
++CONFIG_SPI_FLASH_WINBOND=y
++# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
++CONFIG_SPI_FLASH_MTD=y
++CONFIG_SPI=y
+--
+2.20.1
+
--- /dev/null
+From 7e690876a4d143df61950c4c60c56dc27d8fb0e2 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 29 Jul 2023 11:29:26 +0200
+Subject: [PATCH 4043/4044] sunxi: add support for emac on PG pins
+
+Some boards use Port G pins for muxing EMAC.
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ arch/riscv/dts/sunxi-d1s-t113.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+index 324353905f..2426c71f25 100644
+--- a/arch/riscv/dts/sunxi-d1s-t113.dtsi
++++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
+@@ -101,6 +101,14 @@
+ function = "emac";
+ };
+
++ /omit-if-no-ref/
++ rgmii_pg_pins: rgmii-pg-pins {
++ pins = "PG0", "PG1", "PG2", "PG3", "PG4",
++ "PG5", "PG6", "PG7", "PG8", "PG9",
++ "PG11", "PG12", "PG13", "PG14", "PG15";
++ function = "emac";
++ };
++
+ /omit-if-no-ref/
+ rmii_pe_pins: rmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+--
+2.20.1
+
--- /dev/null
+From d664819e1142f0f44945ed31d62e666146639403 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 29 Jul 2023 11:34:19 +0200
+Subject: [PATCH 4044/4044] sunxi: add ethernet support on MYIR MYD-YT113X-SPI
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ .../dts/sun8i-t113s-myir-myd-yt113x-spi.dts | 34 +++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
+index f72bab29a6..431d5593d6 100644
+--- a/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
++++ b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
+@@ -19,6 +19,23 @@
+ chosen {
+ stdout-path = "serial5:115200n8";
+ };
++
++ reg_vcc5v: regulator-5v {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-5v";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
++
++ /* SY8008 DC/DC regulator on the board */
++ reg_3v3: regulator-3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <®_vcc5v>;
++ };
+ };
+
+ &cpu0 {
+@@ -57,3 +74,20 @@
+ spi-max-frequency = <52000000>;
+ };
+ };
++
++&emac {
++ pinctrl-names = "default";
++ pinctrl-0 = <&rgmii_pg_pins>;
++ phy-supply = <®_3v3>;
++ phy-handle = <&ext_rgmii_phy>;
++ phy-mode = "rgmii-id";
++
++ status = "okay";
++};
++
++&mdio {
++ ext_rgmii_phy: ethernet-phy@4 {
++ compatible = "ethernet-phy-ieee802.3-c22";
++ reg = <4>;
++ };
++};
+--
+2.20.1
+
--- /dev/null
+From d44bacf6dab96824f23f06d264271d370f2f4431 Mon Sep 17 00:00:00 2001
+From: Weijie Gao <weijie.gao@mediatek.com>
+Date: Wed, 27 Jul 2022 16:36:13 +0800
+Subject: [PATCH 46/46] mtd: spi-nand: backport from upstream kernel
+
+Backport new features from upstream kernel
+
+Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
+---
+ drivers/mtd/nand/spi/Kconfig | 8 +
+ drivers/mtd/nand/spi/core.c | 101 ++++++----
+ drivers/mtd/nand/spi/gigadevice.c | 322 ++++++++++++++++++++++++++----
+ drivers/mtd/nand/spi/macronix.c | 173 +++++++++++++---
+ drivers/mtd/nand/spi/micron.c | 50 ++---
+ drivers/mtd/nand/spi/toshiba.c | 66 +++---
+ drivers/mtd/nand/spi/winbond.c | 171 +++++++++++++---
+ include/linux/mtd/spinand.h | 86 +++++---
+ 8 files changed, 753 insertions(+), 224 deletions(-)
+
+diff --git a/drivers/mtd/nand/spi/Kconfig b/drivers/mtd/nand/spi/Kconfig
+index 0777dfdf0a..bbd0981968 100644
+--- a/drivers/mtd/nand/spi/Kconfig
++++ b/drivers/mtd/nand/spi/Kconfig
+@@ -5,3 +5,11 @@ menuconfig MTD_SPI_NAND
+ select SPI_MEM
+ help
+ This is the framework for the SPI NAND device drivers.
++
++config MTD_SPI_NAND_W25N01KV
++ tristate "Winbond W25N01KV Support"
++ select MTD_SPI_NAND
++ default n
++ help
++ Winbond W25N01KV share the same ID with W25N01GV. However, they have
++ different attributes.
+diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
+index 134bf22c80..46ce48e0ea 100644
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -17,6 +17,7 @@
+ #include <linux/mtd/spinand.h>
+ #include <linux/of.h>
+ #include <linux/slab.h>
++#include <linux/string.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spi-mem.h>
+ #else
+@@ -451,10 +452,11 @@ out:
+ return status & STATUS_BUSY ? -ETIMEDOUT : 0;
+ }
+
+-static int spinand_read_id_op(struct spinand_device *spinand, u8 *buf)
++static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr,
++ u8 ndummy, u8 *buf)
+ {
+- struct spi_mem_op op = SPINAND_READID_OP(0, spinand->scratchbuf,
+- SPINAND_MAX_ID_LEN);
++ struct spi_mem_op op = SPINAND_READID_OP(
++ naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN);
+ int ret;
+
+ ret = spi_mem_exec_op(spinand->slave, &op);
+@@ -464,18 +466,6 @@ static int spinand_read_id_op(struct spinand_device *spinand, u8 *buf)
+ return ret;
+ }
+
+-static int spinand_reset_op(struct spinand_device *spinand)
+-{
+- struct spi_mem_op op = SPINAND_RESET_OP;
+- int ret;
+-
+- ret = spi_mem_exec_op(spinand->slave, &op);
+- if (ret)
+- return ret;
+-
+- return spinand_wait(spinand, NULL);
+-}
+-
+ static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
+ {
+ return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock);
+@@ -836,24 +826,63 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = {
+ &winbond_spinand_manufacturer,
+ };
+
+-static int spinand_manufacturer_detect(struct spinand_device *spinand)
++static int spinand_manufacturer_match(struct spinand_device *spinand,
++ enum spinand_readid_method rdid_method)
+ {
++ u8 *id = spinand->id.data;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(spinand_manufacturers); i++) {
+- ret = spinand_manufacturers[i]->ops->detect(spinand);
+- if (ret > 0) {
+- spinand->manufacturer = spinand_manufacturers[i];
+- return 0;
+- } else if (ret < 0) {
+- return ret;
+- }
++ const struct spinand_manufacturer *manufacturer =
++ spinand_manufacturers[i];
++
++ if (id[0] != manufacturer->id)
++ continue;
++
++ ret = spinand_match_and_init(spinand,
++ manufacturer->chips,
++ manufacturer->nchips,
++ rdid_method);
++ if (ret < 0)
++ continue;
++
++ spinand->manufacturer = manufacturer;
++ return 0;
+ }
+
+ return -ENOTSUPP;
+ }
+
++static int spinand_id_detect(struct spinand_device *spinand)
++{
++ u8 *id = spinand->id.data;
++ int ret;
++
++ ret = spinand_read_id_op(spinand, 0, 0, id);
++ if (ret)
++ return ret;
++ ret = spinand_manufacturer_match(spinand, SPINAND_READID_METHOD_OPCODE);
++ if (!ret)
++ return 0;
++
++ ret = spinand_read_id_op(spinand, 1, 0, id);
++ if (ret)
++ return ret;
++ ret = spinand_manufacturer_match(spinand,
++ SPINAND_READID_METHOD_OPCODE_ADDR);
++ if (!ret)
++ return 0;
++
++ ret = spinand_read_id_op(spinand, 0, 1, id);
++ if (ret)
++ return ret;
++ ret = spinand_manufacturer_match(spinand,
++ SPINAND_READID_METHOD_OPCODE_DUMMY);
++
++ return ret;
++}
++
+ static int spinand_manufacturer_init(struct spinand_device *spinand)
+ {
+ if (spinand->manufacturer->ops->init)
+@@ -909,9 +938,9 @@ spinand_select_op_variant(struct spinand_device *spinand,
+ * @spinand: SPI NAND object
+ * @table: SPI NAND device description table
+ * @table_size: size of the device description table
++ * @rdid_method: read id method to match
+ *
+- * Should be used by SPI NAND manufacturer drivers when they want to find a
+- * match between a device ID retrieved through the READ_ID command and an
++ * Match between a device ID retrieved through the READ_ID command and an
+ * entry in the SPI NAND description table. If a match is found, the spinand
+ * object will be initialized with information provided by the matching
+ * spinand_info entry.
+@@ -920,8 +949,10 @@ spinand_select_op_variant(struct spinand_device *spinand,
+ */
+ int spinand_match_and_init(struct spinand_device *spinand,
+ const struct spinand_info *table,
+- unsigned int table_size, u8 devid)
++ unsigned int table_size,
++ enum spinand_readid_method rdid_method)
+ {
++ u8 *id = spinand->id.data;
+ struct nand_device *nand = spinand_to_nand(spinand);
+ unsigned int i;
+
+@@ -929,13 +960,17 @@ int spinand_match_and_init(struct spinand_device *spinand,
+ const struct spinand_info *info = &table[i];
+ const struct spi_mem_op *op;
+
+- if (devid != info->devid)
++ if (rdid_method != info->devid.method)
++ continue;
++
++ if (memcmp(id + 1, info->devid.id, info->devid.len))
+ continue;
+
+ nand->memorg = table[i].memorg;
+ nand->eccreq = table[i].eccreq;
+ spinand->eccinfo = table[i].eccinfo;
+ spinand->flags = table[i].flags;
++ spinand->id.len = 1 + table[i].devid.len;
+ spinand->select_target = table[i].select_target;
+
+ op = spinand_select_op_variant(spinand,
+@@ -967,17 +1002,7 @@ static int spinand_detect(struct spinand_device *spinand)
+ struct nand_device *nand = spinand_to_nand(spinand);
+ int ret;
+
+- ret = spinand_reset_op(spinand);
+- if (ret)
+- return ret;
+-
+- ret = spinand_read_id_op(spinand, spinand->id.data);
+- if (ret)
+- return ret;
+-
+- spinand->id.len = SPINAND_MAX_ID_LEN;
+-
+- ret = spinand_manufacturer_detect(spinand);
++ ret = spinand_id_detect(spinand);
+ if (ret) {
+ dev_err(spinand->slave->dev, "unknown raw ID %*phN\n",
+ SPINAND_MAX_ID_LEN, spinand->id.data);
+diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
+index a2c93486f4..5357f02ddc 100644
+--- a/drivers/mtd/nand/spi/gigadevice.c
++++ b/drivers/mtd/nand/spi/gigadevice.c
+@@ -22,8 +22,13 @@
+
+ #define GD5FXGQXXEXXG_REG_STATUS2 0xf0
+
++#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4)
++#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4)
++#define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS (1 << 4)
++#define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR (7 << 4)
++
+ /* Q4 devices, QUADIO: Dummy bytes valid for 1 and 2 GBit variants */
+-static SPINAND_OP_VARIANTS(gd5fxgq4_read_cache_variants,
++static SPINAND_OP_VARIANTS(read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+@@ -31,8 +36,17 @@ static SPINAND_OP_VARIANTS(gd5fxgq4_read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+-/* Q5 devices, QUADIO: Dummy bytes only valid for 1 GBit variants */
+-static SPINAND_OP_VARIANTS(gd5f1gq5_read_cache_variants,
++static SPINAND_OP_VARIANTS(read_cache_variants_f,
++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
++
++/* For Q5 devices, QUADIO use different dummy byte settings */
++/* Q5 1Gb */
++static SPINAND_OP_VARIANTS(dummy2_read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+@@ -40,6 +54,15 @@ static SPINAND_OP_VARIANTS(gd5f1gq5_read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
++/* Q5 2Gb & 4Gb */
++static SPINAND_OP_VARIANTS(dummy4_read_cache_variants,
++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
+ static SPINAND_OP_VARIANTS(write_cache_variants,
+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
+@@ -48,7 +71,65 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
+-static int gd5fxgqxxexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
++static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ region->offset = (16 * section) + 8;
++ region->length = 8;
++
++ return 0;
++}
++
++static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ if (section) {
++ region->offset = 16 * section;
++ region->length = 8;
++ } else {
++ /* section 0 has one byte reserved for bad block mark */
++ region->offset = 1;
++ region->length = 7;
++ }
++ return 0;
++}
++
++static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
++ .ecc = gd5fxgq4xa_ooblayout_ecc,
++ .rfree = gd5fxgq4xa_ooblayout_free,
++};
++
++static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
++ u8 status)
++{
++ switch (status & STATUS_ECC_MASK) {
++ case STATUS_ECC_NO_BITFLIPS:
++ return 0;
++
++ case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
++ /* 1-7 bits are flipped. return the maximum. */
++ return 7;
++
++ case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
++ return 8;
++
++ case STATUS_ECC_UNCOR_ERROR:
++ return -EBADMSG;
++
++ default:
++ break;
++ }
++
++ return -EINVAL;
++}
++
++static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+ {
+ if (section)
+@@ -60,7 +141,7 @@ static int gd5fxgqxxexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
+ return 0;
+ }
+
+-static int gd5fxgqxxexxg_ooblayout_free(struct mtd_info *mtd, int section,
++static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+ {
+ if (section)
+@@ -73,7 +154,13 @@ static int gd5fxgqxxexxg_ooblayout_free(struct mtd_info *mtd, int section,
+ return 0;
+ }
+
+-static int gd5fxgq4xexxg_ecc_get_status(struct spinand_device *spinand,
++/* Valid for Q4/Q5 and Q6 (untested) devices */
++static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
++ .ecc = gd5fxgqx_variant2_ooblayout_ecc,
++ .rfree = gd5fxgqx_variant2_ooblayout_free,
++};
++
++static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
+ u8 status)
+ {
+ u8 status2;
+@@ -152,59 +239,214 @@ static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
+ return -EINVAL;
+ }
+
+-static const struct mtd_ooblayout_ops gd5fxgqxxexxg_ooblayout = {
+- .ecc = gd5fxgqxxexxg_ooblayout_ecc,
+- .rfree = gd5fxgqxxexxg_ooblayout_free,
++static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
++ u8 status)
++{
++ switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
++ case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
++ return 0;
++
++ case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
++ return 3;
++
++ case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
++ return -EBADMSG;
++
++ default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
++ return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
++ }
++
++ return -EINVAL;
++}
++
++static int esmt_1_ooblayout_ecc(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ region->offset = (16 * section) + 8;
++ region->length = 8;
++
++ return 0;
++}
++
++static int esmt_1_ooblayout_free(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ region->offset = (16 * section) + 2;
++ region->length = 6;
++
++ return 0;
++}
++
++static const struct mtd_ooblayout_ops esmt_1_ooblayout = {
++ .ecc = esmt_1_ooblayout_ecc,
++ .rfree = esmt_1_ooblayout_free,
+ };
+
+ static const struct spinand_info gigadevice_spinand_table[] = {
+- SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
+- NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++ SPINAND_INFO("F50L1G41LB",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01),
++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+- SPINAND_INFO_OP_VARIANTS(&gd5fxgq4_read_cache_variants,
++ SPINAND_INFO_OP_VARIANTS(&dummy2_read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+- SPINAND_ECCINFO(&gd5fxgqxxexxg_ooblayout,
+- gd5fxgq4xexxg_ecc_get_status)),
+- SPINAND_INFO("GD5F1GQ5UExxG", 0x51,
++ SPINAND_ECCINFO(&esmt_1_ooblayout, NULL)),
++ SPINAND_INFO("GD5F1GQ4xA",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
++ gd5fxgq4xa_ecc_get_status)),
++ SPINAND_INFO("GD5F2GQ4xA",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
++ NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
++ gd5fxgq4xa_ecc_get_status)),
++ SPINAND_INFO("GD5F4GQ4xA",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
++ NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
++ gd5fxgq4xa_ecc_get_status)),
++ SPINAND_INFO("GD5F1GQ4UExxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq4uexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F1GQ4UFxxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq4ufxxg_ecc_get_status)),
++ SPINAND_INFO("GD5F1GQ5UExxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(4, 512),
+- SPINAND_INFO_OP_VARIANTS(&gd5f1gq5_read_cache_variants,
++ SPINAND_INFO_OP_VARIANTS(&dummy2_read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+- 0,
+- SPINAND_ECCINFO(&gd5fxgqxxexxg_ooblayout,
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq5xexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F2GQ5UExxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52),
++ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq5xexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F4GQ6UExxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x55),
++ NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq5xexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F1GM7UExxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x91),
++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq4uexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F2GM7UExxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x92),
++ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq4uexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F4GM8UExxG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x95),
++ NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq4uexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F1GQ5UExxH",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x31),
++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&dummy2_read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq5xexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F2GQ5UExxH",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x32),
++ NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++ gd5fxgq5xexxg_ecc_get_status)),
++ SPINAND_INFO("GD5F4GQ6UExxH",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
++ NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
+ gd5fxgq5xexxg_ecc_get_status)),
+ };
+
+-static int gigadevice_spinand_detect(struct spinand_device *spinand)
+-{
+- u8 *id = spinand->id.data;
+- int ret;
+-
+- /*
+- * For GD NANDs, There is an address byte needed to shift in before IDs
+- * are read out, so the first byte in raw_id is dummy.
+- */
+- if (id[1] != SPINAND_MFR_GIGADEVICE)
+- return 0;
+-
+- ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
+- ARRAY_SIZE(gigadevice_spinand_table),
+- id[2]);
+- if (ret)
+- return ret;
+-
+- return 1;
+-}
+-
+ static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
+- .detect = gigadevice_spinand_detect,
+ };
+
+ const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
+ .id = SPINAND_MFR_GIGADEVICE,
+ .name = "GigaDevice",
++ .chips = gigadevice_spinand_table,
++ .nchips = ARRAY_SIZE(gigadevice_spinand_table),
+ .ops = &gigadevice_spinand_manuf_ops,
+ };
+diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
+index 6d643a8000..34e622d6e9 100644
+--- a/drivers/mtd/nand/spi/macronix.c
++++ b/drivers/mtd/nand/spi/macronix.c
+@@ -105,7 +105,8 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
+ }
+
+ static const struct spinand_info macronix_spinand_table[] = {
+- SPINAND_INFO("MX35LF1GE4AB", 0x12,
++ SPINAND_INFO("MX35LF1GE4AB",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(4, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -114,7 +115,8 @@ static const struct spinand_info macronix_spinand_table[] = {
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ mx35lf1ge4ab_ecc_get_status)),
+- SPINAND_INFO("MX35LF2GE4AB", 0x22,
++ SPINAND_INFO("MX35LF2GE4AB",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 2, 1, 1),
+ NAND_ECCREQ(4, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -122,7 +124,96 @@ static const struct spinand_info macronix_spinand_table[] = {
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
+- SPINAND_INFO("MX35UF4GE4AD", 0xb7,
++ SPINAND_INFO("MX35LF2GE4AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26),
++ NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35LF4GE4AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37),
++ NAND_MEMORG(1, 4096, 128, 64, 2048, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35LF1G24AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
++ SPINAND_INFO("MX35LF2G24AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
++ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
++ SPINAND_INFO("MX35LF4G24AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
++ NAND_MEMORG(1, 4096, 256, 64, 2048, 2, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
++ SPINAND_INFO("MX31LF1GE4BC",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX31UF1GE4BC",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),
++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++
++ SPINAND_INFO("MX35LF2G14AC",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20),
++ NAND_MEMORG(1, 2048, 64, 64, 2048, 2, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35UF4G24AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5),
++ NAND_MEMORG(1, 4096, 256, 64, 2048, 2, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35UF4GE4AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -131,7 +222,28 @@ static const struct spinand_info macronix_spinand_table[] = {
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ mx35lf1ge4ab_ecc_get_status)),
+- SPINAND_INFO("MX35UF2GE4AD", 0xa6,
++ SPINAND_INFO("MX35UF2G14AC",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0),
++ NAND_MEMORG(1, 2048, 64, 64, 2048, 2, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35UF2G24AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4),
++ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35UF2GE4AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -140,16 +252,38 @@ static const struct spinand_info macronix_spinand_table[] = {
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ mx35lf1ge4ab_ecc_get_status)),
+- SPINAND_INFO("MX35UF2GE4AC", 0xa2,
++ SPINAND_INFO("MX35UF2GE4AC",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2),
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35UF1G14AC",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90),
++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35UF1G24AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94),
++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ mx35lf1ge4ab_ecc_get_status)),
+- SPINAND_INFO("MX35UF1GE4AD", 0x96,
++ SPINAND_INFO("MX35UF1GE4AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -158,7 +292,8 @@ static const struct spinand_info macronix_spinand_table[] = {
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ mx35lf1ge4ab_ecc_get_status)),
+- SPINAND_INFO("MX35UF1GE4AC", 0x92,
++ SPINAND_INFO("MX35UF1GE4AC",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(4, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -170,33 +305,13 @@ static const struct spinand_info macronix_spinand_table[] = {
+
+ };
+
+-static int macronix_spinand_detect(struct spinand_device *spinand)
+-{
+- u8 *id = spinand->id.data;
+- int ret;
+-
+- /*
+- * Macronix SPI NAND read ID needs a dummy byte, so the first byte in
+- * raw_id is garbage.
+- */
+- if (id[1] != SPINAND_MFR_MACRONIX)
+- return 0;
+-
+- ret = spinand_match_and_init(spinand, macronix_spinand_table,
+- ARRAY_SIZE(macronix_spinand_table),
+- id[2]);
+- if (ret)
+- return ret;
+-
+- return 1;
+-}
+-
+ static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
+- .detect = macronix_spinand_detect,
+ };
+
+ const struct spinand_manufacturer macronix_spinand_manufacturer = {
+ .id = SPINAND_MFR_MACRONIX,
+ .name = "Macronix",
++ .chips = macronix_spinand_table,
++ .nchips = ARRAY_SIZE(macronix_spinand_table),
+ .ops = ¯onix_spinand_manuf_ops,
+ };
+diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
+index 6bacf14aaf..cecd3db958 100644
+--- a/drivers/mtd/nand/spi/micron.c
++++ b/drivers/mtd/nand/spi/micron.c
+@@ -120,7 +120,8 @@ static int micron_8_ecc_get_status(struct spinand_device *spinand,
+
+ static const struct spinand_info micron_spinand_table[] = {
+ /* M79A 2Gb 3.3V */
+- SPINAND_INFO("MT29F2G01ABAGD", 0x24,
++ SPINAND_INFO("MT29F2G01ABAGD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -130,7 +131,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ SPINAND_ECCINFO(µn_8_ooblayout,
+ micron_8_ecc_get_status)),
+ /* M79A 2Gb 1.8V */
+- SPINAND_INFO("MT29F2G01ABBGD", 0x25,
++ SPINAND_INFO("MT29F2G01ABBGD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -140,7 +142,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ SPINAND_ECCINFO(µn_8_ooblayout,
+ micron_8_ecc_get_status)),
+ /* M78A 1Gb 3.3V */
+- SPINAND_INFO("MT29F1G01ABAFD", 0x14,
++ SPINAND_INFO("MT29F1G01ABAFD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -150,7 +153,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ SPINAND_ECCINFO(µn_8_ooblayout,
+ micron_8_ecc_get_status)),
+ /* M78A 1Gb 1.8V */
+- SPINAND_INFO("MT29F1G01ABAFD", 0x15,
++ SPINAND_INFO("MT29F1G01ABAFD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -160,7 +164,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ SPINAND_ECCINFO(µn_8_ooblayout,
+ micron_8_ecc_get_status)),
+ /* M79A 4Gb 3.3V */
+- SPINAND_INFO("MT29F4G01ADAGD", 0x36,
++ SPINAND_INFO("MT29F4G01ADAGD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x36),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 2),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -171,7 +176,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ micron_8_ecc_get_status),
+ SPINAND_SELECT_TARGET(micron_select_target)),
+ /* M70A 4Gb 3.3V */
+- SPINAND_INFO("MT29F4G01ABAFD", 0x34,
++ SPINAND_INFO("MT29F4G01ABAFD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -181,7 +187,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ SPINAND_ECCINFO(µn_8_ooblayout,
+ micron_8_ecc_get_status)),
+ /* M70A 4Gb 1.8V */
+- SPINAND_INFO("MT29F4G01ABBFD", 0x35,
++ SPINAND_INFO("MT29F4G01ABBFD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -191,7 +198,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ SPINAND_ECCINFO(µn_8_ooblayout,
+ micron_8_ecc_get_status)),
+ /* M70A 8Gb 3.3V */
+- SPINAND_INFO("MT29F8G01ADAFD", 0x46,
++ SPINAND_INFO("MT29F8G01ADAFD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x46),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 2),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -202,7 +210,8 @@ static const struct spinand_info micron_spinand_table[] = {
+ micron_8_ecc_get_status),
+ SPINAND_SELECT_TARGET(micron_select_target)),
+ /* M70A 8Gb 1.8V */
+- SPINAND_INFO("MT29F8G01ADBFD", 0x47,
++ SPINAND_INFO("MT29F8G01ADBFD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x47),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 2),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -214,26 +223,6 @@ static const struct spinand_info micron_spinand_table[] = {
+ SPINAND_SELECT_TARGET(micron_select_target)),
+ };
+
+-static int micron_spinand_detect(struct spinand_device *spinand)
+-{
+- u8 *id = spinand->id.data;
+- int ret;
+-
+- /*
+- * Micron SPI NAND read ID need a dummy byte,
+- * so the first byte in raw_id is dummy.
+- */
+- if (id[1] != SPINAND_MFR_MICRON)
+- return 0;
+-
+- ret = spinand_match_and_init(spinand, micron_spinand_table,
+- ARRAY_SIZE(micron_spinand_table), id[2]);
+- if (ret)
+- return ret;
+-
+- return 1;
+-}
+-
+ static int micron_spinand_init(struct spinand_device *spinand)
+ {
+ /*
+@@ -248,12 +237,13 @@ static int micron_spinand_init(struct spinand_device *spinand)
+ }
+
+ static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
+- .detect = micron_spinand_detect,
+ .init = micron_spinand_init,
+ };
+
+ const struct spinand_manufacturer micron_spinand_manufacturer = {
+ .id = SPINAND_MFR_MICRON,
+ .name = "Micron",
++ .chips = micron_spinand_table,
++ .nchips = ARRAY_SIZE(micron_spinand_table),
+ .ops = µn_spinand_manuf_ops,
+ };
+diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
+index c2cd3b426b..e057b08c70 100644
+--- a/drivers/mtd/nand/spi/toshiba.c
++++ b/drivers/mtd/nand/spi/toshiba.c
+@@ -111,7 +111,8 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
+
+ static const struct spinand_info toshiba_spinand_table[] = {
+ /* 3.3V 1Gb (1st generation) */
+- SPINAND_INFO("TC58CVG0S3HRAIG", 0xC2,
++ SPINAND_INFO("TC58CVG0S3HRAIG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -121,7 +122,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 3.3V 2Gb (1st generation) */
+- SPINAND_INFO("TC58CVG1S3HRAIG", 0xCB,
++ SPINAND_INFO("TC58CVG1S3HRAIG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -131,7 +133,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 3.3V 4Gb (1st generation) */
+- SPINAND_INFO("TC58CVG2S0HRAIG", 0xCD,
++ SPINAND_INFO("TC58CVG2S0HRAIG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -141,7 +144,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 1.8V 1Gb (1st generation) */
+- SPINAND_INFO("TC58CYG0S3HRAIG", 0xB2,
++ SPINAND_INFO("TC58CYG0S3HRAIG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -151,7 +155,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 1.8V 2Gb (1st generation) */
+- SPINAND_INFO("TC58CYG1S3HRAIG", 0xBB,
++ SPINAND_INFO("TC58CYG1S3HRAIG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -161,7 +166,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 1.8V 4Gb (1st generation) */
+- SPINAND_INFO("TC58CYG2S0HRAIG", 0xBD,
++ SPINAND_INFO("TC58CYG2S0HRAIG",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -176,7 +182,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ * QE_BIT.
+ */
+ /* 3.3V 1Gb (2nd generation) */
+- SPINAND_INFO("TC58CVG0S3HRAIJ", 0xE2,
++ SPINAND_INFO("TC58CVG0S3HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -186,7 +193,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 3.3V 2Gb (2nd generation) */
+- SPINAND_INFO("TC58CVG1S3HRAIJ", 0xEB,
++ SPINAND_INFO("TC58CVG1S3HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -196,7 +204,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 3.3V 4Gb (2nd generation) */
+- SPINAND_INFO("TC58CVG2S0HRAIJ", 0xED,
++ SPINAND_INFO("TC58CVG2S0HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -206,7 +215,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 3.3V 8Gb (2nd generation) */
+- SPINAND_INFO("TH58CVG3S0HRAIJ", 0xE4,
++ SPINAND_INFO("TH58CVG3S0HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
+ NAND_MEMORG(1, 4096, 256, 64, 4096, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -216,7 +226,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 1.8V 1Gb (2nd generation) */
+- SPINAND_INFO("TC58CYG0S3HRAIJ", 0xD2,
++ SPINAND_INFO("TC58CYG0S3HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -226,7 +237,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 1.8V 2Gb (2nd generation) */
+- SPINAND_INFO("TC58CYG1S3HRAIJ", 0xDB,
++ SPINAND_INFO("TC58CYG1S3HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -236,7 +248,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 1.8V 4Gb (2nd generation) */
+- SPINAND_INFO("TC58CYG2S0HRAIJ", 0xDD,
++ SPINAND_INFO("TC58CYG2S0HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD),
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -246,7 +259,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
+ tx58cxgxsxraix_ecc_get_status)),
+ /* 1.8V 8Gb (2nd generation) */
+- SPINAND_INFO("TH58CYG3S0HRAIJ", 0xD4,
++ SPINAND_INFO("TH58CYG3S0HRAIJ",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
+ NAND_MEMORG(1, 4096, 256, 64, 4096, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -257,33 +271,13 @@ static const struct spinand_info toshiba_spinand_table[] = {
+ tx58cxgxsxraix_ecc_get_status)),
+ };
+
+-static int toshiba_spinand_detect(struct spinand_device *spinand)
+-{
+- u8 *id = spinand->id.data;
+- int ret;
+-
+- /*
+- * Toshiba SPI NAND read ID needs a dummy byte,
+- * so the first byte in id is garbage.
+- */
+- if (id[1] != SPINAND_MFR_TOSHIBA)
+- return 0;
+-
+- ret = spinand_match_and_init(spinand, toshiba_spinand_table,
+- ARRAY_SIZE(toshiba_spinand_table),
+- id[2]);
+- if (ret)
+- return ret;
+-
+- return 1;
+-}
+-
+ static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
+- .detect = toshiba_spinand_detect,
+ };
+
+ const struct spinand_manufacturer toshiba_spinand_manufacturer = {
+ .id = SPINAND_MFR_TOSHIBA,
+ .name = "Toshiba",
++ .chips = toshiba_spinand_table,
++ .nchips = ARRAY_SIZE(toshiba_spinand_table),
+ .ops = &toshiba_spinand_manuf_ops,
+ };
+diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
+index c119486efb..7a108cb3e6 100644
+--- a/drivers/mtd/nand/spi/winbond.c
++++ b/drivers/mtd/nand/spi/winbond.c
+@@ -19,6 +19,25 @@
+
+ #define WINBOND_CFG_BUF_READ BIT(3)
+
++#define W25N02_N04KV_STATUS_ECC_MASK (3 << 4)
++#define W25N02_N04KV_STATUS_ECC_NO_BITFLIPS (0 << 4)
++#define W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS (1 << 4)
++#define W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4)
++#define W25N02_N04KV_STATUS_ECC_UNCOR_ERROR (2 << 4)
++
++#define W25N01_M02GV_STATUS_ECC_MASK (3 << 4)
++#define W25N01_M02GV_STATUS_ECC_NO_BITFLIPS (0 << 4)
++#define W25N01_M02GV_STATUS_ECC_1_BITFLIPS (1 << 4)
++#define W25N01_M02GV_STATUS_ECC_UNCOR_ERROR (2 << 4)
++
++#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV)
++#define W25N01KV_STATUS_ECC_MASK (3 << 4)
++#define W25N01KV_STATUS_ECC_NO_BITFLIPS (0 << 4)
++#define W25N01KV_STATUS_ECC_1_3_BITFLIPS (1 << 4)
++#define W25N01KV_STATUS_ECC_4_BITFLIPS (3 << 4)
++#define W25N01KV_STATUS_ECC_UNCOR_ERROR (2 << 4)
++#endif
++
+ static SPINAND_OP_VARIANTS(read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+@@ -35,6 +54,35 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
++static int w25n02kv_n04kv_ooblayout_ecc(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ region->offset = (16 * section) + 64;
++ region->length = 16;
++
++ return 0;
++}
++
++static int w25n02kv_n04kv_ooblayout_free(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ region->offset = (16 * section) + 2;
++ region->length = 14;
++
++ return 0;
++}
++
++static const struct mtd_ooblayout_ops w25n02kv_n04kv_ooblayout = {
++ .ecc = w25n02kv_n04kv_ooblayout_ecc,
++ .rfree = w25n02kv_n04kv_ooblayout_free,
++};
++
+ static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+ {
+@@ -78,8 +126,63 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
+ return spi_mem_exec_op(spinand->slave, &op);
+ }
+
++#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV)
++static int w25n01kv_ecc_get_status(struct spinand_device *spinand,
++ u8 status)
++{
++ switch (status & W25N01KV_STATUS_ECC_MASK) {
++ case W25N01KV_STATUS_ECC_NO_BITFLIPS:
++ return 0;
++
++ case W25N01KV_STATUS_ECC_1_3_BITFLIPS:
++ return 3;
++
++ case W25N01KV_STATUS_ECC_4_BITFLIPS:
++ return 4;
++
++ case W25N01KV_STATUS_ECC_UNCOR_ERROR:
++ return -EBADMSG;
++
++ default:
++ break;
++ }
++
++ return -EINVAL;
++}
++#endif
++
++static int w25n02kv_n04kv_ecc_get_status(struct spinand_device *spinand,
++ u8 status)
++{
++ switch (status & W25N02_N04KV_STATUS_ECC_MASK) {
++ case W25N02_N04KV_STATUS_ECC_NO_BITFLIPS:
++ return 0;
++
++ case W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS:
++ return 3;
++
++ case W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS:
++ return 4;
++
++ /* W25N02_N04KV_use internal 8bit ECC algorithm.
++ * But the ECC strength is 4 bit requried.
++ * Return 3 if the bit bit flip count less than 5.
++ * Return 4 if the bit bit flip count more than 5 to 8.
++ */
++
++ case W25N02_N04KV_STATUS_ECC_UNCOR_ERROR:
++ return -EBADMSG;
++
++ default:
++ break;
++ }
++
++ return -EINVAL;
++}
++
+ static const struct spinand_info winbond_spinand_table[] = {
+- SPINAND_INFO("W25M02GV", 0xAB,
++ SPINAND_INFO("W25M02GV",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 2),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -88,7 +191,19 @@ static const struct spinand_info winbond_spinand_table[] = {
+ 0,
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
+ SPINAND_SELECT_TARGET(w25m02gv_select_target)),
+- SPINAND_INFO("W25N01GV", 0xAA,
++#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV)
++ SPINAND_INFO("W25N01KV",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
++ NAND_MEMORG(1, 2048, 96, 64, 1024, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ 0,
++ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout, w25n01kv_ecc_get_status)),
++#else
++ SPINAND_INFO("W25N01GV",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -96,32 +211,31 @@ static const struct spinand_info winbond_spinand_table[] = {
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+-};
+-
+-/**
+- * winbond_spinand_detect - initialize device related part in spinand_device
+- * struct if it is a Winbond device.
+- * @spinand: SPI NAND device structure
+- */
+-static int winbond_spinand_detect(struct spinand_device *spinand)
+-{
+- u8 *id = spinand->id.data;
+- int ret;
+-
+- /*
+- * Winbond SPI NAND read ID need a dummy byte,
+- * so the first byte in raw_id is dummy.
++#endif
++ SPINAND_INFO("W25N02KV",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
++ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ 0,
++ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
++ w25n02kv_n04kv_ecc_get_status)),
++ /* W25N04KV has 2-die(lun), however, it can select die automatically.
++ * Treat it as single die here and double block size.
+ */
+- if (id[1] != SPINAND_MFR_WINBOND)
+- return 0;
+-
+- ret = spinand_match_and_init(spinand, winbond_spinand_table,
+- ARRAY_SIZE(winbond_spinand_table), id[2]);
+- if (ret)
+- return ret;
+-
+- return 1;
+-}
++ SPINAND_INFO("W25N04KV",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
++ NAND_MEMORG(1, 2048, 128, 64, 4096, 2, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ 0,
++ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
++ w25n02kv_n04kv_ecc_get_status)),
++};
+
+ static int winbond_spinand_init(struct spinand_device *spinand)
+ {
+@@ -142,12 +256,13 @@ static int winbond_spinand_init(struct spinand_device *spinand)
+ }
+
+ static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
+- .detect = winbond_spinand_detect,
+ .init = winbond_spinand_init,
+ };
+
+ const struct spinand_manufacturer winbond_spinand_manufacturer = {
+ .id = SPINAND_MFR_WINBOND,
+ .name = "Winbond",
++ .chips = winbond_spinand_table,
++ .nchips = ARRAY_SIZE(winbond_spinand_table),
+ .ops = &winbond_spinand_manuf_ops,
+ };
+diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
+index 15bcd59f34..3a138f977e 100644
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -39,15 +39,15 @@
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_NO_DATA)
+
+-#define SPINAND_READID_OP(ndummy, buf, len) \
++#define SPINAND_READID_OP(naddr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1), \
+- SPI_MEM_OP_NO_ADDR, \
++ SPI_MEM_OP_ADDR(naddr, 0, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 1))
+
+ #define SPINAND_SET_FEATURE_OP(reg, valptr) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x1f, 1), \
+- SPI_MEM_OP_ADDR(1, reg, 1), \
++ SPI_MEM_OP_ADDR(1, reg, 1), \
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_DATA_OUT(1, valptr, 1))
+
+@@ -75,18 +75,36 @@
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 1))
+
++#define SPINAND_PAGE_READ_FROM_CACHE_OP_3A(fast, addr, ndummy, buf, len)\
++ SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
++ SPI_MEM_OP_ADDR(3, addr, 1), \
++ SPI_MEM_OP_DUMMY(ndummy, 1), \
++ SPI_MEM_OP_DATA_IN(len, buf, 1))
++
+ #define SPINAND_PAGE_READ_FROM_CACHE_X2_OP(addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
+ SPI_MEM_OP_ADDR(2, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 2))
+
++#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(addr, ndummy, buf, len) \
++ SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
++ SPI_MEM_OP_ADDR(3, addr, 1), \
++ SPI_MEM_OP_DUMMY(ndummy, 1), \
++ SPI_MEM_OP_DATA_IN(len, buf, 2))
++
+ #define SPINAND_PAGE_READ_FROM_CACHE_X4_OP(addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
+ SPI_MEM_OP_ADDR(2, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 4))
+
++#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(addr, ndummy, buf, len) \
++ SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
++ SPI_MEM_OP_ADDR(3, addr, 1), \
++ SPI_MEM_OP_DUMMY(ndummy, 1), \
++ SPI_MEM_OP_DATA_IN(len, buf, 4))
++
+ #define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \
+ SPI_MEM_OP_ADDR(2, addr, 2), \
+@@ -153,37 +171,46 @@ struct spinand_device;
+ * @data: buffer containing the id bytes. Currently 4 bytes large, but can
+ * be extended if required
+ * @len: ID length
+- *
+- * struct_spinand_id->data contains all bytes returned after a READ_ID command,
+- * including dummy bytes if the chip does not emit ID bytes right after the
+- * READ_ID command. The responsibility to extract real ID bytes is left to
+- * struct_manufacurer_ops->detect().
+ */
+ struct spinand_id {
+ u8 data[SPINAND_MAX_ID_LEN];
+ int len;
+ };
+
++enum spinand_readid_method {
++ SPINAND_READID_METHOD_OPCODE,
++ SPINAND_READID_METHOD_OPCODE_ADDR,
++ SPINAND_READID_METHOD_OPCODE_DUMMY,
++};
++
++/**
++ * struct spinand_devid - SPI NAND device id structure
++ * @id: device id of current chip
++ * @len: number of bytes in device id
++ * @method: method to read chip id
++ * There are 3 possible variants:
++ * SPINAND_READID_METHOD_OPCODE: chip id is returned immediately
++ * after read_id opcode.
++ * SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after
++ * read_id opcode + 1-byte address.
++ * SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after
++ * read_id opcode + 1 dummy byte.
++ */
++struct spinand_devid {
++ const u8 *id;
++ const u8 len;
++ const enum spinand_readid_method method;
++};
++
+ /**
+ * struct manufacurer_ops - SPI NAND manufacturer specific operations
+- * @detect: detect a SPI NAND device. Every time a SPI NAND device is probed
+- * the core calls the struct_manufacurer_ops->detect() hook of each
+- * registered manufacturer until one of them return 1. Note that
+- * the first thing to check in this hook is that the manufacturer ID
+- * in struct_spinand_device->id matches the manufacturer whose
+- * ->detect() hook has been called. Should return 1 if there's a
+- * match, 0 if the manufacturer ID does not match and a negative
+- * error code otherwise. When true is returned, the core assumes
+- * that properties of the NAND chip (spinand->base.memorg and
+- * spinand->base.eccreq) have been filled
+ * @init: initialize a SPI NAND device
+ * @cleanup: cleanup a SPI NAND device
+ *
+ * Each SPI NAND manufacturer driver should implement this interface so that
+- * NAND chips coming from this vendor can be detected and initialized properly.
++ * NAND chips coming from this vendor can be initialized properly.
+ */
+ struct spinand_manufacturer_ops {
+- int (*detect)(struct spinand_device *spinand);
+ int (*init)(struct spinand_device *spinand);
+ void (*cleanup)(struct spinand_device *spinand);
+ };
+@@ -192,11 +219,16 @@ struct spinand_manufacturer_ops {
+ * struct spinand_manufacturer - SPI NAND manufacturer instance
+ * @id: manufacturer ID
+ * @name: manufacturer name
++ * @devid_len: number of bytes in device ID
++ * @chips: supported SPI NANDs under current manufacturer
++ * @nchips: number of SPI NANDs available in chips array
+ * @ops: manufacturer operations
+ */
+ struct spinand_manufacturer {
+ u8 id;
+ char *name;
++ const struct spinand_info *chips;
++ const size_t nchips;
+ const struct spinand_manufacturer_ops *ops;
+ };
+
+@@ -268,7 +300,7 @@ struct spinand_ecc_info {
+ */
+ struct spinand_info {
+ const char *model;
+- u8 devid;
++ struct spinand_devid devid;
+ u32 flags;
+ struct nand_memory_organization memorg;
+ struct nand_ecc_req eccreq;
+@@ -282,6 +314,13 @@ struct spinand_info {
+ unsigned int target);
+ };
+
++#define SPINAND_ID(__method, ...) \
++ { \
++ .id = (const u8[]){ __VA_ARGS__ }, \
++ .len = sizeof((u8[]){ __VA_ARGS__ }), \
++ .method = __method, \
++ }
++
+ #define SPINAND_INFO_OP_VARIANTS(__read, __write, __update) \
+ { \
+ .read_cache = __read, \
+@@ -440,9 +479,10 @@ static inline void spinand_set_ofnode(struct spinand_device *spinand,
+ }
+ #endif /* __UBOOT__ */
+
+-int spinand_match_and_init(struct spinand_device *dev,
++int spinand_match_and_init(struct spinand_device *spinand,
+ const struct spinand_info *table,
+- unsigned int table_size, u8 devid);
++ unsigned int table_size,
++ enum spinand_readid_method rdid_method);
+
+ int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
+ int spinand_select_target(struct spinand_device *spinand, unsigned int target);
+--
+2.20.1
+
--- /dev/null
+From b943ca1bd3580393f1525cb021c9a2051c9f1958 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 26 Aug 2023 17:45:03 +0200
+Subject: [PATCH 4046/4047] arm: dts: add partition table for MYIR
+ MYD-YT113X-SPI
+
+The original bootloader reports the following as the partition table:
+
+device nand0 <nand>, # parts = 4
+ #: name size offset mask_flags
+ 0: boot0 0x00100000 0x00000000 1
+ 1: uboot 0x00300000 0x00100000 1
+ 2: secure_storage 0x00100000 0x00400000 1
+ 3: sys 0x0fb00000 0x00500000 0
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ .../dts/sun8i-t113s-myir-myd-yt113x-spi.dts | 26 +++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
+index 431d5593d6..a5fd8c6bea 100644
+--- a/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
++++ b/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
+@@ -72,6 +72,32 @@
+ compatible = "spi-nand";
+ reg = <0>;
+ spi-max-frequency = <52000000>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "boot0";
++ reg = <0x0 0x100000>;
++ };
++
++ partition@100000 {
++ label = "uboot";
++ reg = <0x0 0x300000>;
++ };
++
++ partition@400000 {
++ label = "secure_storage";
++ reg = <0x0 0x400000>;
++ };
++
++ partition@500000 {
++ label = "sys";
++ reg = <0x0 0xfb00000>;
++ };
++ };
+ };
+ };
+
+--
+2.20.1
+
--- /dev/null
+From a6fbb8f2e7555c2fdd3e42d9e46523eb2d03d83a Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 26 Aug 2023 17:46:22 +0200
+Subject: [PATCH 4047/4047] configs: enable UBI support for MYIR MYD-YT113X-SPI
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ configs/myir_myd_t113x-spi_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/configs/myir_myd_t113x-spi_defconfig b/configs/myir_myd_t113x-spi_defconfig
+index a433fe0449..d7b9a9bbcf 100644
+--- a/configs/myir_myd_t113x-spi_defconfig
++++ b/configs/myir_myd_t113x-spi_defconfig
+@@ -36,3 +36,4 @@ CONFIG_SPI_FLASH_WINBOND=y
+ # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+ CONFIG_SPI_FLASH_MTD=y
+ CONFIG_SPI=y
++CONFIG_MTD_UBI_FASTMAP=y
+--
+2.20.1
+
--- /dev/null
+From bbc0d9a9ee7da3b64d70010e79098c1ca24c351c Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Sat, 26 Aug 2023 21:09:17 +0200
+Subject: [PATCH 4048/4048] sunxi: r528/d1/t113: add SDC2 pinmux on PC2-7 pins
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ board/sunxi/board.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/board/sunxi/board.c b/board/sunxi/board.c
+index 661137f43c..c00629f9b5 100644
+--- a/board/sunxi/board.c
++++ b/board/sunxi/board.c
+@@ -424,6 +424,13 @@ static void mmc_pinmux_setup(int sdc)
+ sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
+ sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
++#elif defined(CONFIG_MACH_SUN8I_R528)
++ /* SDC2: PC2-PC7 */
++ for (pin = SUNXI_GPC(2); pin <= SUNXI_GPC(7); pin++) {
++ sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
++ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
++ sunxi_gpio_set_drv(pin, 2);
++ }
+ #elif defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I)
+ /* SDC2: PC5-PC6, PC8-PC16 */
+ for (pin = SUNXI_GPC(5); pin <= SUNXI_GPC(6); pin++) {
+--
+2.20.1
+
+++ /dev/null
-From 6ab5a9624210408ea57e957c3ebbafd35ece224d Mon Sep 17 00:00:00 2001
-From: Sam Edwards <cfsworks@gmail.com>
-Date: Thu, 1 Jun 2023 15:48:11 -0600
-Subject: [PATCH 4100/4103] SQUASH ME
-
-This patch contains only register defs for cpu_sunxi_ncat2.h, and should
-be combined (as appropriate) into:
-
-sunxi: introduce NCAT2 generation model
----
- arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-index d01508517c..25f71bbccd 100644
---- a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
-@@ -17,6 +17,9 @@
- #define SUNXI_SIDC_BASE 0x03006000
- #define SUNXI_SID_BASE 0x03006200
- #define SUNXI_TIMER_BASE 0x02050000
-+#define SUNXI_GIC400_BASE 0x03020000
-+#define SUNXI_CPUX_BASE 0x09010000
-+#define SUNXI_CPUCFG_BASE 0
-
- #ifdef CONFIG_MACH_SUN50I_H6
- #define SUNXI_DRAM_COM_BASE 0x04002000
-@@ -34,11 +37,11 @@
- #define SUNXI_SPI0_BASE 0x04025000
- #define SUNXI_SPI1_BASE 0x04026000
-
--#define SUNXI_RTC_BASE 0x07000000
- #define SUNXI_R_CPUCFG_BASE 0x07000400
- #define SUNXI_PRCM_BASE 0x07010000
- #define SUNXI_R_WDOG_BASE 0x07020400
--#define SUNXI_R_TWI_BASE 0x07081400
-+#define SUNXI_R_TWI_BASE 0x07020800
-+#define SUNXI_RTC_BASE 0x07090000
-
- #ifndef __ASSEMBLY__
- void sunxi_board_init(void);
---
-2.20.1
-
+++ /dev/null
-From a183878133f04cb53810e2e70cb39169efde27c4 Mon Sep 17 00:00:00 2001
-From: Sam Edwards <cfsworks@gmail.com>
-Date: Thu, 1 Jun 2023 15:48:12 -0600
-Subject: [PATCH 4101/4103] sunxi: psci: clean away preprocessor macros
-
-This patch restructures psci.c to get away from the "many different
-function definitions switched by #ifdef" paradigm to the preferred style
-of having a single function definition with `if (IS_ENABLED(...))` to
-make the optimizer include only the appropriate function bodies instead.
-
-There are no functional changes here.
-
-Signed-off-by: Sam Edwards <CFSworks@gmail.com>
----
- arch/arm/cpu/armv7/sunxi/psci.c | 94 ++++++++++++++-------------------
- 1 file changed, 41 insertions(+), 53 deletions(-)
-
-diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
-index e1d3638b5c..7809b074f8 100644
---- a/arch/arm/cpu/armv7/sunxi/psci.c
-+++ b/arch/arm/cpu/armv7/sunxi/psci.c
-@@ -76,28 +76,24 @@ static void __secure __mdelay(u32 ms)
- isb();
- }
-
--static void __secure clamp_release(u32 __maybe_unused *clamp)
-+static void __secure clamp_release(u32 *clamp)
- {
--#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
-- defined(CONFIG_MACH_SUN8I_H3) || \
-- defined(CONFIG_MACH_SUN8I_R40)
-- u32 tmp = 0x1ff;
-- do {
-- tmp >>= 1;
-- writel(tmp, clamp);
-- } while (tmp);
--
-- __mdelay(10);
--#endif
-+ if (clamp) {
-+ u32 tmp = 0x1ff;
-+ do {
-+ tmp >>= 1;
-+ writel(tmp, clamp);
-+ } while (tmp);
-+
-+ __mdelay(10);
-+ }
- }
-
--static void __secure clamp_set(u32 __maybe_unused *clamp)
-+static void __secure clamp_set(u32 *clamp)
- {
--#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
-- defined(CONFIG_MACH_SUN8I_H3) || \
-- defined(CONFIG_MACH_SUN8I_R40)
-- writel(0xff, clamp);
--#endif
-+ if (clamp) {
-+ writel(0xff, clamp);
-+ }
- }
-
- static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
-@@ -118,53 +114,45 @@ static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
- }
- }
-
--#ifdef CONFIG_MACH_SUN8I_R40
--/* secondary core entry address is programmed differently on R40 */
- static void __secure sunxi_set_entry_address(void *entry)
- {
-- writel((u32)entry,
-- SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
--}
--#else
--static void __secure sunxi_set_entry_address(void *entry)
--{
-- struct sunxi_cpucfg_reg *cpucfg =
-- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-+ /* secondary core entry address is programmed differently on R40 */
-+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
-+ writel((u32)entry,
-+ SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
-+ } else {
-+ struct sunxi_cpucfg_reg *cpucfg =
-+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
-- writel((u32)entry, &cpucfg->priv0);
-+ writel((u32)entry, &cpucfg->priv0);
-+ }
- }
--#endif
-
--#ifdef CONFIG_MACH_SUN7I
--/* sun7i (A20) is different from other single cluster SoCs */
--static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on)
--{
-- struct sunxi_cpucfg_reg *cpucfg =
-- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
--
-- sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
-- on, 0);
--}
--#elif defined CONFIG_MACH_SUN8I_R40
- static void __secure sunxi_cpu_set_power(int cpu, bool on)
- {
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
-- sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu),
-- (void *)cpucfg + SUN8I_R40_PWROFF,
-- on, cpu);
--}
--#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
--static void __secure sunxi_cpu_set_power(int cpu, bool on)
--{
-- struct sunxi_prcm_reg *prcm =
-- (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
-+ /* sun7i (A20) is different from other single cluster SoCs */
-+ if (IS_ENABLED(CONFIG_MACH_SUN7I)) {
-+ sunxi_power_switch(NULL, &cpucfg->cpu1_pwroff, on, 0);
-+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
-+ sunxi_power_switch(NULL, (void *)cpucfg + SUN8I_R40_PWROFF,
-+ on, cpu);
-+ } else {
-+#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
-+ struct sunxi_prcm_reg *prcm =
-+ (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
-
-- sunxi_power_switch(&prcm->cpu_pwr_clamp[cpu], &prcm->cpu_pwroff,
-- on, cpu);
-+ u32 *clamp = &prcm->cpu_pwr_clamp[cpu];
-+ if (IS_ENABLED(CONFIG_MACH_SUN6I) ||
-+ IS_ENABLED(CONFIG_MACH_SUN8I_H3))
-+ clamp = NULL;
-+
-+ sunxi_power_switch(clamp, &prcm->cpu_pwroff, on, cpu);
-+#endif
-+ }
- }
--#endif /* CONFIG_MACH_SUN7I */
-
- void __secure sunxi_cpu_power_off(u32 cpuid)
- {
---
-2.20.1
-
+++ /dev/null
-From 1422f560d647d466f2b99fbc917ac4f6a1d3af38 Mon Sep 17 00:00:00 2001
-From: Sam Edwards <cfsworks@gmail.com>
-Date: Thu, 1 Jun 2023 15:48:13 -0600
-Subject: [PATCH 4102/4103] sunxi: psci: refactor register access to separate
- functions
-
-This is to prepare for R528, which does not have the typical
-"CPUCFG" block; it has a "CPUX" block which provides these
-same functions but is organized differently.
-
-Moving the hardware-access bits to their own functions separates the
-logic from the hardware so we can reuse the same logic.
-
-Signed-off-by: Sam Edwards <CFSworks@gmail.com>
----
- arch/arm/cpu/armv7/sunxi/psci.c | 66 +++++++++++++++++++++++----------
- 1 file changed, 47 insertions(+), 19 deletions(-)
-
-diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
-index 7809b074f8..94120e7526 100644
---- a/arch/arm/cpu/armv7/sunxi/psci.c
-+++ b/arch/arm/cpu/armv7/sunxi/psci.c
-@@ -114,7 +114,7 @@ static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
- }
- }
-
--static void __secure sunxi_set_entry_address(void *entry)
-+static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
- {
- /* secondary core entry address is programmed differently on R40 */
- if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
-@@ -154,30 +154,60 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
- }
- }
-
--void __secure sunxi_cpu_power_off(u32 cpuid)
-+static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
-+{
-+ struct sunxi_cpucfg_reg *cpucfg =
-+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-+
-+ writel(reset ? 0b00 : 0b11, &cpucfg->cpu[cpu].rst);
-+}
-+
-+static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
- {
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-+
-+ if (lock)
-+ clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
-+ else
-+ setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
-+}
-+
-+static bool __secure sunxi_cpu_poll_wfi(int cpu)
-+{
-+ struct sunxi_cpucfg_reg *cpucfg =
-+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-+
-+ return !!(readl(&cpucfg->cpu[cpu].status) & BIT(2));
-+}
-+
-+static void __secure sunxi_cpu_invalidate_cache(int cpu)
-+{
-+ struct sunxi_cpucfg_reg *cpucfg =
-+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-+
-+ clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
-+}
-+
-+void __secure sunxi_cpu_power_off(u32 cpuid)
-+{
- u32 cpu = cpuid & 0x3;
-
- /* Wait for the core to enter WFI */
-- while (1) {
-- if (readl(&cpucfg->cpu[cpu].status) & BIT(2))
-- break;
-+ while (!sunxi_cpu_poll_wfi(cpu))
- __mdelay(1);
-- }
-
- /* Assert reset on target CPU */
-- writel(0, &cpucfg->cpu[cpu].rst);
-+ sunxi_cpu_set_reset(cpu, true);
-
- /* Lock CPU (Disable external debug access) */
-- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
-+ sunxi_cpu_set_locking(cpu, true);
-
- /* Power down CPU */
- sunxi_cpu_set_power(cpuid, false);
-
-- /* Unlock CPU (Disable external debug access) */
-- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
-+ /* Unlock CPU (Reenable external debug access) */
-+ sunxi_cpu_set_locking(cpu, false);
- }
-
- static u32 __secure cp15_read_scr(void)
-@@ -234,33 +264,31 @@ out:
- int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
- u32 context_id)
- {
-- struct sunxi_cpucfg_reg *cpucfg =
-- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
- u32 cpu = (mpidr & 0x3);
-
- /* store target PC and context id */
- psci_save(cpu, pc, context_id);
-
- /* Set secondary core power on PC */
-- sunxi_set_entry_address(&psci_cpu_entry);
-+ sunxi_cpu_set_entry(cpu, &psci_cpu_entry);
-
- /* Assert reset on target CPU */
-- writel(0, &cpucfg->cpu[cpu].rst);
-+ sunxi_cpu_set_reset(cpu, true);
-
- /* Invalidate L1 cache */
-- clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
-+ sunxi_cpu_invalidate_cache(cpu);
-
- /* Lock CPU (Disable external debug access) */
-- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
-+ sunxi_cpu_set_locking(cpu, true);
-
- /* Power up target CPU */
- sunxi_cpu_set_power(cpu, true);
-
- /* De-assert reset on target CPU */
-- writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst);
-+ sunxi_cpu_set_reset(cpu, false);
-
-- /* Unlock CPU (Disable external debug access) */
-- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
-+ /* Unlock CPU (Reenable external debug access) */
-+ sunxi_cpu_set_locking(cpu, false);
-
- return ARM_PSCI_RET_SUCCESS;
- }
---
-2.20.1
-
+++ /dev/null
-From bc42c4edff3af5b31702989527c4adb691838084 Mon Sep 17 00:00:00 2001
-From: Sam Edwards <cfsworks@gmail.com>
-Date: Thu, 1 Jun 2023 15:48:14 -0600
-Subject: [PATCH 4103/4103] sunxi: psci: implement PSCI on R528
-
-This patch adds the necessary code to make nonsec booting and PSCI
-secondary core management functional on the R528/T113.
-
-Signed-off-by: Sam Edwards <CFSworks@gmail.com>
-Tested-by: Maksim Kiselev <bigunclemax@gmail.com>
----
- arch/arm/cpu/armv7/sunxi/psci.c | 47 ++++++++++++++++++++++++++++++++-
- arch/arm/mach-sunxi/Kconfig | 2 ++
- include/configs/sunxi-common.h | 8 ++++++
- 3 files changed, 56 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
-index 94120e7526..f3c1c459c2 100644
---- a/arch/arm/cpu/armv7/sunxi/psci.c
-+++ b/arch/arm/cpu/armv7/sunxi/psci.c
-@@ -38,6 +38,19 @@
- #define SUN8I_R40_PWR_CLAMP(cpu) (0x120 + (cpu) * 0x4)
- #define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc)
-
-+/*
-+ * R528 is also different, as it has both cores powered up (but held in reset
-+ * state) after the SoC is reset. Like the R40, it uses a "soft" entry point
-+ * address register, but unlike the R40, it uses a newer "CPUX" block to manage
-+ * CPU state, rather than the older CPUCFG system.
-+ */
-+#define SUN8I_R528_SOFT_ENTRY (0x1c8)
-+#define SUN8I_R528_C0_RST_CTRL (0x0000)
-+#define SUN8I_R528_C0_CTRL_REG0 (0x0010)
-+#define SUN8I_R528_C0_CPU_STATUS (0x0080)
-+
-+#define SUN8I_R528_C0_STATUS_STANDBYWFI (16)
-+
- static void __secure cp15_write_cntp_tval(u32 tval)
- {
- asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
-@@ -116,10 +129,13 @@ static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
-
- static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
- {
-- /* secondary core entry address is programmed differently on R40 */
-+ /* secondary core entry address is programmed differently on R40/528 */
- if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
- writel((u32)entry,
- SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
-+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
-+ writel((u32)entry,
-+ SUNXI_R_CPUCFG_BASE + SUN8I_R528_SOFT_ENTRY);
- } else {
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-@@ -139,6 +155,8 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
- } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
- sunxi_power_switch(NULL, (void *)cpucfg + SUN8I_R40_PWROFF,
- on, cpu);
-+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
-+ /* R528 leaves both cores powered up, manages them via reset */
- } else {
- #if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
- struct sunxi_prcm_reg *prcm =
-@@ -159,6 +177,17 @@ static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
-+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
-+ if (reset) {
-+ clrbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_RST_CTRL,
-+ BIT(cpu));
-+ } else {
-+ setbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_RST_CTRL,
-+ BIT(cpu));
-+ }
-+ return;
-+ }
-+
- writel(reset ? 0b00 : 0b11, &cpucfg->cpu[cpu].rst);
- }
-
-@@ -167,6 +196,11 @@ static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
-+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
-+ /* Not required on R528 */
-+ return;
-+ }
-+
- if (lock)
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
- else
-@@ -178,6 +212,11 @@ static bool __secure sunxi_cpu_poll_wfi(int cpu)
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
-+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
-+ return !!(readl(SUNXI_CPUX_BASE + SUN8I_R528_C0_CPU_STATUS) &
-+ BIT(SUN8I_R528_C0_STATUS_STANDBYWFI + cpu));
-+ }
-+
- return !!(readl(&cpucfg->cpu[cpu].status) & BIT(2));
- }
-
-@@ -186,6 +225,12 @@ static void __secure sunxi_cpu_invalidate_cache(int cpu)
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
-+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
-+ clrbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_CTRL_REG0,
-+ BIT(cpu));
-+ return;
-+ }
-+
- clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
- }
-
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index 59fa62c8d5..1d126a00ec 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -321,6 +321,8 @@ config MACH_SUN8I_R40
- config MACH_SUN8I_R528
- bool "sun8i (Allwinner R528)"
- select CPU_V7A
-+ select CPU_V7_HAS_NONSEC
-+ select ARCH_SUPPORT_PSCI
- select SUNXI_GEN_NCAT2
- select SUNXI_NEW_PINCTRL
- select MMC_SUNXI_HAS_NEW_MODE
-diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
-index 2a8c54a7a8..0f6086e54f 100644
---- a/include/configs/sunxi-common.h
-+++ b/include/configs/sunxi-common.h
-@@ -34,6 +34,14 @@
-
- /* CPU */
-
-+/*
-+ * Newer ARM SoCs have moved the GIC, but have not updated their ARM cores to
-+ * reflect the correct address in CBAR/PERIPHBASE.
-+ */
-+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
-+#define CFG_ARM_GIC_BASE_ADDRESS 0x03020000
-+#endif
-+
- /*
- * The DRAM Base differs between some models. We cannot use macros for the
- * CONFIG_FOO defines which contain the DRAM base address since they end
---
-2.20.1
-
+++ /dev/null
-From patchwork Fri May 19 13:40:07 2023
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Maksim Kiselev <bigunclemax@gmail.com>
-X-Patchwork-Id: 1783781
-X-Patchwork-Delegate: andre.przywara@arm.com
-Return-Path: <u-boot-bounces@lists.denx.de>
-X-Original-To: incoming@patchwork.ozlabs.org
-Delivered-To: patchwork-incoming@legolas.ozlabs.org
-Authentication-Results: legolas.ozlabs.org;
- spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
- (client-ip=85.214.62.61; helo=phobos.denx.de;
- envelope-from=u-boot-bounces@lists.denx.de; receiver=<UNKNOWN>)
-Authentication-Results: legolas.ozlabs.org;
- dkim=pass (2048-bit key;
- unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256
- header.s=20221208 header.b=cTD9tSbd;
- dkim-atps=neutral
-Received: from phobos.denx.de (phobos.denx.de [85.214.62.61])
- (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
- key-exchange X25519 server-signature ECDSA (P-384))
- (No client certificate requested)
- by legolas.ozlabs.org (Postfix) with ESMTPS id 4QN7Jx1TH1z20dv
- for <incoming@patchwork.ozlabs.org>; Fri, 19 May 2023 23:40:49 +1000 (AEST)
-Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
- by phobos.denx.de (Postfix) with ESMTP id BC5EE86312;
- Fri, 19 May 2023 15:40:37 +0200 (CEST)
-Authentication-Results: phobos.denx.de;
- dmarc=pass (p=none dis=none) header.from=gmail.com
-Authentication-Results: phobos.denx.de;
- spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
-Authentication-Results: phobos.denx.de;
- dkim=pass (2048-bit key;
- unprotected) header.d=gmail.com header.i=@gmail.com header.b="cTD9tSbd";
- dkim-atps=neutral
-Received: by phobos.denx.de (Postfix, from userid 109)
- id 76B3D86312; Fri, 19 May 2023 15:40:35 +0200 (CEST)
-X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
-X-Spam-Level:
-X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,
- DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,SPF_HELO_NONE,
- SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no
- version=3.4.2
-Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com
- [IPv6:2a00:1450:4864:20::42c])
- (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))
- (No client certificate requested)
- by phobos.denx.de (Postfix) with ESMTPS id 5F8AE862F7
- for <u-boot@lists.denx.de>; Fri, 19 May 2023 15:40:32 +0200 (CEST)
-Authentication-Results: phobos.denx.de;
- dmarc=pass (p=none dis=none) header.from=gmail.com
-Authentication-Results: phobos.denx.de;
- spf=pass smtp.mailfrom=bigunclemax@gmail.com
-Received: by mail-wr1-x42c.google.com with SMTP id
- ffacd0b85a97d-30957dd7640so370247f8f.3
- for <u-boot@lists.denx.de>; Fri, 19 May 2023 06:40:32 -0700 (PDT)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20221208; t=1684503631; x=1687095631;
- h=content-transfer-encoding:mime-version:references:in-reply-to
- :message-id:date:subject:cc:to:from:from:to:cc:subject:date
- :message-id:reply-to;
- bh=YUP1z0w4h2cZv/wQXQCw1Cy1zgJe6JHGfqSmy2vVnL8=;
- b=cTD9tSbdyQlxF0Y7erPxsd79LYuLiPINAeD1DMRr/7GOIs4kwUj3c+aIdBEPDd2sNx
- QUUWCtJO8xyhoqLLZPq6VRe4vgHDv6xGVMZGEKJ+WtKyZ3ki9MTyErk/jL0xZMTlMYdk
- os6PhwH/RpouCAMKTMyq++YZtUBMRnLMF/9nc7vwWLPEmx/2U4za8Qe90XS02sB/hwsT
- HU4v0YoXBkX2drI2tERNRIKzsIXJRoeu3mwV4QW8dDkGkIP45XtW2BqQjgCwd19q4LOf
- cnlkGxCIlk5fuS5QghrV+W1tN7S1hGLCHgD4U3ddN4sZHhCxZTOnBYxUEHMCLnV3XZsy
- 4xFg==
-X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=1e100.net; s=20221208; t=1684503631; x=1687095631;
- h=content-transfer-encoding:mime-version:references:in-reply-to
- :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc
- :subject:date:message-id:reply-to;
- bh=YUP1z0w4h2cZv/wQXQCw1Cy1zgJe6JHGfqSmy2vVnL8=;
- b=KjEg432zx44xNg4Z1IwQygnJdbxJPj9HjQq03tgXlZF6K3tBgBrjSuzzq1Gbvlz6PZ
- LhlH3p0PzZpJpNwxIVul5ETVJAKUBYPmVgziizxy54jhi7INZF5OYiv9504QKW5slpBv
- R4lq+U/kRVbgfydEXRBdE6vbDPfUvg6kHtHT1S14Cd+KZXI1mplmaQulTBmSXpTH0UH9
- KF9DNiZXlS2zU64vkurAlefEj78IIHt4b1O6qEgpBi+rt6ah4RW5Uapn296g/Dgy6b/T
- QCjmIh5KVlFOTi9vFwTPKDo9qQ0Nzq709I5rxhNNZEbuO0Gd/nSk+RzvYHAEjBFpAnJe
- Fe1g==
-X-Gm-Message-State: AC+VfDyvlP1JR37qkV9MYt5TDplSIUbUgxJODKI0TwJTMNVb/VhJVqrd
- 9zNxItUGraxvDCAiwxhXu/mYGBxAhKs=
-X-Google-Smtp-Source:
- ACHHUZ5G99dPHkK4AviYJ4YM/vZ1llN4335rcmycK/cfHMEFhg609FaTXuZb6u10r9U2wYvZcRHwKQ==
-X-Received: by 2002:adf:e60b:0:b0:309:a4e:52d3 with SMTP id
- p11-20020adfe60b000000b003090a4e52d3mr2047534wrm.5.1684503631220;
- Fri, 19 May 2023 06:40:31 -0700 (PDT)
-Received: from localhost.localdomain ([176.221.215.212])
- by smtp.gmail.com with ESMTPSA id
- l5-20020adfe585000000b002f7780eee10sm5315421wrm.59.2023.05.19.06.40.30
- (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
- Fri, 19 May 2023 06:40:30 -0700 (PDT)
-From: Maxim Kiselev <bigunclemax@gmail.com>
-To: u-boot@lists.denx.de
-Cc: Maxim Kiselev <bigunclemax@gmail.com>,
- Jagan Teki <jagan@amarulasolutions.com>,
- Andre Przywara <andre.przywara@arm.com>, Rick Chen <rick@andestech.com>,
- Leo <ycliang@andestech.com>
-Subject: [RFC PATCH v1 1/3] sunxi: SPL SPI: Add SPI boot support for the
- Allwinner R528/T113 SoCs
-Date: Fri, 19 May 2023 16:40:07 +0300
-Message-Id: <20230519134010.3102343-2-bigunclemax@gmail.com>
-X-Mailer: git-send-email 2.39.2
-In-Reply-To: <20230519134010.3102343-1-bigunclemax@gmail.com>
-References: <20230519134010.3102343-1-bigunclemax@gmail.com>
-MIME-Version: 1.0
-X-BeenThere: u-boot@lists.denx.de
-X-Mailman-Version: 2.1.39
-Precedence: list
-List-Id: U-Boot discussion <u-boot.lists.denx.de>
-List-Unsubscribe: <https://lists.denx.de/options/u-boot>,
- <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>
-List-Archive: <https://lists.denx.de/pipermail/u-boot/>
-List-Post: <mailto:u-boot@lists.denx.de>
-List-Help: <mailto:u-boot-request@lists.denx.de?subject=help>
-List-Subscribe: <https://lists.denx.de/listinfo/u-boot>,
- <mailto:u-boot-request@lists.denx.de?subject=subscribe>
-Errors-To: u-boot-bounces@lists.denx.de
-Sender: "U-Boot" <u-boot-bounces@lists.denx.de>
-X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de
-X-Virus-Status: Clean
-
-R528/T113 SoCs uses the same SPI IP as the H6, also have the same clocks
-and reset bits layout, but the CCU base is different. Another difference
-is that the new SoCs do not have a clock divider inside. Instead of this
-we should configure sample mode depending on input clock rate.
-
-The pin assignment is also different: the H6 uses PC0, the R528/T113 PC4
-instead. This makes for a change in spi0_pinmux_setup() routine.
-
-This patch extends the H6/H616 #ifdef guards to also cover the R528/T113,
-using the shared CONFIG_SUNXI_GEN_NCAT2 and CONFIG_MACH_SUN8I_R528
-symbols. Also use CONFIG_SUNXI_GEN_NCAT2 symbol for the Kconfig
-dependency.
-
-Signed-off-by: Maxim Kiselev <bigunclemax@gmail.com>
-Tested-by: Sam Edwards <CFSworks@gmail.com>
----
- arch/arm/mach-sunxi/Kconfig | 2 +-
- arch/arm/mach-sunxi/spl_spi_sunxi.c | 78 +++++++++++++++++++++--------
- 2 files changed, 58 insertions(+), 22 deletions(-)
-
-diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
-index 142d86afc6..210dd41176 100644
---- a/arch/arm/mach-sunxi/Kconfig
-+++ b/arch/arm/mach-sunxi/Kconfig
-@@ -998,7 +998,7 @@ config SPL_STACK_R_ADDR
-
- config SPL_SPI_SUNXI
- bool "Support for SPI Flash on Allwinner SoCs in SPL"
-- depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6 || MACH_SUNIV
-+ depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6 || MACH_SUNIV || SUNXI_GEN_NCAT2
- help
- Enable support for SPI Flash. This option allows SPL to read from
- sunxi SPI Flash. It uses the same method as the boot ROM, so does
-diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
-index c2410dd7bb..3cfbf56d59 100644
---- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
-+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
-@@ -73,18 +73,27 @@
- #define SUN6I_CTL_ENABLE BIT(0)
- #define SUN6I_CTL_MASTER BIT(1)
- #define SUN6I_CTL_SRST BIT(31)
-+#define SUN6I_TCR_SDM BIT(13)
- #define SUN6I_TCR_XCH BIT(31)
-
- /*****************************************************************************/
-
--#define CCM_AHB_GATING0 (0x01C20000 + 0x60)
--#define CCM_H6_SPI_BGR_REG (0x03001000 + 0x96c)
--#ifdef CONFIG_SUN50I_GEN_H6
--#define CCM_SPI0_CLK (0x03001000 + 0x940)
-+#if defined(CONFIG_SUN50I_GEN_H6)
-+#define CCM_BASE 0x03001000
-+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
-+#define CCM_BASE 0x02001000
- #else
--#define CCM_SPI0_CLK (0x01C20000 + 0xA0)
-+#define CCM_BASE 0x01C20000
- #endif
--#define SUN6I_BUS_SOFT_RST_REG0 (0x01C20000 + 0x2C0)
-+
-+#define CCM_AHB_GATING0 (CCM_BASE + 0x60)
-+#define CCM_H6_SPI_BGR_REG (CCM_BASE + 0x96c)
-+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
-+#define CCM_SPI0_CLK (CCM_BASE + 0x940)
-+#else
-+#define CCM_SPI0_CLK (CCM_BASE + 0xA0)
-+#endif
-+#define SUN6I_BUS_SOFT_RST_REG0 (CCM_BASE + 0x2C0)
-
- #define AHB_RESET_SPI0_SHIFT 20
- #define AHB_GATE_OFFSET_SPI0 20
-@@ -102,17 +111,22 @@
- */
- static void spi0_pinmux_setup(unsigned int pin_function)
- {
-- /* All chips use PC0 and PC2. */
-- sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
-+ /* All chips use PC2. And all chips use PC0, except R528/T113 */
-+ if (!IS_ENABLED(CONFIG_MACH_SUN8I_R528))
-+ sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
-+
- sunxi_gpio_set_cfgpin(SUNXI_GPC(2), pin_function);
-
-- /* All chips except H6 and H616 use PC1. */
-- if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
-+ /* All chips except H6/H616/R528/T113 use PC1. */
-+ if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
-+ !IS_ENABLED(CONFIG_MACH_SUN8I_R528))
- sunxi_gpio_set_cfgpin(SUNXI_GPC(1), pin_function);
-
-- if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
-+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H6) ||
-+ IS_ENABLED(CONFIG_MACH_SUN8I_R528))
- sunxi_gpio_set_cfgpin(SUNXI_GPC(5), pin_function);
-- if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
-+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
-+ IS_ENABLED(CONFIG_MACH_SUN8I_R528))
- sunxi_gpio_set_cfgpin(SUNXI_GPC(4), pin_function);
-
- /* Older generations use PC23 for CS, newer ones use PC3. */
-@@ -126,7 +140,8 @@ static void spi0_pinmux_setup(unsigned int pin_function)
- static bool is_sun6i_gen_spi(void)
- {
- return IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
-- IS_ENABLED(CONFIG_SUN50I_GEN_H6);
-+ IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
-+ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2);
- }
-
- static uintptr_t spi0_base_address(void)
-@@ -137,6 +152,9 @@ static uintptr_t spi0_base_address(void)
- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
- return 0x05010000;
-
-+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
-+ return 0x04025000;
-+
- if (!is_sun6i_gen_spi() ||
- IS_ENABLED(CONFIG_MACH_SUNIV))
- return 0x01C05000;
-@@ -152,23 +170,30 @@ static void spi0_enable_clock(void)
- uintptr_t base = spi0_base_address();
-
- /* Deassert SPI0 reset on SUN6I */
-- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
-+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
-+ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
- setbits_le32(CCM_H6_SPI_BGR_REG, (1U << 16) | 0x1);
- else if (is_sun6i_gen_spi())
- setbits_le32(SUN6I_BUS_SOFT_RST_REG0,
- (1 << AHB_RESET_SPI0_SHIFT));
-
- /* Open the SPI0 gate */
-- if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
-+ if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
-+ !IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
- setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
-
- if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
- /* Divide by 32, clock source is AHB clock 200MHz */
- writel(SPI0_CLK_DIV_BY_32, base + SUN6I_SPI0_CCTL);
- } else {
-- /* Divide by 4 */
-- writel(SPI0_CLK_DIV_BY_4, base + (is_sun6i_gen_spi() ?
-- SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL));
-+ /* New SoCs do not have a clock divider inside */
-+ if (!IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
-+ /* Divide by 4 */
-+ writel(SPI0_CLK_DIV_BY_4,
-+ base + (is_sun6i_gen_spi() ? SUN6I_SPI0_CCTL :
-+ SUN4I_SPI0_CCTL));
-+ }
-+
- /* 24MHz from OSC24M */
- writel((1 << 31), CCM_SPI0_CLK);
- }
-@@ -180,6 +205,14 @@ static void spi0_enable_clock(void)
- /* Wait for completion */
- while (readl(base + SUN6I_SPI0_GCR) & SUN6I_CTL_SRST)
- ;
-+
-+ /*
-+ * For new SoCs we should configure sample mode depending on
-+ * input clock. As 24MHz from OSC24M is used, we could use
-+ * normal sample mode by setting SDM bit in the TCR register
-+ */
-+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
-+ setbits_le32(base + SUN6I_SPI0_TCR, SUN6I_TCR_SDM);
- } else {
- /* Enable SPI in the master mode and reset FIFO */
- setbits_le32(base + SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
-@@ -206,11 +239,13 @@ static void spi0_disable_clock(void)
- writel(0, CCM_SPI0_CLK);
-
- /* Close the SPI0 gate */
-- if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
-+ if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
-+ !IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
- clrbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
-
- /* Assert SPI0 reset on SUN6I */
-- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
-+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
-+ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
- clrbits_le32(CCM_H6_SPI_BGR_REG, (1U << 16) | 0x1);
- else if (is_sun6i_gen_spi())
- clrbits_le32(SUN6I_BUS_SOFT_RST_REG0,
-@@ -224,7 +259,8 @@ static void spi0_init(void)
- if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
- IS_ENABLED(CONFIG_SUN50I_GEN_H6))
- pin_function = SUN50I_GPC_SPI0;
-- else if (IS_ENABLED(CONFIG_MACH_SUNIV))
-+ else if (IS_ENABLED(CONFIG_MACH_SUNIV) ||
-+ IS_ENABLED(CONFIG_MACH_SUN8I_R528))
- pin_function = SUNIV_GPC_SPI0;
-
- spi0_pinmux_setup(pin_function);
-
-From patchwork Fri May 19 13:40:08 2023
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Maksim Kiselev <bigunclemax@gmail.com>
-X-Patchwork-Id: 1783782
-X-Patchwork-Delegate: andre.przywara@arm.com
-Return-Path: <u-boot-bounces@lists.denx.de>
-X-Original-To: incoming@patchwork.ozlabs.org
-Delivered-To: patchwork-incoming@legolas.ozlabs.org
-Authentication-Results: legolas.ozlabs.org;
- spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
- (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;
- envelope-from=u-boot-bounces@lists.denx.de; receiver=<UNKNOWN>)
-Authentication-Results: legolas.ozlabs.org;
- dkim=pass (2048-bit key;
- unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256
- header.s=20221208 header.b=XVN86gy6;
- dkim-atps=neutral
-Received: from phobos.denx.de (phobos.denx.de
- [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])
- (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
- key-exchange X25519 server-signature ECDSA (P-384))
- (No client certificate requested)
- by legolas.ozlabs.org (Postfix) with ESMTPS id 4QN7KH4Bzbz20dv
- for <incoming@patchwork.ozlabs.org>; Fri, 19 May 2023 23:41:07 +1000 (AEST)
-Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
- by phobos.denx.de (Postfix) with ESMTP id 0451386328;
- Fri, 19 May 2023 15:40:42 +0200 (CEST)
-Authentication-Results: phobos.denx.de;
- dmarc=pass (p=none dis=none) header.from=gmail.com
-Authentication-Results: phobos.denx.de;
- spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
-Authentication-Results: phobos.denx.de;
- dkim=pass (2048-bit key;
- unprotected) header.d=gmail.com header.i=@gmail.com header.b="XVN86gy6";
- dkim-atps=neutral
-Received: by phobos.denx.de (Postfix, from userid 109)
- id 8B5B986327; Fri, 19 May 2023 15:40:40 +0200 (CEST)
-X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
-X-Spam-Level:
-X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,
- DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,SPF_HELO_NONE,
- SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no
- version=3.4.2
-Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com
- [IPv6:2a00:1450:4864:20::42a])
- (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))
- (No client certificate requested)
- by phobos.denx.de (Postfix) with ESMTPS id 4A39286131
- for <u-boot@lists.denx.de>; Fri, 19 May 2023 15:40:37 +0200 (CEST)
-Authentication-Results: phobos.denx.de;
- dmarc=pass (p=none dis=none) header.from=gmail.com
-Authentication-Results: phobos.denx.de;
- spf=pass smtp.mailfrom=bigunclemax@gmail.com
-Received: by mail-wr1-x42a.google.com with SMTP id
- ffacd0b85a97d-307d20548adso2178236f8f.0
- for <u-boot@lists.denx.de>; Fri, 19 May 2023 06:40:37 -0700 (PDT)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20221208; t=1684503636; x=1687095636;
- h=content-transfer-encoding:mime-version:references:in-reply-to
- :message-id:date:subject:cc:to:from:from:to:cc:subject:date
- :message-id:reply-to;
- bh=y8+rF/p5Jdncjufm65vWHEGLS+C/ytaDC9RSOXQj3YY=;
- b=XVN86gy67HoVcRBvpuLqZWNZjA0qoeGsc1plc19OUmaDbDkfIz97H+xr4reZEBCj12
- PokzHuazEC6QCiGZI46+hcptobvX09pQGcfer9yoxdFD7W7w9uDhwAgceQZ9NILRaH/I
- gvaxtYIQ9jjvb60TnHm3E9ORj5KlcY3aS1B2iDBw3tstlcrKeLTT2gWaSvZf4m4WBaF3
- R0fz+CDnjhfAAZkyj9vr9/wvPSl4aVe/MxctoNRRZOTW3nC5Vr7G9OMH5V9wtlp5X9f/
- FFOfUSx62PitgyezRFVsdororOdlHsSqq9tGh9qaVbBPBtGWI0J69haBU/Vi5OVBUox/
- C+Wg==
-X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=1e100.net; s=20221208; t=1684503636; x=1687095636;
- h=content-transfer-encoding:mime-version:references:in-reply-to
- :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc
- :subject:date:message-id:reply-to;
- bh=y8+rF/p5Jdncjufm65vWHEGLS+C/ytaDC9RSOXQj3YY=;
- b=BIVofAJc2HA5kiEUXl6+vfzeq5peOA4vRnGVTtbcSRRoATcx72Yv+fTJEjA7usMwB7
- 3DMiHkH14gVXqDLM020VfVyJI9s3Wa2eQAracOP2LaBMOhDuG/XoLdGTomPPbA/hDNdk
- w+RWBpG0oY3dpjEgsGTOo7op70GZ2ugI5SYe8ZIFTTO8DN71MYq/z0wo6On4k9l5X3sP
- nv15nZkgqzwBVi8n+zSuz+ocXR08O9c+pgqWNoX7XwohjHjU9EOhNosihH1HKv/WpV6G
- /VNimAooGEcGiulbeMgirYC2qOb9/nq6TzFa7xnYNff3MR5MDE4G7s+wlfaB0/WwD+sU
- +C7g==
-X-Gm-Message-State: AC+VfDzbvvkLM5kEmV1WxzB5hTeKHweME4U+BnwLiEXS8cX2Tj5flr98
- DRNdhkguOOYWqDZIPsvxebO06NiixPk=
-X-Google-Smtp-Source:
- ACHHUZ5ZYgm4pzeYsvUicktbj4rwgRUtHboj9r3ofAcxlNjpTAnaHo/yhaOSHex344NVs25oWALOmg==
-X-Received: by 2002:adf:df84:0:b0:306:2dc3:8b67 with SMTP id
- z4-20020adfdf84000000b003062dc38b67mr1991533wrl.53.1684503636216;
- Fri, 19 May 2023 06:40:36 -0700 (PDT)
-Received: from localhost.localdomain ([176.221.215.212])
- by smtp.gmail.com with ESMTPSA id
- l5-20020adfe585000000b002f7780eee10sm5315421wrm.59.2023.05.19.06.40.35
- (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
- Fri, 19 May 2023 06:40:35 -0700 (PDT)
-From: Maxim Kiselev <bigunclemax@gmail.com>
-To: u-boot@lists.denx.de
-Cc: Maxim Kiselev <bigunclemax@gmail.com>,
- Jagan Teki <jagan@amarulasolutions.com>,
- Andre Przywara <andre.przywara@arm.com>, Rick Chen <rick@andestech.com>,
- Leo <ycliang@andestech.com>
-Subject: [RFC PATCH v1 2/3] spi: sunxi: Add support for R329/D1/R528/T113 SPI
- controller
-Date: Fri, 19 May 2023 16:40:08 +0300
-Message-Id: <20230519134010.3102343-3-bigunclemax@gmail.com>
-X-Mailer: git-send-email 2.39.2
-In-Reply-To: <20230519134010.3102343-1-bigunclemax@gmail.com>
-References: <20230519134010.3102343-1-bigunclemax@gmail.com>
-MIME-Version: 1.0
-X-BeenThere: u-boot@lists.denx.de
-X-Mailman-Version: 2.1.39
-Precedence: list
-List-Id: U-Boot discussion <u-boot.lists.denx.de>
-List-Unsubscribe: <https://lists.denx.de/options/u-boot>,
- <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>
-List-Archive: <https://lists.denx.de/pipermail/u-boot/>
-List-Post: <mailto:u-boot@lists.denx.de>
-List-Help: <mailto:u-boot-request@lists.denx.de?subject=help>
-List-Subscribe: <https://lists.denx.de/listinfo/u-boot>,
- <mailto:u-boot-request@lists.denx.de?subject=subscribe>
-Errors-To: u-boot-bounces@lists.denx.de
-Sender: "U-Boot" <u-boot-bounces@lists.denx.de>
-X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de
-X-Virus-Status: Clean
-
-These SoCs have two SPI controllers that are quite similar to the SPI
-on previous Allwinner SoCs. The main difference is that new SoCs
-don't have a clock divider (SPI_CCR register) inside SPI IP.
-
-Instead SPI sample mode should be configured depending on the input clock.
-
-For now SPI input clock source selection is not supported by this driver,
-and only HOSC@24MHz can be used as input clock. Therefore, according to
-the, manual we could change the SPI sample mode from delay half
-cycle(default) to normal.
-
-This patch adds a quirk for this kind of SPI controllers
-
-Signed-off-by: Maxim Kiselev <bigunclemax@gmail.com>
-Tested-by: Sam Edwards <CFSworks@gmail.com>
----
- drivers/spi/spi-sunxi.c | 34 +++++++++++++++++++++++++++++++++-
- 1 file changed, 33 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
-index c56d82d998..9ec6b359e2 100644
---- a/drivers/spi/spi-sunxi.c
-+++ b/drivers/spi/spi-sunxi.c
-@@ -117,6 +117,8 @@ enum sun4i_spi_bits {
- SPI_TCR_XCH,
- SPI_TCR_CS_MANUAL,
- SPI_TCR_CS_LEVEL,
-+ SPI_TCR_SDC,
-+ SPI_TCR_SDM,
- SPI_FCR_TF_RST,
- SPI_FCR_RF_RST,
- SPI_FSR_RF_CNT_MASK,
-@@ -128,6 +130,7 @@ struct sun4i_spi_variant {
- u32 fifo_depth;
- bool has_soft_reset;
- bool has_burst_ctl;
-+ bool has_clk_ctl;
- };
-
- struct sun4i_spi_plat {
-@@ -302,7 +305,19 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
- setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
- SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
-
-- sun4i_spi_set_speed_mode(dev->parent);
-+ if (priv->variant->has_clk_ctl) {
-+ sun4i_spi_set_speed_mode(dev->parent);
-+ } else {
-+ /*
-+ * At this moment there is no ability to change input clock.
-+ * Therefore, we can only use default HOSC@24MHz clock and
-+ * set SPI sampling mode to normal
-+ */
-+ clrsetbits_le32(SPI_REG(priv, SPI_TCR),
-+ SPI_BIT(priv, SPI_TCR_SDC) |
-+ SPI_BIT(priv, SPI_TCR_SDM),
-+ SPI_BIT(priv, SPI_TCR_SDM));
-+ }
-
- return 0;
- }
-@@ -516,6 +531,8 @@ static const u32 sun6i_spi_bits[] = {
- [SPI_TCR_CS_MASK] = 0x30,
- [SPI_TCR_CS_MANUAL] = BIT(6),
- [SPI_TCR_CS_LEVEL] = BIT(7),
-+ [SPI_TCR_SDC] = BIT(11),
-+ [SPI_TCR_SDM] = BIT(13),
- [SPI_TCR_XCH] = BIT(31),
- [SPI_FCR_RF_RST] = BIT(15),
- [SPI_FCR_TF_RST] = BIT(31),
-@@ -526,6 +543,7 @@ static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
- .regs = sun4i_spi_regs,
- .bits = sun4i_spi_bits,
- .fifo_depth = 64,
-+ .has_clk_ctl = true,
- };
-
- static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
-@@ -534,6 +552,7 @@ static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
- .fifo_depth = 128,
- .has_soft_reset = true,
- .has_burst_ctl = true,
-+ .has_clk_ctl = true,
- };
-
- static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
-@@ -542,6 +561,15 @@ static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
- .fifo_depth = 64,
- .has_soft_reset = true,
- .has_burst_ctl = true,
-+ .has_clk_ctl = true,
-+};
-+
-+static const struct sun4i_spi_variant sun50i_r329_spi_variant = {
-+ .regs = sun6i_spi_regs,
-+ .bits = sun6i_spi_bits,
-+ .fifo_depth = 64,
-+ .has_soft_reset = true,
-+ .has_burst_ctl = true,
- };
-
- static const struct udevice_id sun4i_spi_ids[] = {
-@@ -557,6 +585,10 @@ static const struct udevice_id sun4i_spi_ids[] = {
- .compatible = "allwinner,sun8i-h3-spi",
- .data = (ulong)&sun8i_h3_spi_variant,
- },
-+ {
-+ .compatible = "allwinner,sun50i-r329-spi",
-+ .data = (ulong)&sun50i_r329_spi_variant,
-+ },
- { /* sentinel */ }
- };
-
-
-From patchwork Fri May 19 13:40:09 2023
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Maksim Kiselev <bigunclemax@gmail.com>
-X-Patchwork-Id: 1783783
-X-Patchwork-Delegate: andre.przywara@arm.com
-Return-Path: <u-boot-bounces@lists.denx.de>
-X-Original-To: incoming@patchwork.ozlabs.org
-Delivered-To: patchwork-incoming@legolas.ozlabs.org
-Authentication-Results: legolas.ozlabs.org;
- spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
- (client-ip=85.214.62.61; helo=phobos.denx.de;
- envelope-from=u-boot-bounces@lists.denx.de; receiver=<UNKNOWN>)
-Authentication-Results: legolas.ozlabs.org;
- dkim=pass (2048-bit key;
- unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256
- header.s=20221208 header.b=WKEkOHKi;
- dkim-atps=neutral
-Received: from phobos.denx.de (phobos.denx.de [85.214.62.61])
- (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
- key-exchange X25519 server-signature ECDSA (P-384))
- (No client certificate requested)
- by legolas.ozlabs.org (Postfix) with ESMTPS id 4QN7KT2Ntcz20dv
- for <incoming@patchwork.ozlabs.org>; Fri, 19 May 2023 23:41:17 +1000 (AEST)
-Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
- by phobos.denx.de (Postfix) with ESMTP id 4EBFA8634E;
- Fri, 19 May 2023 15:40:47 +0200 (CEST)
-Authentication-Results: phobos.denx.de;
- dmarc=pass (p=none dis=none) header.from=gmail.com
-Authentication-Results: phobos.denx.de;
- spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
-Authentication-Results: phobos.denx.de;
- dkim=pass (2048-bit key;
- unprotected) header.d=gmail.com header.i=@gmail.com header.b="WKEkOHKi";
- dkim-atps=neutral
-Received: by phobos.denx.de (Postfix, from userid 109)
- id 7157D86334; Fri, 19 May 2023 15:40:43 +0200 (CEST)
-X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
-X-Spam-Level:
-X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,
- DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,SPF_HELO_NONE,
- SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no
- version=3.4.2
-Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com
- [IPv6:2a00:1450:4864:20::432])
- (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))
- (No client certificate requested)
- by phobos.denx.de (Postfix) with ESMTPS id C224E86131
- for <u-boot@lists.denx.de>; Fri, 19 May 2023 15:40:40 +0200 (CEST)
-Authentication-Results: phobos.denx.de;
- dmarc=pass (p=none dis=none) header.from=gmail.com
-Authentication-Results: phobos.denx.de;
- spf=pass smtp.mailfrom=bigunclemax@gmail.com
-Received: by mail-wr1-x432.google.com with SMTP id
- ffacd0b85a97d-309550d4f73so501090f8f.1
- for <u-boot@lists.denx.de>; Fri, 19 May 2023 06:40:40 -0700 (PDT)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20221208; t=1684503640; x=1687095640;
- h=content-transfer-encoding:mime-version:references:in-reply-to
- :message-id:date:subject:cc:to:from:from:to:cc:subject:date
- :message-id:reply-to;
- bh=NrlUXRmVOv93TD0HdBbwH04KM6T5eHPc/wRD/kVHw50=;
- b=WKEkOHKiGzpdoQNn0FShQ9ESX297aAOR2qdZ43W5RSGiXWij7hEgbg3BzrPR3w9okx
- X21Je0wJ4l+VUyv48EHiHlhMezq1Vgk44Ne/aOOYikouUf8k6fkjzjoT9wkw0x+Sqgr6
- MgodDFL5CQ1qpMCU3lQxKqSE1eVQd1O2KNT5JMucQrnux/0gLwAf3sLczeydvCvK0nv8
- m3vmYqBy/w8MzGD4ogeM1slUX24ilT7wZHx1fDoz2K6ygRgeN7UzRJP9iqNMuxjVWj2o
- YLngIulrlZarjLLeH8Yas8HPrycICIb+QgA84WIY65U+F0s5Bliv/EW1CIqFPBFxrxET
- OhUQ==
-X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=1e100.net; s=20221208; t=1684503640; x=1687095640;
- h=content-transfer-encoding:mime-version:references:in-reply-to
- :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc
- :subject:date:message-id:reply-to;
- bh=NrlUXRmVOv93TD0HdBbwH04KM6T5eHPc/wRD/kVHw50=;
- b=L3leC190RMssJ8neJlB3kWCGFUE71ArJn2vb/I6cuJ1N/CJ3XZRIdjsDUFNw7ED//R
- 2JpNx3x7mnB/fhojtzCkk+UuzkRuZNISO/Bgu/7pxVoRVth4aEx7frZ+boGZlMy9oUQ0
- KYPzme2rcMGpi+Gl2P9Rv65K3jrnZs7N+r2VvcEDd+Y3TmL+xogAuuC+2l46qJHQ2qXT
- OOHfKXTsAxyc5vOKrL7WpF+EynCAWhuj03Ps4FxQfllOA4CGGiEUv5jKm0yM8D/HpBz8
- ys1nHELarilGdHatUQO5gAB87Ir9vKsfTKt9hleIFJdWN1B0wvXYi0o2Lkj8TCI5D3l2
- SE9w==
-X-Gm-Message-State: AC+VfDyMqvODjmLMCPv0QeUpXa78p1k0ZcyJHKZLfTTaiVbDjq+aL7JT
- c4Qx93jxKzpnkxV7RPOXLurVp/bZ8qA=
-X-Google-Smtp-Source:
- ACHHUZ6RxZNvSxCvoRohqWdRTv2thSi33TWc4CN0RsmFexdSvPZtKWRMQQ7Nqt/2bACBm66BUi/Qcw==
-X-Received: by 2002:a5d:5305:0:b0:306:3ec9:99c5 with SMTP id
- e5-20020a5d5305000000b003063ec999c5mr1949351wrv.9.1684503639737;
- Fri, 19 May 2023 06:40:39 -0700 (PDT)
-Received: from localhost.localdomain ([176.221.215.212])
- by smtp.gmail.com with ESMTPSA id
- l5-20020adfe585000000b002f7780eee10sm5315421wrm.59.2023.05.19.06.40.38
- (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
- Fri, 19 May 2023 06:40:39 -0700 (PDT)
-From: Maxim Kiselev <bigunclemax@gmail.com>
-To: u-boot@lists.denx.de
-Cc: Maxim Kiselev <bigunclemax@gmail.com>,
- Jagan Teki <jagan@amarulasolutions.com>,
- Andre Przywara <andre.przywara@arm.com>, Rick Chen <rick@andestech.com>,
- Leo <ycliang@andestech.com>
-Subject: [RFC PATCH v1 3/3] riscv: dts: allwinner: d1: Add SPI controllers
- node
-Date: Fri, 19 May 2023 16:40:09 +0300
-Message-Id: <20230519134010.3102343-4-bigunclemax@gmail.com>
-X-Mailer: git-send-email 2.39.2
-In-Reply-To: <20230519134010.3102343-1-bigunclemax@gmail.com>
-References: <20230519134010.3102343-1-bigunclemax@gmail.com>
-MIME-Version: 1.0
-X-BeenThere: u-boot@lists.denx.de
-X-Mailman-Version: 2.1.39
-Precedence: list
-List-Id: U-Boot discussion <u-boot.lists.denx.de>
-List-Unsubscribe: <https://lists.denx.de/options/u-boot>,
- <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>
-List-Archive: <https://lists.denx.de/pipermail/u-boot/>
-List-Post: <mailto:u-boot@lists.denx.de>
-List-Help: <mailto:u-boot-request@lists.denx.de?subject=help>
-List-Subscribe: <https://lists.denx.de/listinfo/u-boot>,
- <mailto:u-boot-request@lists.denx.de?subject=subscribe>
-Errors-To: u-boot-bounces@lists.denx.de
-Sender: "U-Boot" <u-boot-bounces@lists.denx.de>
-X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de
-X-Virus-Status: Clean
-
-Some boards form the MangoPi family (MQ\MQ-Dual\MQ-R) may have
-an optional SPI flash that connects to the SPI0 controller.
-
-This controller is the same for R329/D1/R528/T113s SoCs and
-should be supported by the sun50i-r329-spi driver.
-
-So let's add its DT nodes.
-
-Signed-off-by: Maxim Kiselev <bigunclemax@gmail.com>
-Reviewed-by: Sam Edwards <CFSworks@gmail.com>
----
- arch/riscv/dts/sunxi-d1s-t113.dtsi | 37 ++++++++++++++++++++++++++++++
- 1 file changed, 37 insertions(+)
-
-diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-index a7c95f59a0..094ad0e460 100644
---- a/arch/riscv/dts/sunxi-d1s-t113.dtsi
-+++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
-@@ -123,6 +123,12 @@
- function = "emac";
- };
-
-+ /omit-if-no-ref/
-+ spi0_pins: spi0-pins {
-+ pins = "PC2", "PC3", "PC4", "PC5";
-+ function = "spi0";
-+ };
-+
- /omit-if-no-ref/
- uart1_pg6_pins: uart1-pg6-pins {
- pins = "PG6", "PG7";
-@@ -456,6 +462,37 @@
- #size-cells = <0>;
- };
-
-+ spi0: spi@4025000 {
-+ compatible = "allwinner,sun20i-d1-spi",
-+ "allwinner,sun50i-r329-spi";
-+ reg = <0x04025000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(15) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
-+ clock-names = "ahb", "mod";
-+ dmas = <&dma 22>, <&dma 22>;
-+ dma-names = "rx", "tx";
-+ resets = <&ccu RST_BUS_SPI0>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ spi1: spi@4026000 {
-+ compatible = "allwinner,sun20i-d1-spi-dbi",
-+ "allwinner,sun50i-r329-spi-dbi",
-+ "allwinner,sun50i-r329-spi";
-+ reg = <0x04026000 0x1000>;
-+ interrupts = <SOC_PERIPHERAL_IRQ(16) IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
-+ clock-names = "ahb", "mod";
-+ dmas = <&dma 23>, <&dma 23>;
-+ dma-names = "rx", "tx";
-+ resets = <&ccu RST_BUS_SPI1>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
- usb_otg: usb@4100000 {
- compatible = "allwinner,sun20i-d1-musb",
- "allwinner,sun8i-a33-musb";
+++ /dev/null
-diff -ruN u-boot-2023.04/arch/arm/dts/Makefile spi/arch/arm/dts/Makefile
---- u-boot-2023.04/arch/arm/dts/Makefile 2023-07-20 13:58:39.714010154 +0200
-+++ spi/arch/arm/dts/Makefile 2023-07-20 14:46:44.403569974 +0200
-@@ -715,6 +715,7 @@
- sun8i-t113s-mangopi-mq-r-t113.dtb \
- sun8i-t113s-mangopi-mqdual-t113.dtb \
- sun8i-t113s-myir-myd-yt113x.dtb \
-+ sun8i-t113s-myir-myd-yt113x-spi.dtb \
- sun8i-t113s-rongpin-rp-t113.dtb
- dtb-$(CONFIG_MACH_SUN50I_H5) += \
- sun50i-h5-bananapi-m2-plus.dtb \
-diff -ruN u-boot-2023.04/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts spi/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts
---- u-boot-2023.04/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts 1970-01-01 01:00:00.000000000 +0100
-+++ spi/arch/arm/dts/sun8i-t113s-myir-myd-yt113x-spi.dts 2023-07-20 14:52:36.468334540 +0200
-@@ -0,0 +1,59 @@
-+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
-+// Copyright (C) 2022 Arm Ltd.
-+
-+#include <dt-bindings/interrupt-controller/irq.h>
-+
-+/dts-v1/;
-+
-+#include "sun8i-t113s.dtsi"
-+#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
-+
-+/ {
-+ model = "MYIR MYD-YT113X (SPI)";
-+ compatible = "myir,myd-yt113x", "myir,myc-yt113x", "allwinner,sun8i-t113s";
-+
-+ aliases {
-+ serial5 = &uart5;
-+ };
-+
-+ chosen {
-+ stdout-path = "serial5:115200n8";
-+ };
-+};
-+
-+&cpu0 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&cpu1 {
-+ cpu-supply = <®_vcc_core>;
-+};
-+
-+&pio {
-+ /omit-if-no-ref/
-+ uart5_pins: uart5-pins {
-+ pins = "PE6", "PE7";
-+ function = "uart5";
-+ };
-+};
-+
-+&uart5 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart5_pins>;
-+ status = "okay";
-+};
-+
-+&uart3 {
-+ status = "disabled";
-+};
-+
-+&spi0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi0_pins>;
-+ status = "okay";
-+ spi_nand@0 {
-+ compatible = "spi-nand";
-+ reg = <0>;
-+ spi-max-frequency = <52000000>;
-+ };
-+};
-diff -ruN u-boot-2023.04/configs/myir_myd_t113x-spi_defconfig spi/configs/myir_myd_t113x-spi_defconfig
---- u-boot-2023.04/configs/myir_myd_t113x-spi_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ spi/configs/myir_myd_t113x-spi_defconfig 2023-07-20 14:33:59.790587258 +0200
-@@ -0,0 +1,37 @@
-+CONFIG_ARM=y
-+CONFIG_ARCH_SUNXI=y
-+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-myir-myd-yt113x-spi"
-+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
-+CONFIG_SPL=y
-+CONFIG_SPL_SPI_SUNXI=y
-+CONFIG_MTD_SPI_NAND=y
-+CONFIG_MACH_SUN8I_R528=y
-+CONFIG_CONS_INDEX=6
-+CONFIG_MMC0_CD_PIN="PF6"
-+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-+CONFIG_SYS_MONITOR_LEN=786432
-+CONFIG_DRAM_CLK=792
-+CONFIG_DRAM_ZQ=8092667
-+CONFIG_DRAM_SUNXI_ODT_EN=0
-+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
-+CONFIG_DRAM_SUNXI_TPR11=0x340000
-+CONFIG_DRAM_SUNXI_TPR12=0x46
-+CONFIG_DRAM_SUNXI_TPR13=0x34000100
-+CONFIG_PHY_MOTORCOMM=y
-+CONFIG_SUN8I_EMAC=y
-+CONFIG_RGMII=y
-+CONFIG_RMII=y
-+CONFIG_MTD=y
-+CONFIG_DM_MTD=y
-+CONFIG_SYS_MTDPARTS_RUNTIME=y
-+CONFIG_NAND_STM32_FMC2=y
-+CONFIG_SYS_NAND_ONFI_DETECTION=y
-+CONFIG_MTD_SPI_NAND=y
-+CONFIG_DM_SPI_FLASH=y
-+CONFIG_SPI_FLASH_MACRONIX=y
-+CONFIG_SPI_FLASH_SPANSION=y
-+CONFIG_SPI_FLASH_STMICRO=y
-+CONFIG_SPI_FLASH_WINBOND=y
-+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
-+CONFIG_SPI_FLASH_MTD=y
-+CONFIG_SPI=y