Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-sunxi into next

Assorted fixes, refactorings and additions that are ready, and shave
off some load from upcoming series'.

Improves MMC performance on D1/T113 (missed clock divider), enables
eMMC access on the H616 family (never worked, many thanks to Jernej for
the fix!), DRAM detection fixes for the H616 (now reportedly stable).

Some patches for the upcoming Allwinner A133 SoC support: a few
refactorings, plus the DM clock and pinctrl driver. The DRAM init
routines work, but need some more polishing, that also holds back the
actual enablement patch, which will hopefully follow for v2025.07 still.

Also some preparatory patches for the Allwinner A523 SoC support, for
now just to improve the FEL save/restore code. There will be more patches
coming up for this, ideally also in the coming cycle still.

Gitlab CI passed, and I booted that briefly on some boards.
diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 939869b..f7707ac 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -63,9 +63,12 @@
 1:	wfi
 	b	1b
 
+fel_stash_addr:			// must immediately precede back_in_32:
+	.word   0x00000000	// receives fel_stash addr, by AA64 code above
+
 /* AArch32 code to restore the state from fel_stash and return back to FEL. */
 back_in_32:
-	.word	0xe59f0028	// ldr	r0, [pc, #40]	; load fel_stash address
+	.word	0xe51f000c	// ldr	r0, [pc, #-12]  ; load fel_stash address
 	.word	0xe5901008	// ldr	r1, [r0, #8]
 	.word	0xe129f001	// msr	CPSR_fc, r1
 	.word	0xf57ff06f	// isb
@@ -77,6 +80,4 @@
 	.word	0xee011f10	// mcr	15, 0, r1, cr1, cr0, {0}  ; SCTLR
 	.word	0xf57ff06f	// isb
 	.word	0xe12fff1e	// bx	lr		; return to FEL
-fel_stash_addr:
-	.word   0x00000000	// receives fel_stash addr, by AA64 code above
 ENDPROC(return_to_fel)
diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 6b2bb5a..24c8139 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -16,10 +16,11 @@
  */
 	tst     x0, x0                  // this is "b #0x84" in ARM
 	b       reset
-	.space  0x7c
+	.space  0x78
+	.word	fel_stash - .
 
-	.word	0xe28f0070	// add     r0, pc, #112	 // @(fel_stash - .)
-	.word	0xe59f106c	// ldr     r1, [pc, #108] // fel_stash - .
+	.word	0xe24f000c	// sub     r0, pc, #12  // @(fel_stash - .)
+	.word	0xe51f1010	// ldr     r1, [pc, #-16] // fel_stash - .
 	.word	0xe0800001	// add     r0, r0, r1
 	.word	0xe580d000	// str     sp, [r0]
 	.word	0xe580e004	// str     lr, [r0, #4]
@@ -54,7 +55,6 @@
 #else
 	.word   CONFIG_TEXT_BASE
 #endif
-	.word	fel_stash - .
 #else
 /* normal execution */
 	b	reset
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index ba1b154..ab43239 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -457,6 +457,9 @@
 	select SUN50I_GEN_H6
 	imply OF_UPSTREAM
 
+config MACH_SUN50I_A133
+	bool "sun50i (Allwinner A133)"
+
 endchoice
 
 # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33"
@@ -713,16 +716,10 @@
 
 config SYS_CLK_FREQ
 	default 408000000 if MACH_SUNIV
-	default 1008000000 if MACH_SUN4I
-	default 1008000000 if MACH_SUN5I
-	default 1008000000 if MACH_SUN6I
-	default 912000000 if MACH_SUN7I
 	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
-	default 1008000000 if MACH_SUN8I
-	default 1008000000 if MACH_SUN9I
 	default 888000000 if MACH_SUN50I_H6
-	default 1008000000 if MACH_SUN50I_H616
-	default 1008000000 if MACH_SUN8I_R528
+	default 912000000 if MACH_SUN7I
+	default 1008000000
 
 config SYS_CONFIG_NAME
 	default "suniv" if MACH_SUNIV
@@ -1131,10 +1128,6 @@
 	  The used address is "bdaddr" if set, and "ethaddr" with the LSB
 	  flipped elsewise.
 
-source "board/sunxi/Kconfig"
-
-endif
-
 config CHIP_DIP_SCAN
 	bool "Enable DIPs detection for CHIP board"
 	select SUPPORT_EXTENSION_SCAN
@@ -1143,3 +1136,7 @@
 	select W1_EEPROM
 	select W1_EEPROM_DS24XXX
 	select CMD_EXTENSION
+
+source "board/sunxi/Kconfig"
+
+endif
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index b424a78..359513d 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -147,15 +147,20 @@
 	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;
 	}
 
+	/*
+	 * The factors encoded in the register describe the doubled clock
+	 * frequency, expect for the H6, where it's the quadrupled frequency.
+	 * Compensate for that here.
+	 */
+	if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+		m = 4;
+	else
+		m = 2;
+
 	return 24000000U * n / m / div1 / div2;
 }
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index b3554cc..cd9d321 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -1360,36 +1360,94 @@
 	panic("This DRAM setup is currently not supported.\n");
 }
 
+static void mctl_write_pattern(void)
+{
+	unsigned int i;
+	u32 *ptr, val;
+
+	ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+	for (i = 0; i < 16; ptr++, i++) {
+		if (i & 1)
+			val = ~(ulong)ptr;
+		else
+			val = (ulong)ptr;
+		writel(val, ptr);
+	}
+}
+
+static bool mctl_check_pattern(ulong offset)
+{
+	unsigned int i;
+	u32 *ptr, val;
+
+	ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+	for (i = 0; i < 16; ptr++, i++) {
+		if (i & 1)
+			val = ~(ulong)ptr;
+		else
+			val = (ulong)ptr;
+		if (val != *(ptr + offset / 4))
+			return false;
+	}
+
+	return true;
+}
+
 static void mctl_auto_detect_dram_size(const struct dram_para *para,
 				       struct dram_config *config)
 {
-	unsigned int shift;
+	unsigned int shift, cols, rows;
+	u32 buffer[16];
 
 	/* max. config for columns, but not rows */
 	config->cols = 11;
 	config->rows = 13;
 	mctl_core_init(para, config);
 
+	/*
+	 * Store content so it can be restored later. This is important
+	 * if controller was already initialized and holds any data
+	 * which is important for restoring system.
+	 */
+	memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+
+	mctl_write_pattern();
+
 	shift = config->bus_full_width + 1;
 
 	/* detect column address bits */
-	for (config->cols = 8; config->cols < 11; config->cols++) {
-		if (mctl_mem_matches(1ULL << (config->cols + shift)))
+	for (cols = 8; cols < 11; cols++) {
+		if (mctl_check_pattern(1ULL << (cols + shift)))
 			break;
 	}
-	debug("detected %u columns\n", config->cols);
+	debug("detected %u columns\n", cols);
+
+	/* restore data */
+	memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
 
 	/* reconfigure to make sure that all active rows are accessible */
-	config->rows = 18;
+	config->cols = 8;
+	config->rows = 17;
 	mctl_core_init(para, config);
 
+	/* store data again as it might be moved */
+	memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+
+	mctl_write_pattern();
+
 	/* detect row address bits */
 	shift = config->bus_full_width + 4 + config->cols;
-	for (config->rows = 13; config->rows < 18; config->rows++) {
-		if (mctl_mem_matches(1ULL << (config->rows + shift)))
+	for (rows = 13; rows < 17; rows++) {
+		if (mctl_check_pattern(1ULL << (rows + shift)))
 			break;
 	}
-	debug("detected %u rows\n", config->rows);
+	debug("detected %u rows\n", rows);
+
+	/* restore data again */
+	memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+
+	config->cols = cols;
+	config->rows = rows;
 }
 
 static unsigned long mctl_calc_size(const struct dram_config *config)
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
index 8e19324..c77dc53 100644
--- a/arch/arm/mach-sunxi/pmic_bus.c
+++ b/arch/arm/mach-sunxi/pmic_bus.c
@@ -16,33 +16,10 @@
 #include <power/pmic.h>
 #include <asm/arch/pmic_bus.h>
 
-#define AXP152_I2C_ADDR			0x30
-
-#define AXP209_I2C_ADDR			0x34
-#define AXP717_I2C_ADDR			0x34
-
-#define AXP305_I2C_ADDR			0x36
-#define AXP313_I2C_ADDR			0x36
-
 #define AXP221_CHIP_ADDR		0x68
 
 #if CONFIG_IS_ENABLED(PMIC_AXP)
 static struct udevice *pmic;
-#else
-static int pmic_i2c_address(void)
-{
-	if (IS_ENABLED(CONFIG_AXP152_POWER))
-		return AXP152_I2C_ADDR;
-	if (IS_ENABLED(CONFIG_AXP305_POWER))
-		return AXP305_I2C_ADDR;
-	if (IS_ENABLED(CONFIG_AXP313_POWER))
-		return AXP313_I2C_ADDR;
-	if (IS_ENABLED(CONFIG_AXP717_POWER))
-		return AXP717_I2C_ADDR;
-
-	/* Other AXP2xx and AXP8xx variants */
-	return AXP209_I2C_ADDR;
-}
 #endif
 
 int pmic_bus_init(void)
@@ -88,7 +65,7 @@
 	if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
 		return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data);
 
-	return i2c_read(pmic_i2c_address(), reg, 1, data, 1);
+	return i2c_read(CONFIG_AXP_I2C_ADDRESS, reg, 1, data, 1);
 #endif
 }
 
@@ -102,7 +79,7 @@
 	if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
 		return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data);
 
-	return i2c_write(pmic_i2c_address(), reg, 1, &data, 1);
+	return i2c_write(CONFIG_AXP_I2C_ADDRESS, reg, 1, &data, 1);
 #endif
 }
 
diff --git a/arch/arm/mach-sunxi/rmr_switch.S b/arch/arm/mach-sunxi/rmr_switch.S
index 33e55d4..422007c 100644
--- a/arch/arm/mach-sunxi/rmr_switch.S
+++ b/arch/arm/mach-sunxi/rmr_switch.S
@@ -16,7 +16,9 @@
 @ the machine code must be inserted as verbatim .word statements into the
 @ beginning of the AArch64 U-Boot code.
 @ To get the encoded bytes, use:
-@ ${CROSS_COMPILE}gcc -c -o rmr_switch.o rmr_switch.S
+@ ${CROSS_COMPILE}gcc -c -Iinclude -Iarch/arm/include	\
+@   -D__ASSEMBLY__ -DCONFIG_ARM64			\
+@   -o rmr_switch.o arch/arm/mach-sunxi/rmr_switch.S
 @ ${CROSS_COMPILE}objdump -d rmr_switch.o
 @
 @ The resulting words should be inserted into the U-Boot file at
@@ -29,14 +31,40 @@
 #include <config.h>
 
 .text
+	b	start32			// this is "tst x0, x0" in AArch64
+	.word	0x14000047		// this is "b   reset"  in AArch64
 
-#ifndef CONFIG_SUN50I_GEN_H6
-	ldr	r1, =0x017000a0		@ MMIO mapped RVBAR[0] register
+	.space  0x78			// gap distance set by the common
+					// encoding of the first instruction
+fel_stash_addr:
+	.word	fel_stash - .		// distance to fel_stash buffer
+
+start32:
+	adr	r0, fel_stash_addr	// absolute location of fel_stash_addr
+	ldr	r1, fel_stash_addr	// distance to actual fel_stash
+	add	r0, r0, r1		// real address of fel_stash
+
+	/* save the current state as needed by the BROM for a later return */
+	str	sp, [r0]
+	str	lr, [r0, #4]
+	mrs	lr, CPSR
+	str	lr, [r0, #8]
+	mrc	p15, 0, lr, cr1, cr0, 0		// SCTLR
+	str	lr, [r0, #12]
+	mrc	p15, 0, lr, cr12, cr0, 0	// VBAR
+	str	lr, [r0, #16]
+
+	ldr	r1, =CONFIG_SUNXI_RVBAR_ADDRESS
+	ldr	r0, =SUNXI_SRAMC_BASE
+	ldr	r0, [r0, #36]			// SRAM_VER_REG
+	ands	r0, r0, #0xff
+	ldrne	r1, =CONFIG_SUNXI_RVBAR_ALTERNATIVE
+#ifdef CONFIG_XPL_BUILD
+	ldr	r0, =CONFIG_SPL_TEXT_BASE
 #else
-	ldr	r1, =0x09010040		@ MMIO mapped RVBAR[0] register
+	ldr	r0, =CONFIG_TEXT_BASE
 #endif
-	ldr	r0, =0x57aA7add		@ start address, to be replaced
-	str	r0, [r1]
+	str	r0, [r1]			// store start address in RVBAR
 	dsb	sy
 	isb	sy
 	mrc	15, 0, r0, cr12, cr0, 2	@ read RMR register
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index c7a2205..ac9cefc 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -563,7 +563,8 @@
 #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
 	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
 	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER || \
-	defined CONFIG_AXP313_POWER || defined CONFIG_AXP717_POWER
+	defined CONFIG_AXP313_POWER || defined CONFIG_AXP717_POWER || \
+	defined CONFIG_AXP803_POWER
 	power_failed = axp_init();
 
 	if (IS_ENABLED(CONFIG_AXP_DISABLE_BOOT_ON_POWERON) && !power_failed) {
@@ -581,6 +582,8 @@
 #endif
 #ifdef CONFIG_AXP_DCDC2_VOLT
 	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
+#endif
+#ifdef CONFIG_AXP_DCDC3_VOLT
 	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
 #endif
 #ifdef CONFIG_AXP_DCDC4_VOLT
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 97f542f..36dd064c 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -80,11 +80,10 @@
 	default 0x1b000 if AM33XX && !TI_SECURE_DEVICE
 	default 0xec00 if OMAP34XX
 	default 0x10000 if ARCH_MX6 && !MX6_OCRAM_256KB
-	default 0x7fa0 if SUNXI_SRAM_ADDRESS = 0x10000
-	default 0x7fa0 if SUNXI_SRAM_ADDRESS = 0x20000 && !MACH_SUN50I_H616
 	default 0xbfa0 if MACH_SUN50I_H616
 	default 0x7000 if RCAR_GEN3
 	default 0x5fa0 if SUNXI_SRAM_ADDRESS = 0x0
+	default 0x7fa0 if ARCH_SUNXI
 	default 0x10000 if ASPEED_AST2600
 	default 0x27000 if IMX8MM && SPL_TEXT_BASE = 0x7E1000
 	default 0x30000 if ARCH_SC5XX && (SC59X_64 || SC59X)
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index 8bdc094..f44db76 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -122,4 +122,11 @@
 	  This enables common clock driver support for platforms based
 	  on Allwinner A64 SoC.
 
+config CLK_SUN50I_A100
+	bool "Clock driver for Allwinner A100/A133"
+	default MACH_SUN50I_A133
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner A100/A133 SoCs.
+
 endif # CLK_SUNXI
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 90a2774..7ff71c7 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -24,3 +24,4 @@
 obj-$(CONFIG_CLK_SUN50I_H6_R) += clk_h6_r.o
 obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
+obj-$(CONFIG_CLK_SUN50I_A100) += clk_a100.o
diff --git a/drivers/clk/sunxi/clk_a100.c b/drivers/clk/sunxi/clk_a100.c
new file mode 100644
index 0000000..b641feb
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a100.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023-2024 Arm Ltd.
+ */
+
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/sun50i-a100-ccu.h>
+#include <dt-bindings/reset/sun50i-a100-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate a100_gates[] = {
+	[CLK_PLL_PERIPH0]	= GATE(0x020, BIT(31) | BIT(27)),
+
+	[CLK_APB1]		= GATE_DUMMY,
+
+	[CLK_DE]		= GATE(0x600, BIT(31)),
+	[CLK_BUS_DE]		= GATE(0x60c, BIT(0)),
+
+	[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_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_SPI2]		= GATE(0x948, BIT(31)),
+
+	[CLK_BUS_SPI0]		= GATE(0x96c, BIT(0)),
+	[CLK_BUS_SPI1]		= GATE(0x96c, BIT(1)),
+	[CLK_BUS_SPI2]		= GATE(0x96c, BIT(2)),
+
+	[CLK_BUS_EMAC]		= GATE(0x97c, BIT(0)),
+
+	[CLK_USB_PHY0]		= GATE(0xa70, BIT(29)),
+	[CLK_USB_OHCI0]		= GATE(0xa70, BIT(31)),
+
+	[CLK_USB_PHY1]		= GATE(0xa74, BIT(29)),
+	[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_TCON_LCD]		= GATE(0xb60, BIT(31)),
+	[CLK_BUS_TCON_LCD]	= GATE(0xb7c, BIT(0)),
+};
+
+static struct ccu_reset a100_resets[] = {
+	[RST_BUS_DE]		= RESET(0x60c, BIT(16)),
+
+	[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_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_SPI2]		= RESET(0x96c, BIT(18)),
+
+	[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_TCON_LCD]	= RESET(0xb7c, BIT(16)),
+};
+
+const struct ccu_desc a100_ccu_desc = {
+	.gates = a100_gates,
+	.resets = a100_resets,
+	.num_gates = ARRAY_SIZE(a100_gates),
+	.num_resets = ARRAY_SIZE(a100_resets),
+};
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
index 2ef4f45..e0765cb 100644
--- a/drivers/clk/sunxi/clk_sunxi.c
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -122,6 +122,7 @@
 extern const struct ccu_desc h3_ccu_desc;
 extern const struct ccu_desc h6_ccu_desc;
 extern const struct ccu_desc h616_ccu_desc;
+extern const struct ccu_desc a100_ccu_desc;
 extern const struct ccu_desc h6_r_ccu_desc;
 extern const struct ccu_desc r40_ccu_desc;
 extern const struct ccu_desc v3s_ccu_desc;
@@ -215,6 +216,10 @@
 	{ .compatible = "allwinner,sun50i-h616-r-ccu",
 	  .data = (ulong)&h6_r_ccu_desc },
 #endif
+#ifdef CONFIG_CLK_SUN50I_A100
+	{ .compatible = "allwinner,sun50i-a100-ccu",
+	  .data = (ulong)&a100_ccu_desc },
+#endif
 #ifdef CONFIG_CLK_SUNIV_F1C100S
 	{ .compatible = "allwinner,suniv-f1c100s-ccu",
 	  .data = (ulong)&f1c100s_ccu_desc },
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 0b56d14..951e6ac 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -92,6 +92,13 @@
 		pll = CCM_MMC_CTRL_PLL6;
 		pll_hz = clock_get_pll6();
 #endif
+		/*
+		 * On the D1/R528/T113 mux source 1 refers to PLL_PERIPH0(1x),
+		 * like for the older SoCs. However we still have the hidden
+		 * divider of 2x, so compensate for that here.
+		 */
+		if (IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+			pll_hz /= 2;
 	}
 
 	div = pll_hz / hz;
@@ -442,6 +449,26 @@
 	return error;
 }
 
+static void sunxi_mmc_reset(void *regs)
+{
+	/* Reset controller */
+	writel(SUNXI_MMC_GCTRL_RESET, regs + SUNXI_MMC_GCTRL);
+	udelay(1000);
+
+	if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
+		/* Reset card */
+		writel(SUNXI_MMC_HWRST_ASSERT, regs + SUNXI_MMC_HWRST);
+		udelay(10);
+		writel(SUNXI_MMC_HWRST_DEASSERT, regs + SUNXI_MMC_HWRST);
+		udelay(300);
+
+		/* Setup FIFO R/W threshold. Needed on H616. */
+		writel(SUNXI_MMC_THLDC_READ_THLD(512) |
+		       SUNXI_MMC_THLDC_WRITE_EN |
+		       SUNXI_MMC_THLDC_READ_EN, regs + SUNXI_MMC_THLDC);
+	}
+}
+
 /* non-DM code here is used by the (ARM) SPL only */
 
 #if !CONFIG_IS_ENABLED(DM_MMC)
@@ -489,9 +516,7 @@
 {
 	struct sunxi_mmc_priv *priv = mmc->priv;
 
-	/* Reset controller */
-	writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
-	udelay(1000);
+	sunxi_mmc_reset(priv->reg);
 
 	return 0;
 }
@@ -684,9 +709,7 @@
 
 	upriv->mmc = &plat->mmc;
 
-	/* Reset controller */
-	writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
-	udelay(1000);
+	sunxi_mmc_reset(priv->reg);
 
 	return 0;
 }
diff --git a/drivers/mmc/sunxi_mmc.h b/drivers/mmc/sunxi_mmc.h
index f4ae5a7..7186516 100644
--- a/drivers/mmc/sunxi_mmc.h
+++ b/drivers/mmc/sunxi_mmc.h
@@ -37,7 +37,9 @@
 	u32 res0;		/* 0x54 reserved */
 	u32 a12a;		/* 0x58 Auto command 12 argument */
 	u32 ntsr;		/* 0x5c	New timing set register */
-	u32 res1[8];
+	u32 res1[6];
+	u32 hwrst;		/* 0x78 Hardware Reset */
+	u32 res5;
 	u32 dmac;		/* 0x80 internal DMA control */
 	u32 dlba;		/* 0x84 internal DMA descr list base address */
 	u32 idst;		/* 0x88 internal DMA status */
@@ -46,7 +48,8 @@
 	u32 cbda;		/* 0x94 */
 	u32 res2[26];
 #if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
-	u32 res3[17];
+	u32 thldc;		/* 0x100 Threshold control */
+	u32 res3[16];
 	u32 samp_dl;
 	u32 res4[46];
 #endif
@@ -57,6 +60,7 @@
 #define SUNXI_MMC_CLK_ENABLE		(0x1 << 16)
 #define SUNXI_MMC_CLK_DIVIDER_MASK	(0xff)
 
+#define SUNXI_MMC_GCTRL		0x000
 #define SUNXI_MMC_GCTRL_SOFT_RESET	(0x1 << 0)
 #define SUNXI_MMC_GCTRL_FIFO_RESET	(0x1 << 1)
 #define SUNXI_MMC_GCTRL_DMA_RESET	(0x1 << 2)
@@ -123,6 +127,10 @@
 
 #define SUNXI_MMC_NTSR_MODE_SEL_NEW		(0x1 << 31)
 
+#define SUNXI_MMC_HWRST		0x078
+#define SUNXI_MMC_HWRST_ASSERT		(0x0 << 0)
+#define SUNXI_MMC_HWRST_DEASSERT	(0x1 << 0)
+
 #define SUNXI_MMC_IDMAC_RESET		(0x1 << 0)
 #define SUNXI_MMC_IDMAC_FIXBURST	(0x1 << 1)
 #define SUNXI_MMC_IDMAC_ENABLE		(0x1 << 7)
@@ -133,6 +141,12 @@
 #define SUNXI_MMC_COMMON_CLK_GATE		(1 << 16)
 #define SUNXI_MMC_COMMON_RESET			(1 << 18)
 
+#define SUNXI_MMC_THLDC		0x100
+#define SUNXI_MMC_THLDC_READ_EN		(0x1 << 0)
+#define SUNXI_MMC_THLDC_BSY_CLR_INT_EN	(0x1 << 1)
+#define SUNXI_MMC_THLDC_WRITE_EN	(0x1 << 2)
+#define SUNXI_MMC_THLDC_READ_THLD(x)	(((x) & 0xfff) << 16)
+
 #define SUNXI_MMC_CAL_DL_SW_EN		(0x1 << 7)
 
 #endif /* _SUNXI_MMC_H */
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index cbd6179..65e8192 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -124,6 +124,16 @@
 	default MACH_SUN50I_H616
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN50I_A100
+	bool "Support for the Allwinner A100/A133 PIO"
+	default MACH_SUN50I_A133
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_A100_R
+	bool "Support for the Allwinner A100/A133 R-PIO"
+	default MACH_SUN50I_A133
+	select PINCTRL_SUNXI
+
 config PINCTRL_SUN20I_D1
 	bool "Support for the Allwinner D1/R528 PIO"
 	default MACH_SUN8I_R528
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 37ea937..c38edf7 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -774,6 +774,41 @@
 	.num_banks	= 1,
 };
 
+static const struct sunxi_pinctrl_function sun50i_a100_pinctrl_functions[] = {
+	{ "emac0",	5 },	/* PH0-PH16 */
+	{ "gpio_in",	0 },
+	{ "gpio_out",	1 },
+	{ "mmc0",	2 },	/* PF0-PF5 */
+	{ "mmc1",	2 },	/* PG0-PG5 */
+	{ "mmc2",	3 },	/* PC0-PC16 */
+	{ "spi0",	4 },	/* PC2-PC4, PC7, PC12, PC15-PC16 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+	{ "uart0",	3 },	/* PF2-PF4 */
+#else
+	{ "uart0",	2 },	/* PB9-PB10 */
+#endif
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a100_pinctrl_desc = {
+	.functions	= sun50i_a100_pinctrl_functions,
+	.num_functions	= ARRAY_SIZE(sun50i_a100_pinctrl_functions),
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_function sun50i_a100_r_pinctrl_functions[] = {
+	{ "gpio_in",	0 },
+	{ "gpio_out",	1 },
+	{ "s_i2c0",	2 },
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a100_r_pinctrl_desc = {
+	.functions	= sun50i_a100_r_pinctrl_functions,
+	.num_functions	= ARRAY_SIZE(sun50i_a100_r_pinctrl_functions),
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 1,
+};
+
 static const struct udevice_id sunxi_pinctrl_ids[] = {
 #ifdef CONFIG_PINCTRL_SUNIV_F1C100S
 	{
@@ -937,6 +972,18 @@
 		.data = (ulong)&sun50i_h616_r_pinctrl_desc,
 	},
 #endif
+#ifdef CONFIG_PINCTRL_SUN50I_A100
+	{
+		.compatible = "allwinner,sun50i-a100-pinctrl",
+		.data = (ulong)&sun50i_a100_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_A100_R
+	{
+		.compatible = "allwinner,sun50i-a100-r-pinctrl",
+		.data = (ulong)&sun50i_a100_r_pinctrl_desc,
+	},
+#endif
 	{}
 };
 
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 4b81aeb..eed6505 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -116,6 +116,12 @@
 	---help---
 	Select this to enable support for the AXP717 PMIC found on some boards.
 
+config AXP803_POWER
+	bool "AXP803 PMIC support"
+	select AXP_PMIC_BUS
+	---help---
+	Select this to enable support for the AXP803 PMIC found on some boards.
+
 config AXP809_POWER
 	bool "axp809 pmic support"
 	depends on MACH_SUN9I
@@ -142,10 +148,20 @@
 
 endchoice
 
+config AXP_I2C_ADDRESS
+	hex "AXP PMIC I2C address"
+	depends on ARCH_SUNXI && !SUNXI_NO_PMIC
+	default 0x36 if AXP305_POWER
+	default 0x36 if AXP313_POWER
+	default 0x30 if AXP152_POWER
+	default 0x34
+	---help---
+	I2C address of the AXP PMIC, used for the SPL only.
+
 config AXP_DCDC1_VOLT
 	int "axp pmic dcdc1 voltage"
-	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
-	default 3300 if AXP818_POWER || MACH_SUN8I_R40
+	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP803_POWER
+	default 3300 if AXP818_POWER || MACH_SUN8I_R40 || AXP803_POWER
 	default 3000 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
 	---help---
 	Set the voltage (mV) to program the axp pmic dcdc1 at, set to 0 to
@@ -158,11 +174,12 @@
 
 config AXP_DCDC2_VOLT
 	int "axp pmic dcdc2 voltage"
-	depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER || AXP717_POWER
+	depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER || AXP717_POWER || AXP803_POWER
 	default 900 if AXP818_POWER
 	default 1400 if AXP152_POWER || AXP209_POWER
 	default 1000 if AXP313_POWER
 	default 1000 if AXP717_POWER
+	default 1000 if AXP803_POWER
 	default 1200 if MACH_SUN6I
 	default 1100 if MACH_SUN8I
 	default 0 if MACH_SUN9I
@@ -219,7 +236,7 @@
 
 config AXP_DCDC5_VOLT
 	int "axp pmic dcdc5 voltage"
-	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
+	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP803_POWER
 	default 1500 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
 	---help---
 	Set the voltage (mV) to program the axp pmic dcdc5 at, set to 0 to
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 3f4d56f..3363191 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -17,6 +17,7 @@
 obj-$(CONFIG_AXP717_POWER)	+= axp_spl.o
 obj-$(CONFIG_AXP809_POWER)	+= axp809.o
 obj-$(CONFIG_AXP818_POWER)	+= axp818.o
+obj-$(CONFIG_AXP803_POWER)	+= axp_spl.o
 endif
 obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
 obj-$(CONFIG_SY8106A_POWER)	+= sy8106a.o
diff --git a/drivers/power/axp_spl.c b/drivers/power/axp_spl.c
index 3c86eb2..7c51a9b 100644
--- a/drivers/power/axp_spl.c
+++ b/drivers/power/axp_spl.c
@@ -36,6 +36,23 @@
 #define AXP_SHUTDOWN_REG	0x27
 #define AXP_SHUTDOWN_MASK	BIT(0)
 
+#elif defined(CONFIG_AXP803_POWER)				/* AXP803 */
+
+static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
+	{ 0x10, BIT(0), 0x20, 0x1f, 1600, 3400, 100, NA },
+	{ 0x10, BIT(1), 0x21, 0x7f,  500, 1300,  10, 70 },
+	{ 0x10, BIT(2), 0x22, 0x7f,  500, 1300,  10, 70 },
+	{ 0x10, BIT(3), 0x23, 0x7f,  500, 1300,  10, 70 },
+	{ 0x10, BIT(4), 0x24, 0x7f,  800, 1840,  10, 32 },
+	{ 0x10, BIT(5), 0x25, 0x7f,  600, 1520,  10, 50 },
+};
+
+#define AXP_CHIP_VERSION	0x3
+#define AXP_CHIP_VERSION_MASK	0xcf
+#define AXP_CHIP_ID		0x41
+#define AXP_SHUTDOWN_REG	0x32
+#define AXP_SHUTDOWN_MASK	BIT(7)
+
 #elif defined(CONFIG_AXP313_POWER)				/* AXP313 */
 
 static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {