From d5ddf67a66d77d04a6f0f6856af02704f486fd73 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sun, 14 Oct 2018 22:13:53 +0100 Subject: [PATCH] allwinner: H6: Factor out I2C platform setup In the H6 platform code there is a routine to do the platform initialisation of the R_I2C controller. We will need a very similar setup routine to initialise the RSB controller on the A64. Move this code to sunxi_common.c and generalise it to support all SoCs and also to cover the related RSB bus. Signed-off-by: Andre Przywara --- plat/allwinner/common/include/sunxi_private.h | 1 + plat/allwinner/common/sunxi_common.c | 57 +++++++++++++++++++ plat/allwinner/sun50i_h6/sunxi_power.c | 40 +++---------- 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h index 54cc27e4..6c9c509c 100644 --- a/plat/allwinner/common/include/sunxi_private.h +++ b/plat/allwinner/common/include/sunxi_private.h @@ -19,5 +19,6 @@ void sunxi_security_setup(void); uint16_t sunxi_read_soc_id(void); void sunxi_set_gpio_out(char port, int pin, bool level_high); +int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb); #endif /* SUNXI_PRIVATE_H */ diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c index 88156b51..a39c149e 100644 --- a/plat/allwinner/common/sunxi_common.c +++ b/plat/allwinner/common/sunxi_common.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include +#include #include #include #include @@ -100,3 +102,58 @@ void sunxi_set_gpio_out(char port, int pin, bool level_high) 0x7 << ((pin % 8) * 4), 0x1 << ((pin % 8) * 4)); } + +int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb) +{ + uint32_t pin_func = 0x77; + uint32_t device_bit; + unsigned int reset_offset = 0xb0; + + switch (socid) { + case SUNXI_SOC_H5: + if (use_rsb) + return -ENODEV; + pin_func = 0x22; + device_bit = BIT(6); + break; + case SUNXI_SOC_H6: + if (use_rsb) + return -ENODEV; + pin_func = 0x33; + device_bit = BIT(16); + reset_offset = 0x19c; + break; + case SUNXI_SOC_A64: + pin_func = use_rsb ? 0x22 : 0x33; + device_bit = use_rsb ? BIT(3) : BIT(6); + break; + default: + INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid); + return -ENODEV; + } + + /* un-gate R_PIO clock */ + if (socid != SUNXI_SOC_H6) + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0)); + + /* switch pins PL0 and PL1 to the desired function */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func); + + /* level 2 drive strength */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU); + + /* set both pins to pull-up */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U); + + /* assert, then de-assert reset of I2C/RSB controller */ + mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); + mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); + + /* un-gate clock */ + if (socid != SUNXI_SOC_H6) + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit); + else + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0)); + + return 0; +} diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c index 8e293107..0a62eaa9 100644 --- a/plat/allwinner/sun50i_h6/sunxi_power.c +++ b/plat/allwinner/sun50i_h6/sunxi_power.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -25,36 +26,6 @@ enum pmic_type { enum pmic_type pmic; -static int sunxi_init_r_i2c(void) -{ - uint32_t reg; - - /* switch pins PL0 and PL1 to I2C */ - reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x00); - mmio_write_32(SUNXI_R_PIO_BASE + 0x00, (reg & ~0xff) | 0x33); - - /* level 2 drive strength */ - reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x14); - mmio_write_32(SUNXI_R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa); - - /* set both ports to pull-up */ - reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x1c); - mmio_write_32(SUNXI_R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5); - - /* assert & de-assert reset of R_I2C */ - reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c); - mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg & ~BIT(16)); - mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16)); - - /* un-gate R_I2C clock */ - mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16) | BIT(0)); - - /* call mi2cv driver */ - i2c_init((void *)SUNXI_R_I2C_BASE); - - return 0; -} - int axp_i2c_read(uint8_t chip, uint8_t reg, uint8_t *val) { int ret; @@ -101,7 +72,9 @@ int sunxi_pmic_setup(uint16_t socid) { int ret; - sunxi_init_r_i2c(); + sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); + /* initialise mi2cv driver */ + i2c_init((void *)SUNXI_R_I2C_BASE); NOTICE("PMIC: Probing AXP805\n"); pmic = AXP805; @@ -121,7 +94,10 @@ void __dead2 sunxi_power_down(void) switch (pmic) { case AXP805: - sunxi_init_r_i2c(); + /* Re-initialise after rich OS might have used it. */ + sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); + /* initialise mi2cv driver */ + i2c_init((void *)SUNXI_R_I2C_BASE); axp_i2c_read(AXP805_ADDR, 0x32, &val); axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80); break; -- 2.30.2