1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <zephyr/device.h>
7 #include <zephyr/devicetree.h>
8 #include <zephyr/drivers/adc.h>
9 #include <zephyr/drivers/regulator.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/ztest.h>
12 
13 #define ADC_INIT(node_id, prop, idx) \
14 	ADC_DT_SPEC_GET_BY_IDX(node_id, idx),
15 
16 static const struct device *regs[] = {
17 	DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(resources), regulators, DEVICE_DT_GET_BY_IDX, (,))
18 };
19 
20 static const struct adc_dt_spec adc_chs[] = {
21 	DT_FOREACH_PROP_ELEM(DT_NODELABEL(resources), io_channels, ADC_INIT)
22 };
23 
24 static const int32_t tols[] =
25 	DT_PROP(DT_NODELABEL(resources), tolerance_microvolt);
26 
27 static const unsigned int adc_avg_count = DT_PROP(DT_NODELABEL(resources),
28 						  adc_avg_count);
29 static const int32_t set_read_delay_ms = DT_PROP(DT_NODELABEL(resources),
30 						 set_read_delay_ms);
31 
32 static const int32_t min_microvolt = DT_PROP(DT_NODELABEL(resources), min_microvolt);
33 static const int32_t max_microvolt = DT_PROP(DT_NODELABEL(resources), max_microvolt);
34 
ZTEST(regulator_voltage,test_output_voltage)35 ZTEST(regulator_voltage, test_output_voltage)
36 {
37 	int16_t buf;
38 	struct adc_sequence sequence = {
39 		.buffer = &buf,
40 		.buffer_size = sizeof(buf),
41 	};
42 
43 	for (size_t i = 0U; i < ARRAY_SIZE(regs); i++) {
44 		int ret;
45 		unsigned int volt_cnt;
46 		int32_t volt_uv;
47 
48 		ret = adc_sequence_init_dt(&adc_chs[i], &sequence);
49 		zassert_equal(ret, 0);
50 
51 		volt_cnt = regulator_count_voltages(regs[i]);
52 		zassume_not_equal(volt_cnt, 0U);
53 
54 		TC_PRINT("Testing %s, %u voltage/s (tolerance: %d uV)\n",
55 			 regs[i]->name, volt_cnt, tols[i]);
56 
57 		ret = regulator_enable(regs[i]);
58 		zassert_equal(ret, 0);
59 
60 		for (unsigned int j = 0U; j < volt_cnt; j++) {
61 			int32_t val_mv = 0;
62 
63 			(void)regulator_list_voltage(regs[i], j, &volt_uv);
64 			/* Check if voltage is outside user constraints */
65 			if (!regulator_is_supported_voltage(regs[i],
66 				volt_uv, volt_uv)) {
67 				continue;
68 			}
69 
70 			if ((volt_uv < min_microvolt) || (volt_uv > max_microvolt)) {
71 				TC_PRINT("Skip: %d uV\n", volt_uv);
72 				continue;
73 			}
74 
75 			ret = regulator_set_voltage(regs[i], volt_uv, volt_uv);
76 			zassert_equal(ret, 0);
77 
78 			if (set_read_delay_ms > 0) {
79 				k_msleep(set_read_delay_ms);
80 			}
81 
82 			for (unsigned int k = 0U; k < adc_avg_count; k++) {
83 				ret = adc_read_dt(&adc_chs[i], &sequence);
84 				zassert_equal(ret, 0);
85 
86 				val_mv += buf;
87 			}
88 
89 			val_mv /= (int32_t)adc_avg_count;
90 
91 			ret = adc_raw_to_millivolts_dt(&adc_chs[i], &val_mv);
92 			zassert_equal(ret, 0);
93 
94 			TC_PRINT("Set: %d, read: %d uV\n", volt_uv,
95 				 val_mv * 1000);
96 
97 			zassert_between_inclusive(val_mv * 1000,
98 						  volt_uv - tols[i],
99 						  volt_uv + tols[i]);
100 		}
101 
102 		ret = regulator_disable(regs[i]);
103 		zassert_equal(ret, 0);
104 	}
105 }
106 
setup(void)107 void *setup(void)
108 {
109 	zassert_equal(ARRAY_SIZE(regs), ARRAY_SIZE(adc_chs));
110 	zassert_equal(ARRAY_SIZE(regs), ARRAY_SIZE(tols));
111 
112 	for (size_t i = 0U; i < ARRAY_SIZE(regs); i++) {
113 		zassert_true(device_is_ready(regs[i]));
114 		zassert_true(adc_is_ready_dt(&adc_chs[i]));
115 		zassert_equal(adc_channel_setup_dt(&adc_chs[i]), 0);
116 	}
117 
118 	return NULL;
119 }
120 
121 ZTEST_SUITE(regulator_voltage, NULL, setup, NULL, NULL, NULL);
122