samples: shields: npm6001_ek: add utility to test regulators

Add a utility sub-shell to test all regulators embedded in 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:34:16 +01:00 committed by Carles Cufí
commit 460f2d04fa
2 changed files with 317 additions and 0 deletions

View file

@ -10,6 +10,7 @@ This sample is provided as an example to test the :ref:`npm6001_ek`. The sample
provides a shell interface that allows to test multiple functionalities offered
by the nPM6001 PMIC, including:
- Regulators (BUCK0/1/2/3 and LDO0/1)
- GPIO
- Watchdog
@ -41,6 +42,68 @@ Note that this sample automatically sets ``SHIELD`` to ``npm6001_ek``. Once
flashed, you should boot into the shell interface. The ``npm6001`` command is
provided to test the PMIC. Below you can find details for each subcommand.
Regulators
==========
The ``npm6001`` shell interface provides the ``regulator`` subcommand to test
the regulators embedded in the PMIC (BUCK0/1/2/3 and LDO0/1). Below you can
find some command examples.
.. code-block:: bash
# list all the available regulators
npm6001 regulator list
BUCK0
BUCK1
BUCK2
BUCK3
LDO0
LDO1
.. code-block:: bash
# list all the supported voltages by BUCK2
npm6001 regulator voltages BUCK2
1200 mV
1250 mV
1300 mV
1350 mV
1400 mV
.. code-block:: bash
# enable BUCK3
npm6001 regulator enable BUCK3
# disable BUCK3
npm6001 regulator disable BUCK3
.. code-block:: bash
# set BUCK3 voltage to exactly 3000 mV
npm6001 regulator set BUCK3 3000
# obtain the actual BUCK3 configured voltage
npm6001 regulator get BUCK3
3000 mV
# set BUCK0 voltage to a value between 2350 mV and 2450 mV
npm6001 regulator set BUCK0 2350 2450
# obtain the actual BUCK0 configured voltage
npm6001 regulator get BUCK3
2400 mV
.. code-block:: bash
# set BUCK0 to hysteretic mode
npm6001 regulator modeset BUCK0 hys
# set BUCK0 to PWM mode
npm6001 regulator modeset BUCK0 pwm
.. code-block:: bash
# get active errors on BUCK0
npm6001 regulator errors BUCK0
Overcurrent: [ ]
Overtemp.: [ ]
GPIO
====

View file

