diff options
author | Icenowy Zheng <icenowy@aosc.io> | 2018-07-22 21:30:14 +0800 |
---|---|---|
committer | Icenowy Zheng <icenowy@aosc.io> | 2018-09-07 23:20:17 +0800 |
commit | 6d37282807c8540319777cb50f411a2e56607438 (patch) | |
tree | 969eb5dbcb01d19d5f69408500040a5e6ed7cfed /plat/allwinner | |
parent | 5686b2eca292c9e96c1f18c5b81848053a782ed2 (diff) |
allwinner: sun50i_h6: add initial AXP805 PMIC code
The OTT reference design of Allwinner H6 SoC uses an X-Powers AXP805
PMIC.
Add initial code for it.
Currently it's only detected.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Diffstat (limited to 'plat/allwinner')
-rw-r--r-- | plat/allwinner/sun50i_h6/platform.mk | 2 | ||||
-rw-r--r-- | plat/allwinner/sun50i_h6/sunxi_power.c | 109 |
2 files changed, 109 insertions, 2 deletions
diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk index e9ee23d0..c3901d01 100644 --- a/plat/allwinner/sun50i_h6/platform.mk +++ b/plat/allwinner/sun50i_h6/platform.mk @@ -7,6 +7,7 @@ include lib/xlat_tables_v2/xlat_tables.mk AW_PLAT := plat/allwinner +AW_DRIVERS := drivers/allwinner PLAT_INCLUDES := -Iinclude/plat/arm/common \ -Iinclude/plat/arm/common/aarch64 \ @@ -15,6 +16,7 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common \ PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \ drivers/ti/uart/${ARCH}/16550_console.S \ + ${AW_DRIVERS}/sunxi_i2c.c \ ${XLAT_TABLES_LIB_SRCS} \ ${AW_PLAT}/common/plat_helpers.S \ ${AW_PLAT}/common/sunxi_common.c diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c index 50eaa6b9..3638a199 100644 --- a/plat/allwinner/sun50i_h6/sunxi_power.c +++ b/plat/allwinner/sun50i_h6/sunxi_power.c @@ -6,11 +6,116 @@ */ #include <debug.h> +#include <delay_timer.h> +#include <errno.h> +#include <mmio.h> +#include <mentor/mi2cv.h> +#include <string.h> +#include <sunxi_mmap.h> + +#define AXP805_ADDR 0x36 +#define AXP805_ID 0x03 + +enum pmic_type { + NO_PMIC, + AXP805, +}; + +enum pmic_type pmic; + +static int sunxi_init_r_i2c(void) +{ + uint32_t reg; + + /* get currently configured function for pins PL0 and PL1 */ + reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x00); + if ((reg & 0xff) == 0x33) { + NOTICE("PMIC: already configured for TWI\n"); + } + + /* switch pins PL0 and PL1 to I2C */ + 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, 0); + reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c); + mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | 0x00010000); + + /* un-gate R_I2C clock */ + reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c); + mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | 0x00000001); + + /* 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; + + ret = i2c_write(chip, 0, 0, ®, 1); + if (ret) + return ret; + + return i2c_read(chip, 0, 0, val, 1); +} + +int axp_i2c_write(uint8_t chip, uint8_t reg, uint8_t val) +{ + return i2c_write(chip, reg, 1, &val, 1); +} + +static int axp805_probe(void) +{ + int ret; + uint8_t val; + + ret = axp_i2c_write(AXP805_ADDR, 0xff, 0x0); + if (ret) { + ERROR("PMIC: Cannot put AXP805 to master mode.\n"); + return -EPERM; + } + + ret = axp_i2c_read(AXP805_ADDR, AXP805_ID, &val); + + if (!ret && ((val & 0xcf) == 0x40)) + NOTICE("PMIC: AXP805 detected\n"); + else if (ret) { + ERROR("PMIC: Cannot communicate with AXP805.\n"); + return -EPERM; + } else { + ERROR("PMIC: Non-AXP805 chip attached at AXP805's address.\n"); + return -EINVAL; + } + + return 0; +} int sunxi_pmic_setup(void) { - /* STUB */ - NOTICE("BL31: STUB PMIC setup code called\n"); + int ret; + + sunxi_init_r_i2c(); + + NOTICE("PMIC: Probing AXP805\n"); + pmic = AXP805; + + ret = axp805_probe(); + if (ret) + pmic = NO_PMIC; + else + pmic = AXP805; return 0; } |