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:
parent
cae297d917
commit
81682a7c09
8 changed files with 271 additions and 0 deletions
9
tests/drivers/regulator/pmic/CMakeLists.txt
Normal file
9
tests/drivers/regulator/pmic/CMakeLists.txt
Normal 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})
|
10
tests/drivers/regulator/pmic/Kconfig
Normal file
10
tests/drivers/regulator/pmic/Kconfig
Normal 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
|
16
tests/drivers/regulator/pmic/README.txt
Normal file
16
tests/drivers/regulator/pmic/README.txt
Normal 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.
|
|
@ -0,0 +1 @@
|
|||
CONFIG_TEST_PMIC_REGULATOR_NAME="LDO2_REG"
|
|
@ -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>;
|
||||
};
|
||||
};
|
6
tests/drivers/regulator/pmic/prj.conf
Normal file
6
tests/drivers/regulator/pmic/prj.conf
Normal 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
|
206
tests/drivers/regulator/pmic/src/main.c
Normal file
206
tests/drivers/regulator/pmic/src/main.c
Normal 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);
|
||||
}
|
11
tests/drivers/regulator/pmic/testcase.yaml
Normal file
11
tests/drivers/regulator/pmic/testcase.yaml
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue