Skip to contentSkip to conversation

sunxi: H6/H616: SPL PMIC access over RSB, use it on the OrangePi Zero2

PATCH In review Arun Iyengar 2 participants 4 messages Nov 10

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover sunxi: H6/H616: SPL PMIC access over RSB, use it on the OrangePi Zero2

On H6/H616 boards the AXP305/AXP805/AXP806 PMIC can be wired to R_RSB, as on the OrangePi Zero2. TF-A then switches the PMIC to RSB mode (Linux uses RSB too), and it stays there until it loses power. The SPL can only reach it over R_I2C on these SoCs, so after every warm reboot axp_init() fails with "Failed to set core voltage! Can't set CPU frequency" and the CPU stays at 408 MHz until Linux cpufreq takes over.

Patch 1 adds the H6 generation to the SPL part of the sun8i RSB driver and uses the RSB address of the AXP305/805/806. Nothing changes for boards that do not select CONFIG_SYS_I2C_SUN8I_RSB.
Patch 2 switches the OrangePi Zero2 SPL to RSB.

Tested on an OrangePi Zero2 (H616, AXP305): cold boot and warm reboots come up without the core voltage error, TF-A and Linux still find the PMIC on RSB. A v2027.01-rc2 build with these patches (together with my sunxi DRAM and USB hub series) also came up from a warm reboot without the error and with 1 GiB. Build-tested for orangepi_zero2, orangepi_zero3, x96_mate, orangepi_3, pine_h64 and Cubieboard4 (sun9i, the other SPL RSB user) with no new warnings.

These patches were developed with Claude (Anthropic) as a coding assistant: it investigated the problems, wrote the code and the commit messages. I reviewed them, and they were tested on an Orange Pi Zero2 (H616) as described above.

---
Arun Iyengar (2):
sunxi: H6/H616: support the RSB bus for the SPL PMIC access
sunxi: configs: OrangePi Zero2: talk to the AXP305 over RSB

 arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h |  1 +
 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h   |  3 +++
 arch/arm/mach-sunxi/pmic_bus.c                  | 22 ++++++++++++++++++----
 configs/orangepi_zero2_defconfig                |  6 +-----
 drivers/i2c/sun8i_rsb.c                         | 10 ++++++++++
 5 files changed, 33 insertions(+), 9 deletions(-)

---
base-commit: ecdcf9e365df6249a57cd8cc946e7026804ff4ae
change-id: 20261110-h616-rsb-spl-b95a3b8d564e

Best regards,

Signature · 1 line
Arun Iyengar <[email protected]>
#1 lore raw

PATCH 1/2 sunxi: H6/H616: support the RSB bus for the SPL PMIC access

On H6/H616 boards the AXP305/AXP805/AXP806 PMIC is described on the R_RSB bus in the Linux device tree (e.g. pmic@745 on the OrangePi Zero2). TF-A switches the PMIC into RSB mode (AXP "device mode" register 0x3e = 0x7c) and Linux talks RSB to it. The PMIC keeps that mode until it loses power, so after every warm reboot the SPL, which can only use R_I2C on these SoCs, gets no acknowledge from the PMIC, axp_init() fails and the SPL prints

Failed to set core voltage! Can't set CPU frequency

The CPU then stays at the 408 MHz clock_init_safe() value through the SPL, TF-A and U-Boot proper.

Teach the SPL side of the sun8i RSB driver about the H6 generation:
- the controller is at 0x07083000, its gate and reset are bits 0 and 16 of PRCM register 0x1bc (like the R_I2C one at 0x19c); R_PIO has no gate to open. PL0/PL1 use pin function 2 as on sun8i.
- pmic_bus: the AXP305/805/806 answer at the "secondary" RSB hardware address 0x745 (runtime address 0x3a), the other RSB AXPs at the primary 0x3a3/0x2d. The mapping is fixed, see drivers/bus/sunxi-rsb.c in Linux.

rsb_init() issues the device-mode switch itself, so a cold boot with the PMIC still in I2C mode works as well. Nothing changes for boards that do not select CONFIG_SYS_I2C_SUN8I_RSB.

Tested on an OrangePi Zero2 (H616, AXP305) together with the next patch:
cold boot and warm reboot both come up without the core voltage error, TF-A still finds the AXP305 on RSB and Linux's sunxi-rsb driver probes it; the SPL to TF-A time on a warm reboot dropped from 1.5 s to 1.0 s (serial console timestamps).

---
 arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h |  1 +
 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h   |  3 +++
 arch/arm/mach-sunxi/pmic_bus.c                  | 22 ++++++++++++++++++----
 drivers/i2c/sun8i_rsb.c                         | 10 ++++++++++
 4 files changed, 32 insertions(+), 4 deletions(-)
arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h +1 -0
index 2a9b086991c..18ac118ca15 100644
@@ -47,6 +47,7 @@
 #define SUNXI_PRCM_BASE			0x07010000
 #define SUNXI_R_WDOG_BASE		0x07020400
 #define SUNXI_R_TWI_BASE		0x07081400
+#define SUNXI_RSB_BASE			0x07083000
 
 #ifndef __ASSEMBLY__
 void sunxi_board_init(void);
arch/arm/include/asm/arch-sunxi/prcm_sun50i.h +3 -0
index d6653c3bb06..6e9bf587a55 100644
@@ -11,6 +11,7 @@
 #ifndef __ASSEMBLY__
 
 #define CCU_PRCM_I2C_GATE_RESET		0x19c
+#define CCU_PRCM_RSB_GATE_RESET		0x1bc
 #define CCU_PRCM_PLL_LDO_CFG		0x244
 #define CCU_PRCM_SYS_PWROFF_GATING	0x250
 #define CCU_PRCM_RES_CAL_CTRL		0x310
@@ -18,6 +19,8 @@
 
 #define PRCM_TWI_GATE		(1 << 0)
 #define PRCM_TWI_RESET		(1 << 16)
+#define PRCM_RSB_GATE		(1 << 0)
+#define PRCM_RSB_RESET		(1 << 16)
 
 #endif /* __ASSEMBLY__ */
 #endif /* _PRCM_H */
arch/arm/mach-sunxi/pmic_bus.c +18 -4
index c77dc538456..8c72d773601 100644
@@ -18,6 +18,20 @@
 
 #define AXP221_CHIP_ADDR		0x68
 
+/*
+ * RSB hardware/runtime address pair of the PMIC. AXP305/AXP805/AXP806
+ * sit at the "secondary" address (0x745/0x3a), every other RSB AXP at
+ * the primary one (0x3a3/0x2d); the mapping is fixed, see Linux's
+ * drivers/bus/sunxi-rsb.c.
+ */
+#ifdef CONFIG_AXP305_POWER
+#define AXP_PMIC_RSB_DEVICE_ADDR	AXP_PMIC_SEC_DEVICE_ADDR
+#define AXP_PMIC_RSB_RUNTIME_ADDR	AXP_PMIC_SEC_RUNTIME_ADDR
+#else
+#define AXP_PMIC_RSB_DEVICE_ADDR	AXP_PMIC_PRI_DEVICE_ADDR
+#define AXP_PMIC_RSB_RUNTIME_ADDR	AXP_PMIC_PRI_RUNTIME_ADDR
+#endif
+
 #if CONFIG_IS_ENABLED(PMIC_AXP)
 static struct udevice *pmic;
 #endif
@@ -45,8 +59,8 @@ int pmic_bus_init(void)
 		if (ret)
 			return ret;
 
-		ret = rsb_set_device_address(AXP_PMIC_PRI_DEVICE_ADDR,
-					     AXP_PMIC_PRI_RUNTIME_ADDR);
+		ret = rsb_set_device_address(AXP_PMIC_RSB_DEVICE_ADDR,
+					     AXP_PMIC_RSB_RUNTIME_ADDR);
 	}
 #endif
 
@@ -63,7 +77,7 @@ int pmic_bus_read(u8 reg, u8 *data)
 	if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI))
 		return p2wi_read(reg, data);
 	if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
-		return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data);
+		return rsb_read(AXP_PMIC_RSB_RUNTIME_ADDR, reg, data);
 
 	return i2c_read(CONFIG_AXP_I2C_ADDRESS, reg, 1, data, 1);
 #endif
@@ -77,7 +91,7 @@ int pmic_bus_write(u8 reg, u8 data)
 	if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI))
 		return p2wi_write(reg, data);
 	if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
-		return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data);
+		return rsb_write(AXP_PMIC_RSB_RUNTIME_ADDR, reg, data);
 
 	return i2c_write(CONFIG_AXP_I2C_ADDRESS, reg, 1, &data, 1);
 #endif
drivers/i2c/sun8i_rsb.c +10 -0
index 2197f180566..4a0903ff869 100644
@@ -159,8 +159,18 @@ int rsb_init(void)
 {
 	struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
 
+#if defined(CONFIG_SUN50I_GEN_H6)
+	/*
+	 * H6/H616: the R_PIO clock is always on, the RSB module has its own
+	 * gate/reset register in the PRCM (like the R_I2C one used by
+	 * clock_twi_onoff()).
+	 */
+	setbits_le32((void *)SUNXI_PRCM_BASE + CCU_PRCM_RSB_GATE_RESET,
+		     PRCM_RSB_GATE | PRCM_RSB_RESET);
+#else
 	/* Enable RSB and PIO clk, and de-assert their resets */
 	prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);
+#endif
 
 	if (IS_ENABLED(CONFIG_MACH_SUN9I)) {
 		sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB);
Signature · 1 line
2.55.0
#2 lore raw

PATCH 2/2 sunxi: configs: OrangePi Zero2: talk to the AXP305 over RSB

In reply to Arun Iyengar

The OrangePi Zero2 device tree puts the AXP305 on r_rsb (pmic@745). TF-A and Linux use RSB, and the PMIC stays in RSB mode across warm reboots, so the SPL's R_I2C access fails on every reboot ("Failed to set core voltage! Can't set CPU frequency", CPU left at 408 MHz until Linux cpufreq takes over).

Use the RSB controller in the SPL instead and drop the now unused legacy mvtwsi R_I2C setup. CONFIG_SPL_I2C stays: it builds drivers/i2c, and so the RSB driver, into the SPL.

Tested on an OrangePi Zero2: before this change a cold boot was clean and every warm reboot printed the error; with it neither does. U-Boot proper still finds the PMIC on RSB through the DM driver.

---
 configs/orangepi_zero2_defconfig | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
configs/orangepi_zero2_defconfig +1 -5
index 371398fb70f..a45402e5ba8 100644
@@ -9,16 +9,12 @@ CONFIG_DRAM_SUNXI_TPR6=0x33808080
 CONFIG_DRAM_SUNXI_TPR10=0xf83438
 CONFIG_MACH_SUN50I_H616=y
 CONFIG_SUNXI_DRAM_H616_DDR3_1333=y
-CONFIG_R_I2C_ENABLE=y
 CONFIG_SPL_SPI_SUNXI=y
 CONFIG_SPL_SUNXI_LED_STATUS=y
 CONFIG_SPL_SUNXI_LED_STATUS_GPIO=76
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
-CONFIG_SPL_SYS_I2C_LEGACY=y
-CONFIG_SYS_I2C_MVTWSI=y
-CONFIG_SYS_I2C_SLAVE=0x7f
-CONFIG_SYS_I2C_SPEED=400000
+CONFIG_SYS_I2C_SUN8I_RSB=y
 CONFIG_MTD=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SUN8I_EMAC=y
Signature · 1 line
2.55.0
#3 lore raw
In reply to Arun Iyengar
Quoted 20 lines · On Tue, Nov 10, 2026 at 06:19:35AM +0000, Arun Iyengar via B4 Relay wrote:

On H6/H616 boards the AXP305/AXP805/AXP806 PMIC can be wired to R_RSB, as on the OrangePi Zero2. TF-A then switches the PMIC to RSB mode (Linux uses RSB too), and it stays there until it loses power. The SPL can only reach it over R_I2C on these SoCs, so after every warm reboot axp_init() fails with "Failed to set core voltage! Can't set CPU frequency" and the CPU stays at 408 MHz until Linux cpufreq takes over.

Patch 1 adds the H6 generation to the SPL part of the sun8i RSB driver and uses the RSB address of the AXP305/805/806. Nothing changes for boards that do not select CONFIG_SYS_I2C_SUN8I_RSB.
Patch 2 switches the OrangePi Zero2 SPL to RSB.

Tested on an OrangePi Zero2 (H616, AXP305): cold boot and warm reboots come up without the core voltage error, TF-A and Linux still find the PMIC on RSB. A v2027.01-rc2 build with these patches (together with my sunxi DRAM and USB hub series) also came up from a warm reboot without the error and with 1 GiB. Build-tested for orangepi_zero2, orangepi_zero3, x96_mate, orangepi_3, pine_h64 and Cubieboard4 (sun9i, the other SPL RSB user) with no new warnings.

Quoted 4 lines

These patches were developed with Claude (Anthropic) as a coding assistant: it investigated the problems, wrote the code and the commit messages. I reviewed them, and they were tested on an Orange Pi Zero2 (H616) as described above.

Thank you for being up-front about your LLM usage. The project policy is currently "please don't", and this specific type of usage is on the "don't" side of the spectrum than not. I'll leave it to the sunxi custodian if he wants to review these or not.

Signature · 1 line
Tom