2021-09-22 08:55:23 -05:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021 NXP
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2022-11-11 12:55:56 +01:00
|
|
|
#define DT_DRV_COMPAT nxp_pca9420
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-14 15:43:45 +01:00
|
|
|
#include <errno.h>
|
|
|
|
|
2022-05-06 10:25:46 +02:00
|
|
|
#include <zephyr/kernel.h>
|
2022-11-14 15:43:45 +01:00
|
|
|
#include <zephyr/drivers/i2c.h>
|
2022-05-06 10:25:46 +02:00
|
|
|
#include <zephyr/drivers/regulator.h>
|
2022-08-30 13:25:25 -05:00
|
|
|
#include <zephyr/dt-bindings/regulator/pmic_i2c.h>
|
2022-05-06 10:25:46 +02:00
|
|
|
#include <zephyr/logging/log.h>
|
2022-11-17 10:24:05 +01:00
|
|
|
#include <zephyr/sys/linear_range.h>
|
2022-11-17 11:40:29 +01:00
|
|
|
#include <zephyr/sys/util.h>
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-11 12:55:56 +01:00
|
|
|
LOG_MODULE_REGISTER(pca9420, CONFIG_REGULATOR_LOG_LEVEL);
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-16 21:37:08 +01:00
|
|
|
/** Register memory map. See datasheet for more details. */
|
|
|
|
/** General purpose registers */
|
|
|
|
/** @brief Top level system ctrl 0 */
|
|
|
|
#define PCA9420_TOP_CNTL0 0x09U
|
|
|
|
|
|
|
|
/** Regulator status indication registers */
|
|
|
|
/** @brief Mode configuration for mode 0_0 */
|
|
|
|
#define PCA9420_MODECFG_0_0 0x22U
|
|
|
|
/** @brief Mode configuration for mode 0_1 */
|
|
|
|
#define PCA9420_MODECFG_0_1 0x23U
|
|
|
|
/** @brief Mode configuration for mode 0_2 */
|
|
|
|
#define PCA9420_MODECFG_0_2 0x24U
|
|
|
|
/** @brief Mode configuration for mode 0_3 */
|
|
|
|
#define PCA9420_MODECFG_0_3 0x25U
|
|
|
|
|
|
|
|
/** @brief VIN input current limit selection */
|
2022-11-17 11:40:29 +01:00
|
|
|
#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_POS 5U
|
2022-11-16 21:37:08 +01:00
|
|
|
#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK 0xE0U
|
2022-11-17 11:40:29 +01:00
|
|
|
#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_DISABLED 0x7U
|
2022-11-16 21:37:08 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @brief Mode control selection mask. When this bit is set, the external
|
|
|
|
* PMIC pins MODESEL0 and MODESEL1 can be used to select the active mode
|
|
|
|
*/
|
|
|
|
#define PCA9420_MODECFG_0_MODE_CTRL_SEL_MASK 0x40U
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @brief Mode configuration upon falling edge applied to ON pin. If set,
|
|
|
|
* the device will switch to mode 0 when a valid falling edge is applied.
|
|
|
|
* to the ON pin
|
|
|
|
*/
|
|
|
|
/** @brief Mode output voltage mask */
|
|
|
|
#define PCA9420_MODECFG_0_SW1_OUT_MASK 0x3FU
|
2022-11-17 10:24:05 +01:00
|
|
|
#define PCA9420_MODECFG_0_SW1_OUT_POS 0U
|
2022-11-16 21:37:08 +01:00
|
|
|
/** @brief SW2_OUT offset and voltage level mask */
|
|
|
|
#define PCA9420_MODECFG_1_SW2_OUT_MASK 0x3FU
|
2022-11-17 10:24:05 +01:00
|
|
|
#define PCA9420_MODECFG_1_SW2_OUT_POS 0U
|
2022-11-16 21:37:08 +01:00
|
|
|
/** @brief LDO1_OUT voltage level mask */
|
|
|
|
#define PCA9420_MODECFG_2_LDO1_OUT_MASK 0xF0U
|
2022-11-17 10:24:05 +01:00
|
|
|
#define PCA9420_MODECFG_2_LDO1_OUT_POS 4U
|
2022-11-16 21:37:08 +01:00
|
|
|
/** @brief SW1 Enable */
|
|
|
|
#define PCA9420_MODECFG_2_SW1_EN_MASK 0x08U
|
|
|
|
#define PCA9420_MODECFG_2_SW1_EN_VAL 0x08U
|
|
|
|
/** @brief SW2 Enable */
|
|
|
|
#define PCA9420_MODECFG_2_SW2_EN_MASK 0x04U
|
|
|
|
#define PCA9420_MODECFG_2_SW2_EN_VAL 0x04U
|
|
|
|
/** @brief LDO1 Enable */
|
|
|
|
#define PCA9420_MODECFG_2_LDO1_EN_MASK 0x02U
|
|
|
|
#define PCA9420_MODECFG_2_LDO1_EN_VAL 0x02U
|
|
|
|
/** @brief LDO2 Enable */
|
|
|
|
#define PCA9420_MODECFG_2_LDO2_EN_MASK 0x01U
|
|
|
|
#define PCA9420_MODECFG_2_LDO2_EN_VAL 0x01U
|
|
|
|
/** @brief LDO2_OUT offset and voltage level mask */
|
|
|
|
#define PCA9420_MODECFG_3_LDO2_OUT_MASK 0x3FU
|
2022-11-17 10:24:05 +01:00
|
|
|
#define PCA9420_MODECFG_3_LDO2_OUT_POS 0U
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-17 11:40:29 +01:00
|
|
|
/** VIN ILIM resolution, uA/LSB */
|
|
|
|
#define PCA9420_VIN_ILIM_UA_LSB 170000
|
|
|
|
/** VIN ILIM minimum value, uA */
|
|
|
|
#define PCA9420_VIN_ILIM_MIN_UA 85000
|
|
|
|
|
2022-11-16 21:37:08 +01:00
|
|
|
struct regulator_pca9420_desc {
|
|
|
|
uint8_t enable_reg;
|
|
|
|
uint8_t enable_mask;
|
|
|
|
uint8_t enable_val;
|
|
|
|
uint8_t vsel_reg;
|
|
|
|
uint8_t vsel_mask;
|
2022-11-17 10:24:05 +01:00
|
|
|
uint8_t vsel_pos;
|
|
|
|
uint8_t num_ranges;
|
|
|
|
const struct linear_range *ranges;
|
2022-11-16 21:37:08 +01:00
|
|
|
};
|
|
|
|
|
2022-11-14 15:37:51 +01:00
|
|
|
struct regulator_pca9420_data {
|
2022-01-25 11:58:43 -06:00
|
|
|
struct onoff_sync_service srv;
|
2022-11-17 11:40:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct regulator_pca9420_common_config {
|
|
|
|
struct i2c_dt_spec i2c;
|
|
|
|
int32_t vin_ilim_ua;
|
2022-11-17 12:30:43 +01:00
|
|
|
uint8_t modesel_reg;
|
|
|
|
uint8_t modesel_mask;
|
|
|
|
const uint16_t *allowed_modes;
|
|
|
|
int num_modes;
|
|
|
|
uint16_t initial_mode;
|
2022-01-25 11:58:43 -06:00
|
|
|
};
|
|
|
|
|
2022-11-14 15:37:51 +01:00
|
|
|
struct regulator_pca9420_config {
|
2022-11-17 12:30:43 +01:00
|
|
|
int32_t max_ua;
|
2021-09-22 08:55:23 -05:00
|
|
|
bool enable_inverted;
|
2022-10-13 13:11:20 -05:00
|
|
|
bool boot_on;
|
2022-11-16 21:37:08 +01:00
|
|
|
const struct regulator_pca9420_desc *desc;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct device *parent;
|
2022-11-16 21:37:08 +01:00
|
|
|
};
|
|
|
|
|
2022-11-17 10:24:05 +01:00
|
|
|
static const struct linear_range buck1_ranges[] = {
|
|
|
|
LINEAR_RANGE_INIT(500000, 25000U, 0x0U, 0x28U),
|
|
|
|
LINEAR_RANGE_INIT(1500000, 0U, 0x29U, 0x3E),
|
|
|
|
LINEAR_RANGE_INIT(1800000, 0U, 0x3FU, 0x3FU),
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct linear_range buck2_ranges[] = {
|
|
|
|
LINEAR_RANGE_INIT(1500000, 25000U, 0x0U, 0x18U),
|
|
|
|
LINEAR_RANGE_INIT(2100000, 0U, 0x19U, 0x1F),
|
|
|
|
LINEAR_RANGE_INIT(2700000, 25000U, 0x20U, 0x38U),
|
|
|
|
LINEAR_RANGE_INIT(3300000, 0U, 0x39U, 0x3F),
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct linear_range ldo1_ranges[] = {
|
|
|
|
LINEAR_RANGE_INIT(1700000, 25000U, 0x0U, 0x9U),
|
|
|
|
LINEAR_RANGE_INIT(1900000, 0U, 0x9U, 0xFU),
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct linear_range ldo2_ranges[] = {
|
|
|
|
LINEAR_RANGE_INIT(1500000, 25000U, 0x0U, 0x18U),
|
|
|
|
LINEAR_RANGE_INIT(2100000, 0U, 0x19U, 0x1FU),
|
|
|
|
LINEAR_RANGE_INIT(2700000, 25000U, 0x20U, 0x38U),
|
|
|
|
LINEAR_RANGE_INIT(3300000, 0U, 0x39U, 0x3FU),
|
|
|
|
};
|
|
|
|
|
2022-11-16 21:37:08 +01:00
|
|
|
static const struct regulator_pca9420_desc buck1_desc = {
|
|
|
|
.enable_reg = PCA9420_MODECFG_0_2,
|
|
|
|
.enable_mask = PCA9420_MODECFG_2_SW1_EN_MASK,
|
|
|
|
.enable_val = PCA9420_MODECFG_2_SW1_EN_VAL,
|
|
|
|
.vsel_mask = PCA9420_MODECFG_0_SW1_OUT_MASK,
|
2022-11-17 10:24:05 +01:00
|
|
|
.vsel_pos = PCA9420_MODECFG_0_SW1_OUT_POS,
|
2022-11-16 21:37:08 +01:00
|
|
|
.vsel_reg = PCA9420_MODECFG_0_0,
|
2022-11-17 10:24:05 +01:00
|
|
|
.ranges = buck1_ranges,
|
|
|
|
.num_ranges = ARRAY_SIZE(buck1_ranges),
|
2022-11-16 21:37:08 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct regulator_pca9420_desc buck2_desc = {
|
|
|
|
.enable_reg = PCA9420_MODECFG_0_2,
|
|
|
|
.enable_mask = PCA9420_MODECFG_2_SW2_EN_MASK,
|
|
|
|
.enable_val = PCA9420_MODECFG_2_SW2_EN_VAL,
|
|
|
|
.vsel_mask = PCA9420_MODECFG_1_SW2_OUT_MASK,
|
2022-11-17 10:24:05 +01:00
|
|
|
.vsel_pos = PCA9420_MODECFG_1_SW2_OUT_POS,
|
2022-11-16 21:37:08 +01:00
|
|
|
.vsel_reg = PCA9420_MODECFG_0_1,
|
2022-11-17 10:24:05 +01:00
|
|
|
.ranges = buck2_ranges,
|
|
|
|
.num_ranges = ARRAY_SIZE(buck2_ranges),
|
2022-11-16 21:37:08 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct regulator_pca9420_desc ldo1_desc = {
|
|
|
|
.enable_reg = PCA9420_MODECFG_0_2,
|
|
|
|
.enable_mask = PCA9420_MODECFG_2_LDO1_EN_MASK,
|
|
|
|
.enable_val = PCA9420_MODECFG_2_LDO1_EN_VAL,
|
|
|
|
.vsel_mask = PCA9420_MODECFG_2_LDO1_OUT_MASK,
|
2022-11-17 10:24:05 +01:00
|
|
|
.vsel_pos = PCA9420_MODECFG_2_LDO1_OUT_POS,
|
2022-11-16 21:37:08 +01:00
|
|
|
.vsel_reg = PCA9420_MODECFG_0_2,
|
2022-11-17 10:24:05 +01:00
|
|
|
.ranges = ldo1_ranges,
|
|
|
|
.num_ranges = ARRAY_SIZE(ldo1_ranges),
|
2022-11-16 21:37:08 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct regulator_pca9420_desc ldo2_desc = {
|
|
|
|
.enable_reg = PCA9420_MODECFG_0_2,
|
|
|
|
.enable_mask = PCA9420_MODECFG_2_LDO2_EN_MASK,
|
|
|
|
.enable_val = PCA9420_MODECFG_2_LDO2_EN_VAL,
|
|
|
|
.vsel_reg = PCA9420_MODECFG_0_3,
|
|
|
|
.vsel_mask = PCA9420_MODECFG_3_LDO2_OUT_MASK,
|
2022-11-17 10:24:05 +01:00
|
|
|
.vsel_pos = PCA9420_MODECFG_3_LDO2_OUT_POS,
|
|
|
|
.ranges = ldo2_ranges,
|
|
|
|
.num_ranges = ARRAY_SIZE(ldo2_ranges),
|
2021-09-22 08:55:23 -05:00
|
|
|
};
|
|
|
|
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_is_supported_voltage(const struct device *dev,
|
2022-11-11 14:04:11 +01:00
|
|
|
int32_t min_uv,
|
|
|
|
int32_t max_uv);
|
2022-11-11 12:35:12 +01:00
|
|
|
|
2022-08-30 13:04:56 -05:00
|
|
|
/**
|
|
|
|
* Reads a register from the PMIC
|
|
|
|
* Returns 0 on success, or errno on error
|
|
|
|
*/
|
2022-11-17 11:40:29 +01:00
|
|
|
static int regulator_pca9420_read_register(const struct i2c_dt_spec *i2c,
|
2022-11-14 15:37:51 +01:00
|
|
|
uint8_t reg, uint8_t *out)
|
2022-08-30 13:04:56 -05:00
|
|
|
{
|
2022-08-30 13:25:25 -05:00
|
|
|
int ret;
|
|
|
|
|
2022-11-17 11:40:29 +01:00
|
|
|
ret = i2c_reg_read_byte_dt(i2c, reg, out);
|
2022-08-30 13:25:25 -05:00
|
|
|
LOG_DBG("READ 0x%x: 0x%x", reg, *out);
|
|
|
|
return ret;
|
2022-08-30 13:04:56 -05:00
|
|
|
}
|
|
|
|
|
2021-09-22 08:55:23 -05:00
|
|
|
/**
|
|
|
|
* Modifies a register within the PMIC
|
|
|
|
* Returns 0 on success, or errno on error
|
|
|
|
*/
|
2022-11-17 11:40:29 +01:00
|
|
|
static int regulator_pca9420_modify_register(const struct i2c_dt_spec *i2c,
|
2022-11-14 15:37:51 +01:00
|
|
|
uint8_t reg, uint8_t reg_mask,
|
|
|
|
uint8_t reg_val)
|
2021-09-22 08:55:23 -05:00
|
|
|
{
|
|
|
|
uint8_t reg_current;
|
|
|
|
int rc;
|
|
|
|
|
2022-11-17 11:40:29 +01:00
|
|
|
rc = regulator_pca9420_read_register(i2c, reg, ®_current);
|
2021-09-22 08:55:23 -05:00
|
|
|
if (rc) {
|
|
|
|
return rc;
|
|
|
|
}
|
2022-08-30 13:25:25 -05:00
|
|
|
|
2021-09-22 08:55:23 -05:00
|
|
|
reg_current &= ~reg_mask;
|
2022-08-30 13:25:25 -05:00
|
|
|
reg_current |= (reg_val & reg_mask);
|
|
|
|
LOG_DBG("WRITE 0x%02X to 0x%02X at I2C addr 0x%02X", reg_current,
|
2022-11-17 11:40:29 +01:00
|
|
|
reg, i2c->addr);
|
|
|
|
return i2c_reg_write_byte_dt(i2c, reg, reg_current);
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
|
|
|
|
2022-10-13 12:08:37 -05:00
|
|
|
/*
|
|
|
|
* Internal helper function- gets the voltage from a regulator, with an
|
|
|
|
* offset applied to the vsel_reg. Useful to support reading voltages
|
|
|
|
* in another target mode
|
|
|
|
*/
|
2022-11-17 10:24:05 +01:00
|
|
|
static int regulator_pca9420_get_voltage_offset(const struct device *dev,
|
|
|
|
uint32_t off, int32_t *voltage)
|
2022-10-13 12:08:37 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
|
|
|
|
2022-11-17 10:24:05 +01:00
|
|
|
int ret;
|
2022-10-13 12:08:37 -05:00
|
|
|
uint8_t raw_reg;
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
ret = regulator_pca9420_read_register(&cconfig->i2c,
|
2022-11-17 11:40:29 +01:00
|
|
|
config->desc->vsel_reg + off,
|
2022-11-17 10:24:05 +01:00
|
|
|
&raw_reg);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
2022-11-17 10:24:05 +01:00
|
|
|
|
|
|
|
raw_reg = (raw_reg & config->desc->vsel_mask) >> config->desc->vsel_pos;
|
|
|
|
|
|
|
|
return linear_range_group_get_value(config->desc->ranges,
|
|
|
|
config->desc->num_ranges, raw_reg,
|
|
|
|
voltage);
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal helper function- sets the voltage for a regulator, with an
|
|
|
|
* offset applied to the vsel_reg. Useful to support setting voltages in
|
|
|
|
* another target mode.
|
|
|
|
*/
|
2022-11-11 13:53:11 +01:00
|
|
|
static int regulator_set_voltage_offset(const struct device *dev,
|
2022-11-11 14:04:11 +01:00
|
|
|
int32_t min_uv, int32_t max_uv,
|
2022-11-11 13:53:11 +01:00
|
|
|
uint32_t off)
|
2022-10-13 12:08:37 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-11-17 10:24:05 +01:00
|
|
|
uint16_t idx;
|
|
|
|
int ret;
|
2022-10-13 12:08:37 -05:00
|
|
|
|
2022-11-17 10:24:05 +01:00
|
|
|
ret = linear_range_group_get_win_index(config->desc->ranges,
|
|
|
|
config->desc->num_ranges, min_uv,
|
|
|
|
max_uv, &idx);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
2022-11-17 10:24:05 +01:00
|
|
|
|
|
|
|
idx <<= config->desc->vsel_pos;
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
return regulator_pca9420_modify_register(&cconfig->i2c,
|
2022-11-16 21:37:08 +01:00
|
|
|
config->desc->vsel_reg + off,
|
|
|
|
config->desc->vsel_mask,
|
2022-11-17 10:24:05 +01:00
|
|
|
(uint8_t)idx);
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
|
|
|
|
2021-09-22 08:55:23 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* Returns the number of supported voltages
|
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_count_voltages(const struct device *dev)
|
2021-09-22 08:55:23 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-01-19 11:00:48 +01:00
|
|
|
|
2022-11-17 10:24:05 +01:00
|
|
|
return linear_range_group_values_count(config->desc->ranges,
|
|
|
|
config->desc->num_ranges);
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
|
|
|
|
2022-08-30 13:25:25 -05:00
|
|
|
/**
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* Counts the number of modes supported by a regulator
|
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_count_modes(const struct device *dev)
|
2022-08-30 13:25:25 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-08-30 13:25:25 -05:00
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
return cconfig->num_modes;
|
2022-08-30 13:25:25 -05:00
|
|
|
}
|
|
|
|
|
2021-09-22 08:55:23 -05:00
|
|
|
/**
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* Returns the supported voltage in uV for a given selector value
|
|
|
|
*/
|
2022-11-11 13:53:11 +01:00
|
|
|
static int32_t regulator_pca9420_list_voltages(const struct device *dev,
|
|
|
|
unsigned int selector)
|
2021-09-22 08:55:23 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 10:24:05 +01:00
|
|
|
int32_t value;
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-17 10:24:05 +01:00
|
|
|
if (linear_range_group_get_value(config->desc->ranges,
|
|
|
|
config->desc->num_ranges, selector,
|
|
|
|
&value) < 0) {
|
|
|
|
return 0;
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
2022-11-17 10:24:05 +01:00
|
|
|
|
|
|
|
return value;
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
|
|
|
|
2021-09-24 17:11:54 -05:00
|
|
|
/**
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* Returns true if the regulator supports a voltage in the given range.
|
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_is_supported_voltage(const struct device *dev,
|
2022-11-11 14:04:11 +01:00
|
|
|
int32_t min_uv,
|
|
|
|
int32_t max_uv)
|
2021-09-22 08:55:23 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 10:24:05 +01:00
|
|
|
uint16_t idx;
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-17 10:24:05 +01:00
|
|
|
return linear_range_group_get_win_index(config->desc->ranges,
|
|
|
|
config->desc->num_ranges,
|
|
|
|
min_uv, max_uv, &idx);
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
|
|
|
|
2021-09-24 17:11:54 -05:00
|
|
|
/**
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* Sets the output voltage to the closest supported voltage value
|
|
|
|
*/
|
2022-11-11 13:53:11 +01:00
|
|
|
static int regulator_pca9420_set_voltage(const struct device *dev,
|
2022-11-11 14:04:11 +01:00
|
|
|
int32_t min_uv, int32_t max_uv)
|
2021-09-24 17:11:54 -05:00
|
|
|
{
|
2022-11-11 14:04:11 +01:00
|
|
|
return regulator_set_voltage_offset(dev, min_uv, max_uv, 0);
|
2021-09-24 17:11:54 -05:00
|
|
|
}
|
|
|
|
|
2022-10-13 12:08:37 -05:00
|
|
|
|
2021-09-24 17:11:54 -05:00
|
|
|
/**
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* Gets the current output voltage in uV
|
|
|
|
*/
|
2022-11-11 13:53:11 +01:00
|
|
|
static int32_t regulator_pca9420_get_voltage(const struct device *dev)
|
2021-09-24 17:11:54 -05:00
|
|
|
{
|
2022-11-17 10:24:05 +01:00
|
|
|
int32_t voltage = 0;
|
|
|
|
|
|
|
|
(void)regulator_pca9420_get_voltage_offset(dev, 0, &voltage);
|
|
|
|
|
|
|
|
return voltage;
|
2021-09-24 17:11:54 -05:00
|
|
|
}
|
|
|
|
|
2021-09-24 18:32:32 -05:00
|
|
|
/**
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* Gets the set current limit for the regulator
|
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_get_current_limit(const struct device *dev)
|
2021-09-24 18:32:32 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2021-09-24 17:11:54 -05:00
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
if (cconfig->vin_ilim_ua == 0U) {
|
2022-11-17 11:40:29 +01:00
|
|
|
return config->max_ua;
|
2021-09-24 18:32:32 -05:00
|
|
|
}
|
2022-11-17 11:40:29 +01:00
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
return MIN(config->max_ua, cconfig->vin_ilim_ua);
|
2021-09-24 18:32:32 -05:00
|
|
|
}
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-10-13 12:08:37 -05:00
|
|
|
/*
|
|
|
|
* Part of the extended regulator consumer API.
|
|
|
|
* sets the target voltage for a given regulator mode. This mode does
|
|
|
|
* not need to be the active mode. This API can be used to configure
|
|
|
|
* voltages for a mode, then the regulator can be switched to that mode
|
2022-11-11 12:55:56 +01:00
|
|
|
* with the regulator_pca9420_set_mode api
|
2022-10-13 12:08:37 -05:00
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_set_mode_voltage(const struct device *dev,
|
2022-11-11 14:04:11 +01:00
|
|
|
uint32_t mode, int32_t min_uv,
|
|
|
|
int32_t max_uv)
|
2022-10-13 12:08:37 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-10-13 12:08:37 -05:00
|
|
|
uint8_t i, sel_off;
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
if (cconfig->num_modes == 0) {
|
2022-10-13 12:08:37 -05:00
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for mode ID in allowed modes. */
|
2022-11-17 12:30:43 +01:00
|
|
|
for (i = 0 ; i < cconfig->num_modes; i++) {
|
|
|
|
if (cconfig->allowed_modes[i] == mode) {
|
2022-10-13 12:08:37 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-11-17 12:30:43 +01:00
|
|
|
if (i == cconfig->num_modes) {
|
2022-10-13 12:08:37 -05:00
|
|
|
/* Mode was not found */
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
2022-11-11 14:04:11 +01:00
|
|
|
return regulator_set_voltage_offset(dev, min_uv, max_uv, sel_off);
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Part of the extended regulator consumer API.
|
|
|
|
* Disables the regulator in a given mode. Does not implement the
|
|
|
|
* onoff service, as this is incompatible with multiple mode operation
|
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_mode_disable(const struct device *dev,
|
|
|
|
uint32_t mode)
|
2022-10-13 12:08:37 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-10-13 12:08:37 -05:00
|
|
|
uint8_t i, sel_off, dis_val;
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
if (cconfig->num_modes == 0) {
|
2022-10-13 12:08:37 -05:00
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for mode ID in allowed modes. */
|
2022-11-17 12:30:43 +01:00
|
|
|
for (i = 0 ; i < cconfig->num_modes; i++) {
|
|
|
|
if (cconfig->allowed_modes[i] == mode) {
|
2022-10-13 12:08:37 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-11-17 12:30:43 +01:00
|
|
|
if (i == cconfig->num_modes) {
|
2022-10-13 12:08:37 -05:00
|
|
|
/* Mode was not found */
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
2022-11-16 21:37:08 +01:00
|
|
|
dis_val = config->enable_inverted ? config->desc->enable_val : 0;
|
|
|
|
return regulator_pca9420_modify_register(
|
2022-11-17 12:30:43 +01:00
|
|
|
&cconfig->i2c, config->desc->enable_reg + sel_off,
|
2022-11-16 21:37:08 +01:00
|
|
|
config->desc->enable_mask, dis_val);
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Part of the extended regulator consumer API.
|
|
|
|
* Enables the regulator in a given mode. Does not implement the
|
|
|
|
* onoff service, as this is incompatible with multiple mode operation
|
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_mode_enable(const struct device *dev,
|
|
|
|
uint32_t mode)
|
2022-10-13 12:08:37 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-10-13 12:08:37 -05:00
|
|
|
uint8_t i, sel_off, en_val;
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
if (cconfig->num_modes == 0) {
|
2022-10-13 12:08:37 -05:00
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for mode ID in allowed modes. */
|
2022-11-17 12:30:43 +01:00
|
|
|
for (i = 0 ; i < cconfig->num_modes; i++) {
|
|
|
|
if (cconfig->allowed_modes[i] == mode) {
|
2022-10-13 12:08:37 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-11-17 12:30:43 +01:00
|
|
|
if (i == cconfig->num_modes) {
|
2022-10-13 12:08:37 -05:00
|
|
|
/* Mode was not found */
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
2022-11-16 21:37:08 +01:00
|
|
|
en_val = config->enable_inverted ? 0 : config->desc->enable_val;
|
|
|
|
return regulator_pca9420_modify_register(
|
2022-11-17 12:30:43 +01:00
|
|
|
&cconfig->i2c, config->desc->enable_reg + sel_off,
|
2022-11-16 21:37:08 +01:00
|
|
|
config->desc->enable_mask, en_val);
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Part of the extended regulator consumer API.
|
|
|
|
* gets the target voltage for a given regulator mode. This mode does
|
|
|
|
* not need to be the active mode. This API can be used to read voltages
|
|
|
|
* from a regulator mode other than the default.
|
|
|
|
*/
|
2022-11-11 13:53:11 +01:00
|
|
|
static int32_t regulator_pca9420_get_mode_voltage(const struct device *dev,
|
|
|
|
uint32_t mode)
|
2022-10-13 12:08:37 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-10-13 12:08:37 -05:00
|
|
|
uint8_t i, sel_off;
|
2022-11-17 10:24:05 +01:00
|
|
|
int32_t voltage;
|
2022-10-13 12:08:37 -05:00
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
if (cconfig->num_modes == 0) {
|
2022-10-13 12:08:37 -05:00
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for mode ID in allowed modes. */
|
2022-11-17 12:30:43 +01:00
|
|
|
for (i = 0 ; i < cconfig->num_modes; i++) {
|
|
|
|
if (cconfig->allowed_modes[i] == mode) {
|
2022-10-13 12:08:37 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-11-17 12:30:43 +01:00
|
|
|
if (i == cconfig->num_modes) {
|
2022-10-13 12:08:37 -05:00
|
|
|
/* Mode was not found */
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
2022-11-17 10:24:05 +01:00
|
|
|
|
|
|
|
(void)regulator_pca9420_get_voltage_offset(dev, sel_off, &voltage);
|
|
|
|
|
|
|
|
return voltage;
|
2022-10-13 12:08:37 -05:00
|
|
|
}
|
|
|
|
|
2022-08-30 13:25:25 -05:00
|
|
|
/*
|
|
|
|
* Part of the extended regulator consumer API
|
|
|
|
* switches the regulator to a given mode. This API will apply a mode for
|
2022-10-13 11:23:20 -05:00
|
|
|
* the regulator.
|
2022-08-30 13:25:25 -05:00
|
|
|
*/
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_set_mode(const struct device *dev, uint32_t mode)
|
2022-08-30 13:25:25 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-08-30 13:25:25 -05:00
|
|
|
int rc;
|
|
|
|
uint8_t i, sel_off;
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
if (cconfig->num_modes == 0) {
|
2022-08-30 13:25:25 -05:00
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for mode ID in allowed modes. */
|
2022-11-17 12:30:43 +01:00
|
|
|
for (i = 0 ; i < cconfig->num_modes; i++) {
|
|
|
|
if (cconfig->allowed_modes[i] == mode) {
|
2022-08-30 13:25:25 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-11-17 12:30:43 +01:00
|
|
|
if (i == cconfig->num_modes) {
|
2022-08-30 13:25:25 -05:00
|
|
|
/* Mode was not found */
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
|
|
|
/* Configure mode */
|
|
|
|
if (mode & PMIC_MODE_FLAG_MODESEL_MULTI_REG) {
|
|
|
|
/* Select mode with offset calculation */
|
2022-11-14 15:37:51 +01:00
|
|
|
rc = regulator_pca9420_modify_register(
|
2022-11-17 12:30:43 +01:00
|
|
|
&cconfig->i2c,
|
|
|
|
cconfig->modesel_reg + sel_off,
|
|
|
|
mode & PMIC_MODE_SELECTOR_MASK,
|
|
|
|
cconfig->modesel_mask);
|
2022-08-30 13:25:25 -05:00
|
|
|
} else {
|
|
|
|
/* Select mode without offset to modesel_reg */
|
2022-11-14 15:37:51 +01:00
|
|
|
rc = regulator_pca9420_modify_register(
|
2022-11-17 12:30:43 +01:00
|
|
|
&cconfig->i2c, cconfig->modesel_reg,
|
|
|
|
mode & PMIC_MODE_SELECTOR_MASK,
|
|
|
|
cconfig->modesel_mask);
|
2022-08-30 13:25:25 -05:00
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_enable(const struct device *dev,
|
|
|
|
struct onoff_client *cli)
|
2021-09-22 08:55:23 -05:00
|
|
|
{
|
|
|
|
k_spinlock_key_t key;
|
|
|
|
int rc;
|
|
|
|
uint8_t en_val;
|
2022-11-14 15:37:51 +01:00
|
|
|
struct regulator_pca9420_data *data = dev->data;
|
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2021-09-22 08:55:23 -05:00
|
|
|
|
|
|
|
LOG_DBG("Enabling regulator");
|
|
|
|
rc = onoff_sync_lock(&data->srv, &key);
|
|
|
|
if (rc) {
|
|
|
|
/* Request has already enabled PMIC */
|
|
|
|
return onoff_sync_finalize(&data->srv, key, cli, rc, true);
|
|
|
|
}
|
2022-11-16 21:37:08 +01:00
|
|
|
en_val = config->enable_inverted ? 0 : config->desc->enable_val;
|
2022-11-17 12:30:43 +01:00
|
|
|
rc = regulator_pca9420_modify_register(&cconfig->i2c,
|
2022-11-17 11:40:29 +01:00
|
|
|
config->desc->enable_reg,
|
2022-11-16 21:37:08 +01:00
|
|
|
config->desc->enable_mask,
|
|
|
|
en_val);
|
2022-09-26 15:03:38 -05:00
|
|
|
if (rc != 0) {
|
2021-09-22 08:55:23 -05:00
|
|
|
return onoff_sync_finalize(&data->srv, key, NULL, rc, false);
|
|
|
|
}
|
|
|
|
return onoff_sync_finalize(&data->srv, key, cli, rc, true);
|
|
|
|
}
|
|
|
|
|
2022-11-11 12:55:56 +01:00
|
|
|
static int regulator_pca9420_disable(const struct device *dev)
|
2021-09-22 08:55:23 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
struct regulator_pca9420_data *data = dev->data;
|
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2021-09-22 08:55:23 -05:00
|
|
|
k_spinlock_key_t key;
|
|
|
|
uint8_t dis_val;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
LOG_DBG("Disabling regulator");
|
|
|
|
rc = onoff_sync_lock(&data->srv, &key);
|
|
|
|
if (rc == 0) {
|
|
|
|
rc = -EINVAL;
|
|
|
|
return onoff_sync_finalize(&data->srv, key, NULL, rc, false);
|
2022-09-26 15:03:38 -05:00
|
|
|
} else if (rc == 1) {
|
|
|
|
/* Disable regulator */
|
2022-11-16 21:37:08 +01:00
|
|
|
dis_val = config->enable_inverted ? config->desc->enable_val : 0;
|
|
|
|
rc = regulator_pca9420_modify_register(
|
2022-11-17 12:30:43 +01:00
|
|
|
&cconfig->i2c, config->desc->enable_reg,
|
2022-11-16 21:37:08 +01:00
|
|
|
config->desc->enable_mask, dis_val);
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
2022-09-26 15:03:38 -05:00
|
|
|
return onoff_sync_finalize(&data->srv, key, NULL, rc, false);
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
|
|
|
|
2022-11-14 15:37:51 +01:00
|
|
|
static int regulator_pca9420_init(const struct device *dev)
|
2021-09-22 08:55:23 -05:00
|
|
|
{
|
2022-11-14 15:37:51 +01:00
|
|
|
const struct regulator_pca9420_config *config = dev->config;
|
2022-11-17 12:30:43 +01:00
|
|
|
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
2022-10-13 13:11:20 -05:00
|
|
|
int rc = 0;
|
2021-09-22 08:55:23 -05:00
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
if (!device_is_ready(config->parent)) {
|
2021-09-22 08:55:23 -05:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
2022-11-17 12:30:43 +01:00
|
|
|
|
2022-10-13 13:11:20 -05:00
|
|
|
if (config->boot_on) {
|
2022-11-11 12:55:56 +01:00
|
|
|
rc = regulator_pca9420_enable(dev, NULL);
|
2022-10-13 13:11:20 -05:00
|
|
|
}
|
2022-11-17 12:30:43 +01:00
|
|
|
if (cconfig->initial_mode) {
|
|
|
|
rc = regulator_pca9420_set_mode(dev, cconfig->initial_mode);
|
2022-08-30 13:25:25 -05:00
|
|
|
}
|
2022-10-13 13:11:20 -05:00
|
|
|
return rc;
|
2021-09-22 08:55:23 -05:00
|
|
|
}
|
|
|
|
|
2022-11-17 11:40:29 +01:00
|
|
|
static int regulator_pca9420_common_init(const struct device *dev)
|
|
|
|
{
|
|
|
|
const struct regulator_pca9420_common_config *config = dev->config;
|
|
|
|
uint8_t reg_val = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_DISABLED;
|
|
|
|
|
|
|
|
if (!device_is_ready(config->i2c.bus)) {
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* configure VIN current limit */
|
|
|
|
if (config->vin_ilim_ua != 0U) {
|
|
|
|
reg_val = (config->vin_ilim_ua - PCA9420_VIN_ILIM_MIN_UA) /
|
|
|
|
PCA9420_VIN_ILIM_UA_LSB;
|
|
|
|
}
|
|
|
|
|
|
|
|
return regulator_pca9420_modify_register(
|
|
|
|
&config->i2c, PCA9420_TOP_CNTL0,
|
|
|
|
PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK,
|
|
|
|
reg_val << PCA9420_TOP_CNTL0_VIN_ILIM_SEL_POS);
|
|
|
|
}
|
|
|
|
|
2021-09-22 08:55:23 -05:00
|
|
|
|
|
|
|
static const struct regulator_driver_api api = {
|
2022-11-11 12:55:56 +01:00
|
|
|
.enable = regulator_pca9420_enable,
|
|
|
|
.disable = regulator_pca9420_disable,
|
|
|
|
.count_voltages = regulator_pca9420_count_voltages,
|
|
|
|
.count_modes = regulator_pca9420_count_modes,
|
|
|
|
.list_voltages = regulator_pca9420_list_voltages,
|
|
|
|
.is_supported_voltage = regulator_pca9420_is_supported_voltage,
|
|
|
|
.set_voltage = regulator_pca9420_set_voltage,
|
|
|
|
.get_voltage = regulator_pca9420_get_voltage,
|
|
|
|
.get_current_limit = regulator_pca9420_get_current_limit,
|
|
|
|
.set_mode = regulator_pca9420_set_mode,
|
|
|
|
.set_mode_voltage = regulator_pca9420_set_mode_voltage,
|
|
|
|
.get_mode_voltage = regulator_pca9420_get_mode_voltage,
|
|
|
|
.mode_disable = regulator_pca9420_mode_disable,
|
|
|
|
.mode_enable = regulator_pca9420_mode_enable,
|
2021-09-22 08:55:23 -05:00
|
|
|
};
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
#define REGULATOR_PCA9420_DEFINE(node_id, id, name, _parent) \
|
2022-11-16 16:27:08 +01:00
|
|
|
static struct regulator_pca9420_data data_##id; \
|
2022-11-14 12:37:55 +01:00
|
|
|
\
|
2022-11-16 16:27:08 +01:00
|
|
|
static const struct regulator_pca9420_config config_##id = { \
|
2022-11-17 11:40:29 +01:00
|
|
|
.max_ua = DT_PROP(node_id, regulator_max_microamp), \
|
2022-11-14 12:37:55 +01:00
|
|
|
.enable_inverted = DT_PROP(node_id, enable_inverted), \
|
2022-11-16 14:25:59 +01:00
|
|
|
.boot_on = DT_PROP(node_id, regulator_boot_on), \
|
2022-11-16 21:37:08 +01:00
|
|
|
.desc = &name ## _desc, \
|
2022-11-17 12:30:43 +01:00
|
|
|
.parent = _parent, \
|
2022-11-14 12:37:55 +01:00
|
|
|
}; \
|
|
|
|
\
|
2022-11-16 16:27:08 +01:00
|
|
|
DEVICE_DT_DEFINE(node_id, regulator_pca9420_init, NULL, &data_##id, \
|
|
|
|
&config_##id, POST_KERNEL, \
|
2022-11-14 12:37:55 +01:00
|
|
|
CONFIG_REGULATOR_PCA9420_INIT_PRIORITY, &api);
|
|
|
|
|
2022-11-17 12:30:43 +01:00
|
|
|
#define REGULATOR_PCA9420_DEFINE_COND(inst, child, parent) \
|
2022-11-16 16:27:08 +01:00
|
|
|
COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \
|
|
|
|
(REGULATOR_PCA9420_DEFINE(DT_INST_CHILD(inst, child), \
|
2022-11-17 12:30:43 +01:00
|
|
|
child ## inst, child, parent)), \
|
2022-11-17 11:40:29 +01:00
|
|
|
())
|
2022-11-14 12:37:55 +01:00
|
|
|
|
|
|
|
#define REGULATOR_PCA9420_DEFINE_ALL(inst) \
|
2022-11-17 12:30:43 +01:00
|
|
|
static const uint16_t allowed_modes_##inst[] = \
|
|
|
|
DT_INST_PROP_OR(inst, regulator_allowed_modes, {}); \
|
|
|
|
\
|
2022-11-17 11:40:29 +01:00
|
|
|
static const struct regulator_pca9420_common_config config_##inst = { \
|
|
|
|
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
|
|
|
.vin_ilim_ua = DT_INST_PROP(inst, nxp_vin_ilim_microamp), \
|
2022-11-17 12:30:43 +01:00
|
|
|
.allowed_modes = allowed_modes_##inst, \
|
|
|
|
.num_modes = ARRAY_SIZE(allowed_modes_##inst), \
|
|
|
|
.initial_mode = \
|
|
|
|
DT_INST_PROP_OR(inst, regulator_initial_mode, 0), \
|
|
|
|
.modesel_reg = DT_INST_PROP_OR(inst, modesel_reg, 0), \
|
|
|
|
.modesel_mask = DT_INST_PROP_OR(inst, modesel_mask, 0), \
|
2022-11-17 11:40:29 +01:00
|
|
|
}; \
|
|
|
|
\
|
|
|
|
DEVICE_DT_INST_DEFINE(inst, regulator_pca9420_common_init, NULL, NULL, \
|
|
|
|
&config_##inst, POST_KERNEL, \
|
2022-11-17 12:30:43 +01:00
|
|
|
CONFIG_REGULATOR_PCA9420_COMMON_INIT_PRIORITY, \
|
|
|
|
NULL); \
|
2022-11-17 11:40:29 +01:00
|
|
|
\
|
2022-11-17 12:30:43 +01:00
|
|
|
REGULATOR_PCA9420_DEFINE_COND(inst, buck1, DEVICE_DT_INST_GET(inst)) \
|
|
|
|
REGULATOR_PCA9420_DEFINE_COND(inst, buck2, DEVICE_DT_INST_GET(inst)) \
|
|
|
|
REGULATOR_PCA9420_DEFINE_COND(inst, ldo1, DEVICE_DT_INST_GET(inst)) \
|
|
|
|
REGULATOR_PCA9420_DEFINE_COND(inst, ldo2, DEVICE_DT_INST_GET(inst))
|
2022-11-14 12:37:55 +01:00
|
|
|
|
|
|
|
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_PCA9420_DEFINE_ALL)
|