summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv7/sunxi/Makefile1
-rw-r--r--arch/arm/cpu/armv7/sunxi/pmic_bus.c10
-rw-r--r--board/sunxi/board.c20
-rw-r--r--drivers/power/Kconfig69
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/axp809.c278
-rw-r--r--include/axp809.h75
-rw-r--r--include/axp_pmic.h4
-rw-r--r--include/configs/sunxi-common.h2
9 files changed, 432 insertions, 28 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 0d6335abea..6c341fd2fa 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o
obj-$(CONFIG_AXP152_POWER) += pmic_bus.o
obj-$(CONFIG_AXP209_POWER) += pmic_bus.o
obj-$(CONFIG_AXP221_POWER) += pmic_bus.o
+obj-$(CONFIG_AXP809_POWER) += pmic_bus.o
obj-$(CONFIG_AXP818_POWER) += pmic_bus.o
ifndef CONFIG_SPL_BUILD
diff --git a/arch/arm/cpu/armv7/sunxi/pmic_bus.c b/arch/arm/cpu/armv7/sunxi/pmic_bus.c
index 5b81a8d8e1..d96130b6ed 100644
--- a/arch/arm/cpu/armv7/sunxi/pmic_bus.c
+++ b/arch/arm/cpu/armv7/sunxi/pmic_bus.c
@@ -4,7 +4,7 @@
* Sunxi PMIC bus access helpers
*
* The axp152 & axp209 use an i2c bus, the axp221 uses the p2wi bus and the
- * axp223 uses the rsb bus, these functions abstract this.
+ * axp223/axp809 use the rsb bus, these functions abstract this.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -23,7 +23,7 @@
#define AXP221_CTRL_ADDR 0x3e
#define AXP221_INIT_DATA 0x3e
-/* AXP818 device and runtime addresses are same as AXP223 */
+/* AXP809 and AXP818 device and runtime addresses are same as AXP223 */
#define AXP223_DEVICE_ADDR 0x3a3
#define AXP223_RUNTIME_ADDR 0x2d
@@ -36,7 +36,7 @@ int pmic_bus_init(void)
if (!needs_init)
return 0;
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || defined CONFIG_AXP809_POWER
# ifdef CONFIG_MACH_SUN6I
p2wi_init();
ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
@@ -62,7 +62,7 @@ int pmic_bus_read(u8 reg, u8 *data)
return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
#elif defined CONFIG_AXP209_POWER
return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
-#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER
+#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || defined CONFIG_AXP809_POWER
# ifdef CONFIG_MACH_SUN6I
return p2wi_read(reg, data);
# else
@@ -77,7 +77,7 @@ int pmic_bus_write(u8 reg, u8 data)
return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
#elif defined CONFIG_AXP209_POWER
return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
-#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER
+#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || defined CONFIG_AXP809_POWER
# ifdef CONFIG_MACH_SUN6I
return p2wi_write(reg, data);
# else
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 718810bc19..ea0ab736e9 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -458,10 +458,15 @@ void sunxi_board_init(void)
#endif
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
- defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER
+ defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || \
+ defined CONFIG_AXP809_POWER
power_failed = axp_init();
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER
+#if defined CONFIG_AXP809_POWER
+ power_failed |= axp_set_dc5ldo(CONFIG_AXP_DC5LDO_VOLT);
+#endif
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || \
+ defined CONFIG_AXP809_POWER
power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
#endif
power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
@@ -469,11 +474,13 @@ void sunxi_board_init(void)
#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
#endif
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || \
+ defined CONFIG_AXP809_POWER
power_failed |= axp_set_dcdc5(CONFIG_AXP_DCDC5_VOLT);
#endif
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || \
+ defined CONFIG_AXP809_POWER
power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
#endif
power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
@@ -484,11 +491,14 @@ void sunxi_board_init(void)
power_failed |= axp_set_aldo4(CONFIG_AXP_ALDO4_VOLT);
#endif
-#if defined(CONFIG_AXP221_POWER) || defined(CONFIG_AXP818_POWER)
+#if defined(CONFIG_AXP221_POWER) || defined(CONFIG_AXP818_POWER) || \
+ defined CONFIG_AXP809_POWER
power_failed |= axp_set_dldo(1, CONFIG_AXP_DLDO1_VOLT);
power_failed |= axp_set_dldo(2, CONFIG_AXP_DLDO2_VOLT);
+#if !defined(CONFIG_AXP809_POWER)
power_failed |= axp_set_dldo(3, CONFIG_AXP_DLDO3_VOLT);
power_failed |= axp_set_dldo(4, CONFIG_AXP_DLDO4_VOLT);
+#endif
power_failed |= axp_set_eldo(1, CONFIG_AXP_ELDO1_VOLT);
power_failed |= axp_set_eldo(2, CONFIG_AXP_ELDO2_VOLT);
power_failed |= axp_set_eldo(3, CONFIG_AXP_ELDO3_VOLT);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index adc64552e7..d17e2bd698 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -10,6 +10,7 @@ choice
default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
default AXP818_POWER if MACH_SUN8I_A83T
+ default AXP809_POWER if MACH_SUN9I
default SUNXI_NO_PMIC if MACH_SUN8I_H3
config SUNXI_NO_PMIC
@@ -41,6 +42,14 @@ config AXP221_POWER
Select this to enable support for the axp221/axp223 pmic found on most
A23 and A31 boards.
+config AXP809_POWER
+ boolean "axp809 pmic support"
+ depends on MACH_SUN9I
+ select CMD_POWEROFF
+ ---help---
+ Select this to enable support for the axp809 pmic found on most A80
+ boards.
+
config AXP818_POWER
boolean "axp818 pmic support"
depends on MACH_SUN8I_A83T
@@ -59,9 +68,10 @@ endchoice
config AXP_DCDC1_VOLT
int "axp pmic dcdc1 voltage"
- depends on AXP221_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
default 3300 if AXP818_POWER
default 3000 if MACH_SUN6I || MACH_SUN8I
+ default 3300 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic dcdc1 at, set to 0 to
disable dcdc1. On A23 / A31 / A33 (axp221) boards dcdc1 is used for
@@ -69,14 +79,17 @@ config AXP_DCDC1_VOLT
sdcard interfaces, etc. On most boards dcdc1 is undervolted to 3.0V to
safe battery. On A31 devices dcdc1 is also used for VCC-IO. On A83T
dcdc1 is used for VCC-IO, nand, usb0, sd , etc.
+ On the A80-Q7, dcdc1 is used for peripherals (e.g. GbE PHY) and IO and
+ should be set to 3.3V to ensure compliance with the Qseven specification.
config AXP_DCDC2_VOLT
int "axp pmic dcdc2 voltage"
- depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP818_POWER
+ depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP818_POWER || AXP809_POWER
default 900 if AXP818_POWER
default 1400 if AXP152_POWER || AXP209_POWER
default 1200 if MACH_SUN6I
default 1100 if MACH_SUN8I
+ default 0 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic dcdc2 at, set to 0 to
disable dcdc2.
@@ -84,14 +97,17 @@ config AXP_DCDC2_VOLT
On A31 boards dcdc2 is used for VDD-GPU and should be 1.2V.
On A23/A33 boards dcdc2 is used for VDD-SYS and should be 1.1V.
On A83T boards dcdc2 is used for VDD-CPUA(cluster 0) and should be 0.9V.
+ On A80 boards dcdc2 is used for VDD-GPU and should be 0.9V (we turn it
+ off in U-Boot, as the kernel can turn it on later on, if necessary).
config AXP_DCDC3_VOLT
int "axp pmic dcdc3 voltage"
- depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP818_POWER
+ depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP818_POWER || AXP809_POWER
default 900 if AXP818_POWER
default 1500 if AXP152_POWER
default 1250 if AXP209_POWER
default 1200 if MACH_SUN6I || MACH_SUN8I
+ default 900 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic dcdc3 at, set to 0 to
disable dcdc3.
@@ -100,13 +116,15 @@ config AXP_DCDC3_VOLT
On A10s boards with an axp152 dcdc3 is VCC-DRAM and should be 1.5V.
On A23 / A31 / A33 boards dcdc3 is VDD-CPU and should be 1.2V.
On A83T boards dcdc3 is used for VDD-CPUB(cluster 1) and should be 0.9V.
+ On A80 boards dcdc2 is used for VDD-CPUA(Cortex-A7) and should be 0.9V.
config AXP_DCDC4_VOLT
int "axp pmic dcdc4 voltage"
- depends on AXP152_POWER || AXP221_POWER || AXP818_POWER
+ depends on AXP152_POWER || AXP221_POWER || AXP818_POWER || AXP809_POWER
default 1250 if AXP152_POWER
default 1200 if MACH_SUN6I
default 0 if MACH_SUN8I
+ default 900 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
disable dcdc4.
@@ -114,24 +132,35 @@ config AXP_DCDC4_VOLT
On A31 boards dcdc4 is used for VDD-SYS and should be 1.2V.
On A23 / A33 boards dcdc4 is unused and should be disabled.
On A83T boards dcdc4 is used for VDD-GPU.
+ On A80 boards dcdc4 is used for VDD-SYS and should be 0.9V.
config AXP_DCDC5_VOLT
int "axp pmic dcdc5 voltage"
- depends on AXP221_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
default 1800 if AXP818_POWER
- default 1500 if MACH_SUN6I || MACH_SUN8I
+ default 1500 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic dcdc5 at, set to 0 to
disable dcdc5.
- On A23 / A31 / A33 / A83T boards dcdc5 is VCC-DRAM and should be 1.5V,
- 1.8V for A83T.
+ On A23 / A31 / A33 / A83T / A80 boards dcdc5 is VCC-DRAM and should
+ be 1.5V, 1.8V for A83T.
+
+config AXP_DC5LDO_VOLT
+ int "axp pmic dc5ldo voltage"
+ depends on AXP809_POWER
+ default 900 if MACH_SUN9I
+ ---help---
+ Set the voltage (mV) to program the axp pmic dc5ldo at, set to 0 to
+ disable dc5ldo.
+ On A80 boards dc5ldo is VDD-CPUS and should be 0.9V.
config AXP_ALDO1_VOLT
int "axp pmic (a)ldo1 voltage"
- depends on AXP221_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
default 0 if MACH_SUN6I
default 1800 if MACH_SUN8I_A83T
default 3000 if MACH_SUN8I
+ default 3300 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic aldo1 at, set to 0 to
disable aldo1.
@@ -139,14 +168,16 @@ config AXP_ALDO1_VOLT
On A23 / A33 boards aldo1 is used for VCC-IO and should be 3.0V.
On A83T / H8 boards aldo1 is used for MIPI CSI, DSI, HDMI, EFUSE, and
should be 1.8V.
+ On A80 boards aldo1 is used for VCC-USBH and should be 3.3V.
config AXP_ALDO2_VOLT
int "axp pmic (a)ldo2 voltage"
- depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP818_POWER
+ depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP818_POWER || AXP809_POWER
default 3000 if AXP152_POWER || AXP209_POWER
default 0 if MACH_SUN6I
default 1800 if MACH_SUN8I_A83T
default 2500 if MACH_SUN8I
+ default 0 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic aldo2 at, set to 0 to
disable aldo2.
@@ -159,9 +190,10 @@ config AXP_ALDO2_VOLT
config AXP_ALDO3_VOLT
int "axp pmic (a)ldo3 voltage"
- depends on AXP209_POWER || AXP221_POWER || AXP818_POWER
+ depends on AXP209_POWER || AXP221_POWER || AXP818_POWER || AXP809_POWER
default 0 if AXP209_POWER
default 3000 if MACH_SUN6I || MACH_SUN8I
+ default 0 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic aldo3 at, set to 0 to
disable aldo3.
@@ -181,7 +213,7 @@ config AXP_ALDO4_VOLT
config AXP_DLDO1_VOLT
int "axp pmic dldo1 voltage"
- depends on AXP221_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
default 0
---help---
Set the voltage (mV) to program the axp pmic dldo1 at, set to 0 to
@@ -191,7 +223,7 @@ config AXP_DLDO1_VOLT
config AXP_DLDO2_VOLT
int "axp pmic dldo2 voltage"
- depends on AXP221_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
default 0
---help---
Set the voltage (mV) to program the axp pmic dldo2 at, set to 0 to
@@ -215,7 +247,7 @@ config AXP_DLDO4_VOLT
config AXP_ELDO1_VOLT
int "axp pmic eldo1 voltage"
- depends on AXP221_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
default 0
---help---
Set the voltage (mV) to program the axp pmic eldo1 at, set to 0 to
@@ -223,7 +255,7 @@ config AXP_ELDO1_VOLT
config AXP_ELDO2_VOLT
int "axp pmic eldo2 voltage"
- depends on AXP221_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
default 0
---help---
Set the voltage (mV) to program the axp pmic eldo2 at, set to 0 to
@@ -231,13 +263,16 @@ config AXP_ELDO2_VOLT
config AXP_ELDO3_VOLT
int "axp pmic eldo3 voltage"
- depends on AXP221_POWER || AXP818_POWER
- default 0
+ depends on AXP221_POWER || AXP818_POWER || AXP809_POWER
+ default 0 if !MACH_SUN9I
+ default 1800 if MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic eldo3 at, set to 0 to
disable eldo3. On some A31(s) tablets it might be used to supply
1.2V for the SSD2828 chip (converter of parallel LCD interface
into MIPI DSI).
+ On the A80-Q7 (and other A80 boards) it supplies the CPUS IO pins
+ and should be 1.8V.
config SY8106A_VOUT1_VOLT
int "SY8106A pmic VOUT1 voltage"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 690faa0f5e..b43523e628 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_AS3722_POWER) += as3722.o
obj-$(CONFIG_AXP152_POWER) += axp152.o
obj-$(CONFIG_AXP209_POWER) += axp209.o
obj-$(CONFIG_AXP221_POWER) += axp221.o
+obj-$(CONFIG_AXP809_POWER) += axp809.o
obj-$(CONFIG_AXP818_POWER) += axp818.o
obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
obj-$(CONFIG_FTPMU010_POWER) += ftpmu010.o
diff --git a/drivers/power/axp809.c b/drivers/power/axp809.c
new file mode 100644
index 0000000000..48249de411
--- /dev/null
+++ b/drivers/power/axp809.c
@@ -0,0 +1,278 @@
+/*
+ * AXP809 driver
+ *
+ * (C) Copyright 2016 Theobroma Systems Design und Consulting GmbH
+ * Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+ *
+ * based on AXP221/AXP223 driver (axp221.c):
+ *
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <asm/arch/pmic_bus.h>
+#include <axp_pmic.h>
+
+static u8 axp809_mvolt_to_cfg(int mvolt, int min, int max, int div)
+{
+ if (mvolt < min)
+ mvolt = min;
+ else if (mvolt > max)
+ mvolt = max;
+
+ return (mvolt - min) / div;
+}
+
+int axp_set_dc5ldo(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 1400, 100);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DC5LDO_EN);
+
+ ret = pmic_bus_write(AXP809_DC5LDO_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DC5LDO_EN);
+}
+
+int axp_set_dcdc1(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 1600, 3400, 100);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC1_EN);
+
+ ret = pmic_bus_write(AXP809_DCDC1_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ ret = pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
+ AXP809_OUTPUT_CTRL2_DC1SW_EN);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC1_EN);
+}
+
+int axp_set_dcdc2(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC2_EN);
+
+ ret = pmic_bus_write(AXP809_DCDC2_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC2_EN);
+}
+
+int axp_set_dcdc3(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1860, 20);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC3_EN);
+
+ ret = pmic_bus_write(AXP809_DCDC3_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC3_EN);
+}
+
+int axp_set_dcdc4(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg;
+
+ /* DCDC4 has two separate ramps:
+ 20mV steps for 600mV ... 1540mV
+ 100mV steps for 1800mV ... 2600mV
+ */
+ cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
+ cfg += axp809_mvolt_to_cfg(mvolt, 1800, 2600, 100);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC4_EN);
+
+ ret = pmic_bus_write(AXP809_DCDC4_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC4_EN);
+}
+
+int axp_set_dcdc5(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 1000, 2550, 50);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC5_EN);
+
+ ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_DCDC5_EN);
+}
+
+int axp_set_aldo1(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_ALDO1_EN);
+
+ ret = pmic_bus_write(AXP809_ALDO1_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_ALDO1_EN);
+}
+
+int axp_set_aldo2(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_ALDO2_EN);
+
+ ret = pmic_bus_write(AXP809_ALDO2_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
+ AXP809_OUTPUT_CTRL1_ALDO2_EN);
+}
+
+int axp_set_aldo3(unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
+ AXP809_OUTPUT_CTRL2_ALDO3_EN);
+
+ ret = pmic_bus_write(AXP809_ALDO3_CTRL, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
+ AXP809_OUTPUT_CTRL2_ALDO3_EN);
+}
+
+int axp_set_dldo(int dldo_num, unsigned int mvolt)
+{
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
+ int ret;
+
+ if (dldo_num < 1 || dldo_num > 2)
+ return -EINVAL;
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
+ AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
+
+ ret = pmic_bus_write(AXP809_DLDO1_CTRL + (dldo_num - 1), cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
+ AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
+}
+
+int axp_set_eldo(int eldo_num, unsigned int mvolt)
+{
+ int ret;
+ u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
+ u8 addr, bits;
+
+ switch (eldo_num) {
+ case 3:
+ addr = AXP809_ELDO3_CTRL;
+ bits = AXP809_OUTPUT_CTRL2_ELDO3_EN;
+ break;
+ case 2:
+ addr = AXP809_ELDO2_CTRL;
+ bits = AXP809_OUTPUT_CTRL2_ELDO2_EN;
+ break;
+ case 1:
+ addr = AXP809_ELDO1_CTRL;
+ bits = AXP809_OUTPUT_CTRL2_ELDO1_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (mvolt == 0)
+ return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, bits);
+
+ ret = pmic_bus_write(addr, cfg);
+ if (ret)
+ return ret;
+
+ return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, bits);
+}
+
+int axp_init(void)
+{
+ u8 axp_chip_id;
+ int ret;
+
+ ret = pmic_bus_init();
+ if (ret)
+ return ret;
+
+ ret = pmic_bus_read(AXP809_VERSION, &axp_chip_id);
+ if (ret)
+ return ret;
+
+ axp_chip_id &= AXP809_VERSION_CHIPID_MASK;
+ if (!(axp_chip_id == AXP809_VERSION_CHIPID))
+ return -ENODEV;
+
+ return 0;
+}
+
+int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF);
+
+ /* infinite loop during shutdown */
+ while (1) {}
+
+ /* not reached */
+ return 0;
+}
diff --git a/include/axp809.h b/include/axp809.h
new file mode 100644
index 0000000000..81b3607d06
--- /dev/null
+++ b/include/axp809.h
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2016 Theobroma Systems Design und Consulting GmbH
+ * Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+ *
+ * X-Powers AXP809 Power Management IC driver
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* Page 0 addresses */
+#define AXP809_INPUT_POWER_STATUS 0x00
+#define AXP809_POWERMODE 0x01
+#define AXP809_VERSION 0x03
+#define AXP809_VERSION_CHIPID_MASK 0xcf
+#define AXP809_VERSION_CHIPID 0x42
+#define AXP809_DATACACHE 0x04
+#define AXP809_OUTPUT_CTRL1 0x10
+#define AXP809_OUTPUT_CTRL1_DC5LDO_EN (1 << 0)
+#define AXP809_OUTPUT_CTRL1_DCDC1_EN (1 << 1)
+#define AXP809_OUTPUT_CTRL1_DCDC2_EN (1 << 2)
+#define AXP809_OUTPUT_CTRL1_DCDC3_EN (1 << 3)
+#define AXP809_OUTPUT_CTRL1_DCDC4_EN (1 << 4)
+#define AXP809_OUTPUT_CTRL1_DCDC5_EN (1 << 5)
+#define AXP809_OUTPUT_CTRL1_ALDO1_EN (1 << 6)
+#define AXP809_OUTPUT_CTRL1_ALDO2_EN (1 << 7)
+#define AXP809_OUTPUT_CTRL2 0x12
+#define AXP809_OUTPUT_CTRL2_ELDO1_EN (1 << 0)
+#define AXP809_OUTPUT_CTRL2_ELDO2_EN (1 << 1)
+#define AXP809_OUTPUT_CTRL2_ELDO3_EN (1 << 2)
+#define AXP809_OUTPUT_CTRL2_DLDO1_EN (1 << 3)
+#define AXP809_OUTPUT_CTRL2_DLDO2_EN (1 << 4)
+#define AXP809_OUTPUT_CTRL2_ALDO3_EN (1 << 5)
+#define AXP809_OUTPUT_CTRL2_SWOUT_EN (1 << 6)
+#define AXP809_OUTPUT_CTRL2_DC1SW_EN (1 << 7)
+#define AXP809_DLDO1_CTRL 0x15
+#define AXP809_DLDO2_CTRL 0x16
+#define AXP809_ELDO1_CTRL 0x19
+#define AXP809_ELDO2_CTRL 0x1a
+#define AXP809_ELDO3_CTRL 0x1b
+#define AXP809_DC5LDO_CTRL 0x1c
+#define AXP809_DCDC1_CTRL 0x21
+#define AXP809_DCDC2_CTRL 0x22
+#define AXP809_DCDC3_CTRL 0x23
+#define AXP809_DCDC4_CTRL 0x24
+#define AXP809_DCDC5_CTRL 0x25
+#define AXP809_DCDC23_DVS_CTRL 0x27
+#define AXP809_ALDO1_CTRL 0x28
+#define AXP809_ALDO2_CTRL 0x29
+#define AXP809_ALDO3_CTRL 0x2a
+#define AXP809_VBUS_IPSOUT 0x30
+#define AXP809_VBUS_IPSOUT_DRIVEBUS (1 << 2)
+#define AXP809_WAKEUP 0x31
+#define AXP809_SHUTDOWN 0x32
+#define AXP809_SHUTDOWN_POWEROFF (1 << 7)
+#define AXP809_DCDC_FREQUENCY 0x3b
+#define AXP809_DCDC_MODE 0x80
+#define AXP809_ADC_ENABLE 0x82
+#define AXP809_ADC_CTRL 0x84
+#define AXP809_ADC_RAT 0x85
+#define AXP809_TIMER_CTRL 0x8a
+#define AXP809_PWREN_CTRL1 0x8c
+#define AXP809_PWREN_CTRL2 0x8d
+#define AXP809_MISC_CTRL 0x8f
+#define AXP809_MISC_CTRL_N_VBUSEN_FUNC (1 << 4)
+
+/* For axp_gpio.c */
+#define AXP_POWER_STATUS 0x00
+#define AXP_POWER_STATUS_VBUS_PRESENT (1 << 5)
+#define AXP_GPIO0_CTRL 0x90
+#define AXP_GPIO1_CTRL 0x92
+#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */
+#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */
+#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */
+#define AXP_GPIO_STATE 0x94
+#define AXP_GPIO_STATE_OFFSET 0
diff --git a/include/axp_pmic.h b/include/axp_pmic.h
index 0f14683509..22f31d1c55 100644
--- a/include/axp_pmic.h
+++ b/include/axp_pmic.h
@@ -16,6 +16,9 @@
#ifdef CONFIG_AXP221_POWER
#include <axp221.h>
#endif
+#ifdef CONFIG_AXP809_POWER
+#include <axp809.h>
+#endif
#ifdef CONFIG_AXP818_POWER
#include <axp818.h>
#endif
@@ -25,6 +28,7 @@ int axp_set_dcdc2(unsigned int mvolt);
int axp_set_dcdc3(unsigned int mvolt);
int axp_set_dcdc4(unsigned int mvolt);
int axp_set_dcdc5(unsigned int mvolt);
+int axp_set_dc5ldo(unsigned int mvolt);
int axp_set_aldo1(unsigned int mvolt);
int axp_set_aldo2(unsigned int mvolt);
int axp_set_aldo3(unsigned int mvolt);
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index d750791c76..7fa9833b4d 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -257,7 +257,7 @@ extern int soft_i2c_gpio_scl;
/* PMU */
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER || \
- defined CONFIG_SY8106A_POWER
+ defined CONFIG_AXP809_POWER || defined CONFIG_SY8106A_POWER
#define CONFIG_SPL_POWER_SUPPORT
#endif