@ -7,16 +7,42 @@
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/regulator.h>
#include <zephyr/drivers/watchdog.h>
#include <zephyr/dt-bindings/gpio/nordic-npm6001-gpio.h>
#include <zephyr/dt-bindings/regulator/npm6001.h>
#include <zephyr/posix/unistd.h>
#include <zephyr/shell/shell.h>
#include <zephyr/sys/printk.h>
#include <getopt.h>
struct regulators_map {
const char *name;
const struct device *dev;
};
static const struct device *const gpio = DEVICE_DT_GET_ONE(nordic_npm6001_gpio);
static const struct device *const wdt = DEVICE_DT_GET_ONE(nordic_npm6001_wdt);
static const struct regulators_map regulators[] = {
{ "BUCK0", DEVICE_DT_GET_OR_NULL(DT_NODELABEL(npm6001_ek_buck0)) },
{ "BUCK1", DEVICE_DT_GET_OR_NULL(DT_NODELABEL(npm6001_ek_buck1)) },
{ "BUCK2", DEVICE_DT_GET_OR_NULL(DT_NODELABEL(npm6001_ek_buck2)) },
{ "BUCK3", DEVICE_DT_GET_OR_NULL(DT_NODELABEL(npm6001_ek_buck3)) },
{ "LDO0", DEVICE_DT_GET_OR_NULL(DT_NODELABEL(npm6001_ek_ldo0)) },
{ "LDO1", DEVICE_DT_GET_OR_NULL(DT_NODELABEL(npm6001_ek_ldo1)) },
};
static const struct device *name2reg(const char *name)
{
for (size_t i = 0U; i < ARRAY_SIZE(regulators); i++) {
if (strcmp(name, regulators[i].name) == 0) {
return regulators[i].dev;
}
}
return NULL;
}
void main(void)
{
@ -29,6 +55,213 @@ void main(void)
printk("nPM6001 Watchdog device not ready\n");
return;
}
for (size_t i = 0U; i < ARRAY_SIZE(regulators); i++) {
if ((regulators[i].dev != NULL) &&
!device_is_ready(regulators[i].dev)) {
printk("nPM6001 %s regulator device not ready\n",
regulators[i].name);
return;
}
}
}
static int cmd_regulator_list(const struct shell *sh, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
for (size_t i = 0U; i < ARRAY_SIZE(regulators); i++) {
if (regulators[i].dev != NULL) {
shell_print(sh, "%s", regulators[i].name);
}
}
return 0;
}
static int cmd_regulator_voltages(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev;
unsigned int volt_cnt;
ARG_UNUSED(argc);
dev = name2reg(argv[1]);
if (dev == NULL) {
shell_error(sh, "Invalid regulator: %s", argv[1]);
return -ENODEV;
}
volt_cnt = regulator_count_voltages(dev);
for (unsigned int i = 0U; i < volt_cnt; i++) {
int32_t volt_uv;
(void)regulator_list_voltage(dev, i, &volt_uv);
shell_print(sh, "%d mV", volt_uv / 1000);
}
return 0;
}
static int cmd_regulator_enable(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev;
int ret;
ARG_UNUSED(argc);
dev = name2reg(argv[1]);
if (dev == NULL) {
shell_error(sh, "Invalid regulator: %s", argv[1]);
return -ENODEV;
}
ret = regulator_enable(dev);
if (ret < 0) {
shell_error(sh, "Could not enable regulator (%d)", ret);
return ret;
}
return 0;
}
static int cmd_regulator_disable(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev;
int ret;
ARG_UNUSED(argc);
dev = name2reg(argv[1]);
if (dev == NULL) {
shell_error(sh, "Invalid regulator: %s", argv[1]);
return -ENODEV;
}
ret = regulator_disable(dev);
if (ret < 0) {
shell_error(sh, "Could not disable regulator (%d)", ret);
return ret;
}
return 0;
}
static int cmd_regulator_set(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev;
int32_t min_uv, max_uv;
int ret;
dev = name2reg(argv[1]);
if (dev == NULL) {
shell_error(sh, "Invalid regulator: %s", argv[1]);
return -ENODEV;
}
min_uv = (int32_t)strtoul(argv[2], NULL, 10) * 1000;
if (argc == 4) {
max_uv = (int32_t)strtoul(argv[3], NULL, 10) * 1000;
} else {
max_uv = min_uv;
}
ret = regulator_set_voltage(dev, min_uv, max_uv);
if (ret < 0) {
shell_error(sh, "Could not set voltage (%d)", ret);
return ret;
}
return 0;
}
static int cmd_regulator_get(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev;
int32_t volt_uv;
int ret;
ARG_UNUSED(argc);
dev = name2reg(argv[1]);
if (dev == NULL) {
shell_error(sh, "Invalid regulator: %s", argv[1]);
return -ENODEV;
}
volt_uv = (int32_t)strtoul(argv[1], NULL, 10) * 1000;
ret = regulator_get_voltage(dev, &volt_uv);
if (ret < 0) {
shell_error(sh, "Could not get voltage (%d)", ret);
return ret;
}
shell_print(sh, "%d mV", volt_uv / 1000);
return 0;
}
static int cmd_regulator_modeset(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev;
regulator_mode_t mode;
int ret;
ARG_UNUSED(argc);
dev = name2reg(argv[1]);
if (dev == NULL) {
shell_error(sh, "Invalid regulator: %s", argv[1]);
return -ENODEV;
}
if (strcmp(argv[2], "pwm") == 0) {
mode = NPM6001_MODE_PWM;
} else if (strcmp(argv[2], "hys") == 0) {
mode = NPM6001_MODE_HYS;
} else {
shell_error(sh, "Invalid mode: %s", argv[1]);
return -EINVAL;
}
ret = regulator_set_mode(dev, mode);
if (ret < 0) {
shell_error(sh, "Could not set mode (%d)", ret);
return ret;
}
return 0;
}
static int cmd_regulator_errors(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev;
regulator_error_flags_t errors;
int ret;
ARG_UNUSED(argc);
dev = name2reg(argv[1]);
if (dev == NULL) {
shell_error(sh, "Invalid regulator: %s", argv[1]);
return -ENODEV;
}
ret = regulator_get_error_flags(dev, &errors);
if (ret < 0) {
shell_error(sh, "Could not get error flags (%d)", ret);
return ret;
}
shell_print(sh, "Overcurrent:\t[%s]",
((errors & REGULATOR_ERROR_OVER_CURRENT) != 0U) ? "X" : " ");
shell_print(sh, "Overtemp.:\t[%s]",
((errors & REGULATOR_ERROR_OVER_TEMP) != 0U) ? "X" : " ");
return 0;
}
static int cmd_gpio_configure(const struct shell *sh, size_t argc, char **argv)
@ -190,6 +423,25 @@ static int cmd_wdt_kick(const struct shell *sh, size_t argc, char **argv)
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(sub_npm6001_regulator_cmds,
SHELL_CMD(list, NULL, "List regulator names",
cmd_regulator_list),
SHELL_CMD_ARG(voltages, NULL, "List voltages",
cmd_regulator_voltages, 2, 0),
SHELL_CMD_ARG(enable, NULL, "Enable regulator",
cmd_regulator_enable, 2, 0),
SHELL_CMD_ARG(disable, NULL, "Disable regulator",
cmd_regulator_disable, 2, 0),
SHELL_CMD_ARG(set, NULL, "Set voltage",
cmd_regulator_set, 3, 1),
SHELL_CMD_ARG(get, NULL, "Get voltage",
cmd_regulator_get, 2, 0),
SHELL_CMD_ARG(modeset, NULL, "Set mode PWM/HYS",
cmd_regulator_modeset, 3, 0),
SHELL_CMD_ARG(errors, NULL, "Get active errors",
cmd_regulator_errors, 2, 0),
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(sub_npm6001_gpio_cmds,
SHELL_CMD_ARG(configure, NULL, "Configure GPIO",
cmd_gpio_configure, 5, 3),
@ -211,6 +463,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_npm6001_wdt_cmds,
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(sub_npm6001_cmds,
SHELL_CMD(regulator, &sub_npm6001_regulator_cmds,
"Regulators", NULL),
SHELL_CMD(gpio, &sub_npm6001_gpio_cmds, "GPIO",
NULL),
SHELL_CMD(wdt, &sub_npm6001_wdt_cmds, "Watchdog",