Browse Source

Merge changes I0c5f32e8,Id49c124c,Idcfe933d into integration

* changes:
  allwinner: Use RSB for the PMIC connection on H6
  allwinner: Return the PMIC to I2C mode after use
  allwinner: Always use a 3MHz RSB bus clock
pull/1939/head
André Przywara 4 years ago
committed by TrustedFirmware Code Review
parent
commit
29912cb654
  1. 4
      include/drivers/allwinner/axp.h
  2. 8
      plat/allwinner/common/sunxi_common.c
  3. 21
      plat/allwinner/sun50i_a64/sunxi_power.c
  4. 1
      plat/allwinner/sun50i_h6/include/sunxi_mmap.h
  5. 2
      plat/allwinner/sun50i_h6/platform.mk
  6. 74
      plat/allwinner/sun50i_h6/sunxi_power.c

4
include/drivers/allwinner/axp.h

@ -9,6 +9,10 @@
#include <stdint.h> #include <stdint.h>
#define AXP20X_MODE_REG 0x3e
#define AXP20X_MODE_I2C 0x00
#define AXP20X_MODE_RSB 0x7c
#define NA 0xff #define NA 0xff
enum { enum {

8
plat/allwinner/common/sunxi_common.c

@ -125,11 +125,9 @@ int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb)
device_bit = BIT(6); device_bit = BIT(6);
break; break;
case SUNXI_SOC_H6: case SUNXI_SOC_H6:
if (use_rsb) pin_func = use_rsb ? 0x22 : 0x33;
return -ENODEV;
pin_func = 0x33;
device_bit = BIT(16); device_bit = BIT(16);
reset_offset = 0x19c; reset_offset = use_rsb ? 0x1bc : 0x19c;
break; break;
case SUNXI_SOC_A64: case SUNXI_SOC_A64:
pin_func = use_rsb ? 0x22 : 0x33; pin_func = use_rsb ? 0x22 : 0x33;
@ -157,7 +155,7 @@ int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb)
if (socid != SUNXI_SOC_H6) if (socid != SUNXI_SOC_H6)
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit); mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit);
else else
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0)); mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0));
/* assert, then de-assert reset of I2C/RSB controller */ /* assert, then de-assert reset of I2C/RSB controller */
mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);

21
plat/allwinner/sun50i_a64/sunxi_power.c

@ -92,21 +92,13 @@ static int rsb_init(void)
if (ret) if (ret)
return ret; return ret;
/* Start with 400 KHz to issue the I2C->RSB switch command. */ /* Switch to the recommended 3 MHz bus clock. */
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 400000); ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
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) if (ret)
return ret; return ret;
/* Now in RSB mode, switch to the recommended 3 MHz. */ /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
if (ret) if (ret)
return ret; return ret;
@ -156,6 +148,11 @@ int sunxi_pmic_setup(uint16_t socid, const void *fdt)
pmic = AXP803_RSB; pmic = AXP803_RSB;
axp_setup_regulators(fdt); axp_setup_regulators(fdt);
/* Switch the PMIC back to I2C mode. */
ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
if (ret)
return ret;
break; break;
default: default:
return -ENODEV; return -ENODEV;

1
plat/allwinner/sun50i_h6/include/sunxi_mmap.h

@ -55,6 +55,7 @@
#define SUNXI_R_TWD_BASE 0x07020800 #define SUNXI_R_TWD_BASE 0x07020800
#define SUNXI_R_CPUCFG_BASE 0x07000400 #define SUNXI_R_CPUCFG_BASE 0x07000400
#define SUNXI_R_I2C_BASE 0x07081400 #define SUNXI_R_I2C_BASE 0x07081400
#define SUNXI_R_RSB_BASE 0x07083000
#define SUNXI_R_UART_BASE 0x07080000 #define SUNXI_R_UART_BASE 0x07080000
#define SUNXI_R_PIO_BASE 0x07022000 #define SUNXI_R_PIO_BASE 0x07022000

2
plat/allwinner/sun50i_h6/platform.mk

@ -8,4 +8,4 @@
include plat/allwinner/common/allwinner-common.mk include plat/allwinner/common/allwinner-common.mk
BL31_SOURCES += drivers/allwinner/axp/axp805.c \ BL31_SOURCES += drivers/allwinner/axp/axp805.c \
drivers/mentor/i2c/mi2cv.c drivers/allwinner/sunxi_rsb.c

74
plat/allwinner/sun50i_h6/sunxi_power.c

@ -6,20 +6,17 @@
*/ */
#include <errno.h> #include <errno.h>
#include <string.h>
#include <arch_helpers.h>
#include <common/debug.h> #include <common/debug.h>
#include <drivers/allwinner/axp.h> #include <drivers/allwinner/axp.h>
#include <drivers/delay_timer.h> #include <drivers/allwinner/sunxi_rsb.h>
#include <drivers/mentor/mi2cv.h>
#include <lib/mmio.h>
#include <sunxi_def.h> #include <sunxi_def.h>
#include <sunxi_mmap.h> #include <sunxi_mmap.h>
#include <sunxi_private.h> #include <sunxi_private.h>
#define AXP805_ADDR 0x36 #define AXP805_HW_ADDR 0x745
#define AXP805_RT_ADDR 0x3a
static enum pmic_type { static enum pmic_type {
UNKNOWN, UNKNOWN,
@ -28,67 +25,67 @@ static enum pmic_type {
int axp_read(uint8_t reg) int axp_read(uint8_t reg)
{ {
uint8_t val; return rsb_read(AXP805_RT_ADDR, reg);
int ret;
ret = i2c_write(AXP805_ADDR, 0, 0, &reg, 1);
if (ret == 0)
ret = i2c_read(AXP805_ADDR, 0, 0, &val, 1);
if (ret) {
ERROR("PMIC: Cannot read AXP805 register %02x\n", reg);
return ret;
}
return val;
} }
int axp_write(uint8_t reg, uint8_t val) int axp_write(uint8_t reg, uint8_t val)
{ {
int ret; return rsb_write(AXP805_RT_ADDR, reg, val);
ret = i2c_write(AXP805_ADDR, reg, 1, &val, 1);
if (ret)
ERROR("PMIC: Cannot write AXP805 register %02x\n", reg);
return ret;
} }
static int axp805_probe(void) static int rsb_init(void)
{ {
int ret; int ret;
/* Switch the AXP805 to master/single-PMIC mode. */ ret = rsb_init_controller();
ret = axp_write(0xff, 0x0);
if (ret) if (ret)
return ret; return ret;
ret = axp_check_id(); /* Switch to the recommended 3 MHz bus clock. */
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
if (ret) if (ret)
return ret; return ret;
return 0; /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
if (ret)
return ret;
/* Associate the 8-bit runtime address with the 12-bit bus address. */
ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
if (ret)
return ret;
return axp_check_id();
} }
int sunxi_pmic_setup(uint16_t socid, const void *fdt) int sunxi_pmic_setup(uint16_t socid, const void *fdt)
{ {
int ret; int ret;
INFO("PMIC: Probing AXP805 on I2C\n"); INFO("PMIC: Probing AXP805 on RSB\n");
ret = sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); ret = sunxi_init_platform_r_twi(socid, true);
if (ret) if (ret)
return ret; return ret;
/* initialise mi2cv driver */ ret = rsb_init();
i2c_init((void *)SUNXI_R_I2C_BASE); if (ret)
return ret;
ret = axp805_probe(); /* Switch the AXP805 to master/single-PMIC mode. */
ret = axp_write(0xff, 0x0);
if (ret) if (ret)
return ret; return ret;
pmic = AXP805; pmic = AXP805;
axp_setup_regulators(fdt); axp_setup_regulators(fdt);
/* Switch the PMIC back to I2C mode. */
ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
if (ret)
return ret;
return 0; return 0;
} }
@ -96,10 +93,9 @@ void sunxi_power_down(void)
{ {
switch (pmic) { switch (pmic) {
case AXP805: case AXP805:
/* Re-initialise after rich OS might have used it. */ /* (Re-)init RSB in case the rich OS has disabled it. */
sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
/* initialise mi2cv driver */ rsb_init();
i2c_init((void *)SUNXI_R_I2C_BASE);
axp_power_off(); axp_power_off();
break; break;
default: default:

Loading…
Cancel
Save