summaryrefslogtreecommitdiff
path: root/plat/sun50iw1p1/sunxi_power.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/sun50iw1p1/sunxi_power.c')
-rw-r--r--plat/sun50iw1p1/sunxi_power.c199
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");