drivers: regulator: fix/improve usage of devicetree properties
Most of devicetree properties for regulator, such as: - regulator-min/max-microvolt - regulator-min/max-microamp - regulator-allowed-modes - etc. Are meant to specify limits on what consumers may set. They are **NOT** meant to describe the hardware capabilities. For example, I could have a BUCK converter that supports 0-5V output voltage, but my circuit may only allow working on the 2.7-3.3V range. This patch reworks the API so that the API class layer manages this information. This is done by drivers collecting all such fields in a common configuration structure that is later accessed by the class layer. This simplifies drivers implementation. For example, if A consumer calls regulator_set_voltage() with a voltage that is supported but not allowed, driver code won't be called. Similarly, if a regulator is configured to be `always-on`, enable/disable driver code will never be called. Drivers have been adjusted. PCA9420 mode settings have been removed from devicetree in this commit as they are not actual modes but PMIC states. This will be refactored in a follow-up commit. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
parent
1029a4db6f
commit
10ce9684c3
|
@ -164,34 +164,20 @@ arduino_serial: &flexcomm12 {
|
|||
nxp,enable-modesel-pins;
|
||||
|
||||
pca9420_sw1: BUCK1 {
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-max-microamp = <250000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
pca9420_sw2: BUCK2 {
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-max-microamp = <500000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
pca9420_ldo1: LDO1 {
|
||||
regulator-min-microvolt = <1700000>;
|
||||
regulator-max-microvolt = <1900000>;
|
||||
regulator-max-microamp = <1000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
pca9420_ldo2: LDO2 {
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-max-microamp = <250000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -234,30 +234,18 @@ i2s1: &flexcomm3 {
|
|||
nxp,enable-modesel-pins;
|
||||
|
||||
BUCK1 {
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-max-microamp = <250000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
BUCK2 {
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-max-microamp = <500000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO1 {
|
||||
regulator-min-microvolt = <1700000>;
|
||||
regulator-max-microvolt = <1900000>;
|
||||
regulator-max-microamp = <1000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO2 {
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-max-microamp = <250000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,18 +16,29 @@ void regulator_common_data_init(const struct device *dev)
|
|||
|
||||
int regulator_enable(const struct device *dev)
|
||||
{
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
const struct regulator_common_config *config =
|
||||
(struct regulator_common_config *)dev->config;
|
||||
struct regulator_common_data *data =
|
||||
(struct regulator_common_data *)dev->data;
|
||||
int ret = 0;
|
||||
|
||||
/* enable not supported (always on) */
|
||||
if (api->enable == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* regulator must stay always on */
|
||||
if ((config->flags & REGULATOR_ALWAYS_ON) != 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void)k_mutex_lock(&data->lock, K_FOREVER);
|
||||
|
||||
data->refcnt++;
|
||||
|
||||
if (data->refcnt == 1) {
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
ret = api->enable(dev);
|
||||
if (ret < 0) {
|
||||
data->refcnt--;
|
||||
|
@ -41,18 +52,29 @@ int regulator_enable(const struct device *dev)
|
|||
|
||||
int regulator_disable(const struct device *dev)
|
||||
{
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
const struct regulator_common_config *config =
|
||||
(struct regulator_common_config *)dev->config;
|
||||
struct regulator_common_data *data =
|
||||
(struct regulator_common_data *)dev->data;
|
||||
int ret = 0;
|
||||
|
||||
/* disable not supported (always on) */
|
||||
if (api->disable == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* regulator must stay always on */
|
||||
if ((config->flags & REGULATOR_ALWAYS_ON) != 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void)k_mutex_lock(&data->lock, K_FOREVER);
|
||||
|
||||
data->refcnt--;
|
||||
|
||||
if (data->refcnt == 0) {
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
ret = api->disable(dev);
|
||||
if (ret < 0) {
|
||||
data->refcnt++;
|
||||
|
@ -67,7 +89,16 @@ int regulator_disable(const struct device *dev)
|
|||
bool regulator_is_supported_voltage(const struct device *dev, int32_t min_uv,
|
||||
int32_t max_uv)
|
||||
{
|
||||
unsigned int volt_cnt = regulator_count_voltages(dev);
|
||||
const struct regulator_common_config *config =
|
||||
(struct regulator_common_config *)dev->config;
|
||||
unsigned int volt_cnt;
|
||||
|
||||
/* voltage may not be allowed, even if supported */
|
||||
if ((min_uv < config->min_uv) || (max_uv > config->max_uv)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
volt_cnt = regulator_count_voltages(dev);
|
||||
|
||||
for (unsigned int idx = 0U; idx < volt_cnt; idx++) {
|
||||
int32_t volt_uv;
|
||||
|
@ -81,3 +112,69 @@ bool regulator_is_supported_voltage(const struct device *dev, int32_t min_uv,
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
int regulator_set_voltage(const struct device *dev, int32_t min_uv,
|
||||
int32_t max_uv)
|
||||
{
|
||||
const struct regulator_common_config *config =
|
||||
(struct regulator_common_config *)dev->config;
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
if (api->set_voltage == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* voltage may not be allowed, even if supported */
|
||||
if ((min_uv < config->min_uv) || (max_uv > config->max_uv)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return api->set_voltage(dev, min_uv, max_uv);
|
||||
}
|
||||
|
||||
int regulator_set_current_limit(const struct device *dev, int32_t min_ua,
|
||||
int32_t max_ua)
|
||||
{
|
||||
const struct regulator_common_config *config =
|
||||
(struct regulator_common_config *)dev->config;
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
if (api->set_current_limit == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* current limit may not be allowed, even if supported */
|
||||
if ((min_ua < config->min_ua) || (max_ua > config->max_ua)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return api->set_current_limit(dev, min_ua, max_ua);
|
||||
}
|
||||
|
||||
int regulator_set_mode(const struct device *dev, regulator_mode_t mode)
|
||||
{
|
||||
const struct regulator_common_config *config =
|
||||
(struct regulator_common_config *)dev->config;
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
if (api->set_mode == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* no mode restrictions */
|
||||
if (config->allowed_modes_cnt == 0U) {
|
||||
return api->set_mode(dev, mode);
|
||||
}
|
||||
|
||||
/* check if mode is allowed, apply if it is */
|
||||
for (uint8_t i = 0U; i < config->allowed_modes_cnt; i++) {
|
||||
if (mode == config->allowed_modes[i]) {
|
||||
return api->set_mode(dev, mode);
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
|
|
@ -15,16 +15,11 @@
|
|||
|
||||
LOG_MODULE_REGISTER(regulator_fixed, CONFIG_REGULATOR_LOG_LEVEL);
|
||||
|
||||
#define OPTION_ALWAYS_ON_POS 0
|
||||
#define OPTION_ALWAYS_ON BIT(OPTION_ALWAYS_ON_POS)
|
||||
#define OPTION_BOOT_ON_POS 1
|
||||
#define OPTION_BOOT_ON BIT(OPTION_BOOT_ON_POS)
|
||||
|
||||
struct regulator_fixed_config {
|
||||
struct regulator_common_config common;
|
||||
uint32_t startup_delay_us;
|
||||
uint32_t off_on_delay_us;
|
||||
struct gpio_dt_spec enable;
|
||||
uint8_t options;
|
||||
};
|
||||
|
||||
struct regulator_fixed_data {
|
||||
|
@ -36,10 +31,6 @@ static int regulator_fixed_enable(const struct device *dev)
|
|||
const struct regulator_fixed_config *cfg = dev->config;
|
||||
int ret;
|
||||
|
||||
if ((cfg->options & OPTION_ALWAYS_ON) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = gpio_pin_set_dt(&cfg->enable, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -56,10 +47,6 @@ static int regulator_fixed_disable(const struct device *dev)
|
|||
{
|
||||
const struct regulator_fixed_config *cfg = dev->config;
|
||||
|
||||
if ((cfg->options & OPTION_ALWAYS_ON) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gpio_pin_set_dt(&cfg->enable, 0);
|
||||
}
|
||||
|
||||
|
@ -80,7 +67,7 @@ static int regulator_fixed_init(const struct device *dev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((cfg->options & (OPTION_ALWAYS_ON | OPTION_BOOT_ON)) != 0U) {
|
||||
if ((cfg->common.flags & REGULATOR_INIT_ENABLED) != 0U) {
|
||||
ret = gpio_pin_configure_dt(&cfg->enable, GPIO_OUTPUT_ACTIVE);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -101,13 +88,10 @@ static int regulator_fixed_init(const struct device *dev)
|
|||
static struct regulator_fixed_data data##inst; \
|
||||
\
|
||||
static const struct regulator_fixed_config config##inst = { \
|
||||
.common = REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst), \
|
||||
.startup_delay_us = DT_INST_PROP(inst, startup_delay_us), \
|
||||
.off_on_delay_us = DT_INST_PROP(inst, off_on_delay_us), \
|
||||
.enable = GPIO_DT_SPEC_INST_GET(inst, enable_gpios), \
|
||||
.options = (DT_INST_PROP(inst, regulator_boot_on) \
|
||||
<< OPTION_BOOT_ON_POS) | \
|
||||
(DT_INST_PROP(inst, regulator_always_on) \
|
||||
<< OPTION_ALWAYS_ON_POS), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, regulator_fixed_init, NULL, &data##inst, \
|
||||
|
|
|
@ -81,6 +81,8 @@
|
|||
/** VIN ILIM minimum value, uA */
|
||||
#define PCA9420_VIN_ILIM_MIN_UA 85000
|
||||
|
||||
/** Number of modes */
|
||||
#define PCA9420_NUM_MODES 4U
|
||||
/** Offset applied to MODECFG* registers for a given mode */
|
||||
#define PCA9420_MODECFG_OFFSET(mode) ((mode) * 4U)
|
||||
|
||||
|
@ -91,6 +93,7 @@ struct regulator_pca9420_desc {
|
|||
uint8_t vsel_reg;
|
||||
uint8_t vsel_mask;
|
||||
uint8_t vsel_pos;
|
||||
int32_t max_ua;
|
||||
uint8_t num_ranges;
|
||||
const struct linear_range *ranges;
|
||||
};
|
||||
|
@ -98,8 +101,6 @@ struct regulator_pca9420_desc {
|
|||
struct regulator_pca9420_common_config {
|
||||
struct i2c_dt_spec i2c;
|
||||
int32_t vin_ilim_ua;
|
||||
const uint8_t *allowed_modes;
|
||||
regulator_mode_t allowed_modes_cnt;
|
||||
bool enable_modesel_pins;
|
||||
};
|
||||
|
||||
|
@ -108,9 +109,8 @@ struct regulator_pca9420_common_data {
|
|||
};
|
||||
|
||||
struct regulator_pca9420_config {
|
||||
int32_t max_ua;
|
||||
struct regulator_common_config common;
|
||||
bool enable_inverted;
|
||||
bool boot_on;
|
||||
const struct regulator_pca9420_desc *desc;
|
||||
const struct device *parent;
|
||||
};
|
||||
|
@ -151,6 +151,7 @@ static const struct regulator_pca9420_desc buck1_desc = {
|
|||
.vsel_mask = PCA9420_MODECFG_0_SW1_OUT_MASK,
|
||||
.vsel_pos = PCA9420_MODECFG_0_SW1_OUT_POS,
|
||||
.vsel_reg = PCA9420_MODECFG_0_0,
|
||||
.max_ua = 250000,
|
||||
.ranges = buck1_ranges,
|
||||
.num_ranges = ARRAY_SIZE(buck1_ranges),
|
||||
};
|
||||
|
@ -162,6 +163,7 @@ static const struct regulator_pca9420_desc buck2_desc = {
|
|||
.vsel_mask = PCA9420_MODECFG_1_SW2_OUT_MASK,
|
||||
.vsel_pos = PCA9420_MODECFG_1_SW2_OUT_POS,
|
||||
.vsel_reg = PCA9420_MODECFG_0_1,
|
||||
.max_ua = 500000,
|
||||
.ranges = buck2_ranges,
|
||||
.num_ranges = ARRAY_SIZE(buck2_ranges),
|
||||
};
|
||||
|
@ -173,6 +175,7 @@ static const struct regulator_pca9420_desc ldo1_desc = {
|
|||
.vsel_mask = PCA9420_MODECFG_2_LDO1_OUT_MASK,
|
||||
.vsel_pos = PCA9420_MODECFG_2_LDO1_OUT_POS,
|
||||
.vsel_reg = PCA9420_MODECFG_0_2,
|
||||
.max_ua = 1000,
|
||||
.ranges = ldo1_ranges,
|
||||
.num_ranges = ARRAY_SIZE(ldo1_ranges),
|
||||
};
|
||||
|
@ -184,25 +187,11 @@ static const struct regulator_pca9420_desc ldo2_desc = {
|
|||
.vsel_reg = PCA9420_MODECFG_0_3,
|
||||
.vsel_mask = PCA9420_MODECFG_3_LDO2_OUT_MASK,
|
||||
.vsel_pos = PCA9420_MODECFG_3_LDO2_OUT_POS,
|
||||
.max_ua = 250000,
|
||||
.ranges = ldo2_ranges,
|
||||
.num_ranges = ARRAY_SIZE(ldo2_ranges),
|
||||
};
|
||||
|
||||
static bool regulator_pca9420_is_mode_allowed(const struct device *dev,
|
||||
regulator_mode_t mode)
|
||||
{
|
||||
const struct regulator_pca9420_config *config = dev->config;
|
||||
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
||||
|
||||
for (uint8_t i = 0U; i < cconfig->allowed_modes_cnt; i++) {
|
||||
if (mode == cconfig->allowed_modes[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static unsigned int regulator_pca9420_count_voltages(const struct device *dev)
|
||||
{
|
||||
const struct regulator_pca9420_config *config = dev->config;
|
||||
|
@ -276,9 +265,9 @@ static int regulator_pca9420_get_current_limit(const struct device *dev,
|
|||
const struct regulator_pca9420_common_config *cconfig = config->parent->config;
|
||||
|
||||
if (cconfig->vin_ilim_ua == 0U) {
|
||||
*curr_ua = config->max_ua;
|
||||
*curr_ua = config->desc->max_ua;
|
||||
} else {
|
||||
*curr_ua = MIN(config->max_ua, cconfig->vin_ilim_ua);
|
||||
*curr_ua = MIN(config->desc->max_ua, cconfig->vin_ilim_ua);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -292,10 +281,6 @@ static int regulator_pca9420_set_mode(const struct device *dev,
|
|||
struct regulator_pca9420_common_data *cdata = config->parent->data;
|
||||
int ret;
|
||||
|
||||
if (!regulator_pca9420_is_mode_allowed(dev, mode)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* change mode, to allow configuring voltage, but return -EPERM to
|
||||
* indicate we are not really changing mode, as it is managed externally
|
||||
*/
|
||||
|
@ -349,7 +334,7 @@ static int regulator_pca9420_init(const struct device *dev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (config->boot_on) {
|
||||
if ((config->common.flags & REGULATOR_INIT_ENABLED) != 0U) {
|
||||
rc = regulator_pca9420_enable(dev);
|
||||
}
|
||||
|
||||
|
@ -368,12 +353,12 @@ static int regulator_pca9420_common_init(const struct device *dev)
|
|||
}
|
||||
|
||||
if (config->enable_modesel_pins) {
|
||||
/* enable MODESEL0/1 pins for each allowed mode */
|
||||
for (uint8_t i = 0U; i < config->allowed_modes_cnt; i++) {
|
||||
/* enable MODESEL0/1 pins for each mode */
|
||||
for (uint8_t i = 0U; i < PCA9420_NUM_MODES; i++) {
|
||||
ret = i2c_reg_update_byte_dt(
|
||||
&config->i2c,
|
||||
PCA9420_MODECFG_0_0 +
|
||||
PCA9420_MODECFG_OFFSET(config->allowed_modes[i]),
|
||||
PCA9420_MODECFG_OFFSET(i),
|
||||
PCA9420_MODECFG_0_X_EN_MODE_SEL_BY_PIN,
|
||||
PCA9420_MODECFG_0_X_EN_MODE_SEL_BY_PIN);
|
||||
if (ret < 0) {
|
||||
|
@ -418,9 +403,8 @@ static const struct regulator_driver_api api = {
|
|||
static struct regulator_pca9420_data data_##id; \
|
||||
\
|
||||
static const struct regulator_pca9420_config config_##id = { \
|
||||
.max_ua = DT_PROP(node_id, regulator_max_microamp), \
|
||||
.common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \
|
||||
.enable_inverted = DT_PROP(node_id, enable_inverted), \
|
||||
.boot_on = DT_PROP(node_id, regulator_boot_on), \
|
||||
.desc = &name ## _desc, \
|
||||
.parent = _parent, \
|
||||
}; \
|
||||
|
@ -436,18 +420,13 @@ static const struct regulator_driver_api api = {
|
|||
())
|
||||
|
||||
#define REGULATOR_PCA9420_DEFINE_ALL(inst) \
|
||||
static const uint8_t allowed_modes_##inst[] = \
|
||||
DT_INST_PROP(inst, regulator_allowed_modes); \
|
||||
\
|
||||
static struct regulator_pca9420_common_data data_##inst = { \
|
||||
.mode = DT_INST_PROP(inst, regulator_initial_mode) \
|
||||
.mode = 0U \
|
||||
}; \
|
||||
\
|
||||
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), \
|
||||
.allowed_modes = allowed_modes_##inst, \
|
||||
.allowed_modes_cnt = ARRAY_SIZE(allowed_modes_##inst), \
|
||||
.enable_modesel_pins = \
|
||||
DT_INST_PROP(inst, nxp_enable_modesel_pins), \
|
||||
}; \
|
||||
|
|
|
@ -28,20 +28,9 @@ description: |
|
|||
|
||||
compatible: "nxp,pca9420"
|
||||
|
||||
include:
|
||||
- name: base.yaml
|
||||
- name: regulator.yaml
|
||||
property-allowlist:
|
||||
- regulator-allowed-modes
|
||||
- regulator-initial-mode
|
||||
include: base.yaml
|
||||
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
default: [0, 1, 2, 3]
|
||||
|
||||
regulator-initial-mode:
|
||||
default: 0
|
||||
|
||||
nxp,enable-modesel-pins:
|
||||
type: boolean
|
||||
description:
|
||||
|
@ -78,22 +67,13 @@ child-binding:
|
|||
include:
|
||||
- name: regulator.yaml
|
||||
property-allowlist:
|
||||
- regulator-always-on
|
||||
- regulator-boot-on
|
||||
- regulator-min-microvolt
|
||||
- regulator-max-microvolt
|
||||
- regulator-max-microamp
|
||||
|
||||
description: Voltage output of PMIC controller regulator
|
||||
properties:
|
||||
regulator-min-microvolt:
|
||||
required: true
|
||||
|
||||
regulator-max-microvolt:
|
||||
required: true
|
||||
|
||||
regulator-max-microamp:
|
||||
required: true
|
||||
|
||||
enable-inverted:
|
||||
type: boolean
|
||||
description: |
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -46,6 +47,82 @@ __subsystem struct regulator_driver_api {
|
|||
int (*set_mode)(const struct device *dev, regulator_mode_t mode);
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Regulator flags
|
||||
* @anchor REGULATOR_FLAGS
|
||||
* @{
|
||||
*/
|
||||
/** Indicates regulator must stay always ON */
|
||||
#define REGULATOR_ALWAYS_ON BIT(0)
|
||||
/** Indicates regulator must be initialized ON */
|
||||
#define REGULATOR_BOOT_ON BIT(1)
|
||||
/** Indicates if regulator must be enabled when initialized */
|
||||
#define REGULATOR_INIT_ENABLED (REGULATOR_ALWAYS_ON | REGULATOR_BOOT_ON)
|
||||
|
||||
/** @} */
|
||||
|
||||
/** Indicates initial mode is unknown/not specified */
|
||||
#define REGULATOR_INITIAL_MODE_UNKNOWN UINT8_MAX
|
||||
|
||||
/**
|
||||
* @brief Common regulator config.
|
||||
*
|
||||
* This structure **must** be placed first in the driver's config structure.
|
||||
*/
|
||||
struct regulator_common_config {
|
||||
/** Minimum allowed voltage, in microvolts. */
|
||||
int32_t min_uv;
|
||||
/** Maximum allowed voltage, in microvolts. */
|
||||
int32_t max_uv;
|
||||
/** Minimum allowed current, in microamps. */
|
||||
int32_t min_ua;
|
||||
/** Maximum allowed current, in microamps. */
|
||||
int32_t max_ua;
|
||||
/** Allowed modes */
|
||||
const regulator_mode_t *allowed_modes;
|
||||
/** Number of allowed modes */
|
||||
uint8_t allowed_modes_cnt;
|
||||
/** Regulator initial mode */
|
||||
regulator_mode_t initial_mode;
|
||||
/** Flags (@reg REGULATOR_FLAGS). */
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize common driver config from devicetree.
|
||||
*
|
||||
* @param node_id Node identifier.
|
||||
*/
|
||||
#define REGULATOR_DT_COMMON_CONFIG_INIT(node_id) \
|
||||
{ \
|
||||
.min_uv = DT_PROP_OR(node_id, regulator_min_microvolts, \
|
||||
INT32_MIN), \
|
||||
.max_uv = DT_PROP_OR(node_id, regulator_max_microvolts, \
|
||||
INT32_MAX), \
|
||||
.min_ua = DT_PROP_OR(node_id, regulator_min_microamps, \
|
||||
INT32_MIN), \
|
||||
.max_ua = DT_PROP_OR(node_id, regulator_max_microamps, \
|
||||
INT32_MAX), \
|
||||
.allowed_modes = (const regulator_mode_t []) \
|
||||
DT_PROP_OR(node_id, regulator_allowed_modes, {}), \
|
||||
.allowed_modes_cnt = \
|
||||
DT_PROP_LEN_OR(node_id, regulator_allowed_modes, 0), \
|
||||
.initial_mode = DT_PROP_OR(node_id, regulator_initial_mode, \
|
||||
REGULATOR_INITIAL_MODE_UNKNOWN), \
|
||||
.flags = ((DT_PROP_OR(node_id, regulator_always_on, 0U) * \
|
||||
REGULATOR_ALWAYS_ON) | \
|
||||
(DT_PROP_OR(node_id, regulator_boot_on, 0U) * \
|
||||
REGULATOR_BOOT_ON)), \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize common driver config from devicetree instance.
|
||||
*
|
||||
* @param inst Instance.
|
||||
*/
|
||||
#define REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst) \
|
||||
REGULATOR_DT_COMMON_CONFIG_INIT(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Common regulator data.
|
||||
*
|
||||
|
@ -73,7 +150,9 @@ void regulator_common_data_init(const struct device *dev);
|
|||
* @brief Enable a regulator.
|
||||
*
|
||||
* Reference-counted request that a regulator be turned on. A regulator is
|
||||
* considered "on" when it has reached a stable/usable state.
|
||||
* considered "on" when it has reached a stable/usable state. Regulators that
|
||||
* are always on, or configured in devicetree with `regulator-always-on` will
|
||||
* always stay enabled, and so this function will always succeed.
|
||||
*
|
||||
* @param dev Regulator device instance
|
||||
*
|
||||
|
@ -86,11 +165,9 @@ int regulator_enable(const struct device *dev);
|
|||
* @brief Disable a regulator.
|
||||
*
|
||||
* Release a regulator after a previous regulator_enable() completed
|
||||
* successfully.
|
||||
*
|
||||
* If the release removes the last dependency on the regulator it will begin a
|
||||
* transition to its "off" state. There is currently no mechanism to notify when
|
||||
* the regulator has completely turned off.
|
||||
* successfully. Regulators that are always on, or configured in devicetree with
|
||||
* `regulator-always-on` will always stay enabled, and so this function will
|
||||
* always succeed.
|
||||
*
|
||||
* This must be invoked at most once for each successful regulator_enable().
|
||||
*
|
||||
|
@ -170,7 +247,9 @@ bool regulator_is_supported_voltage(const struct device *dev, int32_t min_uv,
|
|||
*
|
||||
* The output voltage will be configured to the closest supported output
|
||||
* voltage. regulator_get_voltage() can be used to obtain the actual configured
|
||||
* voltage. The voltage will be applied to the active or selected mode.
|
||||
* voltage. The voltage will be applied to the active or selected mode. Output
|
||||
* voltage may be limited using `regulator-min-microvolt` and/or
|
||||
* `regulator-max-microvolt` in devicetree.
|
||||
*
|
||||
* @param dev Regulator device instance.
|
||||
* @param min_uv Minimum acceptable voltage in microvolts.
|
||||
|
@ -181,18 +260,8 @@ bool regulator_is_supported_voltage(const struct device *dev, int32_t min_uv,
|
|||
* @retval -ENOSYS If function is not implemented.
|
||||
* @retval -errno In case of any other error.
|
||||
*/
|
||||
static inline int regulator_set_voltage(const struct device *dev,
|
||||
int32_t min_uv, int32_t max_uv)
|
||||
{
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
if (api->set_voltage == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return api->set_voltage(dev, min_uv, max_uv);
|
||||
}
|
||||
int regulator_set_voltage(const struct device *dev, int32_t min_uv,
|
||||
int32_t max_uv);
|
||||
|
||||
/**
|
||||
* @brief Obtain output voltage.
|
||||
|
@ -222,7 +291,8 @@ static inline int regulator_get_voltage(const struct device *dev,
|
|||
*
|
||||
* The output current limit will be configured to the closest supported output
|
||||
* current limit. regulator_get_current_limit() can be used to obtain the actual
|
||||
* configured current limit.
|
||||
* configured current limit. Current may be limited using `current-min-microamp`
|
||||
* and/or `current-max-microamp` in Devicetree.
|
||||
*
|
||||
* @param dev Regulator device instance.
|
||||
* @param min_ua Minimum acceptable current limit in microamps.
|
||||
|
@ -233,18 +303,8 @@ static inline int regulator_get_voltage(const struct device *dev,
|
|||
* @retval -ENOSYS If function is not implemented.
|
||||
* @retval -errno In case of any other error.
|
||||
*/
|
||||
static inline int regulator_set_current_limit(const struct device *dev,
|
||||
int32_t min_ua, int32_t max_ua)
|
||||
{
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
if (api->set_current_limit == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return api->set_current_limit(dev, min_ua, max_ua);
|
||||
}
|
||||
int regulator_set_current_limit(const struct device *dev, int32_t min_ua,
|
||||
int32_t max_ua);
|
||||
|
||||
/**
|
||||
* @brief Get output current limit.
|
||||
|
@ -274,7 +334,8 @@ static inline int regulator_get_current_limit(const struct device *dev,
|
|||
*
|
||||
* Regulators can support multiple modes in order to permit different voltage
|
||||
* configuration or better power savings. This API will apply a mode for
|
||||
* the regulator.
|
||||
* the regulator. Allowed modes may be limited using `regulator-allowed-modes`
|
||||
* devicetree property.
|
||||
*
|
||||
* Some regulators may only allow setting mode externally, but still allow
|
||||
* configuring the parameters such as the output voltage. For such devices, this
|
||||
|
@ -284,26 +345,15 @@ static inline int regulator_get_current_limit(const struct device *dev,
|
|||
* Some regulators may apply a mode to all of its regulators simultaneously.
|
||||
*
|
||||
* @param dev Regulator device instance.
|
||||
* @param mode Mode to select for this regulator. Only modes present in the
|
||||
* `regulator-allowed-modes` devicetree property are permitted.
|
||||
* @param mode Mode to select for this regulator.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EPERM If mode can not be changed.
|
||||
* @retval -ENOTSUP If mode is not supported.
|
||||
* @retval -ENOSYS If function is not implemented.
|
||||
* @retval -errno In case of any other error.
|
||||
*/
|
||||
static inline int regulator_set_mode(const struct device *dev,
|
||||
regulator_mode_t mode)
|
||||
{
|
||||
const struct regulator_driver_api *api =
|
||||
(const struct regulator_driver_api *)dev->api;
|
||||
|
||||
if (api->set_mode == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return api->set_mode(dev, mode);
|
||||
}
|
||||
int regulator_set_mode(const struct device *dev, regulator_mode_t mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue