drivers: regulator: initial driver for nPM6001

Add initial driver for the nPM6001 PMIC.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
Gerard Marull-Paretas 2022-12-12 12:27:31 +01:00 committed by Carles Cufí
commit 7568749c8c
6 changed files with 833 additions and 0 deletions

View file

@ -5,5 +5,6 @@ zephyr_library()
zephyr_library_sources(regulator_common.c) zephyr_library_sources(regulator_common.c)
zephyr_library_sources_ifdef(CONFIG_REGULATOR_FIXED regulator_fixed.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_FIXED regulator_fixed.c)
zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM6001 regulator_npm6001.c)
zephyr_library_sources_ifdef(CONFIG_REGULATOR_PCA9420 regulator_pca9420.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_PCA9420 regulator_pca9420.c)
zephyr_library_sources_ifdef(CONFIG_REGULATOR_SHELL regulator_shell.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_SHELL regulator_shell.c)

View file

@ -22,6 +22,7 @@ module-str = regulator
source "subsys/logging/Kconfig.template.log_config" source "subsys/logging/Kconfig.template.log_config"
source "drivers/regulator/Kconfig.fixed" source "drivers/regulator/Kconfig.fixed"
source "drivers/regulator/Kconfig.npm6001"
source "drivers/regulator/Kconfig.pca9420" source "drivers/regulator/Kconfig.pca9420"
endif # REGULATOR endif # REGULATOR

View file

@ -0,0 +1,28 @@
# Copyright (c) 2022 Nordic Semiconductor ASA
# SPDX -License-Identifier: Apache-2.0
config REGULATOR_NPM6001
bool "nPM6001 PMIC regulator driver"
default y
depends on DT_HAS_NORDIC_NPM6001_REGULATOR_ENABLED
select I2C
help
Enable the Nordic nPM6001 PMIC regulator driver
if REGULATOR_NPM6001
config REGULATOR_NPM6001_COMMON_INIT_PRIORITY
int "nPM6001 regulator driver init priority (common part)"
default 75
help
Init priority for the Nordic nPM6001 regulator driver (common part).
It must be greater than I2C init priority.
config REGULATOR_NPM6001_INIT_PRIORITY
int "nPM6001 regulator driver init priority"
default 76
help
Init priority for the Nordic nPM6001 regulator driver. It must be
greater than REGULATOR_NPM6001_COMMON_INIT_PRIORITY.
endif

View file

@ -0,0 +1,680 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nordic_npm6001_regulator
#include <errno.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/regulator.h>
#include <zephyr/dt-bindings/regulator/npm6001.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/linear_range.h>
#include <zephyr/sys/util.h>
/* nPM6001 voltage sources */
enum npm6001_sources {
NPM6001_SOURCE_BUCK0,
NPM6001_SOURCE_BUCK1,
NPM6001_SOURCE_BUCK2,
NPM6001_SOURCE_BUCK3,
NPM6001_SOURCE_LDO0,
NPM6001_SOURCE_LDO1,
};
/* nPM6001 regulator related registers */
#define NPM6001_TASKS_START_BUCK3 0x02U
#define NPM6001_TASKS_START_LDO0 0x03U
#define NPM6001_TASKS_START_LDO1 0x04U
#define NPM6001_TASKS_STOP_BUCK3 0x08U
#define NPM6001_TASKS_STOP_LDO0 0x09U
#define NPM6001_TASKS_STOP_LDO1 0x0AU
#define NPM6001_TASKS_UPDATE_VOUTPWM 0x0EU
#define NPM6001_EVENTS_THWARN 0x1EU
#define NPM6001_EVENTS_BUCK0OC 0x1FU
#define NPM6001_EVENTS_BUCK1OC 0x20U
#define NPM6001_EVENTS_BUCK2OC 0x21U
#define NPM6001_EVENTS_BUCK3OC 0x22U
#define NPM6001_BUCK0VOUTULP 0x3AU
#define NPM6001_BUCK1VOUTULP 0x3CU
#define NPM6001_BUCK2VOUTULP 0x40U
#define NPM6001_BUCK3SELDAC 0x44U
#define NPM6001_BUCK3VOUT 0x45U
#define NPM6001_LDO0VOUT 0x46U
#define NPM6001_BUCK0CONFPWMMODE 0x4AU
#define NPM6001_BUCK1CONFPWMMODE 0x4BU
#define NPM6001_BUCK2CONFPWMMODE 0x4CU
#define NPM6001_BUCK3CONFPWMMODE 0x4DU
#define NPM6001_BUCKMODEPADCONF 0x4EU
#define NPM6001_PADDRIVESTRENGTH 0x53U
/* nPM6001 LDO0VOUT values */
#define NPM6001_LDO0VOUT_SET1V8 0x06U
#define NPM6001_LDO0VOUT_SET2V1 0x0BU
#define NPM6001_LDO0VOUT_SET2V41 0x10U
#define NPM6001_LDO0VOUT_SET2V7 0x15U
#define NPM6001_LDO0VOUT_SET3V0 0x1AU
#define NPM6001_LDO0VOUT_SET3V3 0x1EU
/* nPM6001 BUCKXCONFPWMMODE fields */
#define NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM_MSK 0x8U
#define NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM_POS 3
#define NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM \
BIT(NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM_POS)
#define NPM6001_BUCKMODEPADCONF_BUCKMODE0PADTYPE_CMOS BIT(0)
#define NPM6001_BUCKMODEPADCONF_BUCKMODE1PADTYPE_CMOS BIT(1)
#define NPM6001_BUCKMODEPADCONF_BUCKMODE2PADTYPE_CMOS BIT(2)
#define NPM6001_BUCKMODEPADCONF_BUCKMODE0PULLD_ENABLED BIT(4)
#define NPM6001_BUCKMODEPADCONF_BUCKMODE1PULLD_ENABLED BIT(5)
#define NPM6001_BUCKMODEPADCONF_BUCKMODE2PULLD_ENABLED BIT(6)
/* nPM6001 PADDRIVESTRENGTH fields */
#define NPM6001_PADDRIVESTRENGTH_READY_HIGH BIT(2)
#define NPM6001_PADDRIVESTRENGTH_NINT_HIGH BIT(3)
#define NPM6001_PADDRIVESTRENGTH_SDA_HIGH BIT(5)
struct regulator_npm6001_pconfig {
struct i2c_dt_spec i2c;
uint8_t buck_pad_val;
uint8_t pad_val;
};
struct regulator_npm6001_config {
struct regulator_common_config common;
const struct device *p;
uint8_t source;
};
struct regulator_npm6001_data {
struct regulator_common_data data;
};
struct regulator_npm6001_vmap {
uint8_t reg_val;
int32_t volt_uv;
};
static const struct linear_range buck0_range =
LINEAR_RANGE_INIT(1800000, 100000U, 0x0U, 0xFU);
static const struct linear_range buck1_range =
LINEAR_RANGE_INIT(700000, 50000U, 0x0U, 0xEU);
static const struct linear_range buck2_range =
LINEAR_RANGE_INIT(1200000, 50000U, 0xAU, 0xEU);
static const struct linear_range buck3_range =
LINEAR_RANGE_INIT(500000, 25000U, 0x0U, 0x70U);
static const struct regulator_npm6001_vmap ldo0_voltages[] = {
{ NPM6001_LDO0VOUT_SET1V8, 1800000 },
{ NPM6001_LDO0VOUT_SET2V1, 2100000 },
{ NPM6001_LDO0VOUT_SET2V41, 2410000 },
{ NPM6001_LDO0VOUT_SET2V7, 2700000 },
{ NPM6001_LDO0VOUT_SET3V0, 3000000 },
{ NPM6001_LDO0VOUT_SET3V3, 3300000 },
};
static int regulator_npm6001_ldo0_list_voltage(const struct device *dev,
unsigned int idx,
int32_t *volt_uv)
{
if (idx >= ARRAY_SIZE(ldo0_voltages)) {
return -EINVAL;
}
*volt_uv = ldo0_voltages[idx].volt_uv;
return 0;
}
static int regulator_npm6001_buck012_set_voltage(
const struct device *dev, int32_t min_uv, int32_t max_uv,
const struct linear_range *range, uint8_t vout_reg, uint8_t conf_reg)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t conf, buf[3];
uint16_t idx;
int ret;
ret = linear_range_get_win_index(range, min_uv, max_uv, &idx);
if (ret < 0) {
return ret;
}
/* force PWM mode when updating voltage */
ret = i2c_reg_read_byte_dt(&pconfig->i2c, conf_reg, &conf);
if (ret < 0) {
return ret;
}
if ((conf & NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM) == 0U) {
ret = i2c_reg_write_byte_dt(
&pconfig->i2c, conf_reg,
conf | NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM);
if (ret < 0) {
return ret;
}
}
/* write voltage in both ULP/PWM registers */
buf[0] = vout_reg;
buf[1] = (uint8_t)idx;
buf[2] = (uint8_t)idx;
ret = i2c_write_dt(&pconfig->i2c, buf, sizeof(buf));
if (ret < 0) {
return ret;
}
ret = i2c_reg_write_byte_dt(&pconfig->i2c, NPM6001_TASKS_UPDATE_VOUTPWM,
1U);
if (ret < 0) {
return ret;
}
/* restore HYS mode if enabled before */
if ((conf & NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM) == 0U) {
ret = i2c_reg_write_byte_dt(&pconfig->i2c, conf_reg, conf);
if (ret < 0) {
return ret;
}
}
return 0;
}
static int regulator_npm6001_buck3_set_voltage(const struct device *dev,
int32_t min_uv, int32_t max_uv)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint16_t idx;
uint8_t conf;
int ret;
ret = linear_range_get_win_index(&buck3_range, min_uv, max_uv, &idx);
if (ret < 0) {
return ret;
}
/* force PWM mode when updating voltage */
ret = i2c_reg_read_byte_dt(&pconfig->i2c, NPM6001_BUCK3CONFPWMMODE,
&conf);
if (ret < 0) {
return ret;
}
if ((conf & NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM) == 0U) {
ret = i2c_reg_write_byte_dt(
&pconfig->i2c, NPM6001_BUCK3CONFPWMMODE,
conf | NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM);
if (ret < 0) {
return ret;
}
}
ret = i2c_reg_write_byte_dt(&pconfig->i2c, NPM6001_BUCK3VOUT,
(uint8_t)idx);
if (ret < 0) {
return ret;
}
/* restore HYS mode if enabled before */
if ((conf & NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM) == 0U) {
ret = i2c_reg_write_byte_dt(&pconfig->i2c,
NPM6001_BUCK3CONFPWMMODE, conf);
if (ret < 0) {
return ret;
}
}
return 0;
}
static int regulator_npm6001_ldo0_set_voltage(const struct device *dev,
int32_t min_uv, int32_t max_uv)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t val;
size_t i;
for (i = 0U; i < ARRAY_SIZE(ldo0_voltages); i++) {
if ((min_uv <= ldo0_voltages[i].volt_uv) &&
(max_uv >= ldo0_voltages[i].volt_uv)) {
val = ldo0_voltages[i].reg_val;
break;
}
}
if (i == ARRAY_SIZE(ldo0_voltages)) {
return -EINVAL;
}
return i2c_reg_write_byte_dt(&pconfig->i2c, NPM6001_LDO0VOUT, val);
}
static int
regulator_npm6001_buck0123_get_voltage(const struct device *dev,
const struct linear_range *range,
uint8_t vout_reg, int32_t *volt_uv)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t idx;
int ret;
ret = i2c_reg_read_byte_dt(&pconfig->i2c, vout_reg, &idx);
if (ret < 0) {
return ret;
}
return linear_range_get_value(range, idx, volt_uv);
}
static int regulator_npm6001_ldo0_get_voltage(const struct device *dev,
int32_t *volt_uv)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t val;
int ret;
ret = i2c_reg_read_byte_dt(&pconfig->i2c, NPM6001_LDO0VOUT, &val);
if (ret < 0) {
return ret;
}
for (size_t i = 0U; i < ARRAY_SIZE(ldo0_voltages); i++) {
if (val == ldo0_voltages[i].reg_val) {
*volt_uv = ldo0_voltages[i].volt_uv;
return 0;
}
}
__ASSERT(NULL, "Unexpected voltage");
return -EINVAL;
}
static unsigned int regulator_npm6001_count_voltages(const struct device *dev)
{
const struct regulator_npm6001_config *config = dev->config;
switch (config->source) {
case NPM6001_SOURCE_BUCK0:
return linear_range_values_count(&buck0_range);
case NPM6001_SOURCE_BUCK1:
return linear_range_values_count(&buck1_range);
case NPM6001_SOURCE_BUCK2:
return linear_range_values_count(&buck2_range);
case NPM6001_SOURCE_BUCK3:
return linear_range_values_count(&buck3_range);
case NPM6001_SOURCE_LDO0:
return 6U;
case NPM6001_SOURCE_LDO1:
return 1U;
default:
__ASSERT(NULL, "Unexpected source");
}
return 0;
}
static int regulator_npm6001_list_voltage(const struct device *dev,
unsigned int idx, int32_t *volt_uv)
{
const struct regulator_npm6001_config *config = dev->config;
switch (config->source) {
case NPM6001_SOURCE_BUCK0:
return linear_range_get_value(&buck0_range, idx, volt_uv);
case NPM6001_SOURCE_BUCK1:
return linear_range_get_value(&buck1_range, idx, volt_uv);
case NPM6001_SOURCE_BUCK2:
return linear_range_get_value(
&buck2_range, idx + buck2_range.min_idx, volt_uv);
case NPM6001_SOURCE_BUCK3:
return linear_range_get_value(&buck3_range, idx, volt_uv);
case NPM6001_SOURCE_LDO0:
return regulator_npm6001_ldo0_list_voltage(dev, idx, volt_uv);
case NPM6001_SOURCE_LDO1:
*volt_uv = 1800000;
break;
default:
__ASSERT(NULL, "Unexpected source");
}
return 0;
}
static int regulator_npm6001_set_voltage(const struct device *dev,
int32_t min_uv, int32_t max_uv)
{
const struct regulator_npm6001_config *config = dev->config;
switch (config->source) {
case NPM6001_SOURCE_BUCK0:
return regulator_npm6001_buck012_set_voltage(
dev, min_uv, max_uv, &buck0_range, NPM6001_BUCK0VOUTULP,
NPM6001_BUCK0CONFPWMMODE);
case NPM6001_SOURCE_BUCK1:
return regulator_npm6001_buck012_set_voltage(
dev, min_uv, max_uv, &buck1_range, NPM6001_BUCK1VOUTULP,
NPM6001_BUCK1CONFPWMMODE);
case NPM6001_SOURCE_BUCK2:
return regulator_npm6001_buck012_set_voltage(
dev, min_uv, max_uv, &buck2_range, NPM6001_BUCK2VOUTULP,
NPM6001_BUCK2CONFPWMMODE);
case NPM6001_SOURCE_BUCK3:
return regulator_npm6001_buck3_set_voltage(dev, min_uv, max_uv);
case NPM6001_SOURCE_LDO0:
return regulator_npm6001_ldo0_set_voltage(dev, min_uv, max_uv);
case NPM6001_SOURCE_LDO1:
return -ENOTSUP;
default:
__ASSERT(NULL, "Unexpected source");
}
return 0;
}
static int regulator_npm6001_get_voltage(const struct device *dev,
int32_t *volt_uv)
{
const struct regulator_npm6001_config *config = dev->config;
switch (config->source) {
case NPM6001_SOURCE_BUCK0:
return regulator_npm6001_buck0123_get_voltage(
dev, &buck0_range, NPM6001_BUCK0VOUTULP, volt_uv);
case NPM6001_SOURCE_BUCK1:
return regulator_npm6001_buck0123_get_voltage(
dev, &buck1_range, NPM6001_BUCK1VOUTULP, volt_uv);
case NPM6001_SOURCE_BUCK2:
return regulator_npm6001_buck0123_get_voltage(
dev, &buck2_range, NPM6001_BUCK2VOUTULP, volt_uv);
case NPM6001_SOURCE_BUCK3:
return regulator_npm6001_buck0123_get_voltage(
dev, &buck3_range, NPM6001_BUCK3VOUT, volt_uv);
case NPM6001_SOURCE_LDO0:
return regulator_npm6001_ldo0_get_voltage(dev, volt_uv);
case NPM6001_SOURCE_LDO1:
*volt_uv = 1800000U;
break;
default:
__ASSERT(NULL, "Unexpected source");
}
return 0;
}
static int regulator_npm6001_set_mode(const struct device *dev,
regulator_mode_t mode)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t conf_reg;
if (mode > NPM6001_MODE_PWM) {
return -ENOTSUP;
}
switch (config->source) {
case NPM6001_SOURCE_BUCK0:
conf_reg = NPM6001_BUCK0CONFPWMMODE;
break;
case NPM6001_SOURCE_BUCK1:
conf_reg = NPM6001_BUCK1CONFPWMMODE;
break;
case NPM6001_SOURCE_BUCK2:
conf_reg = NPM6001_BUCK2CONFPWMMODE;
break;
case NPM6001_SOURCE_BUCK3:
conf_reg = NPM6001_BUCK3CONFPWMMODE;
break;
default:
return -ENOTSUP;
}
return i2c_reg_update_byte_dt(
&pconfig->i2c, conf_reg,
NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM_MSK,
mode << NPM6001_BUCKXCONFPWMMODE_SETFORCEPWM_POS);
}
static int regulator_npm6001_enable(const struct device *dev)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t start_reg;
switch (config->source) {
case NPM6001_SOURCE_BUCK3:
start_reg = NPM6001_TASKS_START_BUCK3;
break;
case NPM6001_SOURCE_LDO0:
start_reg = NPM6001_TASKS_START_LDO0;
break;
case NPM6001_SOURCE_LDO1:
start_reg = NPM6001_TASKS_START_LDO1;
break;
default:
return 0;
}
/* TASKS_START_(BUCK3|LDO0|LDO1) */
return i2c_reg_write_byte_dt(&pconfig->i2c, start_reg, 1U);
}
static int regulator_npm6001_disable(const struct device *dev)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t stop_reg;
switch (config->source) {
case NPM6001_SOURCE_BUCK3:
stop_reg = NPM6001_TASKS_STOP_BUCK3;
break;
case NPM6001_SOURCE_LDO0:
stop_reg = NPM6001_TASKS_STOP_LDO0;
break;
case NPM6001_SOURCE_LDO1:
stop_reg = NPM6001_TASKS_STOP_LDO1;
break;
default:
return 0;
}
return i2c_reg_write_byte_dt(&pconfig->i2c, stop_reg, 1U);
}
static int regulator_npm6001_get_error_flags(const struct device *dev,
regulator_error_flags_t *flags)
{
const struct regulator_npm6001_config *config = dev->config;
const struct regulator_npm6001_pconfig *pconfig = config->p->config;
uint8_t oc_reg, val;
int ret;
*flags = 0U;
/* read thermal warning */
ret = i2c_reg_read_byte_dt(&pconfig->i2c, NPM6001_EVENTS_THWARN, &val);
if (ret < 0) {
return ret;
}
if (val != 0U) {
/* clear thermal warning */
ret = i2c_reg_write_byte_dt(&pconfig->i2c,
NPM6001_EVENTS_THWARN, 0U);
if (ret < 0) {
return ret;
}
*flags |= REGULATOR_ERROR_OVER_TEMP;
}
/* read overcurrent event */
switch (config->source) {
case NPM6001_SOURCE_BUCK0:
oc_reg = NPM6001_EVENTS_BUCK0OC;
break;
case NPM6001_SOURCE_BUCK1:
oc_reg = NPM6001_EVENTS_BUCK1OC;
break;
case NPM6001_SOURCE_BUCK2:
oc_reg = NPM6001_EVENTS_BUCK2OC;
break;
case NPM6001_SOURCE_BUCK3:
oc_reg = NPM6001_EVENTS_BUCK3OC;
break;
default:
return 0;
}
ret = i2c_reg_read_byte_dt(&pconfig->i2c, oc_reg, &val);
if (ret < 0) {
return ret;
}
if (val != 0U) {
/* clear overcurrent event */
ret = i2c_reg_write_byte_dt(&pconfig->i2c, oc_reg, 0U);
if (ret < 0) {
return ret;
}
*flags |= REGULATOR_ERROR_OVER_CURRENT;
}
return 0;
}
static int regulator_npm6001_init(const struct device *dev)
{
const struct regulator_npm6001_config *config = dev->config;
regulator_common_data_init(dev);
if (!device_is_ready(config->p)) {
return -ENODEV;
}
return regulator_common_init_enable(dev);
}
static int regulator_npm6001_common_init(const struct device *dev)
{
const struct regulator_npm6001_pconfig *config = dev->config;
int ret;
if (!device_is_ready(config->i2c.bus)) {
return -ENODEV;
}
/* always select BUCK3 DAC (does not increase power consumption) */
ret = i2c_reg_write_byte_dt(&config->i2c, NPM6001_BUCK3SELDAC, 1U);
if (ret < 0) {
return ret;
}
/* configure pad properties */
ret = i2c_reg_write_byte_dt(&config->i2c, NPM6001_BUCKMODEPADCONF,
config->buck_pad_val);
if (ret < 0) {
return ret;
}
ret = i2c_reg_write_byte_dt(&config->i2c, NPM6001_PADDRIVESTRENGTH,
config->pad_val);
if (ret < 0) {
return ret;
}
return 0;
}
static const struct regulator_driver_api api = {
.enable = regulator_npm6001_enable,
.disable = regulator_npm6001_disable,
.count_voltages = regulator_npm6001_count_voltages,
.list_voltage = regulator_npm6001_list_voltage,
.set_voltage = regulator_npm6001_set_voltage,
.get_voltage = regulator_npm6001_get_voltage,
.set_mode = regulator_npm6001_set_mode,
.get_error_flags = regulator_npm6001_get_error_flags,
};
#define REGULATOR_NPM6001_DEFINE(node_id, id, _source, parent) \
static struct regulator_npm6001_data data_##id; \
\
static const struct regulator_npm6001_config config_##id = { \
.common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \
.p = parent, \
.source = _source, \
}; \
\
DEVICE_DT_DEFINE(node_id, regulator_npm6001_init, NULL, &data_##id, \
&config_##id, POST_KERNEL, \
CONFIG_REGULATOR_NPM6001_INIT_PRIORITY, &api);
#define REGULATOR_NPM6001_DEFINE_COND(inst, child, source, parent) \
COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \
(REGULATOR_NPM6001_DEFINE(DT_INST_CHILD(inst, child), \
child##inst, source, parent)), \
())
#define REGULATOR_NPM6001_DEFINE_ALL(inst) \
static const struct regulator_npm6001_pconfig config_##inst = { \
.i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)), \
.buck_pad_val = \
((DT_INST_ENUM_IDX(inst, \
nordic_buck_mode0_input_type) * \
NPM6001_BUCKMODEPADCONF_BUCKMODE0PADTYPE_CMOS) | \
(DT_INST_ENUM_IDX(inst, \
nordic_buck_mode1_input_type) * \
NPM6001_BUCKMODEPADCONF_BUCKMODE1PADTYPE_CMOS) | \
(DT_INST_ENUM_IDX(inst, \
nordic_buck_mode2_input_type) * \
NPM6001_BUCKMODEPADCONF_BUCKMODE2PADTYPE_CMOS) | \
(DT_INST_PROP(inst, nordic_buck_mode0_pull_down) * \
NPM6001_BUCKMODEPADCONF_BUCKMODE0PULLD_ENABLED) | \
(DT_INST_PROP(inst, nordic_buck_mode1_pull_down) * \
NPM6001_BUCKMODEPADCONF_BUCKMODE1PULLD_ENABLED) | \
(DT_INST_PROP(inst, nordic_buck_mode2_pull_down) * \
NPM6001_BUCKMODEPADCONF_BUCKMODE2PULLD_ENABLED)), \
.pad_val = ((DT_INST_PROP(inst, nordic_ready_high_drive) * \
NPM6001_PADDRIVESTRENGTH_READY_HIGH) | \
(DT_INST_PROP(inst, nordic_nint_high_drive) * \
NPM6001_PADDRIVESTRENGTH_NINT_HIGH) | \
(DT_INST_PROP(inst, nordic_sda_high_drive) * \
NPM6001_PADDRIVESTRENGTH_SDA_HIGH)), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, regulator_npm6001_common_init, NULL, NULL, \
&config_##inst, POST_KERNEL, \
CONFIG_REGULATOR_NPM6001_COMMON_INIT_PRIORITY, \
NULL); \
\
REGULATOR_NPM6001_DEFINE_COND(inst, buck0, NPM6001_SOURCE_BUCK0, \
DEVICE_DT_INST_GET(inst)) \
REGULATOR_NPM6001_DEFINE_COND(inst, buck1, NPM6001_SOURCE_BUCK1, \
DEVICE_DT_INST_GET(inst)) \
REGULATOR_NPM6001_DEFINE_COND(inst, buck2, NPM6001_SOURCE_BUCK2, \
DEVICE_DT_INST_GET(inst)) \
REGULATOR_NPM6001_DEFINE_COND(inst, buck3, NPM6001_SOURCE_BUCK3, \
DEVICE_DT_INST_GET(inst)) \
REGULATOR_NPM6001_DEFINE_COND(inst, ldo0, NPM6001_SOURCE_LDO0, \
DEVICE_DT_INST_GET(inst)) \
REGULATOR_NPM6001_DEFINE_COND(inst, ldo1, NPM6001_SOURCE_LDO1, \
DEVICE_DT_INST_GET(inst))
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM6001_DEFINE_ALL)

