allwinner: H6: Factor out I2C platform setup
authorAndre Przywara <andre.przywara@arm.com>
Sun, 14 Oct 2018 21:13:53 +0000 (22:13 +0100)
committerAndre Przywara <andre.przywara@arm.com>
Sat, 20 Oct 2018 15:23:59 +0000 (16:23 +0100)
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 <andre.przywara@arm.com>
plat/allwinner/common/include/sunxi_private.h
plat/allwinner/common/sunxi_common.c
plat/allwinner/sun50i_h6/sunxi_power.c

index 54cc27e4fdbd106eaeb85a125e532c5b4d6dfd55..6c9c509c4437c010e385623bd04ebe1feaa768a0 100644 (file)
@@ -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 */
index 88156b51cbe9be7d77fe93efabfc7f10e4fd5edf..a39c149ee6505d87b8dc6d2e237e34e1cff5bd79 100644 (file)
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <debug.h>
+#include <errno.h>
 #include <mmio.h>
 #include <platform.h>
 #include <platform_def.h>
@@ -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;
+}
index 8e29310739a9ab828568e2781d640d6fc3f1e0bd..0a62eaa94b344098a4bc429ea6baca0e6926a574 100644 (file)
@@ -12,6 +12,7 @@
 #include <mmio.h>
 #include <mentor/mi2cv.h>
 #include <string.h>
+#include <sunxi_def.h>
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
@@ -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;