* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <allwinner/sunxi_rsb.h>
#include <arch_helpers.h>
#include <debug.h>
#include <delay_timer.h>
GENERIC_H5,
GENERIC_A64,
REF_DESIGN_H5, /* regulators controlled by GPIO pins on port L */
+ AXP803_RSB, /* PMIC connected via RSB on most A64 boards */
} pmic;
+#define AXP803_HW_ADDR 0x3a3
+#define AXP803_RT_ADDR 0x2d
+
/*
* On boards without a proper PMIC we struggle to turn off the system properly.
* Try to turn off as much off the system as we can, to reduce power
}
}
+static int rsb_init(void)
+{
+ int ret;
+
+ ret = rsb_init_controller();
+ if (ret)
+ return ret;
+
+ /* Start with 400 KHz to issue the I2C->RSB switch command. */
+ ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 400000);
+ if (ret)
+ return ret;
+
+ /*
+ * Initiate an I2C transaction to write 0x7c into register 0x3e,
+ * switching the PMIC to RSB mode.
+ */
+ ret = rsb_set_device_mode(0x7c3e00);
+ if (ret)
+ return ret;
+
+ /* Now in RSB mode, switch to the recommended 3 MHz. */
+ ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
+ if (ret)
+ return ret;
+
+ /* Associate the 8-bit runtime address with the 12-bit bus address. */
+ return rsb_assign_runtime_address(AXP803_HW_ADDR,
+ AXP803_RT_ADDR);
+}
+
+static int axp_setbits(uint8_t reg, uint8_t set_mask)
+{
+ uint8_t regval;
+ int ret;
+
+ ret = rsb_read(AXP803_RT_ADDR, reg);
+ if (ret < 0)
+ return ret;
+
+ regval = ret | set_mask;
+
+ return rsb_write(AXP803_RT_ADDR, reg, regval);
+}
+
int sunxi_pmic_setup(uint16_t socid)
{
+ int ret;
+
switch (socid) {
case SUNXI_SOC_H5:
pmic = REF_DESIGN_H5;
break;
case SUNXI_SOC_A64:
pmic = GENERIC_A64;
+ ret = sunxi_init_platform_r_twi(socid, true);
+ if (ret)
+ return ret;
+
+ ret = rsb_init();
+ if (ret)
+ return ret;
+
+ pmic = AXP803_RSB;
+ NOTICE("BL31: PMIC: Detected AXP803 on RSB.\n");
+
break;
default:
NOTICE("BL31: PMIC: No support for Allwinner %x SoC.\n", socid);
/* Turn off pin controller now. */
mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
+ break;
+ case AXP803_RSB:
+ /* (Re-)init RSB in case the rich OS has disabled it. */
+ sunxi_init_platform_r_twi(SUNXI_SOC_A64, true);
+ rsb_init();
+
+ /* Set "power disable control" bit */
+ axp_setbits(0x32, BIT(7));
break;
default:
break;