View file

@ -0,0 +1,95 @@
# Copyright (c), 2022 Nordic Semiconductor ASA
# SPDX -License-Identifier: Apache-2.0
description: |
Nordic nPM6001 PMIC
The PMIC has four buck converters and two LDOs. All need to be defined as
children nodes, strictly following the BUCK0..3, LDO0..1 node names. For
example:
pmic@70 {
reg = <0x70>;
...
regulators {
compatible = "nordic,npm6001-regulator";
BUCK0 {
/* all properties for BUCK0 */
};
BUCK1 {
/* all properties for BUCK1 */
};
BUCK2 {
/* all properties for BUCK2 */
};
BUCK3 {
/* all properties for BUCK3 */
};
LDO0 {
/* all properties for LDO0 */
};
LDO1 {
/* all properties for LDO1 */
};
};
};
compatible: "nordic,npm6001-regulator"
include: base.yaml
properties:
nordic,ready-high-drive:
type: boolean
description: Set drive strength to high for READY pin.
nordic,nint-high-drive:
type: boolean
description: Set drive strength to high for NINT pin.
nordic,sda-high-drive:
type: boolean
description: Set drive strength to high for SDA pin.
nordic,buck-mode0-input-type:
type: string
default: "schmitt"
enum: ["schmitt", "cmos"]
description: Input type for BUCK_MODE0 pin. Defaults IC boot-time value.
nordic,buck-mode0-pull-down:
type: boolean
description: Enable pull-down resistor for BUCK_MODE0 pin.
nordic,buck-mode1-input-type:
type: string
default: "schmitt"
enum: ["schmitt", "cmos"]
description: Input type for BUCK_MODE1 pin. Defaults IC boot-time value.
nordic,buck-mode1-pull-down:
type: boolean
description: Enable pull-down resistor for BUCK_MODE1 pin.
nordic,buck-mode2-input-type:
type: string
default: "schmitt"
enum: ["schmitt", "cmos"]
description: Input type for BUCK_MODE2 pin. Defaults IC boot-time value.
nordic,buck-mode2-pull-down:
type: boolean
description: Enable pull-down resistor for BUCK_MODE2 pin.
child-binding:
include:
- name: regulator.yaml
property-allowlist:
- regulator-always-on
- regulator-boot-on
- regulator-max-microamp
- regulator-min-microvolt
- regulator-max-microvolt
- regulator-allowed-modes
- regulator-initial-mode

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM6001_H_
#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM6001_H_
/**
* @defgroup regulator_npm6001 NPM6001 Devicetree helpers.
* @ingroup regulator_interface
* @{
*/
/**
* @name NPM6001 Regulator modes
* @{
*/
/** Hysteretic mode */
#define NPM6001_MODE_HYS 0
/** PWM mode */
#define NPM6001_MODE_PWM 1
/** @} */
/** @} */
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM6001_H_*/