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