[PATCH] add axp313a support

Here is the diff of AXP313A PMIC driver. (No board configuration is included)
Signed-off-by: SASANO Takayoshi uaa@uaa.org.uk ---
arch/arm/mach-sunxi/pmic_bus.c | 4 +- board/sunxi/board.c | 9 +- drivers/power/Kconfig | 16 ++- drivers/power/Makefile | 1 + drivers/power/axp313a.c | 171 +++++++++++++++++++++++++++++++++ drivers/power/pmic/axp.c | 1 + include/axp313a.h | 31 ++++++ include/axp_pmic.h | 2 + 8 files changed, 226 insertions(+), 9 deletions(-) create mode 100644 drivers/power/axp313a.c create mode 100644 include/axp313a.h
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c index c090840637..3e7bb5a5d1 100644 --- a/arch/arm/mach-sunxi/pmic_bus.c +++ b/arch/arm/mach-sunxi/pmic_bus.c @@ -21,7 +21,7 @@
#define AXP209_I2C_ADDR 0x34
-#define AXP305_I2C_ADDR 0x36 +#define AXP305_I2C_ADDR 0x36 /* AXP305 and AXP313A */
#define AXP221_CHIP_ADDR 0x68
@@ -32,7 +32,7 @@ static int pmic_i2c_address(void) { if (IS_ENABLED(CONFIG_AXP152_POWER)) return AXP152_I2C_ADDR; - if (IS_ENABLED(CONFIG_AXP305_POWER)) + if (IS_ENABLED(CONFIG_AXP305_POWER) || IS_ENABLED(CONFIG_AXP313A_POWER)) return AXP305_I2C_ADDR;
/* Other AXP2xx and AXP8xx variants */ diff --git a/board/sunxi/board.c b/board/sunxi/board.c index f321cd58a6..9b0069cd52 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -584,6 +584,7 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \ defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \ + defined CONFIG_AXP313A_POWER || \ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER power_failed = axp_init();
@@ -605,7 +606,8 @@ void sunxi_board_init(void) power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT); power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT); #endif -#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) +#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) && \ + !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT); #endif #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \ @@ -617,10 +619,11 @@ void sunxi_board_init(void) defined CONFIG_AXP818_POWER power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT); #endif -#if !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP305_POWER) && !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT); #endif -#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) && \ + !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT); #endif #ifdef CONFIG_AXP209_POWER diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 7f3b990d23..12189eec9f 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -101,6 +101,14 @@ config AXP305_POWER Select this to enable support for the axp305 pmic found on most H616 boards.
+config AXP313A_POWER + bool "axp313a pmic support" + select AXP_PMIC_BUS + select CMD_POWEROFF + ---help--- + Select this to enable support for the axp313a pmic found on some + H616 boards. + config AXP809_POWER bool "axp809 pmic support" depends on MACH_SUN9I @@ -143,8 +151,8 @@ config AXP_DCDC1_VOLT
config AXP_DCDC2_VOLT int "axp pmic dcdc2 voltage" - depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER - default 900 if AXP818_POWER + depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313A_POWER + default 900 if AXP818_POWER || AXP313A_POWER default 1400 if AXP152_POWER || AXP209_POWER default 1200 if MACH_SUN6I default 1100 if MACH_SUN8I @@ -161,8 +169,8 @@ config AXP_DCDC2_VOLT
config AXP_DCDC3_VOLT int "axp pmic dcdc3 voltage" - depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER - default 900 if AXP809_POWER || AXP818_POWER + depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313A_POWER + default 900 if AXP809_POWER || AXP818_POWER || AXP313A_POWER default 1500 if AXP152_POWER default 1250 if AXP209_POWER default 1100 if MACH_SUN8I_R40 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index ba64b2c593..f851f4a94e 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_AXP152_POWER) += axp152.o obj-$(CONFIG_AXP209_POWER) += axp209.o obj-$(CONFIG_AXP221_POWER) += axp221.o obj-$(CONFIG_AXP305_POWER) += axp305.o +obj-$(CONFIG_AXP313A_POWER) += axp313a.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/axp313a.c b/drivers/power/axp313a.c new file mode 100644 index 0000000000..90be8942bb --- /dev/null +++ b/drivers/power/axp313a.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * AXP313A driver based on AXP221 driver + * + * + * (C) Copyright 2023 SASANO Takayoshi uaa@uaa.org.uk + * + * Based on axp221.c + * (C) Copyright 2014 Hans de Goede hdegoede@redhat.com + * (C) Copyright 2013 Oliver Schinagl oliver@schinagl.nl + */ + +#include <common.h> +#include <command.h> +#include <errno.h> +#include <asm/arch/pmic_bus.h> +#include <axp_pmic.h> + +static u8 axp313a_mvolt_to_cfg(int mvolt, int min, int max, int div) +{ + if (mvolt < min) + mvolt = min; + else if (mvolt > max) + mvolt = max; + + return (mvolt - min) / div; +} + +int axp_set_dcdc1(unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (mvolt >= 1600) + cfg = 88 + axp313a_mvolt_to_cfg(mvolt, 1600, 3400, 100); + else if (mvolt >= 1220) + cfg = 71 + axp313a_mvolt_to_cfg(mvolt, 1220, 1540, 20); + else + cfg = axp313a_mvolt_to_cfg(mvolt, 500, 1200, 10); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC1); + + ret = pmic_bus_write(AXP313A_DCDC1_CTRL, cfg); + if (ret) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC1); +} + +int axp_set_dcdc2(unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (mvolt >= 1220) + cfg = 71 + axp313a_mvolt_to_cfg(mvolt, 1220, 1540, 20); + else + cfg = axp313a_mvolt_to_cfg(mvolt, 500, 1200, 10); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC2); + + ret = pmic_bus_write(AXP313A_DCDC2_CTRL, cfg); + if (ret) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC2); +} + +int axp_set_dcdc3(unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (mvolt >= 1220) + cfg = 71 + axp313a_mvolt_to_cfg(mvolt, 1220, 1840, 20); + else + cfg = axp313a_mvolt_to_cfg(mvolt, 500, 1200, 10); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC3); + + ret = pmic_bus_write(AXP313A_DCDC3_CTRL, cfg); + if (ret) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC3); +} + +int axp_set_aldo1(unsigned int mvolt) +{ + int ret; + u8 cfg = axp313a_mvolt_to_cfg(mvolt, 500, 3500, 100); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_ALDO1); + + ret = pmic_bus_write(AXP313A_ALDO1_CTRL, cfg); + if (cfg) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_ALDO1); +} + +int axp_set_dldo(int dldo_num, unsigned int mvolt) +{ + int ret; + u8 cfg = axp313a_mvolt_to_cfg(mvolt, 500, 3500, 100); + + if (dldo_num != 1) + return -EINVAL; + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DLDO1); + + ret = pmic_bus_write(AXP313A_DLDO1_CTRL, cfg); + if (cfg) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DLDO1); +} + +int axp_init(void) +{ + int ret; + u8 axp_chip_id; + + ret = pmic_bus_init(); + if (ret) + return ret; + + ret = pmic_bus_read(AXP313A_CHIP_VERSION, &axp_chip_id); + if (ret) + return ret; + + axp_chip_id &= AXP313A_CHIP_VERSION_MASK; + switch (axp_chip_id) { + case AXP313A_CHIP_VERSION_AXP1530: + case AXP313A_CHIP_VERSION_AXP313A: + case AXP313A_CHIP_VERSION_AXP313B: + break; + default: + return -EINVAL; + } + + return ret; +} + +#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + pmic_bus_write(AXP313A_SHUTDOWN, AXP313A_POWEROFF); + + /* infinite loop during shutdown */ + while (1); + + /* not reached */ + return 0; +} +#endif diff --git a/drivers/power/pmic/axp.c b/drivers/power/pmic/axp.c index 025dac24f2..d23c16d996 100644 --- a/drivers/power/pmic/axp.c +++ b/drivers/power/pmic/axp.c @@ -87,6 +87,7 @@ static const struct udevice_id axp_pmic_ids[] = { { .compatible = "x-powers,axp209", .data = AXP209_ID }, { .compatible = "x-powers,axp221", .data = AXP221_ID }, { .compatible = "x-powers,axp223", .data = AXP223_ID }, + { .compatible = "x-powers,axp313a", .data = AXP313A_ID }, { .compatible = "x-powers,axp803", .data = AXP803_ID }, { .compatible = "x-powers,axp806", .data = AXP806_ID }, { .compatible = "x-powers,axp809", .data = AXP809_ID }, diff --git a/include/axp313a.h b/include/axp313a.h new file mode 100644 index 0000000000..a61a11a53c --- /dev/null +++ b/include/axp313a.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2023 SASANO Takayoshi uaa@uaa.org.uk + */ + +enum axp313a_reg { + AXP313A_POWER_STATUS = 0x00, + AXP313A_CHIP_VERSION = 0x03, + AXP313A_OUTPUT_CTRL = 0x10, + AXP313A_DCDC1_CTRL = 0x13, + AXP313A_DCDC2_CTRL = 0x14, + AXP313A_DCDC3_CTRL = 0x15, + AXP313A_ALDO1_CTRL = 0x16, + AXP313A_DLDO1_CTRL = 0x17, + AXP313A_SHUTDOWN = 0x1a, + AXP313A_IRQ_ENABLE = 0x20, + AXP313A_IRQ_STATUS = 0x21, +}; + +#define AXP313A_CHIP_VERSION_MASK 0xcf +#define AXP313A_CHIP_VERSION_AXP1530 0x48 +#define AXP313A_CHIP_VERSION_AXP313A 0x4b +#define AXP313A_CHIP_VERSION_AXP313B 0x4c + +#define AXP313A_OUTPUT_CTRL_DCDC1 BIT(0) +#define AXP313A_OUTPUT_CTRL_DCDC2 BIT(1) +#define AXP313A_OUTPUT_CTRL_DCDC3 BIT(2) +#define AXP313A_OUTPUT_CTRL_ALDO1 BIT(3) +#define AXP313A_OUTPUT_CTRL_DLDO1 BIT(4) + +#define AXP313A_POWEROFF BIT(7) diff --git a/include/axp_pmic.h b/include/axp_pmic.h index 4ac6486583..9b6d7d900c 100644 --- a/include/axp_pmic.h +++ b/include/axp_pmic.h @@ -13,6 +13,7 @@ #include <axp209.h> #include <axp221.h> #include <axp305.h> +#include <axp313a.h> #include <axp809.h> #include <axp818.h>
@@ -32,6 +33,7 @@ enum { AXP209_ID, AXP221_ID, AXP223_ID, + AXP313A_ID, AXP803_ID, AXP806_ID, AXP809_ID,

Hi,
On Sat, 15 Jul 2023 at 16:01, SASANO Takayoshi uaa@mx5.nisiq.net wrote:
Here is the diff of AXP313A PMIC driver. (No board configuration is included)
Signed-off-by: SASANO Takayoshi uaa@uaa.org.uk
arch/arm/mach-sunxi/pmic_bus.c | 4 +- board/sunxi/board.c | 9 +- drivers/power/Kconfig | 16 ++- drivers/power/Makefile | 1 + drivers/power/axp313a.c | 171 +++++++++++++++++++++++++++++++++ drivers/power/pmic/axp.c | 1 + include/axp313a.h | 31 ++++++ include/axp_pmic.h | 2 + 8 files changed, 226 insertions(+), 9 deletions(-) create mode 100644 drivers/power/axp313a.c create mode 100644 include/axp313a.h
Please can you write this to use driver model? There is a pmic uclass.
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c index c090840637..3e7bb5a5d1 100644 --- a/arch/arm/mach-sunxi/pmic_bus.c +++ b/arch/arm/mach-sunxi/pmic_bus.c @@ -21,7 +21,7 @@
#define AXP209_I2C_ADDR 0x34
-#define AXP305_I2C_ADDR 0x36 +#define AXP305_I2C_ADDR 0x36 /* AXP305 and AXP313A */
#define AXP221_CHIP_ADDR 0x68
@@ -32,7 +32,7 @@ static int pmic_i2c_address(void) { if (IS_ENABLED(CONFIG_AXP152_POWER)) return AXP152_I2C_ADDR;
if (IS_ENABLED(CONFIG_AXP305_POWER))
if (IS_ENABLED(CONFIG_AXP305_POWER) || IS_ENABLED(CONFIG_AXP313A_POWER)) return AXP305_I2C_ADDR; /* Other AXP2xx and AXP8xx variants */
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index f321cd58a6..9b0069cd52 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -584,6 +584,7 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \ defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
defined CONFIG_AXP313A_POWER || \ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER power_failed = axp_init();
@@ -605,7 +606,8 @@ void sunxi_board_init(void) power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT); power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT); #endif -#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) +#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) && \
!defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
#endif #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \ @@ -617,10 +619,11 @@ void sunxi_board_init(void) defined CONFIG_AXP818_POWER power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT); #endif -#if !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP305_POWER) && !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT); #endif -#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) && \
!defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
#endif
OMG that is a mess. It looks like sunxi needs some conversion.
#ifdef CONFIG_AXP209_POWER diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 7f3b990d23..12189eec9f 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -101,6 +101,14 @@ config AXP305_POWER Select this to enable support for the axp305 pmic found on most H616 boards.
+config AXP313A_POWER
bool "axp313a pmic support"
select AXP_PMIC_BUS
select CMD_POWEROFF
---help---
Select this to enable support for the axp313a pmic found on some
H616 boards.
Regards, Simon

Hello,
On Sun, 16 Jul 2023 08:40:36 +0900, Simon Glass wrote:
Hi,
On Sat, 15 Jul 2023 at 16:01, SASANO Takayoshi uaa@mx5.nisiq.net wrote:
Here is the diff of AXP313A PMIC driver. (No board configuration is included)
Signed-off-by: SASANO Takayoshi uaa@uaa.org.uk
arch/arm/mach-sunxi/pmic_bus.c | 4 +- board/sunxi/board.c | 9 +- drivers/power/Kconfig | 16 ++- drivers/power/Makefile | 1 + drivers/power/axp313a.c | 171 +++++++++++++++++++++++++++++++++ drivers/power/pmic/axp.c | 1 + include/axp313a.h | 31 ++++++ include/axp_pmic.h | 2 + 8 files changed, 226 insertions(+), 9 deletions(-) create mode 100644 drivers/power/axp313a.c create mode 100644 include/axp313a.h
Please can you write this to use driver model? There is a pmic uclass.
This is controller-specific driver for power/pmic/axp.c. axp.c (axp_pmic) belongs to UCLASS_PMIC.
-- U_BOOT_DRIVER(axp_pmic) = { .name = "axp_pmic", .id = UCLASS_PMIC, .of_match = axp_pmic_ids, .bind = axp_pmic_bind, .ops = &axp_pmic_ops, }; --
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index f321cd58a6..9b0069cd52 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -584,6 +584,7 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \ defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
defined CONFIG_AXP313A_POWER || \ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER power_failed = axp_init();
@@ -605,7 +606,8 @@ void sunxi_board_init(void) power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT); power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT); #endif -#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) +#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) && \
!defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
#endif #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \ @@ -617,10 +619,11 @@ void sunxi_board_init(void) defined CONFIG_AXP818_POWER power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT); #endif -#if !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP305_POWER) && !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT); #endif -#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) && \
!defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
#endif
OMG that is a mess. It looks like sunxi needs some conversion.
I think so. We have to rewrite what regulator output (dcdcX, aldoX, etc..) is supported (not by controller name), but is it necessary before adding AXP313A code?
Best regards,

Hi SASANO,
On Sat, 15 Jul 2023 at 18:36, SASANO Takayoshi uaa@mx5.nisiq.net wrote:
Hello,
On Sun, 16 Jul 2023 08:40:36 +0900, Simon Glass wrote:
Hi,
On Sat, 15 Jul 2023 at 16:01, SASANO Takayoshi uaa@mx5.nisiq.net wrote:
Here is the diff of AXP313A PMIC driver. (No board configuration is included)
Signed-off-by: SASANO Takayoshi uaa@uaa.org.uk
arch/arm/mach-sunxi/pmic_bus.c | 4 +- board/sunxi/board.c | 9 +- drivers/power/Kconfig | 16 ++- drivers/power/Makefile | 1 + drivers/power/axp313a.c | 171 +++++++++++++++++++++++++++++++++ drivers/power/pmic/axp.c | 1 + include/axp313a.h | 31 ++++++ include/axp_pmic.h | 2 + 8 files changed, 226 insertions(+), 9 deletions(-) create mode 100644 drivers/power/axp313a.c create mode 100644 include/axp313a.h
Please can you write this to use driver model? There is a pmic uclass.
This is controller-specific driver for power/pmic/axp.c. axp.c (axp_pmic) belongs to UCLASS_PMIC.
-- U_BOOT_DRIVER(axp_pmic) = { .name = "axp_pmic", .id = UCLASS_PMIC, .of_match = axp_pmic_ids, .bind = axp_pmic_bind, .ops = &axp_pmic_ops, }; --
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index f321cd58a6..9b0069cd52 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -584,6 +584,7 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \ defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
defined CONFIG_AXP313A_POWER || \ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER power_failed = axp_init();
@@ -605,7 +606,8 @@ void sunxi_board_init(void) power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT); power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT); #endif -#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) +#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) && \
!defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
#endif #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \ @@ -617,10 +619,11 @@ void sunxi_board_init(void) defined CONFIG_AXP818_POWER power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT); #endif -#if !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP305_POWER) && !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT); #endif -#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) && \
!defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
#endif
OMG that is a mess. It looks like sunxi needs some conversion.
I think so. We have to rewrite what regulator output (dcdcX, aldoX, etc..) is supported (not by controller name), but is it necessary before adding AXP313A code?
Looking at the driver, it seems to use a private sunxi implementation
I'm not sure what to do with this, but adding more to this heap doesn't sound like a good idea. You could try asking the pmic maintainer what to do...actually should be copied if you add a 'power:' tag to your patch
+Jaehoon Chung
Best regards,
SASANO Takayoshi (JG1UAA) uaa@mx5.nisiq.net
Regards, Simon

Hello,
Simon told me that you are maintainer of pmic section. I am trying to add AXP313A support to sunxi/AXP code.
Maybe previous mail is CCed but I think you have not read my diff. I attach it again.
board/sunxi/board.c looks complex to maintain. We have to think how handle it after AXP313A supported.
Best regards,
From 9127de42691f86ef5ed22dcf5fa0b44b03288a07 Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi uaa@uaa.org.uk Date: Thu, 13 Jul 2023 20:41:40 +0900 Subject: [PATCH] add axp313a support
Signed-off-by: SASANO Takayoshi uaa@uaa.org.uk ---
arch/arm/mach-sunxi/pmic_bus.c | 4 +- board/sunxi/board.c | 9 +- drivers/power/Kconfig | 16 ++- drivers/power/Makefile | 1 + drivers/power/axp313a.c | 171 +++++++++++++++++++++++++++++++++ drivers/power/pmic/axp.c | 1 + include/axp313a.h | 31 ++++++ include/axp_pmic.h | 2 + 8 files changed, 226 insertions(+), 9 deletions(-) create mode 100644 drivers/power/axp313a.c create mode 100644 include/axp313a.h
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c index c090840637..3e7bb5a5d1 100644 --- a/arch/arm/mach-sunxi/pmic_bus.c +++ b/arch/arm/mach-sunxi/pmic_bus.c @@ -21,7 +21,7 @@
#define AXP209_I2C_ADDR 0x34
-#define AXP305_I2C_ADDR 0x36 +#define AXP305_I2C_ADDR 0x36 /* AXP305 and AXP313A */
#define AXP221_CHIP_ADDR 0x68
@@ -32,7 +32,7 @@ static int pmic_i2c_address(void) { if (IS_ENABLED(CONFIG_AXP152_POWER)) return AXP152_I2C_ADDR; - if (IS_ENABLED(CONFIG_AXP305_POWER)) + if (IS_ENABLED(CONFIG_AXP305_POWER) || IS_ENABLED(CONFIG_AXP313A_POWER)) return AXP305_I2C_ADDR;
/* Other AXP2xx and AXP8xx variants */ diff --git a/board/sunxi/board.c b/board/sunxi/board.c index f321cd58a6..9b0069cd52 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -584,6 +584,7 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \ defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \ + defined CONFIG_AXP313A_POWER || \ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER power_failed = axp_init();
@@ -605,7 +606,8 @@ void sunxi_board_init(void) power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT); power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT); #endif -#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) +#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER) && \ + !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT); #endif #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \ @@ -617,10 +619,11 @@ void sunxi_board_init(void) defined CONFIG_AXP818_POWER power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT); #endif -#if !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP305_POWER) && !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT); #endif -#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER) && \ + !defined(CONFIG_AXP313A_POWER) power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT); #endif #ifdef CONFIG_AXP209_POWER diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 7f3b990d23..12189eec9f 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -101,6 +101,14 @@ config AXP305_POWER Select this to enable support for the axp305 pmic found on most H616 boards.
+config AXP313A_POWER + bool "axp313a pmic support" + select AXP_PMIC_BUS + select CMD_POWEROFF + ---help--- + Select this to enable support for the axp313a pmic found on some + H616 boards. + config AXP809_POWER bool "axp809 pmic support" depends on MACH_SUN9I @@ -143,8 +151,8 @@ config AXP_DCDC1_VOLT
config AXP_DCDC2_VOLT int "axp pmic dcdc2 voltage" - depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER - default 900 if AXP818_POWER + depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313A_POWER + default 900 if AXP818_POWER || AXP313A_POWER default 1400 if AXP152_POWER || AXP209_POWER default 1200 if MACH_SUN6I default 1100 if MACH_SUN8I @@ -161,8 +169,8 @@ config AXP_DCDC2_VOLT
config AXP_DCDC3_VOLT int "axp pmic dcdc3 voltage" - depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER - default 900 if AXP809_POWER || AXP818_POWER + depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313A_POWER + default 900 if AXP809_POWER || AXP818_POWER || AXP313A_POWER default 1500 if AXP152_POWER default 1250 if AXP209_POWER default 1100 if MACH_SUN8I_R40 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index ba64b2c593..f851f4a94e 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_AXP152_POWER) += axp152.o obj-$(CONFIG_AXP209_POWER) += axp209.o obj-$(CONFIG_AXP221_POWER) += axp221.o obj-$(CONFIG_AXP305_POWER) += axp305.o +obj-$(CONFIG_AXP313A_POWER) += axp313a.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/axp313a.c b/drivers/power/axp313a.c new file mode 100644 index 0000000000..90be8942bb --- /dev/null +++ b/drivers/power/axp313a.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * AXP313A driver based on AXP221 driver + * + * + * (C) Copyright 2023 SASANO Takayoshi uaa@uaa.org.uk + * + * Based on axp221.c + * (C) Copyright 2014 Hans de Goede hdegoede@redhat.com + * (C) Copyright 2013 Oliver Schinagl oliver@schinagl.nl + */ + +#include <common.h> +#include <command.h> +#include <errno.h> +#include <asm/arch/pmic_bus.h> +#include <axp_pmic.h> + +static u8 axp313a_mvolt_to_cfg(int mvolt, int min, int max, int div) +{ + if (mvolt < min) + mvolt = min; + else if (mvolt > max) + mvolt = max; + + return (mvolt - min) / div; +} + +int axp_set_dcdc1(unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (mvolt >= 1600) + cfg = 88 + axp313a_mvolt_to_cfg(mvolt, 1600, 3400, 100); + else if (mvolt >= 1220) + cfg = 71 + axp313a_mvolt_to_cfg(mvolt, 1220, 1540, 20); + else + cfg = axp313a_mvolt_to_cfg(mvolt, 500, 1200, 10); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC1); + + ret = pmic_bus_write(AXP313A_DCDC1_CTRL, cfg); + if (ret) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC1); +} + +int axp_set_dcdc2(unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (mvolt >= 1220) + cfg = 71 + axp313a_mvolt_to_cfg(mvolt, 1220, 1540, 20); + else + cfg = axp313a_mvolt_to_cfg(mvolt, 500, 1200, 10); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC2); + + ret = pmic_bus_write(AXP313A_DCDC2_CTRL, cfg); + if (ret) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC2); +} + +int axp_set_dcdc3(unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (mvolt >= 1220) + cfg = 71 + axp313a_mvolt_to_cfg(mvolt, 1220, 1840, 20); + else + cfg = axp313a_mvolt_to_cfg(mvolt, 500, 1200, 10); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC3); + + ret = pmic_bus_write(AXP313A_DCDC3_CTRL, cfg); + if (ret) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DCDC3); +} + +int axp_set_aldo1(unsigned int mvolt) +{ + int ret; + u8 cfg = axp313a_mvolt_to_cfg(mvolt, 500, 3500, 100); + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_ALDO1); + + ret = pmic_bus_write(AXP313A_ALDO1_CTRL, cfg); + if (cfg) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_ALDO1); +} + +int axp_set_dldo(int dldo_num, unsigned int mvolt) +{ + int ret; + u8 cfg = axp313a_mvolt_to_cfg(mvolt, 500, 3500, 100); + + if (dldo_num != 1) + return -EINVAL; + + if (mvolt == 0) + return pmic_bus_clrbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DLDO1); + + ret = pmic_bus_write(AXP313A_DLDO1_CTRL, cfg); + if (cfg) + return ret; + + return pmic_bus_setbits(AXP313A_OUTPUT_CTRL, + AXP313A_OUTPUT_CTRL_DLDO1); +} + +int axp_init(void) +{ + int ret; + u8 axp_chip_id; + + ret = pmic_bus_init(); + if (ret) + return ret; + + ret = pmic_bus_read(AXP313A_CHIP_VERSION, &axp_chip_id); + if (ret) + return ret; + + axp_chip_id &= AXP313A_CHIP_VERSION_MASK; + switch (axp_chip_id) { + case AXP313A_CHIP_VERSION_AXP1530: + case AXP313A_CHIP_VERSION_AXP313A: + case AXP313A_CHIP_VERSION_AXP313B: + break; + default: + return -EINVAL; + } + + return ret; +} + +#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + pmic_bus_write(AXP313A_SHUTDOWN, AXP313A_POWEROFF); + + /* infinite loop during shutdown */ + while (1); + + /* not reached */ + return 0; +} +#endif diff --git a/drivers/power/pmic/axp.c b/drivers/power/pmic/axp.c index 025dac24f2..d23c16d996 100644 --- a/drivers/power/pmic/axp.c +++ b/drivers/power/pmic/axp.c @@ -87,6 +87,7 @@ static const struct udevice_id axp_pmic_ids[] = { { .compatible = "x-powers,axp209", .data = AXP209_ID }, { .compatible = "x-powers,axp221", .data = AXP221_ID }, { .compatible = "x-powers,axp223", .data = AXP223_ID }, + { .compatible = "x-powers,axp313a", .data = AXP313A_ID }, { .compatible = "x-powers,axp803", .data = AXP803_ID }, { .compatible = "x-powers,axp806", .data = AXP806_ID }, { .compatible = "x-powers,axp809", .data = AXP809_ID }, diff --git a/include/axp313a.h b/include/axp313a.h new file mode 100644 index 0000000000..a61a11a53c --- /dev/null +++ b/include/axp313a.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2023 SASANO Takayoshi uaa@uaa.org.uk + */ + +enum axp313a_reg { + AXP313A_POWER_STATUS = 0x00, + AXP313A_CHIP_VERSION = 0x03, + AXP313A_OUTPUT_CTRL = 0x10, + AXP313A_DCDC1_CTRL = 0x13, + AXP313A_DCDC2_CTRL = 0x14, + AXP313A_DCDC3_CTRL = 0x15, + AXP313A_ALDO1_CTRL = 0x16, + AXP313A_DLDO1_CTRL = 0x17, + AXP313A_SHUTDOWN = 0x1a, + AXP313A_IRQ_ENABLE = 0x20, + AXP313A_IRQ_STATUS = 0x21, +}; + +#define AXP313A_CHIP_VERSION_MASK 0xcf +#define AXP313A_CHIP_VERSION_AXP1530 0x48 +#define AXP313A_CHIP_VERSION_AXP313A 0x4b +#define AXP313A_CHIP_VERSION_AXP313B 0x4c + +#define AXP313A_OUTPUT_CTRL_DCDC1 BIT(0) +#define AXP313A_OUTPUT_CTRL_DCDC2 BIT(1) +#define AXP313A_OUTPUT_CTRL_DCDC3 BIT(2) +#define AXP313A_OUTPUT_CTRL_ALDO1 BIT(3) +#define AXP313A_OUTPUT_CTRL_DLDO1 BIT(4) + +#define AXP313A_POWEROFF BIT(7) diff --git a/include/axp_pmic.h b/include/axp_pmic.h index 4ac6486583..9b6d7d900c 100644 --- a/include/axp_pmic.h +++ b/include/axp_pmic.h @@ -13,6 +13,7 @@ #include <axp209.h> #include <axp221.h> #include <axp305.h> +#include <axp313a.h> #include <axp809.h> #include <axp818.h>
@@ -32,6 +33,7 @@ enum { AXP209_ID, AXP221_ID, AXP223_ID, + AXP313A_ID, AXP803_ID, AXP806_ID, AXP809_ID,
participants (2)
-
SASANO Takayoshi
-
Simon Glass