drivers: regulator: pca9420: fix VIN current limit setting
The driver had a conceptual issue regarding current limitation. PCA9420 is able to limit the current flowing through VIN, ie input current. This is a global setting, not individual to each regulator. This patch creates a new DT property: nxp,vin-ilim-microamp to specify such limit. It is applied when the device is initialized. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
parent
dcd63d288f
commit
9219d3d2b5
5 changed files with 100 additions and 136 deletions
|
@ -182,8 +182,6 @@ arduino_serial: &flexcomm12 {
|
||||||
modesel-reg = <PCA9420_MODECFG_0_0>;
|
modesel-reg = <PCA9420_MODECFG_0_0>;
|
||||||
modesel-mask = <PCA9420_MODECFG_0_MODE_CTRL_SEL_MASK>;
|
modesel-mask = <PCA9420_MODECFG_0_MODE_CTRL_SEL_MASK>;
|
||||||
BUCK1 {
|
BUCK1 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <500000>;
|
regulator-min-microvolt = <500000>;
|
||||||
regulator-max-microvolt = <1800000>;
|
regulator-max-microvolt = <1800000>;
|
||||||
regulator-max-microamp = <250000>;
|
regulator-max-microamp = <250000>;
|
||||||
|
@ -191,8 +189,6 @@ arduino_serial: &flexcomm12 {
|
||||||
};
|
};
|
||||||
|
|
||||||
BUCK2 {
|
BUCK2 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <1500000>;
|
regulator-min-microvolt = <1500000>;
|
||||||
regulator-max-microvolt = <3300000>;
|
regulator-max-microvolt = <3300000>;
|
||||||
regulator-max-microamp = <500000>;
|
regulator-max-microamp = <500000>;
|
||||||
|
@ -200,8 +196,6 @@ arduino_serial: &flexcomm12 {
|
||||||
};
|
};
|
||||||
|
|
||||||
LDO1 {
|
LDO1 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <1700000>;
|
regulator-min-microvolt = <1700000>;
|
||||||
regulator-max-microvolt = <1900000>;
|
regulator-max-microvolt = <1900000>;
|
||||||
regulator-max-microamp = <1000>;
|
regulator-max-microamp = <1000>;
|
||||||
|
@ -209,8 +203,6 @@ arduino_serial: &flexcomm12 {
|
||||||
};
|
};
|
||||||
|
|
||||||
LDO2 {
|
LDO2 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <1500000>;
|
regulator-min-microvolt = <1500000>;
|
||||||
regulator-max-microvolt = <3300000>;
|
regulator-max-microvolt = <3300000>;
|
||||||
regulator-max-microamp = <250000>;
|
regulator-max-microamp = <250000>;
|
||||||
|
|
|
@ -252,8 +252,6 @@ i2s1: &flexcomm3 {
|
||||||
modesel-reg = <PCA9420_MODECFG_0_0>;
|
modesel-reg = <PCA9420_MODECFG_0_0>;
|
||||||
modesel-mask = <PCA9420_MODECFG_0_MODE_CTRL_SEL_MASK>;
|
modesel-mask = <PCA9420_MODECFG_0_MODE_CTRL_SEL_MASK>;
|
||||||
BUCK1 {
|
BUCK1 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <500000>;
|
regulator-min-microvolt = <500000>;
|
||||||
regulator-max-microvolt = <1800000>;
|
regulator-max-microvolt = <1800000>;
|
||||||
regulator-max-microamp = <250000>;
|
regulator-max-microamp = <250000>;
|
||||||
|
@ -261,8 +259,6 @@ i2s1: &flexcomm3 {
|
||||||
};
|
};
|
||||||
|
|
||||||
BUCK2 {
|
BUCK2 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <1500000>;
|
regulator-min-microvolt = <1500000>;
|
||||||
regulator-max-microvolt = <3300000>;
|
regulator-max-microvolt = <3300000>;
|
||||||
regulator-max-microamp = <500000>;
|
regulator-max-microamp = <500000>;
|
||||||
|
@ -270,8 +266,6 @@ i2s1: &flexcomm3 {
|
||||||
};
|
};
|
||||||
|
|
||||||
LDO1 {
|
LDO1 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <1700000>;
|
regulator-min-microvolt = <1700000>;
|
||||||
regulator-max-microvolt = <1900000>;
|
regulator-max-microvolt = <1900000>;
|
||||||
regulator-max-microamp = <1000>;
|
regulator-max-microamp = <1000>;
|
||||||
|
@ -279,8 +273,6 @@ i2s1: &flexcomm3 {
|
||||||
};
|
};
|
||||||
|
|
||||||
LDO2 {
|
LDO2 {
|
||||||
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
|
|
||||||
num-current-levels = <7>;
|
|
||||||
regulator-min-microvolt = <1500000>;
|
regulator-min-microvolt = <1500000>;
|
||||||
regulator-max-microvolt = <3300000>;
|
regulator-max-microvolt = <3300000>;
|
||||||
regulator-max-microamp = <250000>;
|
regulator-max-microamp = <250000>;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <zephyr/dt-bindings/regulator/pmic_i2c.h>
|
#include <zephyr/dt-bindings/regulator/pmic_i2c.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
#include <zephyr/sys/linear_range.h>
|
#include <zephyr/sys/linear_range.h>
|
||||||
#include <zephyr/sys/util_macro.h>
|
#include <zephyr/sys/util.h>
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(pca9420, CONFIG_REGULATOR_LOG_LEVEL);
|
LOG_MODULE_REGISTER(pca9420, CONFIG_REGULATOR_LOG_LEVEL);
|
||||||
|
|
||||||
|
@ -33,7 +33,9 @@ LOG_MODULE_REGISTER(pca9420, CONFIG_REGULATOR_LOG_LEVEL);
|
||||||
#define PCA9420_MODECFG_0_3 0x25U
|
#define PCA9420_MODECFG_0_3 0x25U
|
||||||
|
|
||||||
/** @brief VIN input current limit selection */
|
/** @brief VIN input current limit selection */
|
||||||
|
#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_POS 5U
|
||||||
#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK 0xE0U
|
#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK 0xE0U
|
||||||
|
#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_DISABLED 0x7U
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Mode control selection mask. When this bit is set, the external
|
* @brief Mode control selection mask. When this bit is set, the external
|
||||||
|
@ -71,16 +73,15 @@ LOG_MODULE_REGISTER(pca9420, CONFIG_REGULATOR_LOG_LEVEL);
|
||||||
#define PCA9420_MODECFG_3_LDO2_OUT_MASK 0x3FU
|
#define PCA9420_MODECFG_3_LDO2_OUT_MASK 0x3FU
|
||||||
#define PCA9420_MODECFG_3_LDO2_OUT_POS 0U
|
#define PCA9420_MODECFG_3_LDO2_OUT_POS 0U
|
||||||
|
|
||||||
struct current_range {
|
/** VIN ILIM resolution, uA/LSB */
|
||||||
int32_t uA; /* Current limit in uA */
|
#define PCA9420_VIN_ILIM_UA_LSB 170000
|
||||||
uint8_t reg_val; /* Register value for current limit */
|
/** VIN ILIM minimum value, uA */
|
||||||
};
|
#define PCA9420_VIN_ILIM_MIN_UA 85000
|
||||||
|
|
||||||
struct regulator_pca9420_desc {
|
struct regulator_pca9420_desc {
|
||||||
uint8_t enable_reg;
|
uint8_t enable_reg;
|
||||||
uint8_t enable_mask;
|
uint8_t enable_mask;
|
||||||
uint8_t enable_val;
|
uint8_t enable_val;
|
||||||
uint8_t ilim_reg;
|
|
||||||
uint8_t ilim_mask;
|
|
||||||
uint8_t vsel_reg;
|
uint8_t vsel_reg;
|
||||||
uint8_t vsel_mask;
|
uint8_t vsel_mask;
|
||||||
uint8_t vsel_pos;
|
uint8_t vsel_pos;
|
||||||
|
@ -90,21 +91,24 @@ struct regulator_pca9420_desc {
|
||||||
|
|
||||||
struct regulator_pca9420_data {
|
struct regulator_pca9420_data {
|
||||||
struct onoff_sync_service srv;
|
struct onoff_sync_service srv;
|
||||||
const struct current_range *current_levels;
|
};
|
||||||
|
|
||||||
|
struct regulator_pca9420_common_config {
|
||||||
|
struct i2c_dt_spec i2c;
|
||||||
|
int32_t vin_ilim_ua;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct regulator_pca9420_config {
|
struct regulator_pca9420_config {
|
||||||
int num_current_levels;
|
|
||||||
int num_modes;
|
int num_modes;
|
||||||
bool enable_inverted;
|
bool enable_inverted;
|
||||||
bool boot_on;
|
bool boot_on;
|
||||||
struct i2c_dt_spec i2c;
|
struct i2c_dt_spec i2c;
|
||||||
uint16_t initial_mode;
|
uint16_t initial_mode;
|
||||||
const uint32_t *current_array;
|
|
||||||
const uint16_t *allowed_modes;
|
const uint16_t *allowed_modes;
|
||||||
uint8_t modesel_reg;
|
uint8_t modesel_reg;
|
||||||
uint8_t modesel_mask;
|
uint8_t modesel_mask;
|
||||||
const struct regulator_pca9420_desc *desc;
|
const struct regulator_pca9420_desc *desc;
|
||||||
|
const struct regulator_pca9420_common_config *common;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct linear_range buck1_ranges[] = {
|
static const struct linear_range buck1_ranges[] = {
|
||||||
|
@ -136,8 +140,6 @@ static const struct regulator_pca9420_desc buck1_desc = {
|
||||||
.enable_reg = PCA9420_MODECFG_0_2,
|
.enable_reg = PCA9420_MODECFG_0_2,
|
||||||
.enable_mask = PCA9420_MODECFG_2_SW1_EN_MASK,
|
.enable_mask = PCA9420_MODECFG_2_SW1_EN_MASK,
|
||||||
.enable_val = PCA9420_MODECFG_2_SW1_EN_VAL,
|
.enable_val = PCA9420_MODECFG_2_SW1_EN_VAL,
|
||||||
.ilim_reg = PCA9420_TOP_CNTL0,
|
|
||||||
.ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK,
|
|
||||||
.vsel_mask = PCA9420_MODECFG_0_SW1_OUT_MASK,
|
.vsel_mask = PCA9420_MODECFG_0_SW1_OUT_MASK,
|
||||||
.vsel_pos = PCA9420_MODECFG_0_SW1_OUT_POS,
|
.vsel_pos = PCA9420_MODECFG_0_SW1_OUT_POS,
|
||||||
.vsel_reg = PCA9420_MODECFG_0_0,
|
.vsel_reg = PCA9420_MODECFG_0_0,
|
||||||
|
@ -152,8 +154,6 @@ static const struct regulator_pca9420_desc buck2_desc = {
|
||||||
.vsel_mask = PCA9420_MODECFG_1_SW2_OUT_MASK,
|
.vsel_mask = PCA9420_MODECFG_1_SW2_OUT_MASK,
|
||||||
.vsel_pos = PCA9420_MODECFG_1_SW2_OUT_POS,
|
.vsel_pos = PCA9420_MODECFG_1_SW2_OUT_POS,
|
||||||
.vsel_reg = PCA9420_MODECFG_0_1,
|
.vsel_reg = PCA9420_MODECFG_0_1,
|
||||||
.ilim_reg = PCA9420_TOP_CNTL0,
|
|
||||||
.ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK,
|
|
||||||
.ranges = buck2_ranges,
|
.ranges = buck2_ranges,
|
||||||
.num_ranges = ARRAY_SIZE(buck2_ranges),
|
.num_ranges = ARRAY_SIZE(buck2_ranges),
|
||||||
};
|
};
|
||||||
|
@ -165,8 +165,6 @@ static const struct regulator_pca9420_desc ldo1_desc = {
|
||||||
.vsel_mask = PCA9420_MODECFG_2_LDO1_OUT_MASK,
|
.vsel_mask = PCA9420_MODECFG_2_LDO1_OUT_MASK,
|
||||||
.vsel_pos = PCA9420_MODECFG_2_LDO1_OUT_POS,
|
.vsel_pos = PCA9420_MODECFG_2_LDO1_OUT_POS,
|
||||||
.vsel_reg = PCA9420_MODECFG_0_2,
|
.vsel_reg = PCA9420_MODECFG_0_2,
|
||||||
.ilim_reg = PCA9420_TOP_CNTL0,
|
|
||||||
.ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK,
|
|
||||||
.ranges = ldo1_ranges,
|
.ranges = ldo1_ranges,
|
||||||
.num_ranges = ARRAY_SIZE(ldo1_ranges),
|
.num_ranges = ARRAY_SIZE(ldo1_ranges),
|
||||||
};
|
};
|
||||||
|
@ -178,8 +176,6 @@ static const struct regulator_pca9420_desc ldo2_desc = {
|
||||||
.vsel_reg = PCA9420_MODECFG_0_3,
|
.vsel_reg = PCA9420_MODECFG_0_3,
|
||||||
.vsel_mask = PCA9420_MODECFG_3_LDO2_OUT_MASK,
|
.vsel_mask = PCA9420_MODECFG_3_LDO2_OUT_MASK,
|
||||||
.vsel_pos = PCA9420_MODECFG_3_LDO2_OUT_POS,
|
.vsel_pos = PCA9420_MODECFG_3_LDO2_OUT_POS,
|
||||||
.ilim_reg = PCA9420_TOP_CNTL0,
|
|
||||||
.ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK,
|
|
||||||
.ranges = ldo2_ranges,
|
.ranges = ldo2_ranges,
|
||||||
.num_ranges = ARRAY_SIZE(ldo2_ranges),
|
.num_ranges = ARRAY_SIZE(ldo2_ranges),
|
||||||
};
|
};
|
||||||
|
@ -192,13 +188,12 @@ static int regulator_pca9420_is_supported_voltage(const struct device *dev,
|
||||||
* Reads a register from the PMIC
|
* Reads a register from the PMIC
|
||||||
* Returns 0 on success, or errno on error
|
* Returns 0 on success, or errno on error
|
||||||
*/
|
*/
|
||||||
static int regulator_pca9420_read_register(const struct device *dev,
|
static int regulator_pca9420_read_register(const struct i2c_dt_spec *i2c,
|
||||||
uint8_t reg, uint8_t *out)
|
uint8_t reg, uint8_t *out)
|
||||||
{
|
{
|
||||||
const struct regulator_pca9420_config *conf = dev->config;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = i2c_reg_read_byte_dt(&conf->i2c, reg, out);
|
ret = i2c_reg_read_byte_dt(i2c, reg, out);
|
||||||
LOG_DBG("READ 0x%x: 0x%x", reg, *out);
|
LOG_DBG("READ 0x%x: 0x%x", reg, *out);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -207,15 +202,14 @@ static int regulator_pca9420_read_register(const struct device *dev,
|
||||||
* Modifies a register within the PMIC
|
* Modifies a register within the PMIC
|
||||||
* Returns 0 on success, or errno on error
|
* Returns 0 on success, or errno on error
|
||||||
*/
|
*/
|
||||||
static int regulator_pca9420_modify_register(const struct device *dev,
|
static int regulator_pca9420_modify_register(const struct i2c_dt_spec *i2c,
|
||||||
uint8_t reg, uint8_t reg_mask,
|
uint8_t reg, uint8_t reg_mask,
|
||||||
uint8_t reg_val)
|
uint8_t reg_val)
|
||||||
{
|
{
|
||||||
const struct regulator_pca9420_config *conf = dev->config;
|
|
||||||
uint8_t reg_current;
|
uint8_t reg_current;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = regulator_pca9420_read_register(dev, reg, ®_current);
|
rc = regulator_pca9420_read_register(i2c, reg, ®_current);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -223,8 +217,8 @@ static int regulator_pca9420_modify_register(const struct device *dev,
|
||||||
reg_current &= ~reg_mask;
|
reg_current &= ~reg_mask;
|
||||||
reg_current |= (reg_val & reg_mask);
|
reg_current |= (reg_val & reg_mask);
|
||||||
LOG_DBG("WRITE 0x%02X to 0x%02X at I2C addr 0x%02X", reg_current,
|
LOG_DBG("WRITE 0x%02X to 0x%02X at I2C addr 0x%02X", reg_current,
|
||||||
reg, conf->i2c.addr);
|
reg, i2c->addr);
|
||||||
return i2c_reg_write_byte_dt(&conf->i2c, reg, reg_current);
|
return i2c_reg_write_byte_dt(i2c, reg, reg_current);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -239,7 +233,8 @@ static int regulator_pca9420_get_voltage_offset(const struct device *dev,
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t raw_reg;
|
uint8_t raw_reg;
|
||||||
|
|
||||||
ret = regulator_pca9420_read_register(dev, config->desc->vsel_reg + off,
|
ret = regulator_pca9420_read_register(&config->i2c,
|
||||||
|
config->desc->vsel_reg + off,
|
||||||
&raw_reg);
|
&raw_reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -274,7 +269,7 @@ static int regulator_set_voltage_offset(const struct device *dev,
|
||||||
|
|
||||||
idx <<= config->desc->vsel_pos;
|
idx <<= config->desc->vsel_pos;
|
||||||
|
|
||||||
return regulator_pca9420_modify_register(dev,
|
return regulator_pca9420_modify_register(&config->i2c,
|
||||||
config->desc->vsel_reg + off,
|
config->desc->vsel_reg + off,
|
||||||
config->desc->vsel_mask,
|
config->desc->vsel_mask,
|
||||||
(uint8_t)idx);
|
(uint8_t)idx);
|
||||||
|
@ -363,36 +358,6 @@ static int32_t regulator_pca9420_get_voltage(const struct device *dev)
|
||||||
return voltage;
|
return voltage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Part of the extended regulator consumer API
|
|
||||||
* Set the current limit for this device
|
|
||||||
*/
|
|
||||||
static int regulator_pca9420_set_current_limit(const struct device *dev,
|
|
||||||
int32_t min_ua, int32_t max_ua)
|
|
||||||
{
|
|
||||||
const struct regulator_pca9420_config *config = dev->config;
|
|
||||||
struct regulator_pca9420_data *data = dev->data;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (config->num_current_levels == 0) {
|
|
||||||
/* Regulator cannot limit current */
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
/* Locate the desired current limit */
|
|
||||||
while (i < config->num_current_levels &&
|
|
||||||
min_ua > data->current_levels[i].uA) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i == config->num_current_levels ||
|
|
||||||
data->current_levels[i].uA > max_ua) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
/* Set the current limit */
|
|
||||||
return regulator_pca9420_modify_register(
|
|
||||||
dev, config->desc->ilim_reg, config->desc->ilim_mask,
|
|
||||||
data->current_levels[i].reg_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of the extended regulator consumer API
|
* Part of the extended regulator consumer API
|
||||||
* Gets the set current limit for the regulator
|
* Gets the set current limit for the regulator
|
||||||
|
@ -400,27 +365,12 @@ static int regulator_pca9420_set_current_limit(const struct device *dev,
|
||||||
static int regulator_pca9420_get_current_limit(const struct device *dev)
|
static int regulator_pca9420_get_current_limit(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct regulator_pca9420_config *config = dev->config;
|
const struct regulator_pca9420_config *config = dev->config;
|
||||||
struct regulator_pca9420_data *data = dev->data;
|
|
||||||
int rc, i = 0;
|
|
||||||
uint8_t raw_reg;
|
|
||||||
|
|
||||||
if (config->num_current_levels == 0) {
|
if (config->common->vin_ilim_ua == 0U) {
|
||||||
return -ENOTSUP;
|
return config->max_ua;
|
||||||
}
|
}
|
||||||
rc = regulator_pca9420_read_register(dev, config->desc->ilim_reg,
|
|
||||||
&raw_reg);
|
return MIN(config->max_ua, config->common->vin_ilim_ua);
|
||||||
if (rc) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
raw_reg &= config->desc->ilim_mask;
|
|
||||||
while (i < config->num_current_levels &&
|
|
||||||
data->current_levels[i].reg_val != raw_reg) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i == config->num_current_levels) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
return data->current_levels[i].uA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -483,7 +433,7 @@ static int regulator_pca9420_mode_disable(const struct device *dev,
|
||||||
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
||||||
dis_val = config->enable_inverted ? config->desc->enable_val : 0;
|
dis_val = config->enable_inverted ? config->desc->enable_val : 0;
|
||||||
return regulator_pca9420_modify_register(
|
return regulator_pca9420_modify_register(
|
||||||
dev, config->desc->enable_reg + sel_off,
|
&config->i2c, config->desc->enable_reg + sel_off,
|
||||||
config->desc->enable_mask, dis_val);
|
config->desc->enable_mask, dis_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +465,7 @@ static int regulator_pca9420_mode_enable(const struct device *dev,
|
||||||
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT);
|
||||||
en_val = config->enable_inverted ? 0 : config->desc->enable_val;
|
en_val = config->enable_inverted ? 0 : config->desc->enable_val;
|
||||||
return regulator_pca9420_modify_register(
|
return regulator_pca9420_modify_register(
|
||||||
dev, config->desc->enable_reg + sel_off,
|
&config->i2c, config->desc->enable_reg + sel_off,
|
||||||
config->desc->enable_mask, en_val);
|
config->desc->enable_mask, en_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,12 +533,12 @@ static int regulator_pca9420_set_mode(const struct device *dev, uint32_t mode)
|
||||||
if (mode & PMIC_MODE_FLAG_MODESEL_MULTI_REG) {
|
if (mode & PMIC_MODE_FLAG_MODESEL_MULTI_REG) {
|
||||||
/* Select mode with offset calculation */
|
/* Select mode with offset calculation */
|
||||||
rc = regulator_pca9420_modify_register(
|
rc = regulator_pca9420_modify_register(
|
||||||
dev, config->modesel_reg + sel_off,
|
&config->i2c, config->modesel_reg + sel_off,
|
||||||
mode & PMIC_MODE_SELECTOR_MASK, config->modesel_mask);
|
mode & PMIC_MODE_SELECTOR_MASK, config->modesel_mask);
|
||||||
} else {
|
} else {
|
||||||
/* Select mode without offset to modesel_reg */
|
/* Select mode without offset to modesel_reg */
|
||||||
rc = regulator_pca9420_modify_register(
|
rc = regulator_pca9420_modify_register(
|
||||||
dev, config->modesel_reg,
|
&config->i2c, config->modesel_reg,
|
||||||
mode & PMIC_MODE_SELECTOR_MASK, config->modesel_mask);
|
mode & PMIC_MODE_SELECTOR_MASK, config->modesel_mask);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -610,7 +560,8 @@ static int regulator_pca9420_enable(const struct device *dev,
|
||||||
return onoff_sync_finalize(&data->srv, key, cli, rc, true);
|
return onoff_sync_finalize(&data->srv, key, cli, rc, true);
|
||||||
}
|
}
|
||||||
en_val = config->enable_inverted ? 0 : config->desc->enable_val;
|
en_val = config->enable_inverted ? 0 : config->desc->enable_val;
|
||||||
rc = regulator_pca9420_modify_register(dev, config->desc->enable_reg,
|
rc = regulator_pca9420_modify_register(&config->i2c,
|
||||||
|
config->desc->enable_reg,
|
||||||
config->desc->enable_mask,
|
config->desc->enable_mask,
|
||||||
en_val);
|
en_val);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
@ -636,7 +587,7 @@ static int regulator_pca9420_disable(const struct device *dev)
|
||||||
/* Disable regulator */
|
/* Disable regulator */
|
||||||
dis_val = config->enable_inverted ? config->desc->enable_val : 0;
|
dis_val = config->enable_inverted ? config->desc->enable_val : 0;
|
||||||
rc = regulator_pca9420_modify_register(
|
rc = regulator_pca9420_modify_register(
|
||||||
dev, config->desc->enable_reg,
|
&config->i2c, config->desc->enable_reg,
|
||||||
config->desc->enable_mask, dis_val);
|
config->desc->enable_mask, dis_val);
|
||||||
}
|
}
|
||||||
return onoff_sync_finalize(&data->srv, key, NULL, rc, false);
|
return onoff_sync_finalize(&data->srv, key, NULL, rc, false);
|
||||||
|
@ -645,11 +596,8 @@ static int regulator_pca9420_disable(const struct device *dev)
|
||||||
static int regulator_pca9420_init(const struct device *dev)
|
static int regulator_pca9420_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct regulator_pca9420_config *config = dev->config;
|
const struct regulator_pca9420_config *config = dev->config;
|
||||||
struct regulator_pca9420_data *data = dev->data;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/* Do the same cast for current limit ranges */
|
|
||||||
data->current_levels = (struct current_range *)config->current_array;
|
|
||||||
/* Check to verify we have a valid I2C device */
|
/* Check to verify we have a valid I2C device */
|
||||||
if (!device_is_ready(config->i2c.bus)) {
|
if (!device_is_ready(config->i2c.bus)) {
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -663,6 +611,27 @@ static int regulator_pca9420_init(const struct device *dev)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct regulator_driver_api api = {
|
static const struct regulator_driver_api api = {
|
||||||
.enable = regulator_pca9420_enable,
|
.enable = regulator_pca9420_enable,
|
||||||
|
@ -673,7 +642,6 @@ static const struct regulator_driver_api api = {
|
||||||
.is_supported_voltage = regulator_pca9420_is_supported_voltage,
|
.is_supported_voltage = regulator_pca9420_is_supported_voltage,
|
||||||
.set_voltage = regulator_pca9420_set_voltage,
|
.set_voltage = regulator_pca9420_set_voltage,
|
||||||
.get_voltage = regulator_pca9420_get_voltage,
|
.get_voltage = regulator_pca9420_get_voltage,
|
||||||
.set_current_limit = regulator_pca9420_set_current_limit,
|
|
||||||
.get_current_limit = regulator_pca9420_get_current_limit,
|
.get_current_limit = regulator_pca9420_get_current_limit,
|
||||||
.set_mode = regulator_pca9420_set_mode,
|
.set_mode = regulator_pca9420_set_mode,
|
||||||
.set_mode_voltage = regulator_pca9420_set_mode_voltage,
|
.set_mode_voltage = regulator_pca9420_set_mode_voltage,
|
||||||
|
@ -682,43 +650,51 @@ static const struct regulator_driver_api api = {
|
||||||
.mode_enable = regulator_pca9420_mode_enable,
|
.mode_enable = regulator_pca9420_mode_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REGULATOR_PCA9420_DEFINE(node_id, id, name) \
|
#define REGULATOR_PCA9420_DEFINE(node_id, id, name, _common) \
|
||||||
static const uint32_t curr_limits_##id[] = \
|
|
||||||
DT_PROP_OR(node_id, current_levels, {}); \
|
|
||||||
static const uint16_t allowed_modes_##id[] = \
|
static const uint16_t allowed_modes_##id[] = \
|
||||||
DT_PROP_OR(DT_PARENT(node_id), regulator_allowed_modes, {}); \
|
DT_PROP_OR(DT_PARENT(node_id), regulator_allowed_modes, {}); \
|
||||||
\
|
\
|
||||||
static struct regulator_pca9420_data data_##id; \
|
static struct regulator_pca9420_data data_##id; \
|
||||||
\
|
\
|
||||||
static const struct regulator_pca9420_config config_##id = { \
|
static const struct regulator_pca9420_config config_##id = { \
|
||||||
.num_current_levels = DT_PROP(node_id, num_current_levels), \
|
.max_ua = DT_PROP(node_id, regulator_max_microamp), \
|
||||||
.enable_inverted = DT_PROP(node_id, enable_inverted), \
|
.enable_inverted = DT_PROP(node_id, enable_inverted), \
|
||||||
.boot_on = DT_PROP(node_id, regulator_boot_on), \
|
.boot_on = DT_PROP(node_id, regulator_boot_on), \
|
||||||
.num_modes = ARRAY_SIZE(allowed_modes_##id), \
|
.num_modes = ARRAY_SIZE(allowed_modes_##id), \
|
||||||
.initial_mode = DT_PROP_OR(DT_PARENT(node_id), \
|
.initial_mode = DT_PROP_OR(DT_PARENT(node_id), \
|
||||||
regulator_initial_mode, 0), \
|
regulator_initial_mode, 0), \
|
||||||
.i2c = I2C_DT_SPEC_GET(DT_PARENT(node_id)), \
|
.i2c = I2C_DT_SPEC_GET(DT_PARENT(node_id)), \
|
||||||
.current_array = curr_limits_##id, \
|
|
||||||
.allowed_modes = allowed_modes_##id, \
|
.allowed_modes = allowed_modes_##id, \
|
||||||
.modesel_reg = DT_PROP_OR(DT_PARENT(node_id), modesel_reg, 0), \
|
.modesel_reg = DT_PROP_OR(DT_PARENT(node_id), modesel_reg, 0), \
|
||||||
.modesel_mask = \
|
.modesel_mask = \
|
||||||
DT_PROP_OR(DT_PARENT(node_id), modesel_mask, 0), \
|
DT_PROP_OR(DT_PARENT(node_id), modesel_mask, 0), \
|
||||||
.desc = &name ## _desc, \
|
.desc = &name ## _desc, \
|
||||||
|
.common = _common, \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
DEVICE_DT_DEFINE(node_id, regulator_pca9420_init, NULL, &data_##id, \
|
DEVICE_DT_DEFINE(node_id, regulator_pca9420_init, NULL, &data_##id, \
|
||||||
&config_##id, POST_KERNEL, \
|
&config_##id, POST_KERNEL, \
|
||||||
CONFIG_REGULATOR_PCA9420_INIT_PRIORITY, &api);
|
CONFIG_REGULATOR_PCA9420_INIT_PRIORITY, &api);
|
||||||
|
|
||||||
#define REGULATOR_PCA9420_DEFINE_COND(inst, child) \
|
#define REGULATOR_PCA9420_DEFINE_COND(inst, child, common) \
|
||||||
COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \
|
COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \
|
||||||
(REGULATOR_PCA9420_DEFINE(DT_INST_CHILD(inst, child), \
|
(REGULATOR_PCA9420_DEFINE(DT_INST_CHILD(inst, child), \
|
||||||
child ## inst, child)), ())
|
child ## inst, child, common)), \
|
||||||
|
())
|
||||||
|
|
||||||
#define REGULATOR_PCA9420_DEFINE_ALL(inst) \
|
#define REGULATOR_PCA9420_DEFINE_ALL(inst) \
|
||||||
REGULATOR_PCA9420_DEFINE_COND(inst, buck1) \
|
static const struct regulator_pca9420_common_config config_##inst = { \
|
||||||
REGULATOR_PCA9420_DEFINE_COND(inst, buck2) \
|
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||||
REGULATOR_PCA9420_DEFINE_COND(inst, ldo1) \
|
.vin_ilim_ua = DT_INST_PROP(inst, nxp_vin_ilim_microamp), \
|
||||||
REGULATOR_PCA9420_DEFINE_COND(inst, ldo2)
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(inst, regulator_pca9420_common_init, NULL, NULL, \
|
||||||
|
&config_##inst, POST_KERNEL, \
|
||||||
|
CONFIG_REGULATOR_PCA9420_INIT_PRIORITY, NULL); \
|
||||||
|
\
|
||||||
|
REGULATOR_PCA9420_DEFINE_COND(inst, buck1, &config_##inst) \
|
||||||
|
REGULATOR_PCA9420_DEFINE_COND(inst, buck2, &config_##inst) \
|
||||||
|
REGULATOR_PCA9420_DEFINE_COND(inst, ldo1, &config_##inst) \
|
||||||
|
REGULATOR_PCA9420_DEFINE_COND(inst, ldo2, &config_##inst)
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_PCA9420_DEFINE_ALL)
|
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_PCA9420_DEFINE_ALL)
|
||||||
|
|
|
@ -36,6 +36,32 @@ include:
|
||||||
- regulator-initial-mode
|
- regulator-initial-mode
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
|
nxp,vin-ilim-microamp:
|
||||||
|
type: int
|
||||||
|
default: 425000
|
||||||
|
enum:
|
||||||
|
- 85000
|
||||||
|
- 255000
|
||||||
|
- 425000
|
||||||
|
- 595000
|
||||||
|
- 765000
|
||||||
|
- 935000
|
||||||
|
- 1105000
|
||||||
|
description: |
|
||||||
|
VIN input current limit, in microamperes. Value reflects typical value,
|
||||||
|
below you can find min/typical/max values:
|
||||||
|
|
||||||
|
- 74 mA/85 mA/98 mA
|
||||||
|
- 222 mA/255 mA/293 mA
|
||||||
|
- 370 mA/425 mA/489 mA
|
||||||
|
- 517 mA/595 mA/684 mA
|
||||||
|
- 665 mA/765 mA/880 mA
|
||||||
|
- 813 mA/935 mA/1075 mA
|
||||||
|
- 961 mA/1105 mA/1271 mA
|
||||||
|
|
||||||
|
To disable current limit, set property to zero. Defaults to 425mA, the IC
|
||||||
|
default value.
|
||||||
|
|
||||||
modesel-reg:
|
modesel-reg:
|
||||||
type: int
|
type: int
|
||||||
description: |
|
description: |
|
||||||
|
@ -73,16 +99,3 @@ child-binding:
|
||||||
description: |
|
description: |
|
||||||
If the enable bit should be zero to turn the regulator on, add this
|
If the enable bit should be zero to turn the regulator on, add this
|
||||||
property.
|
property.
|
||||||
current-levels:
|
|
||||||
type: array
|
|
||||||
description: |
|
|
||||||
Array of current limit values in uA, followed by the register value
|
|
||||||
that must be written to enable the current limit. For example,
|
|
||||||
[800000, 0x3] denotes a value of 0x3 must be written to the register
|
|
||||||
to set a current limit of 800mA
|
|
||||||
num-current-levels:
|
|
||||||
type: int
|
|
||||||
default: 0
|
|
||||||
description: |
|
|
||||||
Number of current limit levels this regulator supports. If left as
|
|
||||||
default, regulator current support will be disabled.
|
|
||||||
|
|
|
@ -9,15 +9,6 @@
|
||||||
|
|
||||||
#include "pmic_i2c.h"
|
#include "pmic_i2c.h"
|
||||||
|
|
||||||
#define PCA9420_CURRENT_LIMIT_LEVELS \
|
|
||||||
85000 0x00 /* min: 74mA, typ: 85mA, max: 98mA */\
|
|
||||||
225000 0x20 /* min: 222mA, typ: 225mA, max: 293mA */\
|
|
||||||
425000 0x40 /* min: 370mA, typ: 425mA, max: 489mA */\
|
|
||||||
595000 0x60 /* min: 517mA, typ: 595mA, max: 684mA */\
|
|
||||||
765000 0x80 /* min: 665mA, typ: 765mA, max: 880mA */\
|
|
||||||
935000 0xA0 /* min: 813mA, typ: 935mA, max: 1075mA */\
|
|
||||||
1105000 0xC0 /* min: 961mA, typ: 1105mA, max: 1271mA */\
|
|
||||||
|
|
||||||
#define PCA9420_MODECFG0 \
|
#define PCA9420_MODECFG0 \
|
||||||
(PMIC_MODE(0x0, 0x0, 0x0)) /* ModeCfg 0, selected via I2C */
|
(PMIC_MODE(0x0, 0x0, 0x0)) /* ModeCfg 0, selected via I2C */
|
||||||
#define PCA9420_MODECFG1 \
|
#define PCA9420_MODECFG1 \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue