1 /*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define ADC_CONTEXT_USES_KERNEL_TIMER
8 #include "adc_context.h"
9 #include <nrfx_adc.h>
10 #include <zephyr/dt-bindings/adc/nrf-adc.h>
11
12 #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
13 #include <zephyr/logging/log.h>
14 #include <zephyr/irq.h>
15 LOG_MODULE_REGISTER(adc_nrfx_adc);
16
17 #define DT_DRV_COMPAT nordic_nrf_adc
18
19 /* Ensure that definitions in nrf-adc.h match MDK. */
20 BUILD_ASSERT((NRF_ADC_AIN0 == NRF_ADC_CONFIG_INPUT_0) &&
21 (NRF_ADC_AIN1 == NRF_ADC_CONFIG_INPUT_1) &&
22 (NRF_ADC_AIN2 == NRF_ADC_CONFIG_INPUT_2) &&
23 (NRF_ADC_AIN3 == NRF_ADC_CONFIG_INPUT_3) &&
24 (NRF_ADC_AIN4 == NRF_ADC_CONFIG_INPUT_4) &&
25 (NRF_ADC_AIN5 == NRF_ADC_CONFIG_INPUT_5) &&
26 (NRF_ADC_AIN6 == NRF_ADC_CONFIG_INPUT_6) &&
27 (NRF_ADC_AIN7 == NRF_ADC_CONFIG_INPUT_7),
28 "Definitions from nrf-adc.h do not match those from nrf_adc.h");
29
30 struct driver_data {
31 struct adc_context ctx;
32
33 nrf_adc_value_t *buffer;
34 uint8_t active_channels;
35 };
36
37 static struct driver_data m_data = {
38 ADC_CONTEXT_INIT_TIMER(m_data, ctx),
39 ADC_CONTEXT_INIT_LOCK(m_data, ctx),
40 ADC_CONTEXT_INIT_SYNC(m_data, ctx),
41 };
42
43 static nrfx_adc_channel_t m_channels[CONFIG_ADC_NRFX_ADC_CHANNEL_COUNT];
44
45
46 /* Implementation of the ADC driver API function: adc_channel_setup. */
adc_nrfx_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)47 static int adc_nrfx_channel_setup(const struct device *dev,
48 const struct adc_channel_cfg *channel_cfg)
49 {
50 uint8_t channel_id = channel_cfg->channel_id;
51 nrf_adc_config_t *config = &m_channels[channel_id].config;
52
53 if (channel_id >= CONFIG_ADC_NRFX_ADC_CHANNEL_COUNT) {
54 return -EINVAL;
55 }
56
57 if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
58 LOG_ERR("Selected ADC acquisition time is not valid");
59 return -EINVAL;
60 }
61
62 if (channel_cfg->differential) {
63 LOG_ERR("Differential channels are not supported");
64 return -EINVAL;
65 }
66
67 switch (channel_cfg->gain) {
68 case ADC_GAIN_1_3:
69 config->scaling = NRF_ADC_CONFIG_SCALING_INPUT_ONE_THIRD;
70 break;
71 case ADC_GAIN_2_3:
72 config->scaling = NRF_ADC_CONFIG_SCALING_INPUT_TWO_THIRDS;
73 break;
74 case ADC_GAIN_1:
75 config->scaling = NRF_ADC_CONFIG_SCALING_INPUT_FULL_SCALE;
76 break;
77 default:
78 LOG_ERR("Selected ADC gain is not valid");
79 return -EINVAL;
80 }
81
82 switch (channel_cfg->reference) {
83 case ADC_REF_INTERNAL:
84 config->reference = NRF_ADC_CONFIG_REF_VBG;
85 config->extref = NRF_ADC_CONFIG_EXTREFSEL_NONE;
86 break;
87 case ADC_REF_VDD_1_2:
88 config->reference = NRF_ADC_CONFIG_REF_SUPPLY_ONE_HALF;
89 config->extref = NRF_ADC_CONFIG_EXTREFSEL_NONE;
90 break;
91 case ADC_REF_VDD_1_3:
92 config->reference = NRF_ADC_CONFIG_REF_SUPPLY_ONE_THIRD;
93 config->extref = NRF_ADC_CONFIG_EXTREFSEL_NONE;
94 break;
95 case ADC_REF_EXTERNAL0:
96 config->reference = NRF_ADC_CONFIG_REF_EXT;
97 config->extref = NRF_ADC_CONFIG_EXTREFSEL_AREF0;
98 break;
99 case ADC_REF_EXTERNAL1:
100 config->reference = NRF_ADC_CONFIG_REF_EXT;
101 config->extref = NRF_ADC_CONFIG_EXTREFSEL_AREF1;
102 break;
103 default:
104 LOG_ERR("Selected ADC reference is not valid");
105 return -EINVAL;
106 }
107
108 config->input = channel_cfg->input_positive;
109
110 config->resolution = NRF_ADC_CONFIG_RES_8BIT;
111
112 return 0;
113 }
114
adc_context_start_sampling(struct adc_context * ctx)115 static void adc_context_start_sampling(struct adc_context *ctx)
116 {
117 ARG_UNUSED(ctx);
118
119 nrfx_adc_buffer_convert(m_data.buffer, m_data.active_channels);
120 nrfx_adc_sample();
121 }
122
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat)123 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
124 bool repeat)
125 {
126 ARG_UNUSED(ctx);
127
128 if (!repeat) {
129 m_data.buffer += m_data.active_channels;
130 }
131 }
132
check_buffer_size(const struct adc_sequence * sequence,uint8_t active_channels)133 static int check_buffer_size(const struct adc_sequence *sequence,
134 uint8_t active_channels)
135 {
136 size_t needed_buffer_size;
137
138 needed_buffer_size = active_channels * sizeof(nrf_adc_value_t);
139 if (sequence->options) {
140 needed_buffer_size *= (1 + sequence->options->extra_samplings);
141 }
142
143 if (sequence->buffer_size < needed_buffer_size) {
144 LOG_ERR("Provided buffer is too small (%u/%u)",
145 sequence->buffer_size, needed_buffer_size);
146 return -ENOMEM;
147 }
148
149 return 0;
150 }
151
start_read(const struct device * dev,const struct adc_sequence * sequence)152 static int start_read(const struct device *dev,
153 const struct adc_sequence *sequence)
154 {
155 int error;
156 uint32_t selected_channels = sequence->channels;
157 uint8_t active_channels;
158 uint8_t channel_id;
159 nrf_adc_config_resolution_t nrf_resolution;
160
161 /* Signal an error if channel selection is invalid (no channels or
162 * a non-existing one is selected).
163 */
164 if (!selected_channels ||
165 (selected_channels &
166 ~BIT_MASK(CONFIG_ADC_NRFX_ADC_CHANNEL_COUNT))) {
167 LOG_ERR("Invalid selection of channels");
168 return -EINVAL;
169 }
170
171 if (sequence->oversampling != 0U) {
172 LOG_ERR("Oversampling is not supported");
173 return -EINVAL;
174 }
175
176 switch (sequence->resolution) {
177 case 8:
178 nrf_resolution = NRF_ADC_CONFIG_RES_8BIT;
179 break;
180 case 9:
181 nrf_resolution = NRF_ADC_CONFIG_RES_9BIT;
182 break;
183 case 10:
184 nrf_resolution = NRF_ADC_CONFIG_RES_10BIT;
185 break;
186 default:
187 LOG_ERR("ADC resolution value %d is not valid",
188 sequence->resolution);
189 return -EINVAL;
190 }
191
192 active_channels = 0U;
193 nrfx_adc_all_channels_disable();
194
195 /* Enable the channels selected for the pointed sequence.
196 */
197 channel_id = 0U;
198 while (selected_channels) {
199 if (selected_channels & BIT(0)) {
200 /* The nrfx driver requires setting the resolution
201 * for each enabled channel individually.
202 */
203 m_channels[channel_id].config.resolution =
204 nrf_resolution;
205 nrfx_adc_channel_enable(&m_channels[channel_id]);
206 ++active_channels;
207 }
208 selected_channels >>= 1;
209 ++channel_id;
210 }
211
212 error = check_buffer_size(sequence, active_channels);
213 if (error) {
214 return error;
215 }
216
217 m_data.buffer = sequence->buffer;
218 m_data.active_channels = active_channels;
219
220 adc_context_start_read(&m_data.ctx, sequence);
221
222 error = adc_context_wait_for_completion(&m_data.ctx);
223 return error;
224 }
225
226 /* Implementation of the ADC driver API function: adc_read. */
adc_nrfx_read(const struct device * dev,const struct adc_sequence * sequence)227 static int adc_nrfx_read(const struct device *dev,
228 const struct adc_sequence *sequence)
229 {
230 int error;
231
232 adc_context_lock(&m_data.ctx, false, NULL);
233 error = start_read(dev, sequence);
234 adc_context_release(&m_data.ctx, error);
235
236 return error;
237 }
238
239 #ifdef CONFIG_ADC_ASYNC
240 /* Implementation of the ADC driver API function: adc_read_sync. */
adc_nrfx_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)241 static int adc_nrfx_read_async(const struct device *dev,
242 const struct adc_sequence *sequence,
243 struct k_poll_signal *async)
244 {
245 int error;
246
247 adc_context_lock(&m_data.ctx, true, async);
248 error = start_read(dev, sequence);
249 adc_context_release(&m_data.ctx, error);
250
251 return error;
252 }
253 #endif /* CONFIG_ADC_ASYNC */
254
event_handler(const nrfx_adc_evt_t * p_event)255 static void event_handler(const nrfx_adc_evt_t *p_event)
256 {
257 const struct device *const dev = DEVICE_DT_INST_GET(0);
258
259 if (p_event->type == NRFX_ADC_EVT_DONE) {
260 adc_context_on_sampling_done(&m_data.ctx, dev);
261 }
262 }
263
init_adc(const struct device * dev)264 static int init_adc(const struct device *dev)
265 {
266 const nrfx_adc_config_t config = NRFX_ADC_DEFAULT_CONFIG;
267
268 nrfx_err_t result = nrfx_adc_init(&config, event_handler);
269
270 if (result != NRFX_SUCCESS) {
271 LOG_ERR("Failed to initialize device: %s",
272 dev->name);
273 return -EBUSY;
274 }
275
276 IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
277 nrfx_isr, nrfx_adc_irq_handler, 0);
278
279 adc_context_unlock_unconditionally(&m_data.ctx);
280
281 return 0;
282 }
283
284 static const struct adc_driver_api adc_nrfx_driver_api = {
285 .channel_setup = adc_nrfx_channel_setup,
286 .read = adc_nrfx_read,
287 #ifdef CONFIG_ADC_ASYNC
288 .read_async = adc_nrfx_read_async,
289 #endif
290 .ref_internal = 1200,
291 };
292
293 /*
294 * There is only one instance on supported SoCs, so inst is guaranteed
295 * to be 0 if any instance is okay. (We use adc_0 above, so the driver
296 * is relying on the numeric instance value in a way that happens to
297 * be safe.)
298 *
299 * Just in case that assumption becomes invalid in the future, we use
300 * a BUILD_ASSERT().
301 */
302 #define ADC_INIT(inst) \
303 BUILD_ASSERT((inst) == 0, \
304 "multiple instances not supported"); \
305 DEVICE_DT_INST_DEFINE(0, \
306 init_adc, NULL, NULL, NULL, \
307 POST_KERNEL, \
308 CONFIG_ADC_INIT_PRIORITY, \
309 &adc_nrfx_driver_api);
310
311 DT_INST_FOREACH_STATUS_OKAY(ADC_INIT)
312