diff --git a/tests/drivers/regulator/pmic/CMakeLists.txt b/tests/drivers/regulator/pmic/CMakeLists.txt new file mode 100644 index 00000000000..b205447bf83 --- /dev/null +++ b/tests/drivers/regulator/pmic/CMakeLists.txt @@ -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}) diff --git a/tests/drivers/regulator/pmic/Kconfig b/tests/drivers/regulator/pmic/Kconfig new file mode 100644 index 00000000000..369b0b9e717 --- /dev/null +++ b/tests/drivers/regulator/pmic/Kconfig @@ -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 diff --git a/tests/drivers/regulator/pmic/README.txt b/tests/drivers/regulator/pmic/README.txt new file mode 100644 index 00000000000..fc3a5e3564b --- /dev/null +++ b/tests/drivers/regulator/pmic/README.txt @@ -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. diff --git a/tests/drivers/regulator/pmic/boards/mimxrt685_evk_cm33.conf b/tests/drivers/regulator/pmic/boards/mimxrt685_evk_cm33.conf new file mode 100644 index 00000000000..5da34b0a0c6 --- /dev/null +++ b/tests/drivers/regulator/pmic/boards/mimxrt685_evk_cm33.conf @@ -0,0 +1 @@ +CONFIG_TEST_PMIC_REGULATOR_NAME="LDO2_REG" diff --git a/tests/drivers/regulator/pmic/boards/mimxrt685_evk_cm33.overlay b/tests/drivers/regulator/pmic/boards/mimxrt685_evk_cm33.overlay new file mode 100644 index 00000000000..56c4e90a0b3 --- /dev/null +++ b/tests/drivers/regulator/pmic/boards/mimxrt685_evk_cm33.overlay @@ -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>; + }; +}; diff --git a/tests/drivers/regulator/pmic/prj.conf b/tests/drivers/regulator/pmic/prj.conf new file mode 100644 index 00000000000..147271149f7 --- /dev/null +++ b/tests/drivers/regulator/pmic/prj.conf @@ -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 diff --git a/tests/drivers/regulator/pmic/src/main.c b/tests/drivers/regulator/pmic/src/main.c new file mode 100644 index 00000000000..673d7417812 --- /dev/null +++ b/tests/drivers/regulator/pmic/src/main.c @@ -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 +#include +#include +#include +#include +#include + +#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); +} diff --git a/tests/drivers/regulator/pmic/testcase.yaml b/tests/drivers/regulator/pmic/testcase.yaml new file mode 100644 index 00000000000..bd026b2c27a --- /dev/null +++ b/tests/drivers/regulator/pmic/testcase.yaml @@ -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