tests: regulator_pmic: Added PMIC regulator test

Test verifies that i2c pmic regulator can be disabled or enabled using
the regulator API. Verifies PMIC output voltage using ADC.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
Daniel DeGrasse 2021-11-11 17:03:38 -06:00 committed by Christopher Friedt
commit 81682a7c09
8 changed files with 271 additions and 0 deletions

View file

@ -0,0 +1,9 @@
# Copyright 2021 NXP
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(tests_drivers_regulator_pmic)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,10 @@
# Copyright (c) 2021 NXP
# SPDX-License-Identifier: Apache-2.0
mainmenu "PMIC Regulator Test"
source "Kconfig.zephyr"
config TEST_PMIC_REGULATOR_NAME
string "PMIC regulator label to use for the test"
default "" # Must be set by board overlay

View file

@ -0,0 +1,16 @@
PMIC Regulator
###############
This application tests the i2c pmic regulator driver in multiple
configurations. It requires that an output source from the power management IC
be shorted to an ADC input, so that the test can verify the that the pmic is
responding to commands.
Only boards for which an overlay is present can pass this test. Boards
without an overlay, or for which the required wiring is not provided,
will fail with an error like this:
Assertion failed at ../src/main.c:196: test_basic: adc_reading >= 200
is false
No special build options are required to make use of the overlay.

View file

@ -0,0 +1 @@
CONFIG_TEST_PMIC_REGULATOR_NAME="LDO2_REG"

View file

@ -0,0 +1,12 @@
/*
* Copyright 2021 NXP
* SPDX-License-Identifier: Apache-2.0
*/
/ {
zephyr,user {
/* adjust channel number according to pinmux in board.dts */
io-channels = <&lpadc0 0>;
};
};

View file

@ -0,0 +1,6 @@
CONFIG_I2C=y
CONFIG_REGULATOR=y
CONFIG_LOG=y
CONFIG_ADC=y
CONFIG_REGULATOR_LOG_LEVEL_DBG=y
CONFIG_ZTEST=y

View file

@ -0,0 +1,206 @@
/*
* Copyright 2021 NXP
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Based on regulator-fixed test and adc driver sample, with are
* copyright Peter Bigot Consulting, LLC and Libre Solar Technologies GmbH,
* respectively.
*/
#include <zephyr.h>
#include <drivers/gpio.h>
#include <drivers/adc.h>
#include <drivers/regulator.h>
#include <drivers/regulator/consumer.h>
#include <ztest.h>
#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
!DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
#error "No suitable devicetree overlay specified"
#endif
#define ADC_NODE DT_PHANDLE(DT_PATH(zephyr_user), io_channels)
/* Common settings supported by most ADCs */
#define ADC_RESOLUTION 12
#define ADC_GAIN ADC_GAIN_1
#define ADC_REFERENCE ADC_REF_INTERNAL
#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
static int16_t sample_buffer[1];
#define CHANNEL_ID DT_IO_CHANNELS_INPUT_BY_IDX(DT_PATH(zephyr_user), 0)
struct adc_channel_cfg channel_cfg = {
.gain = ADC_GAIN,
.reference = ADC_REFERENCE,
.acquisition_time = ADC_ACQUISITION_TIME,
.channel_id = CHANNEL_ID,
.differential = 0
};
struct adc_sequence sequence = {
/* individual channels will be added below */
.channels = BIT(CHANNEL_ID),
.buffer = sample_buffer,
/* buffer size in bytes, not number of samples */
.buffer_size = sizeof(sample_buffer),
.resolution = ADC_RESOLUTION,
};
static struct onoff_client cli;
static struct onoff_manager *callback_srv;
static struct onoff_client *callback_cli;
static uint32_t callback_state;
static int callback_res;
static onoff_client_callback callback_fn;
static void callback(struct onoff_manager *srv,
struct onoff_client *cli,
uint32_t state,
int res)
{
onoff_client_callback cb = callback_fn;
callback_srv = srv;
callback_cli = cli;
callback_state = state;
callback_res = res;
callback_fn = NULL;
if (cb != NULL) {
cb(srv, cli, state, res);
}
}
static void reset_callback(void)
{
callback_srv = NULL;
callback_cli = NULL;
callback_state = INT_MIN;
callback_res = 0;
callback_fn = NULL;
}
static void reset_client(void)
{
cli = (struct onoff_client){};
reset_callback();
sys_notify_init_callback(&cli.notify, callback);
}
/* Returns voltage level of ADC in mV, or negative value on error */
static int adc_get_reading(const struct device *adc_dev)
{
int rc, adc_vref, mv_value;
adc_vref = adc_ref_internal(adc_dev);
rc = adc_read(adc_dev, &sequence);
if (rc) {
return rc;
}
mv_value = sample_buffer[0];
if (adc_vref > 0) {
adc_raw_to_millivolts(adc_vref, ADC_GAIN, ADC_RESOLUTION, &mv_value);
}
TC_PRINT("ADC read %d mV\n", mv_value);
return mv_value;
}
static void test_basic(void)
{
const struct device *reg_dev, *adc_dev;
int rc, adc_reading;
adc_dev = device_get_binding(DT_LABEL(ADC_NODE));
reg_dev = device_get_binding(CONFIG_TEST_PMIC_REGULATOR_NAME);
zassert_not_null(adc_dev,
"ADC device to check regulator output not defined");
zassert_not_null(reg_dev,
"Could not get regulator device binding");
/* Configure ADC */
adc_channel_setup(adc_dev, &channel_cfg);
reset_client();
/* Turn regulator on */
rc = regulator_enable(reg_dev, &cli);
zassert_true(rc >= 0,
"first enable failed: %d", rc);
/* Wait for regulator to start */
while (sys_notify_fetch_result(&cli.notify, &rc) == -EAGAIN) {
k_yield();
}
rc = sys_notify_fetch_result(&cli.notify, &rc);
zassert_true(rc == 0, "Could not fetch regulator enable result");
zassert_equal(callback_cli, &cli,
"callback not invoked");
zassert_equal(callback_res, 0,
"callback res: %d", callback_res);
zassert_equal(callback_state, ONOFF_STATE_ON,
"callback state: 0x%x", callback_res);
/* Read adc to ensure regulator actually booted */
adc_reading = adc_get_reading(adc_dev);
zassert_true(adc_reading > 200, /* Assume regulator provides at least 200mV */
"Regulator did not supply power, ADC read %d mV",
adc_reading);
/* Turn it on again (another client) */
reset_client();
rc = regulator_enable(reg_dev, &cli);
zassert_true(rc >= 0,
"second enable failed: %d", rc);
zassert_equal(callback_cli, &cli,
"callback not invoked");
zassert_true(callback_res >= 0,
"callback res: %d", callback_res);
zassert_equal(callback_state, ONOFF_STATE_ON,
"callback state: 0x%x", callback_res);
/* Make sure it's still on */
adc_reading = adc_get_reading(adc_dev);
zassert_true(adc_reading >= 200,
"Second on attempt failed, ADC read %d mV", adc_reading);
/* Turn it off once (still has a client) */
rc = regulator_disable(reg_dev);
zassert_true(rc >= 0,
"first disable failed: %d", rc);
/* Make sure it's still on */
adc_reading = adc_get_reading(adc_dev);
zassert_true(adc_reading >= 200,
"Regulator still has client, but ADC read %d mV", adc_reading);
/* Turn it off again (no more clients) */
rc = regulator_disable(reg_dev);
zassert_true(rc >= 0,
"second disable failed: %d", rc);
/* Verify the regulator is off */
adc_reading = adc_get_reading(adc_dev);
zassert_true(adc_reading <= 200,
"Regulator is on with no clients, ADC read %d mV", adc_reading);
}
void test_main(void)
{
ztest_test_suite(regulator_test,
ztest_unit_test(test_basic)
);
ztest_run_test_suite(regulator_test);
}

View file

@ -0,0 +1,11 @@
common:
tags: drivers i2c
depends_on: i2c adc
filter: dt_compat_enabled("regulator-pmic")
harness: ztest
harness_config:
fixture: regulator_pmic
tests:
drivers.regulator.i2c.onoff:
depends_on: i2c adc