diff options
Diffstat (limited to 'plat/sun50iw1p1/sunxi_power.c')
-rw-r--r-- | plat/sun50iw1p1/sunxi_power.c | 199 |
1 files changed, 20 insertions, 179 deletions
diff --git a/plat/sun50iw1p1/sunxi_power.c b/plat/sun50iw1p1/sunxi_power.c index 9ab605e..827f0d5 100644 --- a/plat/sun50iw1p1/sunxi_power.c +++ b/plat/sun50iw1p1/sunxi_power.c @@ -35,181 +35,22 @@ #include "sunxi_def.h" #include "sunxi_private.h" -#define R_PRCM_BASE 0x1f01400ULL -#define R_TWI_BASE 0x1f02400ULL -#define R_PIO_BASE 0x1f02c00ULL +#define PMIC_RSB_RT_ADDR 0x2d -#define RSB_BASE 0x1f03400ULL -#define RSB_CTRL 0x00 -#define RSB_CCR 0x04 -#define RSB_INTE 0x08 -#define RSB_STAT 0x0c -#define RSB_DADDR0 0x10 -#define RSB_DLEN 0x18 -#define RSB_DATA0 0x1c -#define RSB_LCR 0x24 -#define RSB_PMCR 0x28 -#define RSB_CMD 0x2c -#define RSB_SADDR 0x30 - -#define RSBCMD_SRTA 0xE8 -#define RSBCMD_RD8 0x8B -#define RSBCMD_RD16 0x9C -#define RSBCMD_RD32 0xA6 -#define RSBCMD_WR8 0x4E -#define RSBCMD_WR16 0x59 -#define RSBCMD_WR32 0x63 - -#define BIT(n) (1U << (n)) - -#define RUNTIME_ADDR 0x2d -#define AXP803_HW_ADDR 0x3a3 - -/* Initialize the RSB controller and its pins. */ -static int init_rsb(void) -{ - uint32_t reg; - - /* un-gate PIO clock */ - reg = mmio_read_32(R_PRCM_BASE + 0x28); - mmio_write_32(R_PRCM_BASE + 0x28, reg | 0x01); - - /* get currently configured function for pins PL0 and PL1 */ - reg = mmio_read_32(R_PIO_BASE + 0x00); - if ((reg & 0xff) == 0x33) { - NOTICE("already configured for TWI\n"); - return -EBUSY; - } - - if ((reg & 0xff) == 0x22) { - NOTICE("PMIC: already configured for RSB\n"); - return -EEXIST; /* configured for RSB mode already */ - } - - /* switch pins PL0 and PL1 to RSB */ - mmio_write_32(R_PIO_BASE + 0, (reg & ~0xff) | 0x22); - - /* level 2 drive strength */ - reg = mmio_read_32(R_PIO_BASE + 0x14); - mmio_write_32(R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa); - - /* set both ports to pull-up */ - reg = mmio_read_32(R_PIO_BASE + 0x1c); - mmio_write_32(R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5); - - /* assert & de-assert reset of RSB */ - reg = mmio_read_32(R_PRCM_BASE + 0xb0); - mmio_write_32(R_PRCM_BASE + 0xb0, reg & ~0x08); - reg = mmio_read_32(R_PRCM_BASE + 0xb0); - mmio_write_32(R_PRCM_BASE + 0xb0, reg | 0x08); - - /* un-gate RSB clock */ - reg = mmio_read_32(R_PRCM_BASE + 0x28); - mmio_write_32(R_PRCM_BASE + 0x28, reg | 0x08); - - mmio_write_32(RSB_BASE + RSB_CTRL, 0x01); /* soft reset */ - - mmio_write_32(RSB_BASE + RSB_CCR, 0x11d); /* clock to 400 KHz */ - - do { - reg = mmio_read_32(RSB_BASE + RSB_CTRL); - } while (reg & 1); /* transaction in progress */ - - return 0; -} - -int sunxi_pmic_read(uint8_t address) -{ - uint32_t reg; - - mmio_write_32(RSB_BASE + RSB_DLEN, 0x10); /* read a byte, snake oil? */ - mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */ - mmio_write_32(RSB_BASE + RSB_DADDR0, address); - mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); /* start transaction */ - do { - reg = mmio_read_32(RSB_BASE + RSB_CTRL); - } while (reg & 0x80); /* transaction in progress */ - - reg = mmio_read_32(RSB_BASE + RSB_STAT); - if (reg == 0x01) { /* transaction complete */ - reg = mmio_read_32(RSB_BASE + RSB_DATA0); /* result register */ - return reg & 0xff; - } - - return -reg; -} - -int sunxi_pmic_write(uint8_t address, uint8_t value) -{ - uint32_t reg; - - mmio_write_32(RSB_BASE + RSB_DLEN, 0x00); /* write a byte, snake oil? */ - mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_WR8); /* write a byte */ - mmio_write_32(RSB_BASE + RSB_DADDR0, address); - mmio_write_32(RSB_BASE + RSB_DATA0, value); - mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); /* start transaction */ - do { - reg = mmio_read_32(RSB_BASE + RSB_CTRL); - } while (reg & 0x80); /* transaction in progress */ - - reg = mmio_read_32(RSB_BASE + RSB_STAT); - if (reg == 0x01) /* transaction complete */ - return 0; - - return -reg; -} - -static void rsb_wait(const char *desc) +int sunxi_pmic_read(uint8_t reg) { - uint32_t reg; - int cnt = 0; - - do { - reg = mmio_read_32(RSB_BASE + RSB_CTRL); - cnt++; - } while (reg & 0x80); /* transaction in progress */ - - reg = mmio_read_32(RSB_BASE + RSB_STAT); - if (reg == 0x01) - return; + uint32_t val; + int ret; - ERROR("%s: 0x%x\n", desc, reg); + ret = rsb_read(PMIC_RSB_RT_ADDR, reg, &val, 1); + if (ret) + return ret; + return val; } -/* Initialize the RSB PMIC connection. */ -static int pmic_init(uint16_t hw_addr, uint8_t rt_addr) +int sunxi_pmic_write(uint8_t reg, uint8_t value) { - int ret; - - /* Switch PMIC to RSB mode */ - mmio_write_32(RSB_BASE + RSB_PMCR, - 0x00 | (0x3e << 8) | (0x7c << 16) | BIT(31)); - do { - ret = mmio_read_32(RSB_BASE + RSB_PMCR); - } while (ret & (1U << 31)); /* transaction in progress */ - - mmio_write_32(RSB_BASE + RSB_CCR, 0x103); /* 3 MHz */ - - mmio_write_32(RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16)); - mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_SRTA); - mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); - rsb_wait("set run-time address"); - - /* Set slave runtime address */ - mmio_write_32(RSB_BASE + RSB_SADDR, rt_addr << 16); - - ret = sunxi_pmic_read(0x03); - if (ret < 0) { - ERROR("PMIC: error %d reading PMIC type\n", ret); - return -2; - } - - if ((ret & 0xcf) != 0x41) { - ERROR("PMIC: unknown PMIC type number 0x%x\n", ret); - return -3; - } - - return 0; + return rsb_write(PMIC_RSB_RT_ADDR, reg, value, 1); } /* Setup the PMIC: DCDC1 to 3.3V, enable DC1SW and DLDO4 */ @@ -270,20 +111,20 @@ int sunxi_pmic_setup(void) NOTICE("Configuring AXP PMIC\n"); - ret = init_rsb(); - if (ret && ret != -EEXIST) { - ERROR("Could not init RSB controller.\n"); - return -1; + /* Test PMIC communication */ + ret = sunxi_pmic_read(0x03); + if (ret < 0) { + ERROR("PMIC: error %d reading PMIC IC type register\n", ret); + return -2; } - if (ret != -EEXIST) { - ret = pmic_init(AXP803_HW_ADDR, RUNTIME_ADDR); - if (ret) { - ERROR("Could not connect to AXP PMIC.\n"); - return -2; - } + /* Check IC type number equals 0b01xx00001 */ + if ((ret & 0xcf) != 0x41) { + ERROR("PMIC: unknown PMIC IC type 0x%x\n", ret); + return -3; } + /* Setup the PMIC */ ret = pmic_setup(); if (!ret) NOTICE("PMIC: setup successful\n"); |