From fcf787cd711027a42f77507b0666979ca65bcb25 Mon Sep 17 00:00:00 2001 From: Lothar Felten Date: Tue, 17 Dec 2024 19:49:01 +0100 Subject: [PATCH] drivers: regulator: add support for AXP2101 power management IC Add initial support for the AXP2101 power management IC from X-powers. Remark: only DC/DC1 and ALDO have been tested on real hardware. Co-authored-by: TOKITA Hiroshi Signed-off-by: Lothar Felten --- .../m5stack/m5stack_core2/Kconfig.defconfig | 2 +- .../m5stack/m5stickc_plus/Kconfig.defconfig | 2 +- drivers/mfd/CMakeLists.txt | 2 +- drivers/mfd/Kconfig.axp192 | 8 +- drivers/mfd/mfd_axp192.c | 73 +-- drivers/regulator/CMakeLists.txt | 2 +- drivers/regulator/Kconfig.axp192 | 16 +- drivers/regulator/regulator_axp192.c | 418 +++++++++++++++--- dts/bindings/mfd/x-powers,axp2101.yaml | 12 + .../regulator/x-powers,axp2101-regulator.yaml | 91 ++++ tests/drivers/build_all/regulator/i2c.dtsi | 24 + 11 files changed, 544 insertions(+), 106 deletions(-) create mode 100644 dts/bindings/mfd/x-powers,axp2101.yaml create mode 100644 dts/bindings/regulator/x-powers,axp2101-regulator.yaml diff --git a/boards/m5stack/m5stack_core2/Kconfig.defconfig b/boards/m5stack/m5stack_core2/Kconfig.defconfig index c90a78870ba0..1999b90c5b8d 100644 --- a/boards/m5stack/m5stack_core2/Kconfig.defconfig +++ b/boards/m5stack/m5stack_core2/Kconfig.defconfig @@ -14,7 +14,7 @@ config GPIO_HOGS_INIT_PRIORITY config MFD_INIT_PRIORITY default 70 -config REGULATOR_AXP192_INIT_PRIORITY +config REGULATOR_AXP192_AXP2101_INIT_PRIORITY default 71 config GPIO_AXP192_INIT_PRIORITY diff --git a/boards/m5stack/m5stickc_plus/Kconfig.defconfig b/boards/m5stack/m5stickc_plus/Kconfig.defconfig index 86819dba82d3..9399c4d1f328 100644 --- a/boards/m5stack/m5stickc_plus/Kconfig.defconfig +++ b/boards/m5stack/m5stickc_plus/Kconfig.defconfig @@ -11,7 +11,7 @@ config GPIO_HOGS_INIT_PRIORITY config MFD_INIT_PRIORITY default 70 -config REGULATOR_AXP192_INIT_PRIORITY +config REGULATOR_AXP192_AXP2101_INIT_PRIORITY default 71 config GPIO_AXP192_INIT_PRIORITY diff --git a/drivers/mfd/CMakeLists.txt b/drivers/mfd/CMakeLists.txt index 5a7f5faee90a..2de46a5dacc8 100644 --- a/drivers/mfd/CMakeLists.txt +++ b/drivers/mfd/CMakeLists.txt @@ -9,7 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_MFD_NCT38XX mfd_nct38xx.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM2100 mfd_npm2100.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.c) -zephyr_library_sources_ifdef(CONFIG_MFD_AXP192 mfd_axp192.c) +zephyr_library_sources_ifdef(CONFIG_MFD_AXP192_AXP2101 mfd_axp192.c) zephyr_library_sources_ifdef(CONFIG_MFD_AD559X mfd_ad559x.c) zephyr_library_sources_ifdef(CONFIG_MFD_AD559X_BUS_I2C mfd_ad559x_i2c.c) zephyr_library_sources_ifdef(CONFIG_MFD_AD559X_BUS_SPI mfd_ad559x_spi.c) diff --git a/drivers/mfd/Kconfig.axp192 b/drivers/mfd/Kconfig.axp192 index da76c4cc615a..93bef1b72ffb 100644 --- a/drivers/mfd/Kconfig.axp192 +++ b/drivers/mfd/Kconfig.axp192 @@ -1,10 +1,10 @@ # Copyright (c) 2023 Martin Kiepfer # SPDX-License-Identifier: Apache-2.0 -config MFD_AXP192 - bool "AXP192 PMIC multi-function device driver" +config MFD_AXP192_AXP2101 + bool "AXP192/AXP2101 PMIC multi-function device driver" default y - depends on DT_HAS_X_POWERS_AXP192_ENABLED + depends on DT_HAS_X_POWERS_AXP192_ENABLED || DT_HAS_X_POWERS_AXP2101_ENABLED select I2C help - Enable the X-Powers AXP192 PMIC multi-function device driver + Enable the X-Powers AXP192/AXP2101 PMIC multi-function device driver diff --git a/drivers/mfd/mfd_axp192.c b/drivers/mfd/mfd_axp192.c index 421f5d19a37c..1e258c593d5f 100644 --- a/drivers/mfd/mfd_axp192.c +++ b/drivers/mfd/mfd_axp192.c @@ -3,8 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT x_powers_axp192 - #include #include @@ -15,11 +13,26 @@ LOG_MODULE_REGISTER(mfd_axp192, CONFIG_MFD_LOG_LEVEL); +struct mfd_axp192_config { + struct i2c_dt_spec i2c; +#ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED + bool vbusen_disable; +#endif + uint8_t reg_chip_id; + uint8_t vbus_config_reg; + uint8_t chip_id; + uint8_t val_vbusen_disable; +}; + +#ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED + /* Chip ID value */ #define AXP192_CHIP_ID 0x03U +#define AXP2101_CHIP_ID 0x4A /* Registers definitions */ #define AXP192_REG_CHIP_ID 0x03U +#define AXP2101_REG_CHIP_ID 0x03U /* AXP192 GPIO register addresses */ #define AXP192_EXTEN_DCDC2_CONTROL_REG 0x10U @@ -31,9 +44,11 @@ LOG_MODULE_REGISTER(mfd_axp192, CONFIG_MFD_LOG_LEVEL); #define AXP192_GPIO012_PINVAL_REG 0x94U #define AXP192_GPIO34_PINVAL_REG 0x96U #define AXP192_GPIO012_PULLDOWN_REG 0x97U +#define AXP2101_VBUS_CFG_REG 0x00U /* VBUS control reg values */ #define AXP192_VBUS_CFG_VAL_VBUSEN_DISABLE 0x80U +#define AXP2101_VBUS_CFG_VAL_VBUSEN_DISABLE 0x00U /* GPIO function control parameters */ #define AXP192_GPIO012_FUNC_VAL_OUTPUT_OD 0x00U @@ -97,11 +112,6 @@ LOG_MODULE_REGISTER(mfd_axp192, CONFIG_MFD_LOG_LEVEL); #define AXP192_GPIO5_OUTPUT_VAL 0x04U #define AXP192_GPIO5_OUTPUT_SHIFT 3U -struct mfd_axp192_config { - struct i2c_dt_spec i2c; - bool vbusen_disable; -}; - struct mfd_axp192_data { const struct device *gpio_mask_used[AXP192_GPIO_MAX_NUM]; uint8_t gpio_mask_output; @@ -139,12 +149,12 @@ const struct mfd_axp192_func_reg_desc gpio_reg_desc[AXP192_GPIO_MAX_NUM] = { .mask = AXP192_GPIO4_FUNC_MASK, }, }; +#endif /* CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED */ static int mfd_axp192_init(const struct device *dev) { const struct mfd_axp192_config *config = dev->config; uint8_t chip_id; - uint8_t vbus_val; int ret; LOG_DBG("Initializing instance"); @@ -155,29 +165,29 @@ static int mfd_axp192_init(const struct device *dev) } /* Check if axp192 chip is available */ - ret = i2c_reg_read_byte_dt(&config->i2c, AXP192_REG_CHIP_ID, &chip_id); + ret = i2c_reg_read_byte_dt(&config->i2c, config->reg_chip_id, &chip_id); if (ret < 0) { return ret; } - if (chip_id != AXP192_CHIP_ID) { + if (chip_id != config->chip_id) { LOG_ERR("Invalid Chip detected (%d)", chip_id); return -EINVAL; } +#ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED /* Disable N_VBUSEN */ - vbus_val = 0; - if (config->vbusen_disable) { - vbus_val = AXP192_VBUS_CFG_VAL_VBUSEN_DISABLE; - } - ret = i2c_reg_update_byte_dt(&config->i2c, AXP192_VBUS_CFG_REG, - AXP192_VBUS_CFG_VAL_VBUSEN_DISABLE, vbus_val); + ret = i2c_reg_update_byte_dt( + &config->i2c, config->vbus_config_reg, config->val_vbusen_disable, + config->vbusen_disable ? config->val_vbusen_disable : 0); if (ret < 0) { return ret; } +#endif return 0; } +#ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED int mfd_axp192_gpio_func_get(const struct device *dev, uint8_t gpio, enum axp192_gpio_func *func) { const struct mfd_axp192_config *config = dev->config; @@ -605,16 +615,29 @@ int mfd_axp192_gpio_write_port(const struct device *dev, uint8_t value, uint8_t return 0; } - -#define MFD_AXP192_DEFINE(inst) \ - static const struct mfd_axp192_config config##inst = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - .vbusen_disable = DT_INST_PROP_OR(inst, vbusen_disable, false), \ +#endif + +#define MFD_AXP192_CONST_CONFIG(model) \ + .reg_chip_id = AXP##model##_REG_CHIP_ID, \ + .vbus_config_reg = AXP##model##_VBUS_CFG_REG, \ + .chip_id = AXP##model##_CHIP_ID, \ + .val_vbusen_disable = AXP##model##_CHIP_ID, + +#define MFD_AXP192_DEFINE(node, model) \ + static const struct mfd_axp192_config config##node = { \ + .i2c = I2C_DT_SPEC_GET(node), \ + IF_ENABLED(CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED, \ + (.vbusen_disable = DT_PROP_OR(node, vbusen_disable, false),)) \ + MFD_AXP192_CONST_CONFIG(model) \ }; \ \ - static struct mfd_axp192_data data##inst; \ + IF_ENABLED(CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED, \ + (static struct mfd_axp192_data data##node;)) \ \ - DEVICE_DT_INST_DEFINE(inst, mfd_axp192_init, NULL, &data##inst, &config##inst, \ - POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL); + DEVICE_DT_DEFINE(node, mfd_axp192_init, NULL, \ + COND_CODE_1(CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED, \ + (&data##node), (NULL)), \ + &config##node, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL); -DT_INST_FOREACH_STATUS_OKAY(MFD_AXP192_DEFINE); +DT_FOREACH_STATUS_OKAY_VARGS(x_powers_axp192, MFD_AXP192_DEFINE, 192); +DT_FOREACH_STATUS_OKAY_VARGS(x_powers_axp2101, MFD_AXP192_DEFINE, 2101); diff --git a/drivers/regulator/CMakeLists.txt b/drivers/regulator/CMakeLists.txt index 7ed90137c3f2..24f02c3be8be 100644 --- a/drivers/regulator/CMakeLists.txt +++ b/drivers/regulator/CMakeLists.txt @@ -4,7 +4,7 @@ zephyr_library() zephyr_library_sources(regulator_common.c) -zephyr_library_sources_ifdef(CONFIG_REGULATOR_AXP192 regulator_axp192.c) +zephyr_library_sources_ifdef(CONFIG_REGULATOR_AXP192_AXP2101 regulator_axp192.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_ADP5360 regulator_adp5360.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_CP9314 regulator_cp9314.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_DA1469X regulator_da1469x.c) diff --git a/drivers/regulator/Kconfig.axp192 b/drivers/regulator/Kconfig.axp192 index b56868ccdb7a..42a28044bfc2 100644 --- a/drivers/regulator/Kconfig.axp192 +++ b/drivers/regulator/Kconfig.axp192 @@ -1,23 +1,23 @@ # Copyright (c) 2023 Martin Kiepfer # SPDX-License-Identifier: Apache-2.0 -config REGULATOR_AXP192 - bool "X-Power AXP192 PMIC regulator driver" +config REGULATOR_AXP192_AXP2101 + bool "X-Powers AXP192/AXP2101 PMIC regulator driver" default y - depends on DT_HAS_X_POWERS_AXP192_REGULATOR_ENABLED - depends on DT_HAS_X_POWERS_AXP192_ENABLED + depends on DT_HAS_X_POWERS_AXP192_REGULATOR_ENABLED || DT_HAS_X_POWERS_AXP2101_REGULATOR_ENABLED + depends on DT_HAS_X_POWERS_AXP192_ENABLED || DT_HAS_X_POWERS_AXP2101_ENABLED select I2C select MFD help Enable the AXP PMIC regulator driver -if REGULATOR_AXP192 +if REGULATOR_AXP192_AXP2101 -config REGULATOR_AXP192_INIT_PRIORITY - int "AXP192 regulator driver init priority" +config REGULATOR_AXP192_AXP2101_INIT_PRIORITY + int "AXP192/AXP2101 regulator driver init priority" default 86 help - Init priority for the axp192 regulator driver. It must be + Init priority for the axp192/axp2101 regulator driver. It must be greater than MFD_INIT_PRIORITY. endif diff --git a/drivers/regulator/regulator_axp192.c b/drivers/regulator/regulator_axp192.c index c6e09682384b..9c5c7393ed20 100644 --- a/drivers/regulator/regulator_axp192.c +++ b/drivers/regulator/regulator_axp192.c @@ -1,11 +1,10 @@ /* * Copyright (c) 2021 NXP * Copyright (c) 2023 Martin Kiepfer + * Copyright (c) 2024 Lothar Felten * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT x_powers_axp192_regulator - #include #include @@ -18,9 +17,7 @@ #include #include -LOG_MODULE_REGISTER(regulator_axp192, CONFIG_REGULATOR_LOG_LEVEL); - -/* Output control registers */ +/* AXP192 register defines */ #define AXP192_REG_EXTEN_DCDC2_CONTROL 0x10U #define AXP192_REG_DCDC123_LDO23_CONTROL 0x12U #define AXP192_REG_DCDC2_VOLTAGE 0x23U @@ -32,6 +29,41 @@ LOG_MODULE_REGISTER(regulator_axp192, CONFIG_REGULATOR_LOG_LEVEL); #define AXP192_REG_GPIO0_CONTROL 0x90U #define AXP192_REG_LDOIO0_VOLTAGE 0x91U +/* AXP2101 register defines */ +#define AXP2101_REG_CHGLED 0x69U +#define AXP2101_REG_DCDC12345_CONTROL 0x80U +#define AXP2101_REG_DCDCS_PWM_CONTROL 0x81U +#define AXP2101_REG_DCDC1_VOLTAGE 0x82U +#define AXP2101_REG_DCDC2_VOLTAGE 0x83U +#define AXP2101_REG_DCDC3_VOLTAGE 0x84U +#define AXP2101_REG_DCDC4_VOLTAGE 0x85U +#define AXP2101_REG_DCDC5_VOLTAGE 0x86U +#define AXP2101_REG_LDOGRP1_CONTROL 0x90U +#define AXP2101_REG_LDOGRP2_CONTROL 0x91U +#define AXP2101_REG_ALDO1_VOLTAGE 0x92U +#define AXP2101_REG_ALDO2_VOLTAGE 0x93U +#define AXP2101_REG_ALDO3_VOLTAGE 0x94U +#define AXP2101_REG_ALDO4_VOLTAGE 0x95U +#define AXP2101_REG_BLDO1_VOLTAGE 0x96U +#define AXP2101_REG_BLDO2_VOLTAGE 0x97U +#define AXP2101_REG_CPUSLDO_VOLTAGE 0x98U +#define AXP2101_REG_DLDO1_VOLTAGE 0x99U +#define AXP2101_REG_DLDO2_VOLTAGE 0x9AU + +#define AXP2101_CHGLED_CTRL_MASK 0x3 +#define AXP2101_CHGLED_CTRL_OFFSET 1 + +#define AXP2101_VBUS_CFG_REG 0 +#define AXP2101_VBUS_CFG_VAL_VBUSEN_DISABLE 0 + +LOG_MODULE_REGISTER(regulator_axp192, CONFIG_REGULATOR_LOG_LEVEL); + +#define AXP_NODE_HAS_CHILD(node, child) DT_NODE_HAS_STATUS_OKAY(DT_CHILD(node, child)) | +#define AXP192_ANY_HAS_CHILD(child) \ + (DT_FOREACH_STATUS_OKAY_VARGS(x_powers_axp192_regulator, AXP_NODE_HAS_CHILD, child) 0) +#define AXP2101_ANY_HAS_CHILD(child) \ + (DT_FOREACH_STATUS_OKAY_VARGS(x_powers_axp2101_regulator, AXP_NODE_HAS_CHILD, child) 0) + struct regulator_axp192_desc { const uint8_t enable_reg; const uint8_t enable_mask; @@ -56,15 +88,13 @@ struct regulator_axp192_config { const struct regulator_axp192_desc *desc; const struct device *mfd; const struct i2c_dt_spec i2c; - - LOG_INSTANCE_PTR_DECLARE(log); }; -static const struct linear_range dcdc1_ranges[] = { +static const struct linear_range axp192_dcdc1_ranges[] = { LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x7FU), }; -__maybe_unused static const struct regulator_axp192_desc dcdc1_desc = { +__maybe_unused static const struct regulator_axp192_desc axp192_dcdc1_desc = { .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, .enable_mask = 0x01U, .enable_val = 0x01U, @@ -75,15 +105,15 @@ __maybe_unused static const struct regulator_axp192_desc dcdc1_desc = { .workmode_reg = AXP192_REG_DCDC123_WORKMODE, .workmode_mask = 0x08U, .workmode_pwm_val = 0x08U, - .ranges = dcdc1_ranges, - .num_ranges = ARRAY_SIZE(dcdc1_ranges), + .ranges = axp192_dcdc1_ranges, + .num_ranges = ARRAY_SIZE(axp192_dcdc1_ranges), }; -static const struct linear_range dcdc2_ranges[] = { +static const struct linear_range axp192_dcdc2_ranges[] = { LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x3FU), }; -__maybe_unused static const struct regulator_axp192_desc dcdc2_desc = { +__maybe_unused static const struct regulator_axp192_desc axp192_dcdc2_desc = { .enable_reg = AXP192_REG_EXTEN_DCDC2_CONTROL, .enable_mask = 0x01U, .enable_val = 0x01U, @@ -94,15 +124,15 @@ __maybe_unused static const struct regulator_axp192_desc dcdc2_desc = { .workmode_reg = AXP192_REG_DCDC123_WORKMODE, .workmode_mask = 0x04U, .workmode_pwm_val = 0x04U, - .ranges = dcdc2_ranges, - .num_ranges = ARRAY_SIZE(dcdc2_ranges), + .ranges = axp192_dcdc2_ranges, + .num_ranges = ARRAY_SIZE(axp192_dcdc2_ranges), }; -static const struct linear_range dcdc3_ranges[] = { +static const struct linear_range axp192_dcdc3_ranges[] = { LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x7FU), }; -__maybe_unused static const struct regulator_axp192_desc dcdc3_desc = { +__maybe_unused static const struct regulator_axp192_desc axp192_dcdc3_desc = { .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, .enable_mask = 0x02U, .enable_val = 0x02U, @@ -113,15 +143,15 @@ __maybe_unused static const struct regulator_axp192_desc dcdc3_desc = { .workmode_reg = AXP192_REG_DCDC123_WORKMODE, .workmode_mask = 0x02U, .workmode_pwm_val = 0x02U, - .ranges = dcdc3_ranges, - .num_ranges = ARRAY_SIZE(dcdc3_ranges), + .ranges = axp192_dcdc3_ranges, + .num_ranges = ARRAY_SIZE(axp192_dcdc3_ranges), }; -static const struct linear_range ldoio0_ranges[] = { +static const struct linear_range axp192_ldoio0_ranges[] = { LINEAR_RANGE_INIT(1800000u, 100000u, 0x00u, 0x0Fu), }; -__maybe_unused static const struct regulator_axp192_desc ldoio0_desc = { +__maybe_unused static const struct regulator_axp192_desc axp192_ldoio0_desc = { .enable_reg = AXP192_REG_GPIO0_CONTROL, .enable_mask = 0x07u, .enable_val = 0x03u, @@ -131,15 +161,15 @@ __maybe_unused static const struct regulator_axp192_desc ldoio0_desc = { .max_ua = 50000u, .workmode_reg = 0u, .workmode_mask = 0u, - .ranges = ldoio0_ranges, - .num_ranges = ARRAY_SIZE(ldoio0_ranges), + .ranges = axp192_ldoio0_ranges, + .num_ranges = ARRAY_SIZE(axp192_ldoio0_ranges), }; -static const struct linear_range ldo2_ranges[] = { +static const struct linear_range axp192_ldo2_ranges[] = { LINEAR_RANGE_INIT(1800000U, 100000U, 0x00U, 0x0FU), }; -__maybe_unused static const struct regulator_axp192_desc ldo2_desc = { +__maybe_unused static const struct regulator_axp192_desc axp192_ldo2_desc = { .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, .enable_mask = 0x04U, .enable_val = 0x04U, @@ -149,15 +179,15 @@ __maybe_unused static const struct regulator_axp192_desc ldo2_desc = { .max_ua = 200000U, .workmode_reg = 0U, .workmode_mask = 0U, - .ranges = ldo2_ranges, - .num_ranges = ARRAY_SIZE(ldo2_ranges), + .ranges = axp192_ldo2_ranges, + .num_ranges = ARRAY_SIZE(axp192_ldo2_ranges), }; -static const struct linear_range ldo3_ranges[] = { +static const struct linear_range axp192_ldo3_ranges[] = { LINEAR_RANGE_INIT(1800000U, 100000U, 0x00U, 0x0FU), }; -__maybe_unused static const struct regulator_axp192_desc ldo3_desc = { +__maybe_unused static const struct regulator_axp192_desc axp192_ldo3_desc = { .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, .enable_mask = 0x08U, .enable_val = 0x08U, @@ -167,8 +197,238 @@ __maybe_unused static const struct regulator_axp192_desc ldo3_desc = { .max_ua = 200000U, .workmode_reg = 0U, .workmode_mask = 0U, - .ranges = ldo3_ranges, - .num_ranges = ARRAY_SIZE(ldo3_ranges), + .ranges = axp192_ldo3_ranges, + .num_ranges = ARRAY_SIZE(axp192_ldo3_ranges), +}; + +static const struct linear_range axp2101_dcdc1_ranges[] = { + LINEAR_RANGE_INIT(1500000U, 100000U, 0U, 19U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_dcdc1_desc = { + .enable_reg = AXP2101_REG_DCDC12345_CONTROL, + .enable_mask = 0x01U, + .enable_val = 0x01U, + .vsel_reg = AXP2101_REG_DCDC1_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 2000000U, + .ranges = axp2101_dcdc1_ranges, + .num_ranges = ARRAY_SIZE(axp2101_dcdc1_ranges), + .workmode_reg = AXP2101_REG_DCDCS_PWM_CONTROL, + .workmode_mask = BIT(2), + .workmode_pwm_val = BIT(2), +}; + +static const struct linear_range axp2101_dcdc2_ranges[] = { + LINEAR_RANGE_INIT(500000U, 10000U, 0U, 70U), + LINEAR_RANGE_INIT(1220000U, 20000U, 71U, 87U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_dcdc2_desc = { + .enable_reg = AXP2101_REG_DCDC12345_CONTROL, + .enable_mask = 0x02U, + .enable_val = 0x02U, + .vsel_reg = AXP2101_REG_DCDC2_VOLTAGE, + .vsel_mask = 0x7FU, + .vsel_bitpos = 0U, + .max_ua = 2000000U, + .ranges = axp2101_dcdc2_ranges, + .num_ranges = ARRAY_SIZE(axp2101_dcdc2_ranges), + .workmode_reg = AXP2101_REG_DCDCS_PWM_CONTROL, + .workmode_mask = BIT(3), + .workmode_pwm_val = BIT(3), +}; + +static const struct linear_range axp2101_dcdc3_ranges[] = { + LINEAR_RANGE_INIT(500000U, 10000U, 0U, 70U), + LINEAR_RANGE_INIT(1220000U, 20000U, 71U, 87U), + LINEAR_RANGE_INIT(1600000U, 100000U, 88U, 106U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_dcdc3_desc = { + .enable_reg = AXP2101_REG_DCDC12345_CONTROL, + .enable_mask = 0x04U, + .enable_val = 0x04U, + .vsel_reg = AXP2101_REG_DCDC3_VOLTAGE, + .vsel_mask = 0x7FU, + .vsel_bitpos = 0U, + .max_ua = 2000000U, + .ranges = axp2101_dcdc3_ranges, + .num_ranges = ARRAY_SIZE(axp2101_dcdc3_ranges), + .workmode_reg = AXP2101_REG_DCDCS_PWM_CONTROL, + .workmode_mask = BIT(4), + .workmode_pwm_val = BIT(4), +}; + +static const struct linear_range axp2101_dcdc4_ranges[] = { + LINEAR_RANGE_INIT(500000U, 10000U, 0U, 70U), + LINEAR_RANGE_INIT(1220000U, 20000U, 71U, 102U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_dcdc4_desc = { + .enable_reg = AXP2101_REG_DCDC12345_CONTROL, + .enable_mask = 0x08U, + .enable_val = 0x08U, + .vsel_reg = AXP2101_REG_DCDC4_VOLTAGE, + .vsel_mask = 0x7FU, + .vsel_bitpos = 0U, + .max_ua = 1500000U, + .ranges = axp2101_dcdc4_ranges, + .num_ranges = ARRAY_SIZE(axp2101_dcdc4_ranges), + .workmode_reg = AXP2101_REG_DCDCS_PWM_CONTROL, + .workmode_mask = BIT(5), + .workmode_pwm_val = BIT(5), +}; + +static const struct linear_range axp2101_dcdc5_ranges[] = { + LINEAR_RANGE_INIT(1400000U, 100000U, 0U, 23U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_dcdc5_desc = { + .enable_reg = AXP2101_REG_DCDC12345_CONTROL, + .enable_mask = 0x10U, + .enable_val = 0x10U, + .vsel_reg = AXP2101_REG_DCDC5_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 1000000U, + .ranges = axp2101_dcdc5_ranges, + .num_ranges = ARRAY_SIZE(axp2101_dcdc5_ranges), +}; + +static const struct linear_range axp2101_abldox_ranges[] = { + LINEAR_RANGE_INIT(500000U, 100000U, 0U, 30U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_aldo1_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x01U, + .enable_val = 0x01U, + .vsel_reg = AXP2101_REG_ALDO1_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_abldox_ranges, + .num_ranges = ARRAY_SIZE(axp2101_abldox_ranges), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_aldo2_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x02U, + .enable_val = 0x02U, + .vsel_reg = AXP2101_REG_ALDO2_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_abldox_ranges, + .num_ranges = ARRAY_SIZE(axp2101_abldox_ranges), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_aldo3_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x04U, + .enable_val = 0x04U, + .vsel_reg = AXP2101_REG_ALDO3_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_abldox_ranges, + .num_ranges = ARRAY_SIZE(axp2101_abldox_ranges), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_aldo4_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x08U, + .enable_val = 0x08U, + .vsel_reg = AXP2101_REG_ALDO4_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_abldox_ranges, + .num_ranges = ARRAY_SIZE(axp2101_abldox_ranges), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_bldo1_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x10U, + .enable_val = 0x10U, + .vsel_reg = AXP2101_REG_BLDO1_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_abldox_ranges, + .num_ranges = ARRAY_SIZE(axp2101_abldox_ranges), + .workmode_reg = 0U, + .workmode_mask = 0U, +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_bldo2_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x20U, + .enable_val = 0x20U, + .vsel_reg = AXP2101_REG_BLDO2_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_abldox_ranges, + .num_ranges = ARRAY_SIZE(axp2101_abldox_ranges), + .workmode_reg = 0U, + .workmode_mask = 0U, +}; + +static const struct linear_range axp2101_cpusldo_ranges[] = { + LINEAR_RANGE_INIT(500000U, 50000U, 0U, 19U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_cpusldo_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x40U, + .enable_val = 0x40U, + .vsel_reg = AXP2101_REG_CPUSLDO_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 30000U, + .ranges = axp2101_cpusldo_ranges, + .num_ranges = ARRAY_SIZE(axp2101_cpusldo_ranges), + .workmode_reg = 0U, + .workmode_mask = 0U, +}; + +static const struct linear_range axp2101_dldo1_ranges[] = { + LINEAR_RANGE_INIT(500000U, 100000U, 0U, 28U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_dldo1_desc = { + .enable_reg = AXP2101_REG_LDOGRP1_CONTROL, + .enable_mask = 0x80U, + .enable_val = 0x80U, + .vsel_reg = AXP2101_REG_DLDO1_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_dldo1_ranges, + .num_ranges = ARRAY_SIZE(axp2101_dldo1_ranges), + .workmode_reg = 0U, + .workmode_mask = 0U, +}; + +static const struct linear_range axp2101_dldo2_ranges[] = { + LINEAR_RANGE_INIT(500000U, 50000U, 0U, 19U), +}; + +__maybe_unused static const struct regulator_axp192_desc axp2101_dldo2_desc = { + .enable_reg = AXP2101_REG_LDOGRP2_CONTROL, + .enable_mask = 0x01U, + .enable_val = 0x01U, + .vsel_reg = AXP2101_REG_DLDO2_VOLTAGE, + .vsel_mask = 0x1FU, + .vsel_bitpos = 0U, + .max_ua = 300000U, + .ranges = axp2101_dldo2_ranges, + .num_ranges = ARRAY_SIZE(axp2101_dldo2_ranges), + .workmode_reg = 0U, + .workmode_mask = 0U, }; static int axp192_enable(const struct device *dev) @@ -176,20 +436,24 @@ static int axp192_enable(const struct device *dev) const struct regulator_axp192_config *config = dev->config; int ret; - LOG_INST_DBG(config->log, "Enabling regulator"); - LOG_INST_DBG(config->log, "[0x%02x]=0x%02x mask=0x%02x", config->desc->enable_reg, + LOG_DBG("Enabling regulator"); + LOG_DBG("[0x%02x]=0x%02x mask=0x%02x", config->desc->enable_reg, config->desc->enable_val, config->desc->enable_mask); +#if AXP192_ANY_HAS_CHILD(ldoio0) /* special case for LDOIO0, which is multiplexed with GPIO0 */ if (config->desc->enable_reg == AXP192_REG_GPIO0_CONTROL) { ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, 0, AXP192_GPIO_FUNC_LDO); } else { +#endif ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg, config->desc->enable_mask, config->desc->enable_val); +#if AXP192_ANY_HAS_CHILD(ldoio0) } +#endif if (ret != 0) { - LOG_INST_ERR(config->log, "Failed to enable regulator"); + LOG_ERR("Failed to enable regulator"); } return ret; @@ -200,19 +464,24 @@ static int axp192_disable(const struct device *dev) const struct regulator_axp192_config *config = dev->config; int ret; - LOG_INST_DBG(config->log, "Disabling regulator"); - LOG_INST_DBG(config->log, "[0x%02x]=0 mask=0x%x", config->desc->enable_reg, + LOG_DBG("Disabling regulator"); + LOG_DBG("[0x%02x]=0 mask=0x%x", config->desc->enable_reg, config->desc->enable_mask); +#if AXP192_ANY_HAS_CHILD(ldoio0) /* special case for LDOIO0, which is multiplexed with GPIO0 */ if (config->desc->enable_reg == AXP192_REG_GPIO0_CONTROL) { ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, 0, AXP192_GPIO_FUNC_OUTPUT_LOW); } else { +#endif ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg, config->desc->enable_mask, 0u); +#if AXP192_ANY_HAS_CHILD(ldoio0) } +#endif + if (ret != 0) { - LOG_INST_ERR(config->log, "Failed to disable regulator"); + LOG_ERR("Failed to disable regulator"); } return ret; @@ -239,24 +508,24 @@ static int axp192_set_voltage(const struct device *dev, int32_t min_uv, int32_t uint16_t idx; int ret; - LOG_INST_DBG(config->log, "voltage = [min=%d, max=%d]", min_uv, max_uv); + LOG_DBG("voltage = [min=%d, max=%d]", min_uv, max_uv); /* set voltage */ ret = linear_range_group_get_win_index(config->desc->ranges, config->desc->num_ranges, min_uv, max_uv, &idx); if (ret != 0) { - LOG_INST_ERR(config->log, "No voltage range window could be detected"); + LOG_ERR("No voltage range window could be detected"); return ret; } idx <<= config->desc->vsel_bitpos; - LOG_INST_DBG(config->log, "[0x%x]=0x%x mask=0x%x", config->desc->vsel_reg, idx, + LOG_DBG("[0x%x]=0x%x mask=0x%x", config->desc->vsel_reg, idx, config->desc->vsel_mask); ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->vsel_reg, config->desc->vsel_mask, (uint8_t)idx); if (ret != 0) { - LOG_INST_ERR(config->log, "Failed to set regulator voltage"); + LOG_ERR("Failed to set regulator voltage"); } return ret; @@ -291,7 +560,7 @@ static int axp192_set_mode(const struct device *dev, regulator_mode_t mode) if ((mode == AXP192_DCDC_MODE_PWM) && (config->desc->workmode_reg != 0)) { /* configure PWM mode */ - LOG_INST_DBG(config->log, "PWM mode enabled"); + LOG_DBG("PWM mode enabled"); ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->workmode_reg, config->desc->workmode_mask, config->desc->workmode_pwm_val); @@ -313,7 +582,7 @@ static int axp192_set_mode(const struct device *dev, regulator_mode_t mode) return 0; } } else { - LOG_INST_ERR(config->log, "Setting DCDC workmode failed"); + LOG_ERR("Setting DCDC workmode failed"); return -ENOTSUP; } @@ -350,44 +619,63 @@ static int regulator_axp192_init(const struct device *dev) regulator_common_data_init(dev); if (!device_is_ready(config->mfd)) { - LOG_INST_ERR(config->log, "Parent instance not ready!"); + LOG_ERR("Parent instance not ready!"); return -ENODEV; } /* read regulator state */ ret = i2c_reg_read_byte_dt(&config->i2c, config->desc->enable_reg, &enabled_val); if (ret != 0) { - LOG_INST_ERR(config->log, "Reading enable status failed!"); + LOG_ERR("Reading enable status failed!"); return ret; } is_enabled = ((enabled_val & config->desc->enable_mask) == config->desc->enable_val); - LOG_INST_DBG(config->log, "is_enabled: %d", is_enabled); + LOG_DBG("is_enabled: %d", is_enabled); return regulator_common_init(dev, is_enabled); } #define REGULATOR_AXP192_DEFINE(node_id, id, name) \ static struct regulator_axp192_data data_##id; \ - LOG_INSTANCE_REGISTER(name, node_id, CONFIG_REGULATOR_LOG_LEVEL); \ static const struct regulator_axp192_config config_##id = { \ .common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \ - .desc = &name##_desc, \ + .desc = &id##_desc, \ .mfd = DEVICE_DT_GET(DT_GPARENT(node_id)), \ - .i2c = I2C_DT_SPEC_GET(DT_GPARENT(node_id)), \ - LOG_INSTANCE_PTR_INIT(log, name, node_id)}; \ + .i2c = I2C_DT_SPEC_GET(DT_GPARENT(node_id))}; \ DEVICE_DT_DEFINE(node_id, regulator_axp192_init, NULL, &data_##id, &config_##id, \ - POST_KERNEL, CONFIG_REGULATOR_AXP192_INIT_PRIORITY, &api); - -#define REGULATOR_AXP192_DEFINE_COND(inst, child) \ - COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \ - (REGULATOR_AXP192_DEFINE(DT_INST_CHILD(inst, child), child##inst, child)), ()) - -#define REGULATOR_AXP192_DEFINE_ALL(inst) \ - REGULATOR_AXP192_DEFINE_COND(inst, dcdc1) \ - REGULATOR_AXP192_DEFINE_COND(inst, dcdc2) \ - REGULATOR_AXP192_DEFINE_COND(inst, dcdc3) \ - REGULATOR_AXP192_DEFINE_COND(inst, ldoio0) \ - REGULATOR_AXP192_DEFINE_COND(inst, ldo2) \ - REGULATOR_AXP192_DEFINE_COND(inst, ldo3) - -DT_INST_FOREACH_STATUS_OKAY(REGULATOR_AXP192_DEFINE_ALL) + POST_KERNEL, CONFIG_REGULATOR_AXP192_AXP2101_INIT_PRIORITY, &api); + +#define REGULATOR_AXP192_DEFINE_COND(node, child) \ + COND_CODE_1(DT_NODE_EXISTS(DT_CHILD(node, child)), \ + (REGULATOR_AXP192_DEFINE(DT_CHILD(node, child), axp192_##child, child)), ()) + +#define REGULATOR_AXP2101_DEFINE_COND(node, child) \ + COND_CODE_1(DT_NODE_EXISTS(DT_CHILD(node, child)), \ + (REGULATOR_AXP192_DEFINE(DT_CHILD(node, child), axp2101_##child, child)), ()) + +#define REGULATOR_AXP192_DEFINE_ALL(node) \ + REGULATOR_AXP192_DEFINE_COND(node, dcdc1) \ + REGULATOR_AXP192_DEFINE_COND(node, dcdc2) \ + REGULATOR_AXP192_DEFINE_COND(node, dcdc3) \ + REGULATOR_AXP192_DEFINE_COND(node, ldoio0) \ + REGULATOR_AXP192_DEFINE_COND(node, ldo2) \ + REGULATOR_AXP192_DEFINE_COND(node, ldo3) + +#define REGULATOR_AXP2101_DEFINE_ALL(node) \ + REGULATOR_AXP2101_DEFINE_COND(node, dcdc1) \ + REGULATOR_AXP2101_DEFINE_COND(node, dcdc2) \ + REGULATOR_AXP2101_DEFINE_COND(node, dcdc3) \ + REGULATOR_AXP2101_DEFINE_COND(node, dcdc4) \ + REGULATOR_AXP2101_DEFINE_COND(node, dcdc5) \ + REGULATOR_AXP2101_DEFINE_COND(node, aldo1) \ + REGULATOR_AXP2101_DEFINE_COND(node, aldo2) \ + REGULATOR_AXP2101_DEFINE_COND(node, aldo3) \ + REGULATOR_AXP2101_DEFINE_COND(node, aldo4) \ + REGULATOR_AXP2101_DEFINE_COND(node, bldo1) \ + REGULATOR_AXP2101_DEFINE_COND(node, bldo2) \ + REGULATOR_AXP2101_DEFINE_COND(node, cpusldo) \ + REGULATOR_AXP2101_DEFINE_COND(node, dldo1) \ + REGULATOR_AXP2101_DEFINE_COND(node, dldo2) + +DT_FOREACH_STATUS_OKAY(x_powers_axp192_regulator, REGULATOR_AXP192_DEFINE_ALL) +DT_FOREACH_STATUS_OKAY(x_powers_axp2101_regulator, REGULATOR_AXP2101_DEFINE_ALL) diff --git a/dts/bindings/mfd/x-powers,axp2101.yaml b/dts/bindings/mfd/x-powers,axp2101.yaml new file mode 100644 index 000000000000..accf4791ae27 --- /dev/null +++ b/dts/bindings/mfd/x-powers,axp2101.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: X-Powers AXP2101 + +compatible: "x-powers,axp2101" + +include: i2c-device.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/regulator/x-powers,axp2101-regulator.yaml b/dts/bindings/regulator/x-powers,axp2101-regulator.yaml new file mode 100644 index 000000000000..24225cd93264 --- /dev/null +++ b/dts/bindings/regulator/x-powers,axp2101-regulator.yaml @@ -0,0 +1,91 @@ +# Copyright (c), 2021 NXP +# Copyright (c), 2024 Lothar Felten +# SPDX -License-Identifier: Apache-2.0 + +description: | + AXP2101 PMIC + + The PMIC has five DCDC converters and nine LDOs. + All need to be defined as children nodes. + For example: + + i2c { + axp2101@34 { + compatible = "x-powers,axp2101"; + reg = <0x34>; + ... + regulators { + compatible = "x-powers,axp2101-regulator"; + + DCDC1 { + /* all properties for DCDC1 */ + }; + DCDC2 { + /* all properties for DCDC2 */ + }; + DCDC3 { + /* all properties for DCDC3 */ + }; + DCDC4 { + /* all properties for DCDC4 */ + }; + DCDC5 { + /* all properties for DCDC5 */ + }; + LDOA1 { + /* all properties for LDOA1 */ + }; + LDOA2 { + /* all properties for LDOA2 */ + }; + LDOA3 { + /* all properties for LDOA3 */ + }; + LDOA4 { + /* all properties for LDOA4 */ + }; + LDOB1 { + /* all properties for LDOB1 */ + }; + LDOB2 { + /* all properties for LDOB2 */ + }; + LDOC { + /* all properties for LDOC */ + }; + LDOD1 { + /* all properties for LDOD1 */ + }; + LDOD2 { + /* all properties for LDOD2 */ + }; + }; + }; + }; + +compatible: "x-powers,axp2101-regulator" + +include: base.yaml + +child-binding: + include: + - name: regulator.yaml + property-allowlist: + - regulator-init-microvolt + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-always-on + - regulator-boot-on + - regulator-boot-off + - regulator-initial-mode + - regulator-allowed-modes + + properties: + regulator-initial-mode: + type: int + default: 0 + enum: [0, 1] + description: | + Initial operating mode. AXP2101 supports 2 different power modes: + AXP2101_DCDC_MODE_AUTO: Auto (0, default) + AXP2101_DCDC_MODE_PWM: PWM diff --git a/tests/drivers/build_all/regulator/i2c.dtsi b/tests/drivers/build_all/regulator/i2c.dtsi index 489476e69cab..ea81c2c3886f 100644 --- a/tests/drivers/build_all/regulator/i2c.dtsi +++ b/tests/drivers/build_all/regulator/i2c.dtsi @@ -76,6 +76,30 @@ axp192@4 { }; }; +axp2101@7 { + compatible = "x-powers,axp2101"; + reg = <0x7>; + + regulators { + compatible = "x-powers,axp2101-regulator"; + + DCDC1 {}; + DCDC2 {}; + DCDC3 {}; + DCDC4 {}; + DCDC5 {}; + ALDO1 {}; + ALDO2 {}; + ALDO3 {}; + ALDO4 {}; + BLDO1 {}; + BLDO2 {}; + CPUSLDO {}; + DLDO1 {}; + DLDO2 {}; + }; +}; + max20335@5 { compatible = "maxim,max20335"; reg = <0x5>;