1 /*
2  * Copyright (c) 2019 Derek Hageman <hageman@inthat.cloud>
3  * Copyright (c) 2024 Gerson Fernando Budke <nandojve@gmail.com>
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT atmel_sam0_adc
9 
10 #include <soc.h>
11 #include <zephyr/drivers/adc.h>
12 #include <zephyr/drivers/pinctrl.h>
13 
14 #include <zephyr/logging/log.h>
15 #include <zephyr/irq.h>
16 LOG_MODULE_REGISTER(adc_sam0, CONFIG_ADC_LOG_LEVEL);
17 
18 /* clang-format off */
19 
20 #define ADC_CONTEXT_USES_KERNEL_TIMER
21 #include "adc_context.h"
22 
23 #if defined(CONFIG_SOC_SERIES_SAMD21) || defined(CONFIG_SOC_SERIES_SAMR21) || \
24 	defined(CONFIG_SOC_SERIES_SAMD20)
25 /*
26  * SAMD21 Manual 33.6.2.1: The first conversion after changing the reference
27  * is invalid, so we have to discard it.
28  */
29 #define ADC_SAM0_REFERENCE_GLITCH 1
30 #endif
31 
32 struct adc_sam0_data {
33 	struct adc_context ctx;
34 	const struct device *dev;
35 
36 	uint16_t *buffer;
37 
38 	/*
39 	 * Saved initial start, so we can reset the advances we've done
40 	 * if required
41 	 */
42 	uint16_t *repeat_buffer;
43 
44 #ifdef ADC_SAM0_REFERENCE_GLITCH
45 	uint8_t reference_changed;
46 #endif
47 };
48 
49 struct adc_sam0_cfg {
50 	Adc *regs;
51 	const struct pinctrl_dev_config *pcfg;
52 	volatile uint32_t *mclk;
53 	uint32_t mclk_mask;
54 	uint32_t gclk_gen;
55 	uint16_t gclk_id;
56 	uint32_t freq;
57 	uint16_t prescaler;
58 	void (*config_func)(const struct device *dev);
59 };
60 
wait_synchronization(Adc * const adc)61 static void wait_synchronization(Adc *const adc)
62 {
63 	while ((ADC_SYNC(adc) & ADC_SYNC_MASK) != 0) {
64 	}
65 }
66 
adc_sam0_acquisition_to_clocks(const struct device * dev,uint16_t acquisition_time)67 static int adc_sam0_acquisition_to_clocks(const struct device *dev,
68 					  uint16_t acquisition_time)
69 {
70 	const struct adc_sam0_cfg *const cfg = dev->config;
71 	uint64_t scaled_acq;
72 
73 	switch (ADC_ACQ_TIME_UNIT(acquisition_time)) {
74 	case ADC_ACQ_TIME_TICKS:
75 		if (ADC_ACQ_TIME_VALUE(acquisition_time) > 64U) {
76 			return -EINVAL;
77 		}
78 
79 		return (int)ADC_ACQ_TIME_VALUE(acquisition_time) - 1;
80 	case ADC_ACQ_TIME_MICROSECONDS:
81 		scaled_acq = (uint64_t)ADC_ACQ_TIME_VALUE(acquisition_time) *
82 			     1000000U;
83 		break;
84 	case ADC_ACQ_TIME_NANOSECONDS:
85 		scaled_acq = (uint64_t)ADC_ACQ_TIME_VALUE(acquisition_time) *
86 			     1000U;
87 		break;
88 	default:
89 		return -EINVAL;
90 	}
91 
92 	/*
93 	 * sample_time = (sample_length+1) * (clk_adc / 2)
94 	 * sample_length = sample_time * (2/clk_adc) - 1,
95 	 */
96 
97 	scaled_acq *= 2U;
98 	scaled_acq += cfg->freq / 2U;
99 	scaled_acq /= cfg->freq;
100 	if (scaled_acq <= 1U) {
101 		return 0;
102 	}
103 
104 	scaled_acq -= 1U;
105 	if (scaled_acq >= 64U) {
106 		return -EINVAL;
107 	}
108 
109 	return (int)scaled_acq;
110 }
111 
adc_sam0_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)112 static int adc_sam0_channel_setup(const struct device *dev,
113 				  const struct adc_channel_cfg *channel_cfg)
114 {
115 	const struct adc_sam0_cfg *const cfg = dev->config;
116 	Adc *const adc = cfg->regs;
117 	int retval;
118 	uint8_t sampctrl = 0;
119 
120 	if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
121 		retval = adc_sam0_acquisition_to_clocks(dev,
122 							channel_cfg->acquisition_time);
123 		if (retval < 0) {
124 			LOG_ERR("Selected ADC acquisition time is not valid");
125 			return retval;
126 		}
127 
128 		sampctrl |= ADC_SAMPCTRL_SAMPLEN(retval);
129 	}
130 
131 	adc->SAMPCTRL.reg = sampctrl;
132 	wait_synchronization(adc);
133 
134 	uint8_t refctrl;
135 
136 	switch (channel_cfg->reference) {
137 	case ADC_REF_INTERNAL:
138 		refctrl = ADC_REFCTRL_REFSEL_INTERNAL | ADC_REFCTRL_REFCOMP;
139 		/* Enable the internal bandgap reference */
140 		ADC_BGEN = 1;
141 		break;
142 #ifdef ADC_REFCTRL_REFSEL_VDD_1
143 	case ADC_REF_VDD_1:
144 		refctrl = ADC_REFCTRL_REFSEL_VDD_1 | ADC_REFCTRL_REFCOMP;
145 		break;
146 #endif
147 	case ADC_REF_VDD_1_2:
148 		refctrl = ADC_REFCTRL_REFSEL_VDD_1_2 | ADC_REFCTRL_REFCOMP;
149 		break;
150 	case ADC_REF_EXTERNAL0:
151 		refctrl = ADC_REFCTRL_REFSEL_AREFA;
152 		break;
153 #ifdef ADC_REFCTRL_REFSEL_AREFB
154 	case ADC_REF_EXTERNAL1:
155 		refctrl = ADC_REFCTRL_REFSEL_AREFB;
156 		break;
157 #endif
158 	default:
159 		LOG_ERR("Selected reference is not valid");
160 		return -EINVAL;
161 	}
162 	if (adc->REFCTRL.reg != refctrl) {
163 #ifdef ADC_SAM0_REFERENCE_ENABLE_PROTECTED
164 		adc->CTRLA.bit.ENABLE = 0;
165 		wait_synchronization(adc);
166 #endif
167 		adc->REFCTRL.reg = refctrl;
168 		wait_synchronization(adc);
169 #ifdef ADC_SAM0_REFERENCE_ENABLE_PROTECTED
170 		adc->CTRLA.bit.ENABLE = 1;
171 		wait_synchronization(adc);
172 #endif
173 #ifdef ADC_SAM0_REFERENCE_GLITCH
174 		struct adc_sam0_data *data = dev->data;
175 
176 		data->reference_changed = 1;
177 #endif
178 	}
179 
180 	uint32_t inputctrl = 0;
181 
182 	switch (channel_cfg->gain) {
183 	case ADC_GAIN_1:
184 #ifdef ADC_INPUTCTRL_GAIN_1X
185 		inputctrl = ADC_INPUTCTRL_GAIN_1X;
186 #endif
187 		break;
188 #ifdef ADC_INPUTCTRL_GAIN_DIV2
189 	case ADC_GAIN_1_2:
190 		inputctrl = ADC_INPUTCTRL_GAIN_DIV2;
191 		break;
192 #endif
193 #ifdef ADC_INPUTCTRL_GAIN_2X
194 	case ADC_GAIN_2:
195 		inputctrl = ADC_INPUTCTRL_GAIN_2X;
196 		break;
197 #endif
198 #ifdef ADC_INPUTCTRL_GAIN_4X
199 	case ADC_GAIN_4:
200 		inputctrl = ADC_INPUTCTRL_GAIN_4X;
201 		break;
202 #endif
203 #ifdef ADC_INPUTCTRL_GAIN_8X
204 	case ADC_GAIN_8:
205 		inputctrl = ADC_INPUTCTRL_GAIN_8X;
206 		break;
207 #endif
208 #ifdef ADC_INPUTCTRL_GAIN_16X
209 	case ADC_GAIN_16:
210 		inputctrl = ADC_INPUTCTRL_GAIN_16X;
211 		break;
212 #endif
213 	default:
214 		LOG_ERR("Selected ADC gain is not valid");
215 		return -EINVAL;
216 	}
217 
218 	inputctrl |= ADC_INPUTCTRL_MUXPOS(channel_cfg->input_positive);
219 	if (channel_cfg->differential) {
220 		inputctrl |= ADC_INPUTCTRL_MUXNEG(channel_cfg->input_negative);
221 
222 		ADC_DIFF(adc) |= ADC_DIFF_MASK;
223 	} else {
224 		inputctrl |= ADC_INPUTCTRL_MUXNEG_GND;
225 
226 		ADC_DIFF(adc) &= ~ADC_DIFF_MASK;
227 	}
228 	wait_synchronization(adc);
229 
230 	adc->INPUTCTRL.reg = inputctrl;
231 	wait_synchronization(adc);
232 
233 	/* Enable references if they're selected */
234 	switch (channel_cfg->input_positive) {
235 #ifdef ADC_INPUTCTRL_MUXPOS_TEMP_Val
236 	case ADC_INPUTCTRL_MUXPOS_TEMP_Val:
237 		ADC_TSEN = 1;
238 		break;
239 #endif
240 #ifdef ADC_INPUTCTRL_MUXPOS_PTAT_Val
241 	case ADC_INPUTCTRL_MUXPOS_PTAT_Val:
242 		ADC_TSEN = 1;
243 		break;
244 #endif
245 #ifdef ADC_INPUTCTRL_MUXPOS_CTAT_Val
246 	case ADC_INPUTCTRL_MUXPOS_CTAT_Val:
247 		ADC_TSEN = 1;
248 		break;
249 #endif
250 	case ADC_INPUTCTRL_MUXPOS_BANDGAP_Val:
251 		ADC_BGEN = 1;
252 		break;
253 	default:
254 		break;
255 	}
256 
257 	return 0;
258 }
259 
adc_sam0_start_conversion(const struct device * dev)260 static void adc_sam0_start_conversion(const struct device *dev)
261 {
262 	const struct adc_sam0_cfg *const cfg = dev->config;
263 	Adc *const adc = cfg->regs;
264 
265 	LOG_DBG("Starting conversion");
266 
267 	adc->SWTRIG.reg = ADC_SWTRIG_START;
268 	/*
269 	 * Should be safe to not synchronize here because the only things
270 	 * that might access the ADC after this will wait for it to complete
271 	 * (synchronize finished implicitly)
272 	 */
273 }
274 
adc_context_start_sampling(struct adc_context * ctx)275 static void adc_context_start_sampling(struct adc_context *ctx)
276 {
277 	struct adc_sam0_data *data =
278 		CONTAINER_OF(ctx, struct adc_sam0_data, ctx);
279 
280 	adc_sam0_start_conversion(data->dev);
281 }
282 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)283 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
284 					      bool repeat_sampling)
285 {
286 	struct adc_sam0_data *data =
287 		CONTAINER_OF(ctx, struct adc_sam0_data, ctx);
288 
289 	if (repeat_sampling) {
290 		data->buffer = data->repeat_buffer;
291 	}
292 }
293 
check_buffer_size(const struct adc_sequence * sequence,uint8_t active_channels)294 static int check_buffer_size(const struct adc_sequence *sequence,
295 			     uint8_t active_channels)
296 {
297 	size_t needed_buffer_size;
298 
299 	needed_buffer_size = active_channels * sizeof(uint16_t);
300 	if (sequence->options) {
301 		needed_buffer_size *= (1U + sequence->options->extra_samplings);
302 	}
303 
304 	if (sequence->buffer_size < needed_buffer_size) {
305 		LOG_ERR("Provided buffer is too small (%u/%u)",
306 			sequence->buffer_size, needed_buffer_size);
307 		return -ENOMEM;
308 	}
309 	return 0;
310 }
311 
start_read(const struct device * dev,const struct adc_sequence * sequence)312 static int start_read(const struct device *dev,
313 		      const struct adc_sequence *sequence)
314 {
315 	const struct adc_sam0_cfg *const cfg = dev->config;
316 	struct adc_sam0_data *data = dev->data;
317 	Adc *const adc = cfg->regs;
318 	int error;
319 
320 	if (sequence->oversampling > 10U) {
321 		LOG_ERR("Invalid oversampling");
322 		return -EINVAL;
323 	}
324 
325 	adc->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM(sequence->oversampling);
326 	if (sequence->oversampling < 4) {
327 		adc->AVGCTRL.reg |= ADC_AVGCTRL_ADJRES(sequence->oversampling);
328 	} else {
329 		adc->AVGCTRL.reg |= ADC_AVGCTRL_ADJRES(4);
330 	}
331 
332 	/* AVGCTRL is not synchronized */
333 
334 #ifdef CONFIG_SOC_SERIES_SAMD20
335 	/*
336 	 * Errata: silicon revisions B and C do not perform the automatic right
337 	 * shifts in accumulation
338 	 */
339 	if (sequence->oversampling > 4U && DSU->DID.bit.REVISION < 3) {
340 		adc->AVGCTRL.bit.ADJRES = sequence->oversampling - 4U;
341 	}
342 #endif
343 
344 	switch (sequence->resolution) {
345 	case 8:
346 		if (sequence->oversampling) {
347 			LOG_ERR("Oversampling requires 12 bit resolution");
348 			return -EINVAL;
349 		}
350 
351 		ADC_RESSEL(adc) = ADC_RESSEL_8BIT;
352 		break;
353 	case 10:
354 		if (sequence->oversampling) {
355 			LOG_ERR("Oversampling requires 12 bit resolution");
356 			return -EINVAL;
357 		}
358 
359 		ADC_RESSEL(adc) = ADC_RESSEL_10BIT;
360 		break;
361 	case 12:
362 		if (sequence->oversampling) {
363 			ADC_RESSEL(adc) = ADC_RESSEL_16BIT;
364 		} else {
365 			ADC_RESSEL(adc) = ADC_RESSEL_12BIT;
366 		}
367 		break;
368 	default:
369 		LOG_ERR("ADC resolution value %d is not valid",
370 			sequence->resolution);
371 		return -EINVAL;
372 	}
373 
374 	wait_synchronization(adc);
375 
376 	if ((sequence->channels == 0)
377 		|| ((sequence->channels & (sequence->channels - 1)) != 0)) {
378 		/* The caller is expected to identify a single input channel, which will
379 		 * typically be the positive input, though no check is made for this...
380 		 *
381 		 * While ensuring that the channels bitfield matches the positive input
382 		 * might be sensible, this will likely break users before this revision
383 		 * was put in place.
384 		 */
385 		LOG_ERR("Channel scanning is not supported");
386 		return -ENOTSUP;
387 	}
388 
389 	error = check_buffer_size(sequence, 1);
390 	if (error) {
391 		return error;
392 	}
393 
394 	data->buffer = sequence->buffer;
395 	data->repeat_buffer = sequence->buffer;
396 
397 	/* At this point we allow the scheduler to do other things while
398 	 * we wait for the conversions to complete. This is provided by the
399 	 * adc_context functions. However, the caller of this function is
400 	 * blocked until the results are in.
401 	 */
402 	adc_context_start_read(&data->ctx, sequence);
403 
404 	error = adc_context_wait_for_completion(&data->ctx);
405 	return error;
406 }
407 
adc_sam0_read(const struct device * dev,const struct adc_sequence * sequence)408 static int adc_sam0_read(const struct device *dev,
409 			 const struct adc_sequence *sequence)
410 {
411 	struct adc_sam0_data *data = dev->data;
412 	int error;
413 
414 	adc_context_lock(&data->ctx, false, NULL);
415 	error = start_read(dev, sequence);
416 	adc_context_release(&data->ctx, error);
417 
418 	return error;
419 }
420 
adc_sam0_isr(const struct device * dev)421 static void adc_sam0_isr(const struct device *dev)
422 {
423 	struct adc_sam0_data *data = dev->data;
424 	const struct adc_sam0_cfg *const cfg = dev->config;
425 	Adc *const adc = cfg->regs;
426 	uint16_t result;
427 
428 	adc->INTFLAG.reg = ADC_INTFLAG_MASK;
429 
430 	result = (uint16_t)(adc->RESULT.reg);
431 
432 #ifdef ADC_SAM0_REFERENCE_GLITCH
433 	if (data->reference_changed) {
434 		data->reference_changed = 0;
435 		LOG_DBG("Discarded initial conversion due to reference change");
436 
437 		adc_sam0_start_conversion(dev);
438 		return;
439 	}
440 #endif
441 
442 	*data->buffer++ = result;
443 	adc_context_on_sampling_done(&data->ctx, dev);
444 }
445 
adc_sam0_init(const struct device * dev)446 static int adc_sam0_init(const struct device *dev)
447 {
448 	const struct adc_sam0_cfg *const cfg = dev->config;
449 	struct adc_sam0_data *data = dev->data;
450 	Adc *const adc = cfg->regs;
451 	int retval;
452 
453 	*cfg->mclk |= cfg->mclk_mask;
454 
455 #ifdef MCLK
456 	GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN
457 					| GCLK_PCHCTRL_GEN(cfg->gclk_gen);
458 #else
459 	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN
460 			  | GCLK_CLKCTRL_GEN(cfg->gclk_gen)
461 			  | GCLK_CLKCTRL_ID(cfg->gclk_id);
462 #endif
463 
464 	retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
465 	if (retval < 0) {
466 		return retval;
467 	}
468 
469 	ADC_PRESCALER(adc) = cfg->prescaler;
470 	wait_synchronization(adc);
471 
472 	adc->INTENCLR.reg = ADC_INTENCLR_MASK;
473 	adc->INTFLAG.reg = ADC_INTFLAG_MASK;
474 
475 	cfg->config_func(dev);
476 
477 	adc->INTENSET.reg = ADC_INTENSET_RESRDY;
478 
479 	data->dev = dev;
480 #ifdef ADC_SAM0_REFERENCE_GLITCH
481 	data->reference_changed = 1;
482 #endif
483 
484 	adc->CTRLA.bit.ENABLE = 1;
485 	wait_synchronization(adc);
486 
487 	adc_context_unlock_unconditionally(&data->ctx);
488 
489 	return 0;
490 }
491 
492 #ifdef CONFIG_ADC_ASYNC
adc_sam0_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)493 static int adc_sam0_read_async(const struct device *dev,
494 			       const struct adc_sequence *sequence,
495 			       struct k_poll_signal *async)
496 {
497 	struct adc_sam0_data *data = dev->data;
498 	int error;
499 
500 	adc_context_lock(&data->ctx, true, async);
501 	error = start_read(dev, sequence);
502 	adc_context_release(&data->ctx, error);
503 
504 	return error;
505 }
506 #endif
507 
508 static DEVICE_API(adc, adc_sam0_api) = {
509 	.channel_setup = adc_sam0_channel_setup,
510 	.read = adc_sam0_read,
511 	.ref_internal = 1000U,			/* Fixed 1.0 V reference */
512 #ifdef CONFIG_ADC_ASYNC
513 	.read_async = adc_sam0_read_async,
514 #endif
515 };
516 
517 
518 #ifdef MCLK
519 
520 #define ADC_SAM0_CONFIGURE(n)							\
521 do {										\
522 	const struct adc_sam0_cfg *const cfg = dev->config;			\
523 	Adc * const adc = cfg->regs;						\
524 	adc->CALIB.reg = ADC_SAM0_BIASCOMP(n)					\
525 			 | ADC_SAM0_BIASR2R(n)					\
526 			 | ADC_SAM0_BIASREFBUF(n);				\
527 } while (false)
528 
529 #else
530 
531 #define ADC_SAM0_CONFIGURE(n)							\
532 do {										\
533 	const struct adc_sam0_cfg *const cfg = dev->config;			\
534 	Adc * const adc = cfg->regs;						\
535 	/* Linearity is split across two words */				\
536 	uint32_t lin = ((*(uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) &		\
537 		     ADC_FUSES_LINEARITY_0_Msk) >>				\
538 		     ADC_FUSES_LINEARITY_0_Pos;					\
539 	lin |= (((*(uint32_t *)ADC_FUSES_LINEARITY_1_ADDR) &			\
540 		 ADC_FUSES_LINEARITY_1_Msk) >>					\
541 		 ADC_FUSES_LINEARITY_1_Pos) << 4;				\
542 	uint32_t bias = ((*(uint32_t *)ADC_FUSES_BIASCAL_ADDR) &		\
543 		      ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;		\
544 	adc->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) |				\
545 			 ADC_CALIB_LINEARITY_CAL(lin);				\
546 } while (false)
547 
548 #endif
549 
550 #define ASSIGNED_CLOCKS_CELL_BY_NAME						\
551 	ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME
552 
553 #define ADC_SAM0_GCLK_FREQ(n)							\
554 	UTIL_CAT(UTIL_CAT(SOC_ATMEL_SAM0_GCLK,					\
555 			  ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen)),		\
556 		 _FREQ_HZ)
557 
558 #define ADC_SAM0_FREQ(n)							\
559 	.prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV,				\
560 			      UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)),	\
561 	.freq = ADC_SAM0_GCLK_FREQ(n) / DT_INST_PROP(n, prescaler)
562 
563 #define ADC_SAM0_DEVICE(n)							\
564 	PINCTRL_DT_INST_DEFINE(n);						\
565 	static void adc_sam0_config_##n(const struct device *dev);		\
566 	static const struct adc_sam0_cfg adc_sam_cfg_##n = {			\
567 		.regs = (Adc *)DT_INST_REG_ADDR(n),				\
568 		.gclk_gen = ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen),		\
569 		.gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id),		\
570 		.mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n),		\
571 		.mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit),	\
572 		ADC_SAM0_FREQ(n),						\
573 		.config_func = &adc_sam0_config_##n,				\
574 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),			\
575 	};									\
576 	static struct adc_sam0_data adc_sam_data_##n = {			\
577 		ADC_CONTEXT_INIT_TIMER(adc_sam_data_##n, ctx),			\
578 		ADC_CONTEXT_INIT_LOCK(adc_sam_data_##n, ctx),			\
579 		ADC_CONTEXT_INIT_SYNC(adc_sam_data_##n, ctx),			\
580 	};									\
581 	DEVICE_DT_INST_DEFINE(n, adc_sam0_init, NULL,				\
582 			    &adc_sam_data_##n,					\
583 			    &adc_sam_cfg_##n, POST_KERNEL,			\
584 			    CONFIG_ADC_INIT_PRIORITY,				\
585 			    &adc_sam0_api);					\
586 	static void adc_sam0_config_##n(const struct device *dev)		\
587 	{									\
588 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, resrdy, irq),		\
589 			    DT_INST_IRQ_BY_NAME(n, resrdy, priority),		\
590 			    adc_sam0_isr,					\
591 			    DEVICE_DT_INST_GET(n), 0);				\
592 		irq_enable(DT_INST_IRQ_BY_NAME(n, resrdy, irq));		\
593 		ADC_SAM0_CONFIGURE(n);						\
594 	}
595 
596 DT_INST_FOREACH_STATUS_OKAY(ADC_SAM0_DEVICE)
597 
598 /* clang-format on */
599