All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/2] sunxi: power: Add AXP806 and AXP808 support
@ 2017-02-26 18:59 Rask Ingemann Lambertsen
  2017-02-26 19:01 ` [U-Boot] [PATCH 1/2 RFT] " Rask Ingemann Lambertsen
  2017-02-26 19:02 ` [U-Boot] [PATCH 2/2] sunxi: defconfig: Sunchip CX-A99: Raise CPU voltage and clock frequency Rask Ingemann Lambertsen
  0 siblings, 2 replies; 8+ messages in thread
From: Rask Ingemann Lambertsen @ 2017-02-26 18:59 UTC (permalink / raw)
  To: u-boot

The X-Powers AXP806 and AXP808 PMICs are usually found on boards featuring
the Allwinner A80 ARM SoC. The so far supported features are the same on the
two chips. A lack of data sheets to compare makes it impossible to know for
sure what the differences are, but at least two of the power-up voltages
(bldo2 and dcdce) differ.

Patch 1 adds support for the regulators and also sets up the master/slave
mode addressing to match the way it is wired on the board. This is necessary
for the PMIC to respond to register accesses and hopefully solves the AXP806
problems for the Linux 4.9 and 4.10 kernels on Cubieboard4 and A80 Optimus
boards, where the AXP806 is wired for slave mode addressing.

Patch 2 goes on top of "ARM: sunxi: Add defconfig for Sunchip CX-A99". It
updates the defconfig for the Sunchip CX-A99 board. Now that the CPU core
voltage can be controlled, the board is configured for 1200 MHz at 1020 mV,
which is the maximum according to the vendor's sys_config.fex file, instead
of the previous 1008 MHz at 900 mV.

Rask Ingemann Lambertsen (2):
  sunxi: power: Add AXP806 and AXP808 support
  sunxi: defconfig: Sunchip CX-A99: Raise CPU voltage and clock frequency

 arch/arm/include/asm/arch-sunxi/pmic_bus.h |   4 +
 arch/arm/mach-sunxi/Makefile               |   1 +
 arch/arm/mach-sunxi/pmic_bus.c             | 107 ++++++++++---
 board/sunxi/board.c                        |  20 +++
 configs/Sunchip_CX-A99_defconfig           |   2 +
 drivers/power/Kconfig                      | 226 +++++++++++++++++++++++++++-
 drivers/power/Makefile                     |   1 +
 drivers/power/axp806.c                     | 231 +++++++++++++++++++++++++++++
 include/axp806.h                           |  50 +++++++
 include/axp_pmic.h                         |  13 ++
 10 files changed, 625 insertions(+), 30 deletions(-)
 create mode 100644 drivers/power/axp806.c
 create mode 100644 include/axp806.h

-- 
2.10.2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/2 RFT] sunxi: power: Add AXP806 and AXP808 support
  2017-02-26 18:59 [U-Boot] [PATCH 0/2] sunxi: power: Add AXP806 and AXP808 support Rask Ingemann Lambertsen
@ 2017-02-26 19:01 ` Rask Ingemann Lambertsen
  2017-02-27  3:26   ` Chen-Yu Tsai
                     ` (2 more replies)
  2017-02-26 19:02 ` [U-Boot] [PATCH 2/2] sunxi: defconfig: Sunchip CX-A99: Raise CPU voltage and clock frequency Rask Ingemann Lambertsen
  1 sibling, 3 replies; 8+ messages in thread
From: Rask Ingemann Lambertsen @ 2017-02-26 19:01 UTC (permalink / raw)
  To: u-boot

An X-Powers AXP806 or AXP808 PMIC is usually found on boards using the
Allwinner A80 ARM SoC. This patch adds support for the PMIC's regulators
and sets up the runtime address and master/slave mode in pmic_bus_init().

AXP806/AXP808 support is enabled by default on all MACH_SUN9I boards.

Because there are boards with both an AXP806 and an AXP809,
drivers/power/Kconfig and arch/arm/mach-sunxi/pmic_bus.c are changed to
make it possible to have more than one PMIC enabled at a time.

Signed-off-by: Rask Ingemann Lambertsen <rask@formelder.dk>
---
This patch needs to be tested on the following boards which I don't have:
Cubietech Cubieboard4
Merrii A80 Optimus

 arch/arm/include/asm/arch-sunxi/pmic_bus.h |   4 +
 arch/arm/mach-sunxi/Makefile               |   1 +
 arch/arm/mach-sunxi/pmic_bus.c             | 107 ++++++++++---
 board/sunxi/board.c                        |  20 +++
 drivers/power/Kconfig                      | 226 +++++++++++++++++++++++++++-
 drivers/power/Makefile                     |   1 +
 drivers/power/axp806.c                     | 231 +++++++++++++++++++++++++++++
 include/axp806.h                           |  50 +++++++
 include/axp_pmic.h                         |  13 ++
 9 files changed, 623 insertions(+), 30 deletions(-)
 create mode 100644 drivers/power/axp806.c
 create mode 100644 include/axp806.h

diff --git a/arch/arm/include/asm/arch-sunxi/pmic_bus.h b/arch/arm/include/asm/arch-sunxi/pmic_bus.h
index 9c4372a..d143d54 100644
--- a/arch/arm/include/asm/arch-sunxi/pmic_bus.h
+++ b/arch/arm/include/asm/arch-sunxi/pmic_bus.h
@@ -14,5 +14,9 @@ int pmic_bus_read(u8 reg, u8 *data);
 int pmic_bus_write(u8 reg, u8 data);
 int pmic_bus_setbits(u8 reg, u8 bits);
 int pmic_bus_clrbits(u8 reg, u8 bits);
+int pmic2_bus_read(u8 reg, u8 *data);
+int pmic2_bus_write(u8 reg, u8 data);
+int pmic2_bus_setbits(u8 reg, u8 bits);
+int pmic2_bus_clrbits(u8 reg, u8 bits);
 
 #endif
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 7daba11..410fb49 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
 obj-$(CONFIG_AXP152_POWER)	+= pmic_bus.o
 obj-$(CONFIG_AXP209_POWER)	+= pmic_bus.o
 obj-$(CONFIG_AXP221_POWER)	+= pmic_bus.o
+obj-$(CONFIG_AXP806_POWER)	+= pmic_bus.o
 obj-$(CONFIG_AXP809_POWER)	+= pmic_bus.o
 obj-$(CONFIG_AXP818_POWER)	+= pmic_bus.o
 
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
index 7c57f02..a2da40c 100644
--- a/arch/arm/mach-sunxi/pmic_bus.c
+++ b/arch/arm/mach-sunxi/pmic_bus.c
@@ -27,6 +27,15 @@
 #define AXP223_DEVICE_ADDR		0x3a3
 #define AXP223_RUNTIME_ADDR		0x2d
 
+/* AXP806 and AXP808 use the same addresses. */
+#define AXP806_DEVICE_ADDR		0x745
+#define AXP806_RUNTIME_ADDR		0x3a
+
+/* AXP806 and AXP808 address space extension. */
+#define AXP806_REG_ADDR_EXT			0xff
+#define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE	0
+#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE	BIT(4)
+
 int pmic_bus_init(void)
 {
 	/* This cannot be 0 because it is used in SPL before BSS is ready */
@@ -36,7 +45,8 @@ int pmic_bus_init(void)
 	if (!needs_init)
 		return 0;
 
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP806_POWER || \
+	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
 # ifdef CONFIG_MACH_SUN6I
 	p2wi_init();
 	ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
@@ -46,16 +56,70 @@ int pmic_bus_init(void)
 	if (ret)
 		return ret;
 
+#  if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
+	defined CONFIG_AXP818_POWER
 	ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
-# endif
 	if (ret)
 		return ret;
+#  endif
+#  ifdef CONFIG_AXP806_POWER
+	ret = rsb_set_device_address(AXP806_DEVICE_ADDR, AXP806_RUNTIME_ADDR);
+	if (ret)
+		return ret;
+#  endif
+# endif
+
+# ifdef CONFIG_AXP806_POWER
+	/*
+	 * An AXP806 or AXP808 can be wired for either master mode or slave
+	 * mode. The AXP806_REG_ADDR_EXT register must be set accordingly for
+	 * the chip to repond to access to its other registers.
+	 */
+#  ifdef CONFIG_AXP806_POWER_SLAVE_MODE
+	ret = pmic2_bus_write(AXP806_REG_ADDR_EXT,
+			      AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
+#  else
+	ret = pmic2_bus_write(AXP806_REG_ADDR_EXT,
+			      AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
+#  endif
+	if (ret)
+		return ret;
+# endif
 #endif
 
 	needs_init = 0;
 	return 0;
 }
 
+#define PMIC_BUS_SETBITS(pmic_bus_read, pmic_bus_write, reg, bits) \
+{						\
+	int ret;				\
+	u8 val;					\
+						\
+	ret = pmic_bus_read(reg, &val);		\
+	if (ret)				\
+		return ret;			\
+						\
+	val |= bits;				\
+	return pmic_bus_write(reg, val);	\
+}
+
+#define PMIC_BUS_CLRBITS(pmic_bus_read, pmic_bus_write, reg, bits) \
+{						\
+	int ret;				\
+	u8 val;					\
+						\
+	ret = pmic_bus_read(reg, &val);		\
+	if (ret)				\
+		return ret;			\
+						\
+	val &= ~bits;				\
+	return pmic_bus_write(reg, val);	\
+}
+
+#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
+	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
+	defined CONFIG_AXP818_POWER
 int pmic_bus_read(u8 reg, u8 *data)
 {
 #ifdef CONFIG_AXP152_POWER
@@ -87,27 +151,26 @@ int pmic_bus_write(u8 reg, u8 data)
 }
 
 int pmic_bus_setbits(u8 reg, u8 bits)
-{
-	int ret;
-	u8 val;
-
-	ret = pmic_bus_read(reg, &val);
-	if (ret)
-		return ret;
-
-	val |= bits;
-	return pmic_bus_write(reg, val);
-}
+PMIC_BUS_SETBITS(pmic_bus_read, pmic_bus_write, reg, bits)
 
 int pmic_bus_clrbits(u8 reg, u8 bits)
+PMIC_BUS_CLRBITS(pmic_bus_read, pmic_bus_write, reg, bits)
+#endif
+
+#ifdef CONFIG_AXP806_POWER
+int pmic2_bus_read(u8 reg, u8 *data)
 {
-	int ret;
-	u8 val;
-
-	ret = pmic_bus_read(reg, &val);
-	if (ret)
-		return ret;
-
-	val &= ~bits;
-	return pmic_bus_write(reg, val);
+	return rsb_read(AXP806_RUNTIME_ADDR, reg, data);
 }
+
+int pmic2_bus_write(u8 reg, u8 data)
+{
+	return rsb_write(AXP806_RUNTIME_ADDR, reg, data);
+}
+
+int pmic2_bus_setbits(u8 reg, u8 bits)
+PMIC_BUS_SETBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
+
+int pmic2_bus_clrbits(u8 reg, u8 bits)
+PMIC_BUS_CLRBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
+#endif
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 5365638..7847837 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -540,6 +540,26 @@ void sunxi_board_init(void)
 	power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
 #endif
 #endif
+#ifdef CONFIG_AXP806_POWER
+	power_failed |= axp2_init();
+
+	power_failed |= axp_set_dcdca(CONFIG_AXP_DCDCA_VOLT);
+	power_failed |= axp_set_dcdcb(CONFIG_AXP_DCDCB_VOLT);
+	power_failed |= axp_set_dcdcc(CONFIG_AXP_DCDCC_VOLT);
+	power_failed |= axp_set_dcdcd(CONFIG_AXP_DCDCD_VOLT);
+	power_failed |= axp_set_dcdce(CONFIG_AXP_DCDCE_VOLT);
+	power_failed |= axp2_set_aldo(1, CONFIG_AXP2_ALDO1_VOLT);
+	power_failed |= axp2_set_aldo(2, CONFIG_AXP2_ALDO2_VOLT);
+	power_failed |= axp2_set_aldo(3, CONFIG_AXP2_ALDO3_VOLT);
+	power_failed |= axp_set_bldo(1, CONFIG_AXP_BLDO1_VOLT);
+	power_failed |= axp_set_bldo(2, CONFIG_AXP_BLDO2_VOLT);
+	power_failed |= axp_set_bldo(3, CONFIG_AXP_BLDO3_VOLT);
+	power_failed |= axp_set_bldo(4, CONFIG_AXP_BLDO4_VOLT);
+	power_failed |= axp_set_cldo(1, CONFIG_AXP_CLDO1_VOLT);
+	power_failed |= axp_set_cldo(2, CONFIG_AXP_CLDO2_VOLT);
+	power_failed |= axp_set_cldo(3, CONFIG_AXP_CLDO3_VOLT);
+	power_failed |= axp2_set_sw(IS_ENABLED(CONFIG_AXP2_SW_ON));
+#endif
 	printf("DRAM:");
 	ramsize = sunxi_dram_init();
 	printf(" %d MiB\n", (int)(ramsize >> 20));
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index f2c5629..aa32e5a 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -6,19 +6,18 @@ source "drivers/power/pmic/Kconfig"
 
 source "drivers/power/regulator/Kconfig"
 
-choice
-	prompt "Select Sunxi PMIC Variant"
-	depends on ARCH_SUNXI
-	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 SUNXI_NO_PMIC if MACH_SUN8I_H3 || MACH_SUN50I
+if ARCH_SUNXI
+
+comment "Select Sunxi PMIC Variant"
 
 config SUNXI_NO_PMIC
 	bool "board without a pmic"
+	default MACH_SUN8I_H3 || MACH_SUN50I
 	---help---
 	Select this for boards which do not use a PMIC.
 
+if !SUNXI_NO_PMIC
+
 config AXP152_POWER
 	bool "axp152 pmic support"
 	depends on MACH_SUN5I
@@ -30,6 +29,7 @@ config AXP152_POWER
 config AXP209_POWER
 	bool "axp209 pmic support"
 	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
+	default MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
 	select CMD_POWEROFF
 	---help---
 	Select this to enable support for the axp209 pmic found on most
@@ -38,11 +38,31 @@ config AXP209_POWER
 config AXP221_POWER
 	bool "axp221 / axp223 pmic support"
 	depends on MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
+	default MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
 	select CMD_POWEROFF
 	---help---
 	Select this to enable support for the axp221/axp223 pmic found on most
 	A23 and A31 boards.
 
+config AXP806_POWER
+	bool "axp806 / axp808 pmic support"
+	depends on MACH_SUN9I
+	default MACH_SUN9I
+	select CMD_POWEROFF
+	---help---
+	Say y here to enable support for the axp806 or axp808 pmic found
+	on A80 boards.
+
+config AXP806_POWER_SLAVE_MODE
+	bool "axp806 / axp808 pmic slave mode"
+	depends on AXP806_POWER
+	default AXP806_POWER && AXP809_POWER
+	---help---
+	Say y here to address an axp806 / axp808 in slave mode.
+	This is used on all currently supported boards with both an axp806
+	and an axp809. You should probably say n here if your board only has
+	an axp806 or axp808.
+
 config AXP809_POWER
 	bool "axp809 pmic support"
 	depends on MACH_SUN9I
@@ -53,6 +73,7 @@ config AXP809_POWER
 config AXP818_POWER
 	bool "axp818 pmic support"
 	depends on MACH_SUN8I_A83T
+	default MACH_SUN8I_A83T
 	select CMD_POWEROFF
 	---help---
 	Say y here to enable support for the axp818 pmic found on
@@ -65,7 +86,9 @@ config SY8106A_POWER
 	Select this to enable support for the SY8106A pmic found on some
 	H3 boards.
 
-endchoice
+endif
+
+endif
 
 config AXP_DCDC1_VOLT
 	int "axp pmic dcdc1 voltage"
@@ -141,6 +164,63 @@ config AXP_DCDC5_VOLT
 	On A23 / A31 / A33 / A80 / A83T boards dcdc5 is VCC-DRAM and
 	should be 1.5V, 1.35V if DDR3L is used.
 
+config AXP_DCDCA_VOLT
+	int "axp pmic dcdca voltage"
+	depends on AXP806_POWER
+	default 900 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic dcdca at, set to 0 to
+	disable dcdca.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdca
+	powers the Cortex-A15 cores (VDD-CPUB) and should be 0.9 V.
+	On the Sunchip CX-A99 board, dcdca powers the Cortex-A7 cores
+	(VDD-CPUA) and should be 0.9 V at the default 1008 MHz clock frequency.
+
+config AXP_DCDCB_VOLT
+	int "axp pmic dcdcb voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
+	default 1500 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
+	---help---
+	Set the voltage (mV) to program the axp pmic dcdcb at, set to 0 to
+	disable dcdcb.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdcb
+	is unused and can be left off.
+	On the Sunchip CX-A99 board, dcdcb powers VCC-DRAM and should be 1.5 V.
+
+config AXP_DCDCC_VOLT
+	int "axp pmic dcdcc voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic dcdcc at, set to 0 to
+	disable dcdcc.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdcb
+	is unused and can be left off.
+	On the Sunchip CX-A99 board, dcdcc powers VDD-GPU and can be left off.
+
+config AXP_DCDCD_VOLT
+	int "axp pmic dcdcd voltage"
+	depends on AXP806_POWER
+	default 900 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic dcdcd at, set to 0 to
+	disable dcdcd.
+	On A80 boards dcdcd powers VDD-SYS or VDD-VPU and should be 0.9 V.
+
+config AXP_DCDCE_VOLT
+	int "axp pmic dcdce voltage"
+	depends on AXP806_POWER
+	default 2100 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
+	default 3300 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
+	---help---
+	Set the voltage (mV) to program the axp pmic dcdce at, set to 0 to
+	disable dcdce.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdce
+	should be 2.1 V.
+	On the Sunchip CX-A99, dcdce powers several parts which need 3.3 V,
+	such as pin groups B-F and H, the eMMC card and the SD card slot.
+
 config AXP_ALDO1_VOLT
 	int "axp pmic (a)ldo1 voltage"
 	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
@@ -197,6 +277,126 @@ config AXP_ALDO4_VOLT
 	disable aldo4.
 	On A10(s) / A13 / A20 boards aldo4 should be 2.8V.
 
+config AXP2_ALDO1_VOLT
+	int "axp pmic (2) aldo1 voltage"
+	depends on AXP806_POWER
+	default 3000 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
+	default 0 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
+	---help---
+	Set the voltage (mV) to program the axp pmic aldo1 at, set to 0 to
+	disable aldo1.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo1
+	powers AVCC and should be 3.0 V.
+	On the Sunchip CX-A99, it is unknown what aldo1 powers and it can be
+	left off.
+
+config AXP2_ALDO2_VOLT
+	int "axp pmic (2) aldo2 voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
+	default 1800 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
+	---help---
+	Set the voltage (mV) to program the axp pmic aldo2 at, set to 0 to
+	disable aldo2.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo2 is
+	unused and can be left off.
+	On the Sunchip CX-A99, aldo2 powers pin groups G and M, Wifi I/O and
+	codec I/O and should be 1.8 V.
+
+config AXP2_ALDO3_VOLT
+	int "axp pmic (2) aldo3 voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic aldo3 at, set to 0 to
+	disable aldo3.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo3 is
+	unused and can be left off.
+	On the Sunchip CX-A99, aldo3 powers GMAC 2.5 V I/O and can be left off.
+
+config AXP_BLDO1_VOLT
+	int "axp pmic bldo1 voltage"
+	depends on AXP806_POWER
+	default 1800 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic bldo1 at, set to 0 to
+	disable bldo1.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo1
+	powers efuse, ADC, display and camera interface and should be 1.8 V.
+	On the Sunchip CX-A99, bldo1 powers A80 DLLs and PLLs and should be
+	1.8 V.
+
+config AXP_BLDO2_VOLT
+	int "axp pmic bldo2 voltage"
+	depends on AXP806_POWER
+	default 1800 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
+	default 900 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
+	---help---
+	Set the voltage (mV) to program the axp pmic bldo2 at, set to 0 to
+	disable bldo2.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo2
+	powers PLLs which need 1.8 V.
+	On the Sunchip CX-A99, bldo2 powers A80 subsystems which need 0.9 V.
+
+config AXP_BLDO3_VOLT
+	int "axp pmic bldo3 voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic bldo3 at, set to 0 to
+	disable bldo3.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo3 is
+	unused and can be left off.
+	On the Sunchip CX-A99, bldo2 powers the unused USB HSIC interface and
+	can be left off.
+
+config AXP_BLDO4_VOLT
+	int "axp pmic bldo4 voltage"
+	depends on AXP806_POWER
+	default 1800 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
+	default 0 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
+	---help---
+	Set the voltage (mV) to program the axp pmic bldo4 at, set to 0 to
+	disable bldo4.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo4
+	powers VCC12-HSIC and should be 1.2 V.
+	On the Sunchip CX-A99, bldo powers VDD09-HDMI and can be left off.
+
+config AXP_CLDO1_VOLT
+	int "axp pmic cldo1 voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
+	default 3300 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
+	---help---
+	Set the voltage (mV) to program the axp pmic cldo at, set to 0 to
+	disable cldo.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo1
+	supplies the unsupported GMAC 3.3 V and can be left off.
+	On the Sunchip CX-A99, cldo1 powers pin group L and the LEDs and
+	should be 3.3 V.
+
+config AXP_CLDO2_VOLT
+	int "axp pmic cldo2 voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic cldo2 at, set to 0 to
+	disable cldo2.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo2
+	powers the camera and can be left off.
+	On the Sunchip CX-A99, cldo2 powers Wifi+Bluetooth and can be left off.
+
+config AXP_CLDO3_VOLT
+	int "axp pmic cldo3 voltage"
+	depends on AXP806_POWER
+	default 0 if MACH_SUN9I
+	---help---
+	Set the voltage (mV) to program the axp pmic cldo3 at, set to 0 to
+	disable cldo3.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo3
+	powers Wifi I/O and codec I/O and can be left off.
+	On the Sunchip CX-A99, cldo3 powers Wifi+Bluetooth and can be left off.
+
 config AXP_DLDO1_VOLT
 	int "axp pmic dldo1 voltage"
 	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
@@ -295,6 +495,16 @@ config AXP_SW_ON
 	---help---
 	Enable to turn on axp pmic sw.
 
+config AXP2_SW_ON
+	bool "axp pmic (2) sw on"
+	depends on AXP806_POWER
+	default n
+	---help---
+	Enable to turn on axp pmic sw.
+	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, sw is unused
+	and can be left off.
+	On the Sunchip CX-A99, sw powers GMAC and codec and can be left off.
+
 config SY8106A_VOUT1_VOLT
 	int "SY8106A pmic VOUT1 voltage"
 	depends on SY8106A_POWER
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b43523e..aaf8248 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_AXP806_POWER)	+= axp806.o
 obj-$(CONFIG_AXP809_POWER)	+= axp809.o
 obj-$(CONFIG_AXP818_POWER)	+= axp818.o
 obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
diff --git a/drivers/power/axp806.c b/drivers/power/axp806.c
new file mode 100644
index 0000000..be6a9a8
--- /dev/null
+++ b/drivers/power/axp806.c
@@ -0,0 +1,231 @@
+/*
+ * AXP806 and AXP808 driver based on AXP221 and AXP223 driver
+ *
+ * Copyright (C) 2017 Rask Ingemann Lambertsen <rask@formelder.dk>
+ *
+ * Based on axp221.c which is
+ * (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>
+
+/*
+ * Return cfg for a regulator with a linear range from `min' to `max' in steps
+ * of `div' and an optional second linear range from `max' to `max2' in steps
+ * of `div2'. Pass `max2' == `max' and `div2' == `div' for a single range.
+ */
+static u8 axp_mvolt_to_cfg(int mvolt, int min, int max, int div,
+			   int max2, int div2)
+{
+	if (mvolt < min) {
+		mvolt = min;
+	} else if (mvolt > max) {
+		if (mvolt > max2)
+			mvolt = max2;
+		return (mvolt - max) / div2 + (max - min) / div;
+	}
+	return (mvolt - min) / div;
+}
+
+int axp_set_dcdca(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1100, 10, 1520, 20);
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
+					 AXP806_OUTPUT_CTRL1_DCDCA_EN);
+
+	ret = pmic2_bus_write(AXP806_DCDCA_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
+				 AXP806_OUTPUT_CTRL1_DCDCA_EN);
+}
+
+int axp_set_dcdcb(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg = axp_mvolt_to_cfg(mvolt, 1000, 2550, 50, 2550, 50);
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
+					 AXP806_OUTPUT_CTRL1_DCDCB_EN);
+
+	ret = pmic2_bus_write(AXP806_DCDCB_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
+				 AXP806_OUTPUT_CTRL1_DCDCB_EN);
+}
+
+int axp_set_dcdcc(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1100, 10, 1520, 20);
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
+					 AXP806_OUTPUT_CTRL1_DCDCC_EN);
+
+	ret = pmic2_bus_write(AXP806_DCDCC_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
+				 AXP806_OUTPUT_CTRL1_DCDCC_EN);
+}
+
+int axp_set_dcdcd(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1500, 20, 3300, 100);
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
+					 AXP806_OUTPUT_CTRL1_DCDCD_EN);
+
+	ret = pmic2_bus_write(AXP806_DCDCD_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
+				 AXP806_OUTPUT_CTRL1_DCDCD_EN);
+}
+
+int axp_set_dcdce(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg = axp_mvolt_to_cfg(mvolt, 1100, 3400, 100, 3400, 100);
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
+					 AXP806_OUTPUT_CTRL1_DCDCE_EN);
+
+	ret = pmic2_bus_write(AXP806_DCDCE_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
+				 AXP806_OUTPUT_CTRL1_DCDCE_EN);
+}
+
+int axp2_set_aldo(int ldo_num, unsigned int mvolt)
+{
+	int ret;
+	unsigned int ldo = ldo_num - 1;
+	u8 cfg = axp_mvolt_to_cfg(mvolt, 700, 3300, 100, 3300, 100);
+
+	if (ldo_num < 1 || ldo_num > 3)
+		return -EINVAL;
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
+					 AXP806_OUTPUT_CTRL1_ALDO1_EN << ldo);
+
+	ret = pmic2_bus_write(AXP806_ALDO1_CTRL + ldo, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
+				 AXP806_OUTPUT_CTRL1_ALDO1_EN << ldo);
+}
+
+int axp_set_bldo(int ldo_num, unsigned int mvolt)
+{
+	int ret;
+	unsigned int ldo = ldo_num - 1;
+	u8 cfg = axp_mvolt_to_cfg(mvolt, 700, 1900, 100, 1900, 100);
+
+	if (ldo_num < 1 || ldo_num > 4)
+		return -EINVAL;
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
+					AXP806_OUTPUT_CTRL2_BLDO1_EN << ldo);
+
+	ret = pmic2_bus_write(AXP806_BLDO1_CTRL + ldo, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
+				AXP806_OUTPUT_CTRL2_BLDO1_EN << ldo);
+}
+
+int axp_set_cldo(int ldo_num, unsigned int mvolt)
+{
+	int ret;
+	unsigned int ldo = ldo_num - 1;
+	u8 cfg;
+
+	if (ldo_num < 1 || ldo_num > 3)
+		return -EINVAL;
+
+	if (ldo_num == 2)
+		cfg = axp_mvolt_to_cfg(mvolt, 700, 3400, 100, 4200, 200);
+	else
+		cfg = axp_mvolt_to_cfg(mvolt, 700, 3300, 100, 3300, 100);
+
+	if (mvolt == 0)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
+					AXP806_OUTPUT_CTRL2_CLDO1_EN << ldo);
+
+	ret = pmic2_bus_write(AXP806_CLDO1_CTRL + ldo, cfg);
+	if (ret)
+		return ret;
+
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
+				AXP806_OUTPUT_CTRL2_CLDO1_EN << ldo);
+}
+
+int axp2_set_sw(bool on)
+{
+	if (!on)
+		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
+					AXP806_OUTPUT_CTRL2_SW_EN);
+	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
+				AXP806_OUTPUT_CTRL2_SW_EN);
+}
+
+int axp2_init(void)
+{
+	u8 axp_chip_id;
+	int ret;
+
+	ret = pmic_bus_init();
+	if (ret)
+		return ret;
+
+	ret = pmic2_bus_read(AXP806_CHIP_ID, &axp_chip_id);
+	if (ret)
+		return ret;
+
+	if ((axp_chip_id & 0xcf) != 0x40)
+		return -ENODEV;
+
+	return 0;
+}
+
+/* The AXP809 driver also implements do_poweroff() and we can't have both. */
+#ifndef CONFIG_AXP809_POWER
+int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	pmic2_bus_setbits(AXP806_SHUTDOWN_CTRL, AXP806_SHUTDOWN_POWEROFF);
+
+	/* infinite loop during shutdown */
+	while (1)
+		;
+
+	/* not reached */
+	return 0;
+}
+#endif
diff --git a/include/axp806.h b/include/axp806.h
new file mode 100644
index 0000000..d7f7f2b
--- /dev/null
+++ b/include/axp806.h
@@ -0,0 +1,50 @@
+/*
+ * X-Powers AXP806 and AXP808 Power Management IC driver
+ *
+ * Copyright (C) 2017 Rask Ingemann Lambertsen <rask@formelder.dk>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/bitops.h>
+
+#define AXP806_CHIP_ID		0x03
+#define AXP806_OUTPUT_CTRL1	0x10
+#define AXP806_OUTPUT_CTRL2	0x11
+#define AXP806_DCDCA_CTRL	0x12
+#define AXP806_DCDCB_CTRL	0x13
+#define AXP806_DCDCC_CTRL	0x14
+#define AXP806_DCDCD_CTRL	0x15
+#define AXP806_DCDCE_CTRL	0x16
+#define AXP806_ALDO1_CTRL	0x17
+#define AXP806_ALDO2_CTRL	0x18
+#define AXP806_ALDO3_CTRL	0x19
+/* Unused registers here. */
+#define AXP806_BLDO1_CTRL	0x20
+#define AXP806_BLDO2_CTRL	0x21
+#define AXP806_BLDO3_CTRL	0x22
+#define AXP806_BLDO4_CTRL	0x23
+#define AXP806_CLDO1_CTRL	0x24
+#define AXP806_CLDO2_CTRL	0x25
+#define AXP806_CLDO3_CTRL	0x26
+#define AXP806_SHUTDOWN_CTRL	0x32
+
+#define AXP806_OUTPUT_CTRL1_DCDCA_EN	BIT(0)
+#define AXP806_OUTPUT_CTRL1_DCDCB_EN	BIT(1)
+#define AXP806_OUTPUT_CTRL1_DCDCC_EN	BIT(2)
+#define AXP806_OUTPUT_CTRL1_DCDCD_EN	BIT(3)
+#define AXP806_OUTPUT_CTRL1_DCDCE_EN	BIT(4)
+#define AXP806_OUTPUT_CTRL1_ALDO1_EN	BIT(5)
+#define AXP806_OUTPUT_CTRL1_ALDO2_EN	BIT(6)
+#define AXP806_OUTPUT_CTRL1_ALDO3_EN	BIT(7)
+
+#define AXP806_OUTPUT_CTRL2_BLDO1_EN	BIT(0)
+#define AXP806_OUTPUT_CTRL2_BLDO2_EN	BIT(1)
+#define AXP806_OUTPUT_CTRL2_BLDO3_EN	BIT(2)
+#define AXP806_OUTPUT_CTRL2_BLDO4_EN	BIT(3)
+#define AXP806_OUTPUT_CTRL2_CLDO1_EN	BIT(4)
+#define AXP806_OUTPUT_CTRL2_CLDO2_EN	BIT(5)
+#define AXP806_OUTPUT_CTRL2_CLDO3_EN	BIT(6)
+#define AXP806_OUTPUT_CTRL2_SW_EN	BIT(7)
+
+#define AXP806_SHUTDOWN_POWEROFF	BIT(7)
diff --git a/include/axp_pmic.h b/include/axp_pmic.h
index d789ad8..7d5dad7 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_AXP806_POWER
+#include <axp806.h>
+#endif
 #ifdef CONFIG_AXP809_POWER
 #include <axp809.h>
 #endif
