| /* |
| * Copyright (c) 2022 Nordic Semiconductor ASA |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/device.h> |
| #include <zephyr/devicetree.h> |
| #include <zephyr/drivers/adc.h> |
| #include <zephyr/drivers/regulator.h> |
| #include <zephyr/sys/util.h> |
| #include <zephyr/ztest.h> |
| |
| #define REG_INIT(node_id, prop, idx) \ |
| DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)), |
| |
| #define ADC_INIT(node_id, prop, idx) \ |
| ADC_DT_SPEC_GET_BY_IDX(node_id, idx), |
| |
| static const struct device *regs[] = { |
| DT_FOREACH_PROP_ELEM(DT_NODELABEL(resources), regulators, REG_INIT) |
| }; |
| |
| static const struct adc_dt_spec adc_chs[] = { |
| DT_FOREACH_PROP_ELEM(DT_NODELABEL(resources), io_channels, ADC_INIT) |
| }; |
| |
| static const int32_t tols[] = |
| DT_PROP(DT_NODELABEL(resources), tolerance_microvolt); |
| |
| static const unsigned int adc_avg_count = DT_PROP(DT_NODELABEL(resources), |
| adc_avg_count); |
| static const int32_t set_read_delay_ms = DT_PROP(DT_NODELABEL(resources), |
| set_read_delay_ms); |
| |
| ZTEST(regulator_voltage, test_output_voltage) |
| { |
| int16_t buf; |
| struct adc_sequence sequence = { |
| .buffer = &buf, |
| .buffer_size = sizeof(buf), |
| }; |
| |
| for (size_t i = 0U; i < ARRAY_SIZE(regs); i++) { |
| int ret; |
| unsigned int volt_cnt; |
| int32_t volt_uv; |
| |
| ret = adc_sequence_init_dt(&adc_chs[i], &sequence); |
| zassert_equal(ret, 0); |
| |
| volt_cnt = regulator_count_voltages(regs[i]); |
| zassume_not_equal(volt_cnt, 0U); |
| |
| TC_PRINT("Testing %s, %u voltage/s (tolerance: %d uV)\n", |
| regs[i]->name, volt_cnt, tols[i]); |
| |
| ret = regulator_enable(regs[i]); |
| zassert_equal(ret, 0); |
| |
| for (unsigned int j = 0U; j < volt_cnt; j++) { |
| int32_t val_mv = 0; |
| |
| (void)regulator_list_voltage(regs[i], j, &volt_uv); |
| |
| ret = regulator_set_voltage(regs[i], volt_uv, volt_uv); |
| zassert_equal(ret, 0); |
| |
| if (set_read_delay_ms > 0) { |
| k_msleep(set_read_delay_ms); |
| } |
| |
| for (unsigned int k = 0U; k < adc_avg_count; k++) { |
| ret = adc_read(adc_chs[i].dev, &sequence); |
| zassert_equal(ret, 0); |
| |
| val_mv += buf; |
| } |
| |
| val_mv /= (int32_t)adc_avg_count; |
| |
| ret = adc_raw_to_millivolts_dt(&adc_chs[i], &val_mv); |
| zassert_equal(ret, 0); |
| |
| TC_PRINT("Set: %d, read: %d uV\n", volt_uv, |
| val_mv * 1000); |
| |
| zassert_between_inclusive(val_mv * 1000, |
| volt_uv - tols[i], |
| volt_uv + tols[i]); |
| } |
| |
| ret = regulator_disable(regs[i]); |
| zassert_equal(ret, 0); |
| } |
| } |
| |
| void *setup(void) |
| { |
| zassert_equal(ARRAY_SIZE(regs), ARRAY_SIZE(adc_chs)); |
| zassert_equal(ARRAY_SIZE(regs), ARRAY_SIZE(tols)); |
| |
| for (size_t i = 0U; i < ARRAY_SIZE(regs); i++) { |
| zassert_true(device_is_ready(regs[i])); |
| zassert_true(device_is_ready(adc_chs[i].dev)); |
| zassert_equal(adc_channel_setup_dt(&adc_chs[i]), 0); |
| } |
| |
| return NULL; |
| } |
| |
| ZTEST_SUITE(regulator_voltage, NULL, setup, NULL, NULL, NULL); |