@@ -28,15 +31,25 @@ 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_dcdca(unsigned int mvolt);
+int axp_set_dcdcb(unsigned int mvolt);
+int axp_set_dcdcc(unsigned int mvolt);
+int axp_set_dcdcd(unsigned int mvolt);
+int axp_set_dcdce(unsigned int mvolt);
 int axp_set_aldo1(unsigned int mvolt);
 int axp_set_aldo2(unsigned int mvolt);
 int axp_set_aldo3(unsigned int mvolt);
 int axp_set_aldo4(unsigned int mvolt);
+int axp2_set_aldo(int aldo_num, unsigned int mvolt);
+int axp_set_bldo(int bldo_num, unsigned int mvolt);
+int axp_set_cldo(int cldo_num, unsigned int mvolt);
 int axp_set_dldo(int dldo_num, unsigned int mvolt);
 int axp_set_eldo(int eldo_num, unsigned int mvolt);
 int axp_set_fldo(int fldo_num, unsigned int mvolt);
 int axp_set_sw(bool on);
+int axp2_set_sw(bool on);
 int axp_init(void);
+int axp2_init(void);
 int axp_get_sid(unsigned int *sid);
 
 #endif
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 2/2] sunxi: defconfig: Sunchip CX-A99: Raise CPU voltage and clock frequency
  2017-02-26 18:59 [U-Boot] [PATCH 0/2] sunxi: power: Add AXP806 and AXP808 support Rask Ingemann Lambertsen
  2017-02-26 19:01 ` [U-Boot] [PATCH 1/2 RFT] " Rask Ingemann Lambertsen
@ 2017-02-26 19:02 ` Rask Ingemann Lambertsen
  2017-02-27  3:08   ` Chen-Yu Tsai
  1 sibling, 1 reply; 8+ messages in thread
From: Rask Ingemann Lambertsen @ 2017-02-26 19:02 UTC (permalink / raw)
  To: u-boot

This patch uses the AXP808 support to raise the Cortex-A7 core voltage
from the power-on default of 0.9 V to 1.02 V and increases the clock
frequency from the default 1008 MHz to 1200 MHz. This is the maximum clock
frequency listed in the vendor's sys_config.fex file.

Signed-off-by: Rask Ingemann Lambertsen <rask@formelder.dk>
---
This patch goes on top of "ARM: sunxi: Add defconfig for Sunchip CX-A99".

FWIW, I seem to get away with

CONFIG_SYS_CLK_FREQ=1296000000
CONFIG_AXP_DCDCA_VOLT=1100

but neither "Allwinner UltraOcta A80 Datasheet" (revision 1.3) nor 
"Allwinner A80 User Manual" (revision 1.3.1) say anything about the
supported clock frequencies.

 configs/Sunchip_CX-A99_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configs/Sunchip_CX-A99_defconfig b/configs/Sunchip_CX-A99_defconfig
index 7530d7d..3b760d8 100644
--- a/configs/Sunchip_CX-A99_defconfig
+++ b/configs/Sunchip_CX-A99_defconfig
@@ -4,6 +4,7 @@ CONFIG_MACH_SUN9I=y
 CONFIG_DRAM_CLK=600
 CONFIG_DRAM_ZQ=3881915
 CONFIG_DRAM_ODT_EN=y
+CONFIG_SYS_CLK_FREQ=1200000000
 CONFIG_MMC0_CD_PIN="PH17"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB0_VBUS_PIN="PH15"
@@ -17,6 +18,7 @@ CONFIG_SPL=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
+CONFIG_AXP_DCDCA_VOLT=1020
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 2/2] sunxi: defconfig: Sunchip CX-A99: Raise CPU voltage and clock frequency
  2017-02-26 19:02 ` [U-Boot] [PATCH 2/2] sunxi: defconfig: Sunchip CX-A99: Raise CPU voltage and clock frequency Rask Ingemann Lambertsen
@ 2017-02-27  3:08   ` Chen-Yu Tsai
  0 siblings, 0 replies; 8+ messages in thread
From: Chen-Yu Tsai @ 2017-02-27  3:08 UTC (permalink / raw)
  To: u-boot

On Mon, Feb 27, 2017 at 3:02 AM, Rask Ingemann Lambertsen
<rask@formelder.dk> wrote:
> This patch uses the AXP808 support to raise the Cortex-A7 core voltage
> from the power-on default of 0.9 V to 1.02 V and increases the clock
> frequency from the default 1008 MHz to 1200 MHz. This is the maximum clock
> frequency listed in the vendor's sys_config.fex file.

This should really be left to a proper cpufreq/DVFS system. The bootloader
should bring up the system in a safe, usable state.

1008 MHz is the default across all Allwinner SoCs, aside from a few boards
that cannot reach it without overvoltage. It's even the default in BSP
bootloaders.


ChenYu

>
> Signed-off-by: Rask Ingemann Lambertsen <rask@formelder.dk>
> ---
> This patch goes on top of "ARM: sunxi: Add defconfig for Sunchip CX-A99".
>
> FWIW, I seem to get away with
>
> CONFIG_SYS_CLK_FREQ=1296000000
> CONFIG_AXP_DCDCA_VOLT=1100
>
> but neither "Allwinner UltraOcta A80 Datasheet" (revision 1.3) nor
> "Allwinner A80 User Manual" (revision 1.3.1) say anything about the
> supported clock frequencies.
>
>  configs/Sunchip_CX-A99_defconfig | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/configs/Sunchip_CX-A99_defconfig b/configs/Sunchip_CX-A99_defconfig
> index 7530d7d..3b760d8 100644
> --- a/configs/Sunchip_CX-A99_defconfig
> +++ b/configs/Sunchip_CX-A99_defconfig
> @@ -4,6 +4,7 @@ CONFIG_MACH_SUN9I=y
>  CONFIG_DRAM_CLK=600
>  CONFIG_DRAM_ZQ=3881915
>  CONFIG_DRAM_ODT_EN=y
> +CONFIG_SYS_CLK_FREQ=1200000000
>  CONFIG_MMC0_CD_PIN="PH17"
>  CONFIG_MMC_SUNXI_SLOT_EXTRA=2
>  CONFIG_USB0_VBUS_PIN="PH15"
> @@ -17,6 +18,7 @@ CONFIG_SPL=y
>  # CONFIG_CMD_IMLS is not set
>  # CONFIG_CMD_FLASH is not set
>  # CONFIG_CMD_FPGA is not set
> +CONFIG_AXP_DCDCA_VOLT=1020
>  # CONFIG_SPL_DOS_PARTITION is not set
>  # CONFIG_SPL_ISO_PARTITION is not set
>  # CONFIG_SPL_EFI_PARTITION is not set
> --
> 2.10.2
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/2 RFT] sunxi: power: Add AXP806 and AXP808 support
  2017-02-26 19:01 ` [U-Boot] [PATCH 1/2 RFT] " Rask Ingemann Lambertsen
@ 2017-02-27  3:26   ` Chen-Yu Tsai
  2017-03-01 21:29     ` Rask Ingemann Lambertsen
  2017-02-28  4:47   ` Jaehoon Chung
       [not found]   ` <CGME20170421075849epcas1p16a1d961b1717ae9298be1aac91bab593@epcas1p1.samsung.com>
  2 siblings, 1 reply; 8+ messages in thread
From: Chen-Yu Tsai @ 2017-02-27  3:26 UTC (permalink / raw)
  To: u-boot

On Mon, Feb 27, 2017 at 3:01 AM, Rask Ingemann Lambertsen
<rask@formelder.dk> wrote:
> An X-Powers AXP806 or AXP808 PMIC is usually found on boards using the
> Allwinner A80 ARM SoC. This patch adds support for the PMIC's regulators
> and sets up the runtime address and master/slave mode in pmic_bus_init().
>
> AXP806/AXP808 support is enabled by default on all MACH_SUN9I boards.
>
> Because there are boards with both an AXP806 and an AXP809,
> drivers/power/Kconfig and arch/arm/mach-sunxi/pmic_bus.c are changed to
> make it possible to have more than one PMIC enabled at a time.
>
> Signed-off-by: Rask Ingemann Lambertsen <rask@formelder.dk>
> ---
> This patch needs to be tested on the following boards which I don't have:
> Cubietech Cubieboard4
> Merrii A80 Optimus
>
>  arch/arm/include/asm/arch-sunxi/pmic_bus.h |   4 +
>  arch/arm/mach-sunxi/Makefile               |   1 +
>  arch/arm/mach-sunxi/pmic_bus.c             | 107 ++++++++++---
>  board/sunxi/board.c                        |  20 +++
>  drivers/power/Kconfig                      | 226 +++++++++++++++++++++++++++-
>  drivers/power/Makefile                     |   1 +
>  drivers/power/axp806.c                     | 231 +++++++++++++++++++++++++++++
>  include/axp806.h                           |  50 +++++++
>  include/axp_pmic.h                         |  13 ++
>  9 files changed, 623 insertions(+), 30 deletions(-)
>  create mode 100644 drivers/power/axp806.c
>  create mode 100644 include/axp806.h
>
> diff --git a/arch/arm/include/asm/arch-sunxi/pmic_bus.h b/arch/arm/include/asm/arch-sunxi/pmic_bus.h
> index 9c4372a..d143d54 100644
> --- a/arch/arm/include/asm/arch-sunxi/pmic_bus.h
> +++ b/arch/arm/include/asm/arch-sunxi/pmic_bus.h
> @@ -14,5 +14,9 @@ int pmic_bus_read(u8 reg, u8 *data);
>  int pmic_bus_write(u8 reg, u8 data);
>  int pmic_bus_setbits(u8 reg, u8 bits);
>  int pmic_bus_clrbits(u8 reg, u8 bits);
> +int pmic2_bus_read(u8 reg, u8 *data);
> +int pmic2_bus_write(u8 reg, u8 data);
> +int pmic2_bus_setbits(u8 reg, u8 bits);
> +int pmic2_bus_clrbits(u8 reg, u8 bits);
>
>  #endif
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index 7daba11..410fb49 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_MACH_SUN9I)      += clock_sun9i.o gtbus_sun9i.o
>  obj-$(CONFIG_AXP152_POWER)     += pmic_bus.o
>  obj-$(CONFIG_AXP209_POWER)     += pmic_bus.o
>  obj-$(CONFIG_AXP221_POWER)     += pmic_bus.o
> +obj-$(CONFIG_AXP806_POWER)     += pmic_bus.o
>  obj-$(CONFIG_AXP809_POWER)     += pmic_bus.o
>  obj-$(CONFIG_AXP818_POWER)     += pmic_bus.o
>
> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
> index 7c57f02..a2da40c 100644
> --- a/arch/arm/mach-sunxi/pmic_bus.c
> +++ b/arch/arm/mach-sunxi/pmic_bus.c
> @@ -27,6 +27,15 @@
>  #define AXP223_DEVICE_ADDR             0x3a3
>  #define AXP223_RUNTIME_ADDR            0x2d
>
> +/* AXP806 and AXP808 use the same addresses. */
> +#define AXP806_DEVICE_ADDR             0x745
> +#define AXP806_RUNTIME_ADDR            0x3a
> +
> +/* AXP806 and AXP808 address space extension. */
> +#define AXP806_REG_ADDR_EXT                    0xff
> +#define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE   0
> +#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE    BIT(4)
> +
>  int pmic_bus_init(void)
>  {
>         /* This cannot be 0 because it is used in SPL before BSS is ready */
> @@ -36,7 +45,8 @@ int pmic_bus_init(void)
>         if (!needs_init)
>                 return 0;
>
> -#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
> +#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP806_POWER || \
> +       defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  # ifdef CONFIG_MACH_SUN6I
>         p2wi_init();
>         ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
> @@ -46,16 +56,70 @@ int pmic_bus_init(void)
>         if (ret)
>                 return ret;
>
> +#  if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> +       defined CONFIG_AXP818_POWER
>         ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
> -# endif
>         if (ret)
>                 return ret;
> +#  endif
> +#  ifdef CONFIG_AXP806_POWER
> +       ret = rsb_set_device_address(AXP806_DEVICE_ADDR, AXP806_RUNTIME_ADDR);
> +       if (ret)
> +               return ret;
> +#  endif
> +# endif
> +
> +# ifdef CONFIG_AXP806_POWER
> +       /*
> +        * An AXP806 or AXP808 can be wired for either master mode or slave
> +        * mode. The AXP806_REG_ADDR_EXT register must be set accordingly for
> +        * the chip to repond to access to its other registers.
> +        */
> +#  ifdef CONFIG_AXP806_POWER_SLAVE_MODE
> +       ret = pmic2_bus_write(AXP806_REG_ADDR_EXT,
> +                             AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
> +#  else
> +       ret = pmic2_bus_write(AXP806_REG_ADDR_EXT,
> +                             AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
> +#  endif
> +       if (ret)
> +               return ret;
> +# endif
>  #endif
>
>         needs_init = 0;
>         return 0;
>  }
>
> +#define PMIC_BUS_SETBITS(pmic_bus_read, pmic_bus_write, reg, bits) \
> +{                                              \
> +       int ret;                                \
> +       u8 val;                                 \
> +                                               \
> +       ret = pmic_bus_read(reg, &val);         \
> +       if (ret)                                \
> +               return ret;                     \
> +                                               \
> +       val |= bits;                            \
> +       return pmic_bus_write(reg, val);        \
> +}
> +
> +#define PMIC_BUS_CLRBITS(pmic_bus_read, pmic_bus_write, reg, bits) \
> +{                                              \
> +       int ret;                                \
> +       u8 val;                                 \
> +                                               \
> +       ret = pmic_bus_read(reg, &val);         \
> +       if (ret)                                \
> +               return ret;                     \
> +                                               \
> +       val &= ~bits;                           \
> +       return pmic_bus_write(reg, val);        \
> +}
> +
> +#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
> +       defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> +       defined CONFIG_AXP818_POWER
>  int pmic_bus_read(u8 reg, u8 *data)
>  {
>  #ifdef CONFIG_AXP152_POWER
> @@ -87,27 +151,26 @@ int pmic_bus_write(u8 reg, u8 data)
>  }
>
>  int pmic_bus_setbits(u8 reg, u8 bits)
> -{
> -       int ret;
> -       u8 val;
> -
> -       ret = pmic_bus_read(reg, &val);
> -       if (ret)
> -               return ret;
> -
> -       val |= bits;
> -       return pmic_bus_write(reg, val);
> -}
> +PMIC_BUS_SETBITS(pmic_bus_read, pmic_bus_write, reg, bits)
>
>  int pmic_bus_clrbits(u8 reg, u8 bits)
> +PMIC_BUS_CLRBITS(pmic_bus_read, pmic_bus_write, reg, bits)
> +#endif
> +
> +#ifdef CONFIG_AXP806_POWER
> +int pmic2_bus_read(u8 reg, u8 *data)
>  {
> -       int ret;
> -       u8 val;
> -
> -       ret = pmic_bus_read(reg, &val);
> -       if (ret)
> -               return ret;
> -
> -       val &= ~bits;
> -       return pmic_bus_write(reg, val);
> +       return rsb_read(AXP806_RUNTIME_ADDR, reg, data);
>  }
> +
> +int pmic2_bus_write(u8 reg, u8 data)
> +{
> +       return rsb_write(AXP806_RUNTIME_ADDR, reg, data);
> +}
> +
> +int pmic2_bus_setbits(u8 reg, u8 bits)
> +PMIC_BUS_SETBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
> +
> +int pmic2_bus_clrbits(u8 reg, u8 bits)
> +PMIC_BUS_CLRBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
> +#endif

Please split the pmic_bus changes into separate patches, such as the following:

  - Pull out PMIC_BUS_*. However please don't use macros. Just make some
    static functions. The compiler can choose to inline them.

  - Add AXP806 support in master mode

  - Add support for second PMIC to pmic_bus

  - Add AXP806 slave mode support.

> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index 5365638..7847837 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -540,6 +540,26 @@ void sunxi_board_init(void)
>         power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
>  #endif
>  #endif
> +#ifdef CONFIG_AXP806_POWER
> +       power_failed |= axp2_init();
> +
> +       power_failed |= axp_set_dcdca(CONFIG_AXP_DCDCA_VOLT);
> +       power_failed |= axp_set_dcdcb(CONFIG_AXP_DCDCB_VOLT);
> +       power_failed |= axp_set_dcdcc(CONFIG_AXP_DCDCC_VOLT);
> +       power_failed |= axp_set_dcdcd(CONFIG_AXP_DCDCD_VOLT);
> +       power_failed |= axp_set_dcdce(CONFIG_AXP_DCDCE_VOLT);
> +       power_failed |= axp2_set_aldo(1, CONFIG_AXP2_ALDO1_VOLT);
> +       power_failed |= axp2_set_aldo(2, CONFIG_AXP2_ALDO2_VOLT);
> +       power_failed |= axp2_set_aldo(3, CONFIG_AXP2_ALDO3_VOLT);

Allwinner code calls them s_aldo.

> +       power_failed |= axp_set_bldo(1, CONFIG_AXP_BLDO1_VOLT);
> +       power_failed |= axp_set_bldo(2, CONFIG_AXP_BLDO2_VOLT);
> +       power_failed |= axp_set_bldo(3, CONFIG_AXP_BLDO3_VOLT);
> +       power_failed |= axp_set_bldo(4, CONFIG_AXP_BLDO4_VOLT);
> +       power_failed |= axp_set_cldo(1, CONFIG_AXP_CLDO1_VOLT);
> +       power_failed |= axp_set_cldo(2, CONFIG_AXP_CLDO2_VOLT);
> +       power_failed |= axp_set_cldo(3, CONFIG_AXP_CLDO3_VOLT);
> +       power_failed |= axp2_set_sw(IS_ENABLED(CONFIG_AXP2_SW_ON));

And this s_sw.

> +#endif
>         printf("DRAM:");
>         ramsize = sunxi_dram_init();
>         printf(" %d MiB\n", (int)(ramsize >> 20));
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index f2c5629..aa32e5a 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -6,19 +6,18 @@ source "drivers/power/pmic/Kconfig"
>
>  source "drivers/power/regulator/Kconfig"
>
> -choice
> -       prompt "Select Sunxi PMIC Variant"
> -       depends on ARCH_SUNXI
> -       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 SUNXI_NO_PMIC if MACH_SUN8I_H3 || MACH_SUN50I
> +if ARCH_SUNXI
> +
> +comment "Select Sunxi PMIC Variant"

Would this change break existing defconfigs?

>
>  config SUNXI_NO_PMIC
>         bool "board without a pmic"
> +       default MACH_SUN8I_H3 || MACH_SUN50I
>         ---help---
>         Select this for boards which do not use a PMIC.
>
> +if !SUNXI_NO_PMIC
> +
>  config AXP152_POWER
>         bool "axp152 pmic support"
>         depends on MACH_SUN5I
> @@ -30,6 +29,7 @@ config AXP152_POWER
>  config AXP209_POWER
>         bool "axp209 pmic support"
>         depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
> +       default MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
>         select CMD_POWEROFF
>         ---help---
>         Select this to enable support for the axp209 pmic found on most
> @@ -38,11 +38,31 @@ config AXP209_POWER
>  config AXP221_POWER
>         bool "axp221 / axp223 pmic support"
>         depends on MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
> +       default MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
>         select CMD_POWEROFF
>         ---help---
>         Select this to enable support for the axp221/axp223 pmic found on most
>         A23 and A31 boards.
>
> +config AXP806_POWER
> +       bool "axp806 / axp808 pmic support"
> +       depends on MACH_SUN9I
> +       default MACH_SUN9I
> +       select CMD_POWEROFF
> +       ---help---
> +       Say y here to enable support for the axp806 or axp808 pmic found
> +       on A80 boards.
> +
> +config AXP806_POWER_SLAVE_MODE
> +       bool "axp806 / axp808 pmic slave mode"
> +       depends on AXP806_POWER
> +       default AXP806_POWER && AXP809_POWER
> +       ---help---
> +       Say y here to address an axp806 / axp808 in slave mode.
> +       This is used on all currently supported boards with both an axp806
> +       and an axp809. You should probably say n here if your board only has
> +       an axp806 or axp808.
> +
>  config AXP809_POWER
>         bool "axp809 pmic support"
>         depends on MACH_SUN9I
> @@ -53,6 +73,7 @@ config AXP809_POWER
>  config AXP818_POWER
>         bool "axp818 pmic support"
>         depends on MACH_SUN8I_A83T
> +       default MACH_SUN8I_A83T

>         select CMD_POWEROFF
>         ---help---
>         Say y here to enable support for the axp818 pmic found on
> @@ -65,7 +86,9 @@ config SY8106A_POWER
>         Select this to enable support for the SY8106A pmic found on some
>         H3 boards.
>
> -endchoice
> +endif
> +
> +endif
>
>  config AXP_DCDC1_VOLT
>         int "axp pmic dcdc1 voltage"
> @@ -141,6 +164,63 @@ config AXP_DCDC5_VOLT
>         On A23 / A31 / A33 / A80 / A83T boards dcdc5 is VCC-DRAM and
>         should be 1.5V, 1.35V if DDR3L is used.
>
> +config AXP_DCDCA_VOLT
> +       int "axp pmic dcdca voltage"
> +       depends on AXP806_POWER
> +       default 900 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic dcdca at, set to 0 to
> +       disable dcdca.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdca
> +       powers the Cortex-A15 cores (VDD-CPUB) and should be 0.9 V.
> +       On the Sunchip CX-A99 board, dcdca powers the Cortex-A7 cores
> +       (VDD-CPUA) and should be 0.9 V at the default 1008 MHz clock frequency.

Don't mention board names. Instead you could say boards with 2 PMICs with AXP806
in slave mode do A, and boards with only one PMIC do B.

> +
> +config AXP_DCDCB_VOLT
> +       int "axp pmic dcdcb voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +       default 1500 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER

!AXP806_POWER_SLAVE_MODE would be better

> +       ---help---
> +       Set the voltage (mV) to program the axp pmic dcdcb at, set to 0 to
> +       disable dcdcb.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdcb
> +       is unused and can be left off.
> +       On the Sunchip CX-A99 board, dcdcb powers VCC-DRAM and should be 1.5 V.
> +
> +config AXP_DCDCC_VOLT
> +       int "axp pmic dcdcc voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic dcdcc at, set to 0 to
> +       disable dcdcc.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdcb
> +       is unused and can be left off.
> +       On the Sunchip CX-A99 board, dcdcc powers VDD-GPU and can be left off.
> +
> +config AXP_DCDCD_VOLT
> +       int "axp pmic dcdcd voltage"
> +       depends on AXP806_POWER
> +       default 900 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic dcdcd at, set to 0 to
> +       disable dcdcd.
> +       On A80 boards dcdcd powers VDD-SYS or VDD-VPU and should be 0.9 V.
> +
> +config AXP_DCDCE_VOLT
> +       int "axp pmic dcdce voltage"
> +       depends on AXP806_POWER
> +       default 2100 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +       default 3300 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic dcdce at, set to 0 to
> +       disable dcdce.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdce
> +       should be 2.1 V.
> +       On the Sunchip CX-A99, dcdce powers several parts which need 3.3 V,
> +       such as pin groups B-F and H, the eMMC card and the SD card slot.
> +
>  config AXP_ALDO1_VOLT
>         int "axp pmic (a)ldo1 voltage"
>         depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
> @@ -197,6 +277,126 @@ config AXP_ALDO4_VOLT
>         disable aldo4.
>         On A10(s) / A13 / A20 boards aldo4 should be 2.8V.
>
> +config AXP2_ALDO1_VOLT
> +       int "axp pmic (2) aldo1 voltage"
> +       depends on AXP806_POWER
> +       default 3000 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +       default 0 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic aldo1 at, set to 0 to
> +       disable aldo1.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo1
> +       powers AVCC and should be 3.0 V.
> +       On the Sunchip CX-A99, it is unknown what aldo1 powers and it can be
> +       left off.
> +
> +config AXP2_ALDO2_VOLT
> +       int "axp pmic (2) aldo2 voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +       default 1800 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic aldo2 at, set to 0 to
> +       disable aldo2.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo2 is
> +       unused and can be left off.
> +       On the Sunchip CX-A99, aldo2 powers pin groups G and M, Wifi I/O and
> +       codec I/O and should be 1.8 V.

These pins are not used by U-boot are they? Leave them off.

> +
> +config AXP2_ALDO3_VOLT
> +       int "axp pmic (2) aldo3 voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic aldo3 at, set to 0 to
> +       disable aldo3.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo3 is
> +       unused and can be left off.
> +       On the Sunchip CX-A99, aldo3 powers GMAC 2.5 V I/O and can be left off.
> +
> +config AXP_BLDO1_VOLT
> +       int "axp pmic bldo1 voltage"
> +       depends on AXP806_POWER
> +       default 1800 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic bldo1 at, set to 0 to
> +       disable bldo1.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo1
> +       powers efuse, ADC, display and camera interface and should be 1.8 V.
> +       On the Sunchip CX-A99, bldo1 powers A80 DLLs and PLLs and should be
> +       1.8 V.
> +
> +config AXP_BLDO2_VOLT
> +       int "axp pmic bldo2 voltage"
> +       depends on AXP806_POWER
> +       default 1800 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +       default 900 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic bldo2 at, set to 0 to
> +       disable bldo2.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo2
> +       powers PLLs which need 1.8 V.
> +       On the Sunchip CX-A99, bldo2 powers A80 subsystems which need 0.9 V.
> +
> +config AXP_BLDO3_VOLT
> +       int "axp pmic bldo3 voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic bldo3 at, set to 0 to
> +       disable bldo3.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo3 is
> +       unused and can be left off.
> +       On the Sunchip CX-A99, bldo2 powers the unused USB HSIC interface and
> +       can be left off.
> +
> +config AXP_BLDO4_VOLT
> +       int "axp pmic bldo4 voltage"
> +       depends on AXP806_POWER
> +       default 1800 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +       default 0 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic bldo4 at, set to 0 to
> +       disable bldo4.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo4
> +       powers VCC12-HSIC and should be 1.2 V.
> +       On the Sunchip CX-A99, bldo powers VDD09-HDMI and can be left off.
> +
> +config AXP_CLDO1_VOLT
> +       int "axp pmic cldo1 voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +       default 3300 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic cldo at, set to 0 to
> +       disable cldo.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo1
> +       supplies the unsupported GMAC 3.3 V and can be left off.
> +       On the Sunchip CX-A99, cldo1 powers pin group L and the LEDs and
> +       should be 3.3 V.
> +
> +config AXP_CLDO2_VOLT
> +       int "axp pmic cldo2 voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic cldo2 at, set to 0 to
> +       disable cldo2.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo2
> +       powers the camera and can be left off.
> +       On the Sunchip CX-A99, cldo2 powers Wifi+Bluetooth and can be left off.
> +
> +config AXP_CLDO3_VOLT
> +       int "axp pmic cldo3 voltage"
> +       depends on AXP806_POWER
> +       default 0 if MACH_SUN9I
> +       ---help---
> +       Set the voltage (mV) to program the axp pmic cldo3 at, set to 0 to
> +       disable cldo3.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo3
> +       powers Wifi I/O and codec I/O and can be left off.
> +       On the Sunchip CX-A99, cldo3 powers Wifi+Bluetooth and can be left off.
> +
>  config AXP_DLDO1_VOLT
>         int "axp pmic dldo1 voltage"
>         depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
> @@ -295,6 +495,16 @@ config AXP_SW_ON
>         ---help---
>         Enable to turn on axp pmic sw.
>
> +config AXP2_SW_ON
> +       bool "axp pmic (2) sw on"
> +       depends on AXP806_POWER
> +       default n
> +       ---help---
> +       Enable to turn on axp pmic sw.
> +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, sw is unused
> +       and can be left off.
> +       On the Sunchip CX-A99, sw powers GMAC and codec and can be left off.
> +
>  config SY8106A_VOUT1_VOLT
>         int "SY8106A pmic VOUT1 voltage"
>         depends on SY8106A_POWER
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index b43523e..aaf8248 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_AXP806_POWER)     += axp806.o
>  obj-$(CONFIG_AXP809_POWER)     += axp809.o
>  obj-$(CONFIG_AXP818_POWER)     += axp818.o
>  obj-$(CONFIG_EXYNOS_TMU)       += exynos-tmu.o
> diff --git a/drivers/power/axp806.c b/drivers/power/axp806.c
> new file mode 100644
> index 0000000..be6a9a8
> --- /dev/null
> +++ b/drivers/power/axp806.c
> @@ -0,0 +1,231 @@
> +/*
> + * AXP806 and AXP808 driver based on AXP221 and AXP223 driver
> + *
> + * Copyright (C) 2017 Rask Ingemann Lambertsen <rask@formelder.dk>
> + *
> + * Based on axp221.c which is
> + * (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>
> +
> +/*
> + * Return cfg for a regulator with a linear range from `min' to `max' in steps
> + * of `div' and an optional second linear range from `max' to `max2' in steps
> + * of `div2'. Pass `max2' == `max' and `div2' == `div' for a single range.
> + */
> +static u8 axp_mvolt_to_cfg(int mvolt, int min, int max, int div,
> +                          int max2, int div2)
> +{
> +       if (mvolt < min) {
> +               mvolt = min;
> +       } else if (mvolt > max) {
> +               if (mvolt > max2)
> +                       mvolt = max2;
> +               return (mvolt - max) / div2 + (max - min) / div;
> +       }
> +       return (mvolt - min) / div;
> +}
> +
> +int axp_set_dcdca(unsigned int mvolt)
> +{
> +       int ret;
> +       u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1100, 10, 1520, 20);
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +                                        AXP806_OUTPUT_CTRL1_DCDCA_EN);
> +
> +       ret = pmic2_bus_write(AXP806_DCDCA_CTRL, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +                                AXP806_OUTPUT_CTRL1_DCDCA_EN);
> +}
> +
> +int axp_set_dcdcb(unsigned int mvolt)
> +{
> +       int ret;
> +       u8 cfg = axp_mvolt_to_cfg(mvolt, 1000, 2550, 50, 2550, 50);
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +                                        AXP806_OUTPUT_CTRL1_DCDCB_EN);
> +
> +       ret = pmic2_bus_write(AXP806_DCDCB_CTRL, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +                                AXP806_OUTPUT_CTRL1_DCDCB_EN);
> +}
> +
> +int axp_set_dcdcc(unsigned int mvolt)
> +{
> +       int ret;
> +       u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1100, 10, 1520, 20);
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +                                        AXP806_OUTPUT_CTRL1_DCDCC_EN);
> +
> +       ret = pmic2_bus_write(AXP806_DCDCC_CTRL, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +                                AXP806_OUTPUT_CTRL1_DCDCC_EN);
> +}
> +
> +int axp_set_dcdcd(unsigned int mvolt)
> +{
> +       int ret;
> +       u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1500, 20, 3300, 100);
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +                                        AXP806_OUTPUT_CTRL1_DCDCD_EN);
> +
> +       ret = pmic2_bus_write(AXP806_DCDCD_CTRL, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +                                AXP806_OUTPUT_CTRL1_DCDCD_EN);
> +}
> +
> +int axp_set_dcdce(unsigned int mvolt)
> +{
> +       int ret;
> +       u8 cfg = axp_mvolt_to_cfg(mvolt, 1100, 3400, 100, 3400, 100);
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +                                        AXP806_OUTPUT_CTRL1_DCDCE_EN);
> +
> +       ret = pmic2_bus_write(AXP806_DCDCE_CTRL, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +                                AXP806_OUTPUT_CTRL1_DCDCE_EN);
> +}
> +
> +int axp2_set_aldo(int ldo_num, unsigned int mvolt)
> +{
> +       int ret;
> +       unsigned int ldo = ldo_num - 1;
> +       u8 cfg = axp_mvolt_to_cfg(mvolt, 700, 3300, 100, 3300, 100);
> +
> +       if (ldo_num < 1 || ldo_num > 3)
> +               return -EINVAL;
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +                                        AXP806_OUTPUT_CTRL1_ALDO1_EN << ldo);
> +
> +       ret = pmic2_bus_write(AXP806_ALDO1_CTRL + ldo, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +                                AXP806_OUTPUT_CTRL1_ALDO1_EN << ldo);
> +}
> +
> +int axp_set_bldo(int ldo_num, unsigned int mvolt)
> +{
> +       int ret;
> +       unsigned int ldo = ldo_num - 1;
> +       u8 cfg = axp_mvolt_to_cfg(mvolt, 700, 1900, 100, 1900, 100);
> +
> +       if (ldo_num < 1 || ldo_num > 4)
> +               return -EINVAL;
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
> +                                       AXP806_OUTPUT_CTRL2_BLDO1_EN << ldo);
> +
> +       ret = pmic2_bus_write(AXP806_BLDO1_CTRL + ldo, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
> +                               AXP806_OUTPUT_CTRL2_BLDO1_EN << ldo);
> +}
> +
> +int axp_set_cldo(int ldo_num, unsigned int mvolt)
> +{
> +       int ret;
> +       unsigned int ldo = ldo_num - 1;
> +       u8 cfg;
> +
> +       if (ldo_num < 1 || ldo_num > 3)
> +               return -EINVAL;
> +
> +       if (ldo_num == 2)
> +               cfg = axp_mvolt_to_cfg(mvolt, 700, 3400, 100, 4200, 200);
> +       else
> +               cfg = axp_mvolt_to_cfg(mvolt, 700, 3300, 100, 3300, 100);
> +
> +       if (mvolt == 0)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
> +                                       AXP806_OUTPUT_CTRL2_CLDO1_EN << ldo);
> +
> +       ret = pmic2_bus_write(AXP806_CLDO1_CTRL + ldo, cfg);
> +       if (ret)
> +               return ret;
> +
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
> +                               AXP806_OUTPUT_CTRL2_CLDO1_EN << ldo);
> +}
> +
> +int axp2_set_sw(bool on)
> +{
> +       if (!on)
> +               return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
> +                                       AXP806_OUTPUT_CTRL2_SW_EN);
> +       return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
> +                               AXP806_OUTPUT_CTRL2_SW_EN);
> +}
> +
> +int axp2_init(void)
> +{
> +       u8 axp_chip_id;
> +       int ret;
> +
> +       ret = pmic_bus_init();
> +       if (ret)
> +               return ret;
> +
> +       ret = pmic2_bus_read(AXP806_CHIP_ID, &axp_chip_id);
> +       if (ret)
> +               return ret;
> +
> +       if ((axp_chip_id & 0xcf) != 0x40)
> +               return -ENODEV;
> +
> +       return 0;
> +}
> +
> +/* The AXP809 driver also implements do_poweroff() and we can't have both. */
> +#ifndef CONFIG_AXP809_POWER

Use CONFIG_AXP806_POWER_SLAVE_MODE. System power would be controlled by the
master PMIC.

Regards
ChenYu

> +int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       pmic2_bus_setbits(AXP806_SHUTDOWN_CTRL, AXP806_SHUTDOWN_POWEROFF);
> +
> +       /* infinite loop during shutdown */
> +       while (1)
> +               ;
> +
> +       /* not reached */
> +       return 0;
> +}
> +#endif
> diff --git a/include/axp806.h b/include/axp806.h
> new file mode 100644
> index 0000000..d7f7f2b
> --- /dev/null
> +++ b/include/axp806.h
> @@ -0,0 +1,50 @@
> +/*
> + * X-Powers AXP806 and AXP808 Power Management IC driver
> + *
> + * Copyright (C) 2017 Rask Ingemann Lambertsen <rask@formelder.dk>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <linux/bitops.h>
> +
> +#define AXP806_CHIP_ID         0x03
> +#define AXP806_OUTPUT_CTRL1    0x10
> +#define AXP806_OUTPUT_CTRL2    0x11
> +#define AXP806_DCDCA_CTRL      0x12
> +#define AXP806_DCDCB_CTRL      0x13
> +#define AXP806_DCDCC_CTRL      0x14
> +#define AXP806_DCDCD_CTRL      0x15
> +#define AXP806_DCDCE_CTRL      0x16
> +#define AXP806_ALDO1_CTRL      0x17
> +#define AXP806_ALDO2_CTRL      0x18
> +#define AXP806_ALDO3_CTRL      0x19
> +/* Unused registers here. */
> +#define AXP806_BLDO1_CTRL      0x20
> +#define AXP806_BLDO2_CTRL      0x21
> +#define AXP806_BLDO3_CTRL      0x22
> +#define AXP806_BLDO4_CTRL      0x23
> +#define AXP806_CLDO1_CTRL      0x24
> +#define AXP806_CLDO2_CTRL      0x25
> +#define AXP806_CLDO3_CTRL      0x26
> +#define AXP806_SHUTDOWN_CTRL   0x32
> +
> +#define AXP806_OUTPUT_CTRL1_DCDCA_EN   BIT(0)
> +#define AXP806_OUTPUT_CTRL1_DCDCB_EN   BIT(1)
> +#define AXP806_OUTPUT_CTRL1_DCDCC_EN   BIT(2)
> +#define AXP806_OUTPUT_CTRL1_DCDCD_EN   BIT(3)
> +#define AXP806_OUTPUT_CTRL1_DCDCE_EN   BIT(4)
> +#define AXP806_OUTPUT_CTRL1_ALDO1_EN   BIT(5)
> +#define AXP806_OUTPUT_CTRL1_ALDO2_EN   BIT(6)
> +#define AXP806_OUTPUT_CTRL1_ALDO3_EN   BIT(7)
> +
> +#define AXP806_OUTPUT_CTRL2_BLDO1_EN   BIT(0)
> +#define AXP806_OUTPUT_CTRL2_BLDO2_EN   BIT(1)
> +#define AXP806_OUTPUT_CTRL2_BLDO3_EN   BIT(2)
> +#define AXP806_OUTPUT_CTRL2_BLDO4_EN   BIT(3)
> +#define AXP806_OUTPUT_CTRL2_CLDO1_EN   BIT(4)
> +#define AXP806_OUTPUT_CTRL2_CLDO2_EN   BIT(5)
> +#define AXP806_OUTPUT_CTRL2_CLDO3_EN   BIT(6)
> +#define AXP806_OUTPUT_CTRL2_SW_EN      BIT(7)
> +
> +#define AXP806_SHUTDOWN_POWEROFF       BIT(7)
> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
> index d789ad8..7d5dad7 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_AXP806_POWER
> +#include <axp806.h>
> +#endif
>  #ifdef CONFIG_AXP809_POWER
>  #include <axp809.h>
>  #endif
> @@ -28,15 +31,25 @@ 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_dcdca(unsigned int mvolt);
> +int axp_set_dcdcb(unsigned int mvolt);
> +int axp_set_dcdcc(unsigned int mvolt);
> +int axp_set_dcdcd(unsigned int mvolt);
> +int axp_set_dcdce(unsigned int mvolt);
>  int axp_set_aldo1(unsigned int mvolt);
>  int axp_set_aldo2(unsigned int mvolt);
>  int axp_set_aldo3(unsigned int mvolt);
>  int axp_set_aldo4(unsigned int mvolt);
> +int axp2_set_aldo(int aldo_num, unsigned int mvolt);
> +int axp_set_bldo(int bldo_num, unsigned int mvolt);
> +int axp_set_cldo(int cldo_num, unsigned int mvolt);
>  int axp_set_dldo(int dldo_num, unsigned int mvolt);
>  int axp_set_eldo(int eldo_num, unsigned int mvolt);
>  int axp_set_fldo(int fldo_num, unsigned int mvolt);
>  int axp_set_sw(bool on);
> +int axp2_set_sw(bool on);
>  int axp_init(void);
> +int axp2_init(void);
>  int axp_get_sid(unsigned int *sid);
>
>  #endif
> --
> 2.10.2
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/2 RFT] sunxi: power: Add AXP806 and AXP808 support
  2017-02-26 19:01 ` [U-Boot] [PATCH 1/2 RFT] " Rask Ingemann Lambertsen
  2017-02-27  3:26   ` Chen-Yu Tsai
@ 2017-02-28  4:47   ` Jaehoon Chung
       [not found]   ` <CGME20170421075849epcas1p16a1d961b1717ae9298be1aac91bab593@epcas1p1.samsung.com>
  2 siblings, 0 replies; 8+ messages in thread
From: Jaehoon Chung @ 2017-02-28  4:47 UTC (permalink / raw)
  To: u-boot

On 02/27/2017 04:01 AM, Rask Ingemann Lambertsen wrote:
> An X-Powers AXP806 or AXP808 PMIC is usually found on boards using the
> Allwinner A80 ARM SoC. This patch adds support for the PMIC's regulators
> and sets up the runtime address and master/slave mode in pmic_bus_init().
> 
> AXP806/AXP808 support is enabled by default on all MACH_SUN9I boards.
> 
> Because there are boards with both an AXP806 and an AXP809,
> drivers/power/Kconfig and arch/arm/mach-sunxi/pmic_bus.c are changed to
> make it possible to have more than one PMIC enabled at a time.
> 
> Signed-off-by: Rask Ingemann Lambertsen <rask@formelder.dk>
> ---
> This patch needs to be tested on the following boards which I don't have:
> Cubietech Cubieboard4
> Merrii A80 Optimus
> 

As ChenYu, This patch need to separate to some more patches.

Best Regards,
Jaehoon Chung

> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/2 RFT] sunxi: power: Add AXP806 and AXP808 support
  2017-02-27  3:26   ` Chen-Yu Tsai
@ 2017-03-01 21:29     ` Rask Ingemann Lambertsen
  0 siblings, 0 replies; 8+ messages in thread
From: Rask Ingemann Lambertsen @ 2017-03-01 21:29 UTC (permalink / raw)
  To: u-boot

On Mon, Feb 27, 2017 at 11:26:33AM +0800, Chen-Yu Tsai wrote:
> On Mon, Feb 27, 2017 at 3:01 AM, Rask Ingemann Lambertsen
> <rask@formelder.dk> wrote:
> > An X-Powers AXP806 or AXP808 PMIC is usually found on boards using the
> > Allwinner A80 ARM SoC. This patch adds support for the PMIC's regulators
> > and sets up the runtime address and master/slave mode in pmic_bus_init().
> >
> > AXP806/AXP808 support is enabled by default on all MACH_SUN9I boards.
> >
> > Because there are boards with both an AXP806 and an AXP809,
> > drivers/power/Kconfig and arch/arm/mach-sunxi/pmic_bus.c are changed to
> > make it possible to have more than one PMIC enabled at a time.
> >
> > Signed-off-by: Rask Ingemann Lambertsen <rask@formelder.dk>
> > ---
> > This patch needs to be tested on the following boards which I don't have:
> > Cubietech Cubieboard4
> > Merrii A80 Optimus
[...]
> > diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
> > index 7c57f02..a2da40c 100644
> > --- a/arch/arm/mach-sunxi/pmic_bus.c
> > +++ b/arch/arm/mach-sunxi/pmic_bus.c
[...]
> > +#ifdef CONFIG_AXP806_POWER
> > +int pmic2_bus_read(u8 reg, u8 *data)
> >  {
> > -       int ret;
> > -       u8 val;
> > -
> > -       ret = pmic_bus_read(reg, &val);
> > -       if (ret)
> > -               return ret;
> > -
> > -       val &= ~bits;
> > -       return pmic_bus_write(reg, val);
> > +       return rsb_read(AXP806_RUNTIME_ADDR, reg, data);
> >  }
> > +
> > +int pmic2_bus_write(u8 reg, u8 data)
> > +{
> > +       return rsb_write(AXP806_RUNTIME_ADDR, reg, data);
> > +}
> > +
> > +int pmic2_bus_setbits(u8 reg, u8 bits)
> > +PMIC_BUS_SETBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
> > +
> > +int pmic2_bus_clrbits(u8 reg, u8 bits)
> > +PMIC_BUS_CLRBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
> > +#endif
> 
> Please split the pmic_bus changes into separate patches, such as the following:
> 
>   - Pull out PMIC_BUS_*. However please don't use macros. Just make some
>     static functions. The compiler can choose to inline them.
> 
>   - Add AXP806 support in master mode
> 
>   - Add support for second PMIC to pmic_bus
> 
>   - Add AXP806 slave mode support.

OK. I'll take care to not leave a broken state between individual patches.

> > diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> > index 5365638..7847837 100644
> > --- a/board/sunxi/board.c
> > +++ b/board/sunxi/board.c
> > @@ -540,6 +540,26 @@ void sunxi_board_init(void)
> >         power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
> >  #endif
> >  #endif
> > +#ifdef CONFIG_AXP806_POWER
> > +       power_failed |= axp2_init();
> > +
> > +       power_failed |= axp_set_dcdca(CONFIG_AXP_DCDCA_VOLT);
> > +       power_failed |= axp_set_dcdcb(CONFIG_AXP_DCDCB_VOLT);
> > +       power_failed |= axp_set_dcdcc(CONFIG_AXP_DCDCC_VOLT);
> > +       power_failed |= axp_set_dcdcd(CONFIG_AXP_DCDCD_VOLT);
> > +       power_failed |= axp_set_dcdce(CONFIG_AXP_DCDCE_VOLT);
> > +       power_failed |= axp2_set_aldo(1, CONFIG_AXP2_ALDO1_VOLT);
> > +       power_failed |= axp2_set_aldo(2, CONFIG_AXP2_ALDO2_VOLT);
> > +       power_failed |= axp2_set_aldo(3, CONFIG_AXP2_ALDO3_VOLT);
> 
> Allwinner code calls them s_aldo.

OK.

> > +       power_failed |= axp2_set_sw(IS_ENABLED(CONFIG_AXP2_SW_ON));
> 
> And this s_sw.

OK.

> > diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> > index f2c5629..aa32e5a 100644
> > --- a/drivers/power/Kconfig
> > +++ b/drivers/power/Kconfig
> > @@ -6,19 +6,18 @@ source "drivers/power/pmic/Kconfig"
> >
> >  source "drivers/power/regulator/Kconfig"
> >
> > -choice
> > -       prompt "Select Sunxi PMIC Variant"
> > -       depends on ARCH_SUNXI
> > -       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 SUNXI_NO_PMIC if MACH_SUN8I_H3 || MACH_SUN50I
> > +if ARCH_SUNXI
> > +
> > +comment "Select Sunxi PMIC Variant"
> 
> Would this change break existing defconfigs?

It was fine with the six or so that I checked, but that's just 0.5 % of the
defconfigs. It might actually be feasible to check them all, so I'll try
that.

> > @@ -141,6 +164,63 @@ config AXP_DCDC5_VOLT
> >         On A23 / A31 / A33 / A80 / A83T boards dcdc5 is VCC-DRAM and
> >         should be 1.5V, 1.35V if DDR3L is used.
> >
> > +config AXP_DCDCA_VOLT
> > +       int "axp pmic dcdca voltage"
> > +       depends on AXP806_POWER
> > +       default 900 if MACH_SUN9I
> > +       ---help---
> > +       Set the voltage (mV) to program the axp pmic dcdca at, set to 0 to
> > +       disable dcdca.
> > +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdca
> > +       powers the Cortex-A15 cores (VDD-CPUB) and should be 0.9 V.
> > +       On the Sunchip CX-A99 board, dcdca powers the Cortex-A7 cores
> > +       (VDD-CPUA) and should be 0.9 V at the default 1008 MHz clock frequency.
> 
> Don't mention board names. Instead you could say boards with 2 PMICs with AXP806
> in slave mode do A, and boards with only one PMIC do B.

OK.

> > +
> > +config AXP_DCDCB_VOLT
> > +       int "axp pmic dcdcb voltage"
> > +       depends on AXP806_POWER
> > +       default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> > +       default 1500 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> 
> !AXP806_POWER_SLAVE_MODE would be better

OK.

> > +config AXP2_ALDO2_VOLT
> > +       int "axp pmic (2) aldo2 voltage"
> > +       depends on AXP806_POWER
> > +       default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> > +       default 1800 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> > +       ---help---
> > +       Set the voltage (mV) to program the axp pmic aldo2 at, set to 0 to
> > +       disable aldo2.
> > +       On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo2 is
> > +       unused and can be left off.
> > +       On the Sunchip CX-A99, aldo2 powers pin groups G and M, Wifi I/O and
> > +       codec I/O and should be 1.8 V.
> 
> These pins are not used by U-boot are they? Leave them off.

Pin group M controls the LEDs and to my surprice, CONFIG_CMD_LED can't
simply be enabled in the config menu (and thus not in defconfig either)
because it hasn't been converted to Kconfig yet. I'll leave also2 off.

It would be nice to get some sort of feedback without the serial console,
for high on my TODO list is to get USB ports working, so you can attach a
keyboard. An LED could then light up to tell you when extlinux.conf has
been loaded and is ready to accept a selection from the menu, for example.

> > diff --git a/drivers/power/axp806.c b/drivers/power/axp806.c
> > new file mode 100644
> > index 0000000..be6a9a8
> > --- /dev/null
> > +++ b/drivers/power/axp806.c
[...]
> > +/* The AXP809 driver also implements do_poweroff() and we can't have both. */
> > +#ifndef CONFIG_AXP809_POWER
> 
> Use CONFIG_AXP806_POWER_SLAVE_MODE. System power would be controlled by the
> master PMIC.

OK.

-- 
Rask Ingemann Lambertsen

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [U-Boot, 1/2, RFT] sunxi: power: Add AXP806 and AXP808 support
       [not found]   ` <CGME20170421075849epcas1p16a1d961b1717ae9298be1aac91bab593@epcas1p1.samsung.com>
@ 2017-04-21  7:58     ` Jaehoon Chung
  0 siblings, 0 replies; 8+ messages in thread
From: Jaehoon Chung @ 2017-04-21  7:58 UTC (permalink / raw)
  To: u-boot

Hi Rask,

On 02/27/2017 04:01 AM, Rask Ingemann Lambertsen wrote:
> An X-Powers AXP806 or AXP808 PMIC is usually found on boards using the
> Allwinner A80 ARM SoC. This patch adds support for the PMIC's regulators
> and sets up the runtime address and master/slave mode in pmic_bus_init().
> 
> AXP806/AXP808 support is enabled by default on all MACH_SUN9I boards.
> 
> Because there are boards with both an AXP806 and an AXP809,
> drivers/power/Kconfig and arch/arm/mach-sunxi/pmic_bus.c are changed to
> make it possible to have more than one PMIC enabled at a time.
> 
> Signed-off-by: Rask Ingemann Lambertsen <rask@formelder.dk>
> ---
> This patch needs to be tested on the following boards which I don't have:
> Cubietech Cubieboard4
> Merrii A80 Optimus

This patch needs to test from someone with following boards.
how about sending the patches after split to some patches.
(It's more helpful to me for reviewing.)

Best Regards,
Jaehoon Chung

> 
>  arch/arm/include/asm/arch-sunxi/pmic_bus.h |   4 +
>  arch/arm/mach-sunxi/Makefile               |   1 +
>  arch/arm/mach-sunxi/pmic_bus.c             | 107 ++++++++++---
>  board/sunxi/board.c                        |  20 +++
>  drivers/power/Kconfig                      | 226 +++++++++++++++++++++++++++-
>  drivers/power/Makefile                     |   1 +
>  drivers/power/axp806.c                     | 231 +++++++++++++++++++++++++++++
>  include/axp806.h                           |  50 +++++++
>  include/axp_pmic.h                         |  13 ++
>  9 files changed, 623 insertions(+), 30 deletions(-)
>  create mode 100644 drivers/power/axp806.c
>  create mode 100644 include/axp806.h
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/pmic_bus.h b/arch/arm/include/asm/arch-sunxi/pmic_bus.h
> index 9c4372a..d143d54 100644
> --- a/arch/arm/include/asm/arch-sunxi/pmic_bus.h
> +++ b/arch/arm/include/asm/arch-sunxi/pmic_bus.h
> @@ -14,5 +14,9 @@ int pmic_bus_read(u8 reg, u8 *data);
>  int pmic_bus_write(u8 reg, u8 data);
>  int pmic_bus_setbits(u8 reg, u8 bits);
>  int pmic_bus_clrbits(u8 reg, u8 bits);
> +int pmic2_bus_read(u8 reg, u8 *data);
> +int pmic2_bus_write(u8 reg, u8 data);
> +int pmic2_bus_setbits(u8 reg, u8 bits);
> +int pmic2_bus_clrbits(u8 reg, u8 bits);
>  
>  #endif
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index 7daba11..410fb49 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
>  obj-$(CONFIG_AXP152_POWER)	+= pmic_bus.o
>  obj-$(CONFIG_AXP209_POWER)	+= pmic_bus.o
>  obj-$(CONFIG_AXP221_POWER)	+= pmic_bus.o
> +obj-$(CONFIG_AXP806_POWER)	+= pmic_bus.o
>  obj-$(CONFIG_AXP809_POWER)	+= pmic_bus.o
>  obj-$(CONFIG_AXP818_POWER)	+= pmic_bus.o
>  
> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
> index 7c57f02..a2da40c 100644
> --- a/arch/arm/mach-sunxi/pmic_bus.c
> +++ b/arch/arm/mach-sunxi/pmic_bus.c
> @@ -27,6 +27,15 @@
>  #define AXP223_DEVICE_ADDR		0x3a3
>  #define AXP223_RUNTIME_ADDR		0x2d
>  
> +/* AXP806 and AXP808 use the same addresses. */
> +#define AXP806_DEVICE_ADDR		0x745
> +#define AXP806_RUNTIME_ADDR		0x3a
> +
> +/* AXP806 and AXP808 address space extension. */
> +#define AXP806_REG_ADDR_EXT			0xff
> +#define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE	0
> +#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE	BIT(4)
> +
>  int pmic_bus_init(void)
>  {
>  	/* This cannot be 0 because it is used in SPL before BSS is ready */
> @@ -36,7 +45,8 @@ int pmic_bus_init(void)
>  	if (!needs_init)
>  		return 0;
>  
> -#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
> +#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP806_POWER || \
> +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  # ifdef CONFIG_MACH_SUN6I
>  	p2wi_init();
>  	ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
> @@ -46,16 +56,70 @@ int pmic_bus_init(void)
>  	if (ret)
>  		return ret;
>  
> +#  if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> +	defined CONFIG_AXP818_POWER
>  	ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
> -# endif
>  	if (ret)
>  		return ret;
> +#  endif
> +#  ifdef CONFIG_AXP806_POWER
> +	ret = rsb_set_device_address(AXP806_DEVICE_ADDR, AXP806_RUNTIME_ADDR);
> +	if (ret)
> +		return ret;
> +#  endif
> +# endif
> +
> +# ifdef CONFIG_AXP806_POWER
> +	/*
> +	 * An AXP806 or AXP808 can be wired for either master mode or slave
> +	 * mode. The AXP806_REG_ADDR_EXT register must be set accordingly for
> +	 * the chip to repond to access to its other registers.
> +	 */
> +#  ifdef CONFIG_AXP806_POWER_SLAVE_MODE
> +	ret = pmic2_bus_write(AXP806_REG_ADDR_EXT,
> +			      AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
> +#  else
> +	ret = pmic2_bus_write(AXP806_REG_ADDR_EXT,
> +			      AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
> +#  endif
> +	if (ret)
> +		return ret;
> +# endif
>  #endif
>  
>  	needs_init = 0;
>  	return 0;
>  }
>  
> +#define PMIC_BUS_SETBITS(pmic_bus_read, pmic_bus_write, reg, bits) \
> +{						\
> +	int ret;				\
> +	u8 val;					\
> +						\
> +	ret = pmic_bus_read(reg, &val);		\
> +	if (ret)				\
> +		return ret;			\
> +						\
> +	val |= bits;				\
> +	return pmic_bus_write(reg, val);	\
> +}
> +
> +#define PMIC_BUS_CLRBITS(pmic_bus_read, pmic_bus_write, reg, bits) \
> +{						\
> +	int ret;				\
> +	u8 val;					\
> +						\
> +	ret = pmic_bus_read(reg, &val);		\
> +	if (ret)				\
> +		return ret;			\
> +						\
> +	val &= ~bits;				\
> +	return pmic_bus_write(reg, val);	\
> +}
> +
> +#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
> +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> +	defined CONFIG_AXP818_POWER
>  int pmic_bus_read(u8 reg, u8 *data)
>  {
>  #ifdef CONFIG_AXP152_POWER
> @@ -87,27 +151,26 @@ int pmic_bus_write(u8 reg, u8 data)
>  }
>  
>  int pmic_bus_setbits(u8 reg, u8 bits)
> -{
> -	int ret;
> -	u8 val;
> -
> -	ret = pmic_bus_read(reg, &val);
> -	if (ret)
> -		return ret;
> -
> -	val |= bits;
> -	return pmic_bus_write(reg, val);
> -}
> +PMIC_BUS_SETBITS(pmic_bus_read, pmic_bus_write, reg, bits)
>  
>  int pmic_bus_clrbits(u8 reg, u8 bits)
> +PMIC_BUS_CLRBITS(pmic_bus_read, pmic_bus_write, reg, bits)
> +#endif
> +
> +#ifdef CONFIG_AXP806_POWER
> +int pmic2_bus_read(u8 reg, u8 *data)
>  {
> -	int ret;
> -	u8 val;
> -
> -	ret = pmic_bus_read(reg, &val);
> -	if (ret)
> -		return ret;
> -
> -	val &= ~bits;
> -	return pmic_bus_write(reg, val);
> +	return rsb_read(AXP806_RUNTIME_ADDR, reg, data);
>  }
> +
> +int pmic2_bus_write(u8 reg, u8 data)
> +{
> +	return rsb_write(AXP806_RUNTIME_ADDR, reg, data);
> +}
> +
> +int pmic2_bus_setbits(u8 reg, u8 bits)
> +PMIC_BUS_SETBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
> +
> +int pmic2_bus_clrbits(u8 reg, u8 bits)
> +PMIC_BUS_CLRBITS(pmic2_bus_read, pmic2_bus_write, reg, bits)
> +#endif
> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index 5365638..7847837 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -540,6 +540,26 @@ void sunxi_board_init(void)
>  	power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
>  #endif
>  #endif
> +#ifdef CONFIG_AXP806_POWER
> +	power_failed |= axp2_init();
> +
> +	power_failed |= axp_set_dcdca(CONFIG_AXP_DCDCA_VOLT);
> +	power_failed |= axp_set_dcdcb(CONFIG_AXP_DCDCB_VOLT);
> +	power_failed |= axp_set_dcdcc(CONFIG_AXP_DCDCC_VOLT);
> +	power_failed |= axp_set_dcdcd(CONFIG_AXP_DCDCD_VOLT);
> +	power_failed |= axp_set_dcdce(CONFIG_AXP_DCDCE_VOLT);
> +	power_failed |= axp2_set_aldo(1, CONFIG_AXP2_ALDO1_VOLT);
> +	power_failed |= axp2_set_aldo(2, CONFIG_AXP2_ALDO2_VOLT);
> +	power_failed |= axp2_set_aldo(3, CONFIG_AXP2_ALDO3_VOLT);
> +	power_failed |= axp_set_bldo(1, CONFIG_AXP_BLDO1_VOLT);
> +	power_failed |= axp_set_bldo(2, CONFIG_AXP_BLDO2_VOLT);
> +	power_failed |= axp_set_bldo(3, CONFIG_AXP_BLDO3_VOLT);
> +	power_failed |= axp_set_bldo(4, CONFIG_AXP_BLDO4_VOLT);
> +	power_failed |= axp_set_cldo(1, CONFIG_AXP_CLDO1_VOLT);
> +	power_failed |= axp_set_cldo(2, CONFIG_AXP_CLDO2_VOLT);
> +	power_failed |= axp_set_cldo(3, CONFIG_AXP_CLDO3_VOLT);
> +	power_failed |= axp2_set_sw(IS_ENABLED(CONFIG_AXP2_SW_ON));
> +#endif
>  	printf("DRAM:");
>  	ramsize = sunxi_dram_init();
>  	printf(" %d MiB\n", (int)(ramsize >> 20));
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index f2c5629..aa32e5a 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -6,19 +6,18 @@ source "drivers/power/pmic/Kconfig"
>  
>  source "drivers/power/regulator/Kconfig"
>  
> -choice
> -	prompt "Select Sunxi PMIC Variant"
> -	depends on ARCH_SUNXI
> -	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 SUNXI_NO_PMIC if MACH_SUN8I_H3 || MACH_SUN50I
> +if ARCH_SUNXI
> +
> +comment "Select Sunxi PMIC Variant"
>  
>  config SUNXI_NO_PMIC
>  	bool "board without a pmic"
> +	default MACH_SUN8I_H3 || MACH_SUN50I
>  	---help---
>  	Select this for boards which do not use a PMIC.
>  
> +if !SUNXI_NO_PMIC
> +
>  config AXP152_POWER
>  	bool "axp152 pmic support"
>  	depends on MACH_SUN5I
> @@ -30,6 +29,7 @@ config AXP152_POWER
>  config AXP209_POWER
>  	bool "axp209 pmic support"
>  	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
> +	default MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
>  	select CMD_POWEROFF
>  	---help---
>  	Select this to enable support for the axp209 pmic found on most
> @@ -38,11 +38,31 @@ config AXP209_POWER
>  config AXP221_POWER
>  	bool "axp221 / axp223 pmic support"
>  	depends on MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
> +	default MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
>  	select CMD_POWEROFF
>  	---help---
>  	Select this to enable support for the axp221/axp223 pmic found on most
>  	A23 and A31 boards.
>  
> +config AXP806_POWER
> +	bool "axp806 / axp808 pmic support"
> +	depends on MACH_SUN9I
> +	default MACH_SUN9I
> +	select CMD_POWEROFF
> +	---help---
> +	Say y here to enable support for the axp806 or axp808 pmic found
> +	on A80 boards.
> +
> +config AXP806_POWER_SLAVE_MODE
> +	bool "axp806 / axp808 pmic slave mode"
> +	depends on AXP806_POWER
> +	default AXP806_POWER && AXP809_POWER
> +	---help---
> +	Say y here to address an axp806 / axp808 in slave mode.
> +	This is used on all currently supported boards with both an axp806
> +	and an axp809. You should probably say n here if your board only has
> +	an axp806 or axp808.
> +
>  config AXP809_POWER
>  	bool "axp809 pmic support"
>  	depends on MACH_SUN9I
> @@ -53,6 +73,7 @@ config AXP809_POWER
>  config AXP818_POWER
>  	bool "axp818 pmic support"
>  	depends on MACH_SUN8I_A83T
> +	default MACH_SUN8I_A83T
>  	select CMD_POWEROFF
>  	---help---
>  	Say y here to enable support for the axp818 pmic found on
> @@ -65,7 +86,9 @@ config SY8106A_POWER
>  	Select this to enable support for the SY8106A pmic found on some
>  	H3 boards.
>  
> -endchoice
> +endif
> +
> +endif
>  
>  config AXP_DCDC1_VOLT
>  	int "axp pmic dcdc1 voltage"
> @@ -141,6 +164,63 @@ config AXP_DCDC5_VOLT
>  	On A23 / A31 / A33 / A80 / A83T boards dcdc5 is VCC-DRAM and
>  	should be 1.5V, 1.35V if DDR3L is used.
>  
> +config AXP_DCDCA_VOLT
> +	int "axp pmic dcdca voltage"
> +	depends on AXP806_POWER
> +	default 900 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic dcdca at, set to 0 to
> +	disable dcdca.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdca
> +	powers the Cortex-A15 cores (VDD-CPUB) and should be 0.9 V.
> +	On the Sunchip CX-A99 board, dcdca powers the Cortex-A7 cores
> +	(VDD-CPUA) and should be 0.9 V at the default 1008 MHz clock frequency.
> +
> +config AXP_DCDCB_VOLT
> +	int "axp pmic dcdcb voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +	default 1500 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +	---help---
> +	Set the voltage (mV) to program the axp pmic dcdcb at, set to 0 to
> +	disable dcdcb.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdcb
> +	is unused and can be left off.
> +	On the Sunchip CX-A99 board, dcdcb powers VCC-DRAM and should be 1.5 V.
> +
> +config AXP_DCDCC_VOLT
> +	int "axp pmic dcdcc voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic dcdcc at, set to 0 to
> +	disable dcdcc.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdcb
> +	is unused and can be left off.
> +	On the Sunchip CX-A99 board, dcdcc powers VDD-GPU and can be left off.
> +
> +config AXP_DCDCD_VOLT
> +	int "axp pmic dcdcd voltage"
> +	depends on AXP806_POWER
> +	default 900 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic dcdcd at, set to 0 to
> +	disable dcdcd.
> +	On A80 boards dcdcd powers VDD-SYS or VDD-VPU and should be 0.9 V.
> +
> +config AXP_DCDCE_VOLT
> +	int "axp pmic dcdce voltage"
> +	depends on AXP806_POWER
> +	default 2100 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +	default 3300 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +	---help---
> +	Set the voltage (mV) to program the axp pmic dcdce at, set to 0 to
> +	disable dcdce.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, dcdce
> +	should be 2.1 V.
> +	On the Sunchip CX-A99, dcdce powers several parts which need 3.3 V,
> +	such as pin groups B-F and H, the eMMC card and the SD card slot.
> +
>  config AXP_ALDO1_VOLT
>  	int "axp pmic (a)ldo1 voltage"
>  	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
> @@ -197,6 +277,126 @@ config AXP_ALDO4_VOLT
>  	disable aldo4.
>  	On A10(s) / A13 / A20 boards aldo4 should be 2.8V.
>  
> +config AXP2_ALDO1_VOLT
> +	int "axp pmic (2) aldo1 voltage"
> +	depends on AXP806_POWER
> +	default 3000 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +	default 0 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +	---help---
> +	Set the voltage (mV) to program the axp pmic aldo1 at, set to 0 to
> +	disable aldo1.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo1
> +	powers AVCC and should be 3.0 V.
> +	On the Sunchip CX-A99, it is unknown what aldo1 powers and it can be
> +	left off.
> +
> +config AXP2_ALDO2_VOLT
> +	int "axp pmic (2) aldo2 voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +	default 1800 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +	---help---
> +	Set the voltage (mV) to program the axp pmic aldo2 at, set to 0 to
> +	disable aldo2.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo2 is
> +	unused and can be left off.
> +	On the Sunchip CX-A99, aldo2 powers pin groups G and M, Wifi I/O and
> +	codec I/O and should be 1.8 V.
> +
> +config AXP2_ALDO3_VOLT
> +	int "axp pmic (2) aldo3 voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic aldo3 at, set to 0 to
> +	disable aldo3.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, aldo3 is
> +	unused and can be left off.
> +	On the Sunchip CX-A99, aldo3 powers GMAC 2.5 V I/O and can be left off.
> +
> +config AXP_BLDO1_VOLT
> +	int "axp pmic bldo1 voltage"
> +	depends on AXP806_POWER
> +	default 1800 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic bldo1 at, set to 0 to
> +	disable bldo1.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo1
> +	powers efuse, ADC, display and camera interface and should be 1.8 V.
> +	On the Sunchip CX-A99, bldo1 powers A80 DLLs and PLLs and should be
> +	1.8 V.
> +
> +config AXP_BLDO2_VOLT
> +	int "axp pmic bldo2 voltage"
> +	depends on AXP806_POWER
> +	default 1800 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +	default 900 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +	---help---
> +	Set the voltage (mV) to program the axp pmic bldo2 at, set to 0 to
> +	disable bldo2.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo2
> +	powers PLLs which need 1.8 V.
> +	On the Sunchip CX-A99, bldo2 powers A80 subsystems which need 0.9 V.
> +
> +config AXP_BLDO3_VOLT
> +	int "axp pmic bldo3 voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic bldo3 at, set to 0 to
> +	disable bldo3.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo3 is
> +	unused and can be left off.
> +	On the Sunchip CX-A99, bldo2 powers the unused USB HSIC interface and
> +	can be left off.
> +
> +config AXP_BLDO4_VOLT
> +	int "axp pmic bldo4 voltage"
> +	depends on AXP806_POWER
> +	default 1800 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +	default 0 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +	---help---
> +	Set the voltage (mV) to program the axp pmic bldo4 at, set to 0 to
> +	disable bldo4.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, bldo4
> +	powers VCC12-HSIC and should be 1.2 V.
> +	On the Sunchip CX-A99, bldo powers VDD09-HDMI and can be left off.
> +
> +config AXP_CLDO1_VOLT
> +	int "axp pmic cldo1 voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I && AXP806_POWER && AXP809_POWER
> +	default 3300 if MACH_SUN9I && AXP806_POWER && !AXP809_POWER
> +	---help---
> +	Set the voltage (mV) to program the axp pmic cldo at, set to 0 to
> +	disable cldo.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo1
> +	supplies the unsupported GMAC 3.3 V and can be left off.
> +	On the Sunchip CX-A99, cldo1 powers pin group L and the LEDs and
> +	should be 3.3 V.
> +
> +config AXP_CLDO2_VOLT
> +	int "axp pmic cldo2 voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic cldo2 at, set to 0 to
> +	disable cldo2.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo2
> +	powers the camera and can be left off.
> +	On the Sunchip CX-A99, cldo2 powers Wifi+Bluetooth and can be left off.
> +
> +config AXP_CLDO3_VOLT
> +	int "axp pmic cldo3 voltage"
> +	depends on AXP806_POWER
> +	default 0 if MACH_SUN9I
> +	---help---
> +	Set the voltage (mV) to program the axp pmic cldo3 at, set to 0 to
> +	disable cldo3.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, cldo3
> +	powers Wifi I/O and codec I/O and can be left off.
> +	On the Sunchip CX-A99, cldo3 powers Wifi+Bluetooth and can be left off.
> +
>  config AXP_DLDO1_VOLT
>  	int "axp pmic dldo1 voltage"
>  	depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
> @@ -295,6 +495,16 @@ config AXP_SW_ON
>  	---help---
>  	Enable to turn on axp pmic sw.
>  
> +config AXP2_SW_ON
> +	bool "axp pmic (2) sw on"
> +	depends on AXP806_POWER
> +	default n
> +	---help---
> +	Enable to turn on axp pmic sw.
> +	On the Cubietech Cubieboard4 and Merrii A80 Optimus boards, sw is unused
> +	and can be left off.
> +	On the Sunchip CX-A99, sw powers GMAC and codec and can be left off.
> +
>  config SY8106A_VOUT1_VOLT
>  	int "SY8106A pmic VOUT1 voltage"
>  	depends on SY8106A_POWER
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index b43523e..aaf8248 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_AXP806_POWER)	+= axp806.o
>  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
>  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
>  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
> diff --git a/drivers/power/axp806.c b/drivers/power/axp806.c
> new file mode 100644
> index 0000000..be6a9a8
> --- /dev/null
> +++ b/drivers/power/axp806.c
> @@ -0,0 +1,231 @@
> +/*
> + * AXP806 and AXP808 driver based on AXP221 and AXP223 driver
> + *
> + * Copyright (C) 2017 Rask Ingemann Lambertsen <rask@formelder.dk>
> + *
> + * Based on axp221.c which is
> + * (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>
> +
> +/*
> + * Return cfg for a regulator with a linear range from `min' to `max' in steps
> + * of `div' and an optional second linear range from `max' to `max2' in steps
> + * of `div2'. Pass `max2' == `max' and `div2' == `div' for a single range.
> + */
> +static u8 axp_mvolt_to_cfg(int mvolt, int min, int max, int div,
> +			   int max2, int div2)
> +{
> +	if (mvolt < min) {
> +		mvolt = min;
> +	} else if (mvolt > max) {
> +		if (mvolt > max2)
> +			mvolt = max2;
> +		return (mvolt - max) / div2 + (max - min) / div;
> +	}
> +	return (mvolt - min) / div;
> +}
> +
> +int axp_set_dcdca(unsigned int mvolt)
> +{
> +	int ret;
> +	u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1100, 10, 1520, 20);
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +					 AXP806_OUTPUT_CTRL1_DCDCA_EN);
> +
> +	ret = pmic2_bus_write(AXP806_DCDCA_CTRL, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +				 AXP806_OUTPUT_CTRL1_DCDCA_EN);
> +}
> +
> +int axp_set_dcdcb(unsigned int mvolt)
> +{
> +	int ret;
> +	u8 cfg = axp_mvolt_to_cfg(mvolt, 1000, 2550, 50, 2550, 50);
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +					 AXP806_OUTPUT_CTRL1_DCDCB_EN);
> +
> +	ret = pmic2_bus_write(AXP806_DCDCB_CTRL, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +				 AXP806_OUTPUT_CTRL1_DCDCB_EN);
> +}
> +
> +int axp_set_dcdcc(unsigned int mvolt)
> +{
> +	int ret;
> +	u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1100, 10, 1520, 20);
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +					 AXP806_OUTPUT_CTRL1_DCDCC_EN);
> +
> +	ret = pmic2_bus_write(AXP806_DCDCC_CTRL, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +				 AXP806_OUTPUT_CTRL1_DCDCC_EN);
> +}
> +
> +int axp_set_dcdcd(unsigned int mvolt)
> +{
> +	int ret;
> +	u8 cfg = axp_mvolt_to_cfg(mvolt, 600, 1500, 20, 3300, 100);
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +					 AXP806_OUTPUT_CTRL1_DCDCD_EN);
> +
> +	ret = pmic2_bus_write(AXP806_DCDCD_CTRL, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +				 AXP806_OUTPUT_CTRL1_DCDCD_EN);
> +}
> +
> +int axp_set_dcdce(unsigned int mvolt)
> +{
> +	int ret;
> +	u8 cfg = axp_mvolt_to_cfg(mvolt, 1100, 3400, 100, 3400, 100);
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +					 AXP806_OUTPUT_CTRL1_DCDCE_EN);
> +
> +	ret = pmic2_bus_write(AXP806_DCDCE_CTRL, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +				 AXP806_OUTPUT_CTRL1_DCDCE_EN);
> +}
> +
> +int axp2_set_aldo(int ldo_num, unsigned int mvolt)
> +{
> +	int ret;
> +	unsigned int ldo = ldo_num - 1;
> +	u8 cfg = axp_mvolt_to_cfg(mvolt, 700, 3300, 100, 3300, 100);
> +
> +	if (ldo_num < 1 || ldo_num > 3)
> +		return -EINVAL;
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL1,
> +					 AXP806_OUTPUT_CTRL1_ALDO1_EN << ldo);
> +
> +	ret = pmic2_bus_write(AXP806_ALDO1_CTRL + ldo, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL1,
> +				 AXP806_OUTPUT_CTRL1_ALDO1_EN << ldo);
> +}
> +
> +int axp_set_bldo(int ldo_num, unsigned int mvolt)
> +{
> +	int ret;
> +	unsigned int ldo = ldo_num - 1;
> +	u8 cfg = axp_mvolt_to_cfg(mvolt, 700, 1900, 100, 1900, 100);
> +
> +	if (ldo_num < 1 || ldo_num > 4)
> +		return -EINVAL;
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
> +					AXP806_OUTPUT_CTRL2_BLDO1_EN << ldo);
> +
> +	ret = pmic2_bus_write(AXP806_BLDO1_CTRL + ldo, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
> +				AXP806_OUTPUT_CTRL2_BLDO1_EN << ldo);
> +}
> +
> +int axp_set_cldo(int ldo_num, unsigned int mvolt)
> +{
> +	int ret;
> +	unsigned int ldo = ldo_num - 1;
> +	u8 cfg;
> +
> +	if (ldo_num < 1 || ldo_num > 3)
> +		return -EINVAL;
> +
> +	if (ldo_num == 2)
> +		cfg = axp_mvolt_to_cfg(mvolt, 700, 3400, 100, 4200, 200);
> +	else
> +		cfg = axp_mvolt_to_cfg(mvolt, 700, 3300, 100, 3300, 100);
> +
> +	if (mvolt == 0)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
> +					AXP806_OUTPUT_CTRL2_CLDO1_EN << ldo);
> +
> +	ret = pmic2_bus_write(AXP806_CLDO1_CTRL + ldo, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
> +				AXP806_OUTPUT_CTRL2_CLDO1_EN << ldo);
> +}
> +
> +int axp2_set_sw(bool on)
> +{
> +	if (!on)
> +		return pmic2_bus_clrbits(AXP806_OUTPUT_CTRL2,
> +					AXP806_OUTPUT_CTRL2_SW_EN);
> +	return pmic2_bus_setbits(AXP806_OUTPUT_CTRL2,
> +				AXP806_OUTPUT_CTRL2_SW_EN);
> +}
> +
> +int axp2_init(void)
> +{
> +	u8 axp_chip_id;
> +	int ret;
> +
> +	ret = pmic_bus_init();
> +	if (ret)
> +		return ret;
> +
> +	ret = pmic2_bus_read(AXP806_CHIP_ID, &axp_chip_id);
> +	if (ret)
> +		return ret;
> +
> +	if ((axp_chip_id & 0xcf) != 0x40)
> +		return -ENODEV;
> +
> +	return 0;
> +}
> +
> +/* The AXP809 driver also implements do_poweroff() and we can't have both. */
> +#ifndef CONFIG_AXP809_POWER
> +int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	pmic2_bus_setbits(AXP806_SHUTDOWN_CTRL, AXP806_SHUTDOWN_POWEROFF);
> +
> +	/* infinite loop during shutdown */
> +	while (1)
> +		;
> +
> +	/* not reached */
> +	return 0;
> +}
> +#endif
> diff --git a/include/axp806.h b/include/axp806.h
> new file mode 100644
> index 0000000..d7f7f2b
> --- /dev/null
> +++ b/include/axp806.h
> @@ -0,0 +1,50 @@
> +/*
> + * X-Powers AXP806 and AXP808 Power Management IC driver
> + *
> + * Copyright (C) 2017 Rask Ingemann Lambertsen <rask@formelder.dk>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <linux/bitops.h>
> +
> +#define AXP806_CHIP_ID		0x03
> +#define AXP806_OUTPUT_CTRL1	0x10
> +#define AXP806_OUTPUT_CTRL2	0x11
> +#define AXP806_DCDCA_CTRL	0x12
> +#define AXP806_DCDCB_CTRL	0x13
> +#define AXP806_DCDCC_CTRL	0x14
> +#define AXP806_DCDCD_CTRL	0x15
> +#define AXP806_DCDCE_CTRL	0x16
> +#define AXP806_ALDO1_CTRL	0x17
> +#define AXP806_ALDO2_CTRL	0x18
> +#define AXP806_ALDO3_CTRL	0x19
> +/* Unused registers here. */
> +#define AXP806_BLDO1_CTRL	0x20
> +#define AXP806_BLDO2_CTRL	0x21
> +#define AXP806_BLDO3_CTRL	0x22
> +#define AXP806_BLDO4_CTRL	0x23
> +#define AXP806_CLDO1_CTRL	0x24
> +#define AXP806_CLDO2_CTRL	0x25
> +#define AXP806_CLDO3_CTRL	0x26
> +#define AXP806_SHUTDOWN_CTRL	0x32
> +
> +#define AXP806_OUTPUT_CTRL1_DCDCA_EN	BIT(0)
> +#define AXP806_OUTPUT_CTRL1_DCDCB_EN	BIT(1)
> +#define AXP806_OUTPUT_CTRL1_DCDCC_EN	BIT(2)
> +#define AXP806_OUTPUT_CTRL1_DCDCD_EN	BIT(3)
> +#define AXP806_OUTPUT_CTRL1_DCDCE_EN	BIT(4)
> +#define AXP806_OUTPUT_CTRL1_ALDO1_EN	BIT(5)
> +#define AXP806_OUTPUT_CTRL1_ALDO2_EN	BIT(6)
> +#define AXP806_OUTPUT_CTRL1_ALDO3_EN	BIT(7)
> +
> +#define AXP806_OUTPUT_CTRL2_BLDO1_EN	BIT(0)
> +#define AXP806_OUTPUT_CTRL2_BLDO2_EN	BIT(1)
> +#define AXP806_OUTPUT_CTRL2_BLDO3_EN	BIT(2)
> +#define AXP806_OUTPUT_CTRL2_BLDO4_EN	BIT(3)
> +#define AXP806_OUTPUT_CTRL2_CLDO1_EN	BIT(4)
> +#define AXP806_OUTPUT_CTRL2_CLDO2_EN	BIT(5)
> +#define AXP806_OUTPUT_CTRL2_CLDO3_EN	BIT(6)
> +#define AXP806_OUTPUT_CTRL2_SW_EN	BIT(7)
> +
> +#define AXP806_SHUTDOWN_POWEROFF	BIT(7)
> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
> index d789ad8..7d5dad7 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_AXP806_POWER
> +#include <axp806.h>
> +#endif
>  #ifdef CONFIG_AXP809_POWER
>  #include <axp809.h>
>  #endif
> @@ -28,15 +31,25 @@ 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_dcdca(unsigned int mvolt);
> +int axp_set_dcdcb(unsigned int mvolt);
> +int axp_set_dcdcc(unsigned int mvolt);
> +int axp_set_dcdcd(unsigned int mvolt);
> +int axp_set_dcdce(unsigned int mvolt);
>  int axp_set_aldo1(unsigned int mvolt);
>  int axp_set_aldo2(unsigned int mvolt);
>  int axp_set_aldo3(unsigned int mvolt);
>  int axp_set_aldo4(unsigned int mvolt);
> +int axp2_set_aldo(int aldo_num, unsigned int mvolt);
> +int axp_set_bldo(int bldo_num, unsigned int mvolt);
> +int axp_set_cldo(int cldo_num, unsigned int mvolt);
>  int axp_set_dldo(int dldo_num, unsigned int mvolt);
>  int axp_set_eldo(int eldo_num, unsigned int mvolt);
>  int axp_set_fldo(int fldo_num, unsigned int mvolt);
>  int axp_set_sw(bool on);
> +int axp2_set_sw(bool on);
>  int axp_init(void);
> +int axp2_init(void);
>  int axp_get_sid(unsigned int *sid);
>  
>  #endif
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-04-21  7:58 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-26 18:59 [U-Boot] [PATCH 0/2] sunxi: power: Add AXP806 and AXP808 support Rask Ingemann Lambertsen
2017-02-26 19:01 ` [U-Boot] [PATCH 1/2 RFT] " Rask Ingemann Lambertsen
2017-02-27  3:26   ` Chen-Yu Tsai
2017-03-01 21:29     ` Rask Ingemann Lambertsen
2017-02-28  4:47   ` Jaehoon Chung
     [not found]   ` <CGME20170421075849epcas1p16a1d961b1717ae9298be1aac91bab593@epcas1p1.samsung.com>
2017-04-21  7:58     ` [U-Boot] [U-Boot, 1/2, " Jaehoon Chung
2017-02-26 19:02 ` [U-Boot] [PATCH 2/2] sunxi: defconfig: Sunchip CX-A99: Raise CPU voltage and clock frequency Rask Ingemann Lambertsen
2017-02-27  3:08   ` Chen-Yu Tsai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.