1 /*
2  * Copyright (c) 2023 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT silabs_gecko_iadc
8 
9 #include <zephyr/drivers/adc.h>
10 
11 #include <em_iadc.h>
12 #include <em_cmu.h>
13 
14 #define ADC_CONTEXT_USES_KERNEL_TIMER
15 #include "adc_context.h"
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(iadc_gecko, CONFIG_ADC_LOG_LEVEL);
19 
20 /* Number of channels available. */
21 #define GECKO_CHANNEL_COUNT	16
22 #define GECKO_INTERNAL_REFERENCE_mV	1210
23 #define GECKO_DATA_RES12BIT(DATA)	((DATA) & 0x0FFF)
24 
25 struct adc_gecko_channel_config {
26 	IADC_CfgAnalogGain_t gain;
27 	IADC_CfgReference_t reference;
28 	IADC_PosInput_t input_positive;
29 	IADC_NegInput_t input_negative;
30 	bool initialized;
31 };
32 
33 struct adc_gecko_data {
34 	const struct device *dev;
35 	struct adc_context ctx;
36 	uint16_t *buffer;
37 	uint16_t *repeat_buffer;
38 	uint32_t channels;
39 	uint8_t channel_id;
40 	struct adc_gecko_channel_config channel_config[GECKO_CHANNEL_COUNT];
41 };
42 
43 struct adc_gecko_config {
44 	IADC_Config_t config;
45 	IADC_TypeDef *base;
46 	void (*irq_cfg_func)(void);
47 };
48 
adc_gecko_set_config(const struct device * dev)49 static void adc_gecko_set_config(const struct device *dev)
50 {
51 	struct adc_gecko_data *data = dev->data;
52 	struct adc_gecko_channel_config *channel_config = NULL;
53 	const struct adc_gecko_config *config = dev->config;
54 
55 	IADC_TypeDef *iadc = (IADC_TypeDef *)config->base;
56 	IADC_InitSingle_t sInit = IADC_INITSINGLE_DEFAULT;
57 	IADC_SingleInput_t initSingleInput = IADC_SINGLEINPUT_DEFAULT;
58 	IADC_Init_t init = IADC_INIT_DEFAULT;
59 	IADC_AllConfigs_t initAllConfigs = IADC_ALLCONFIGS_DEFAULT;
60 
61 	channel_config = &data->channel_config[data->channel_id];
62 
63 	initSingleInput.posInput = channel_config->input_positive;
64 	initSingleInput.negInput = channel_config->input_negative;
65 
66 	initAllConfigs.configs[0].analogGain = channel_config->gain;
67 
68 	initAllConfigs.configs[0].reference = channel_config->reference;
69 
70 	IADC_init(iadc, &init, &initAllConfigs);
71 
72 	IADC_initSingle(iadc, &sInit, &initSingleInput);
73 }
74 
adc_gecko_check_buffer_size(const struct adc_sequence * sequence,uint8_t active_channels)75 static int adc_gecko_check_buffer_size(const struct adc_sequence *sequence,
76 					uint8_t active_channels)
77 {
78 	size_t needed_buffer_size;
79 
80 	needed_buffer_size = active_channels * sizeof(uint16_t);
81 
82 	if (sequence->options) {
83 		needed_buffer_size *= (1 + sequence->options->extra_samplings);
84 	}
85 
86 	if (sequence->buffer_size < needed_buffer_size) {
87 		LOG_DBG("Provided buffer is too small (%u/%u)",
88 			sequence->buffer_size, needed_buffer_size);
89 		return -ENOMEM;
90 	}
91 
92 	return 0;
93 }
94 
adc_gecko_check_resolution(const struct adc_sequence * sequence)95 static int adc_gecko_check_resolution(const struct adc_sequence *sequence)
96 {
97 	int value = sequence->resolution;
98 
99 	/* Base resolution is on 12, it can be changed only up by oversampling */
100 	if (value != 12) {
101 		return -EINVAL;
102 	}
103 
104 	return value;
105 }
106 
start_read(const struct device * dev,const struct adc_sequence * sequence)107 static int start_read(const struct device *dev, const struct adc_sequence *sequence)
108 {
109 
110 	struct adc_gecko_data *data = dev->data;
111 	uint32_t channels;
112 	uint8_t channel_count;
113 	uint8_t index;
114 	int res;
115 
116 	/* Check if at least 1 channel is requested */
117 	if (sequence->channels == 0) {
118 		LOG_DBG("No channel requested");
119 		return -EINVAL;
120 	}
121 
122 	if (sequence->oversampling) {
123 		LOG_ERR("Oversampling is not supported");
124 		return -ENOTSUP;
125 	}
126 
127 	/* Check resolution setting */
128 	res = adc_gecko_check_resolution(sequence);
129 	if (res < 0) {
130 		return -EINVAL;
131 	}
132 
133 	/* Verify all requested channels are initialized and store resolution */
134 	channels = sequence->channels;
135 	channel_count = 0;
136 	while (channels) {
137 		/* Iterate through all channels and check if they are initialized */
138 		index = find_lsb_set(channels) - 1;
139 		if (index >= GECKO_CHANNEL_COUNT) {
140 			LOG_DBG("Requested channel index not available: %d", index);
141 			return -EINVAL;
142 		}
143 
144 		if (!data->channel_config[index].initialized) {
145 			LOG_DBG("Channel not initialized");
146 			return -EINVAL;
147 		}
148 		channel_count++;
149 		channels &= ~BIT(index);
150 	}
151 
152 	/* Check buffer size */
153 	res = adc_gecko_check_buffer_size(sequence, channel_count);
154 	if (res < 0) {
155 		return res;
156 	}
157 
158 	data->buffer = sequence->buffer;
159 
160 	adc_context_start_read(&data->ctx, sequence);
161 
162 	res = adc_context_wait_for_completion(&data->ctx);
163 
164 	return res;
165 }
166 
adc_gecko_start_channel(const struct device * dev)167 static void adc_gecko_start_channel(const struct device *dev)
168 {
169 	const struct adc_gecko_config *config = dev->config;
170 	struct adc_gecko_data *data = dev->data;
171 
172 	IADC_TypeDef *iadc = (IADC_TypeDef *)config->base;
173 
174 	data->channel_id = find_lsb_set(data->channels) - 1;
175 
176 	LOG_DBG("Starting channel %d", data->channel_id);
177 
178 	adc_gecko_set_config(data->dev);
179 
180 	/* Enable single conversion interrupt */
181 	IADC_enableInt(iadc, IADC_IEN_SINGLEDONE);
182 
183 	/* Start single conversion */
184 	IADC_command(iadc, iadcCmdStartSingle);
185 }
186 
adc_context_start_sampling(struct adc_context * ctx)187 static void adc_context_start_sampling(struct adc_context *ctx)
188 {
189 	struct adc_gecko_data *data =
190 		CONTAINER_OF(ctx, struct adc_gecko_data, ctx);
191 
192 	data->channels = ctx->sequence.channels;
193 	data->repeat_buffer = data->buffer;
194 
195 	adc_gecko_start_channel(data->dev);
196 }
197 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)198 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
199 						bool repeat_sampling)
200 {
201 	struct adc_gecko_data *data =
202 		CONTAINER_OF(ctx, struct adc_gecko_data, ctx);
203 
204 	if (repeat_sampling) {
205 		data->buffer = data->repeat_buffer;
206 	}
207 }
208 
adc_gecko_isr(void * arg)209 static void adc_gecko_isr(void *arg)
210 {
211 	const struct device *dev = (const struct device *)arg;
212 	const struct adc_gecko_config *config = dev->config;
213 	struct adc_gecko_data *data = dev->data;
214 	IADC_TypeDef *iadc = config->base;
215 	IADC_Result_t sample;
216 	uint32_t flags, err;
217 
218 	/*
219 	 * IRQ is enabled only for SINGLEDONE. However, other
220 	 * interrupt flags - the ones singaling an error - may be
221 	 * set simultaneously with SINGLEDONE. We read & clear them
222 	 * to determine if conversion is successful or not.
223 	 */
224 	flags = IADC_getInt(iadc);
225 
226 	__ASSERT(flags & IADC_IF_SINGLEDONE,
227 		 "unexpected IADC IRQ (flags=0x%08x)!", flags);
228 
229 	err = flags & (IADC_IF_PORTALLOCERR |
230 			IADC_IF_POLARITYERR |
231 			IADC_IF_EM23ABORTERROR);
232 	if (!err) {
233 		sample = IADC_readSingleResult(iadc);
234 
235 		*data->buffer++ = GECKO_DATA_RES12BIT((uint16_t)sample.data);
236 		data->channels &= ~BIT(data->channel_id);
237 
238 		if (data->channels) {
239 			adc_gecko_start_channel(dev);
240 		} else {
241 			adc_context_on_sampling_done(&data->ctx, dev);
242 		}
243 	} else {
244 		LOG_ERR("IADC conversion error, flags=%08x", err);
245 		adc_context_complete(&data->ctx, -EIO);
246 	}
247 
248 	IADC_clearInt(iadc, IADC_IF_SINGLEDONE | err);
249 }
250 
adc_gecko_read(const struct device * dev,const struct adc_sequence * sequence)251 static int adc_gecko_read(const struct device *dev,
252 			  const struct adc_sequence *sequence)
253 {
254 	struct adc_gecko_data *data = dev->data;
255 	int error;
256 
257 	adc_context_lock(&data->ctx, false, NULL);
258 	error = start_read(dev, sequence);
259 	adc_context_release(&data->ctx, error);
260 
261 	return error;
262 }
263 
264 #ifdef CONFIG_ADC_ASYNC
adc_gecko_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)265 static int adc_gecko_read_async(const struct device *dev,
266 				const struct adc_sequence *sequence,
267 				struct k_poll_signal *async)
268 {
269 	struct adc_gecko_data *data = dev->data;
270 	int error;
271 
272 	adc_context_lock(&data->ctx, true, async);
273 	error = start_read(dev, sequence);
274 	adc_context_release(&data->ctx, error);
275 
276 	return error;
277 }
278 #endif
279 
adc_gecko_gpio_busalloc_pos(IADC_PosInput_t input)280 static void adc_gecko_gpio_busalloc_pos(IADC_PosInput_t input)
281 {
282 	uint32_t port = ((input << _IADC_SCAN_PINPOS_SHIFT) &
283 			_IADC_SCAN_PORTPOS_MASK) >> _IADC_SCAN_PORTPOS_SHIFT;
284 	uint32_t pin = ((input << _IADC_SCAN_PINPOS_SHIFT) &
285 			_IADC_SCAN_PINPOS_MASK) >> _IADC_SCAN_PINPOS_SHIFT;
286 
287 	switch (port) {
288 	case _IADC_SCAN_PORTPOS_PORTA:
289 		if (pin & 1) {
290 			GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AODD0_ADC0;
291 		} else {
292 			GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AEVEN0_ADC0;
293 		}
294 		break;
295 
296 	case _IADC_SCAN_PORTPOS_PORTB:
297 		if (pin & 1) {
298 			GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BODD0_ADC0;
299 		} else {
300 			GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BEVEN0_ADC0;
301 		}
302 		break;
303 
304 	case _IADC_SCAN_PORTPOS_PORTC:
305 	case _IADC_SCAN_PORTPOS_PORTD:
306 		if (pin & 1) {
307 			GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDODD0_ADC0;
308 		} else {
309 			GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDEVEN0_ADC0;
310 		}
311 		break;
312 
313 	default:
314 	}
315 }
316 
adc_gecko_gpio_busalloc_neg(IADC_NegInput_t input)317 static void adc_gecko_gpio_busalloc_neg(IADC_NegInput_t input)
318 {
319 	uint32_t port = ((input << _IADC_SCAN_PINNEG_SHIFT) &
320 			_IADC_SCAN_PORTNEG_MASK) >> _IADC_SCAN_PORTNEG_SHIFT;
321 	uint32_t pin = ((input << _IADC_SCAN_PINNEG_SHIFT) &
322 			_IADC_SCAN_PINNEG_MASK) >> _IADC_SCAN_PINNEG_SHIFT;
323 
324 	switch (port) {
325 	case _IADC_SCAN_PORTNEG_PORTA:
326 		if (pin & 1) {
327 			GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AODD0_ADC0;
328 		} else {
329 			GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AEVEN0_ADC0;
330 		}
331 		break;
332 
333 	case _IADC_SCAN_PORTNEG_PORTB:
334 		if (pin & 1) {
335 			GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BODD0_ADC0;
336 		} else {
337 			GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BEVEN0_ADC0;
338 		}
339 		break;
340 
341 	case _IADC_SCAN_PORTNEG_PORTC:
342 	case _IADC_SCAN_PORTNEG_PORTD:
343 		if (pin & 1) {
344 			GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDODD0_ADC0;
345 		} else {
346 			GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDEVEN0_ADC0;
347 		}
348 		break;
349 
350 	default:
351 	}
352 }
353 
adc_gecko_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)354 static int adc_gecko_channel_setup(const struct device *dev,
355 				const struct adc_channel_cfg *channel_cfg)
356 {
357 	struct adc_gecko_data *data = dev->data;
358 	struct adc_gecko_channel_config *channel_config = NULL;
359 
360 	if (channel_cfg->channel_id < GECKO_CHANNEL_COUNT) {
361 		channel_config = &data->channel_config[channel_cfg->channel_id];
362 	} else {
363 		LOG_DBG("Requested channel index not available: %d", channel_cfg->channel_id);
364 		return -EINVAL;
365 	}
366 
367 	channel_config->initialized = false;
368 
369 	channel_config->input_positive = channel_cfg->input_positive;
370 
371 	if (channel_cfg->differential) {
372 		channel_config->input_negative = channel_cfg->input_negative;
373 	} else {
374 		channel_config->input_negative = iadcNegInputGnd;
375 	}
376 
377 	/* Setup input */
378 
379 	switch (channel_cfg->gain) {
380 #if defined(_IADC_CFG_ANALOGGAIN_ANAGAIN0P25)
381 	case ADC_GAIN_1_4:
382 		channel_config->gain = iadcCfgAnalogGain0P25x;
383 		break;
384 #endif
385 	case ADC_GAIN_1_2:
386 		channel_config->gain = iadcCfgAnalogGain0P5x;
387 		break;
388 	case ADC_GAIN_1:
389 		channel_config->gain = iadcCfgAnalogGain1x;
390 		break;
391 	case ADC_GAIN_2:
392 		channel_config->gain = iadcCfgAnalogGain2x;
393 		break;
394 	case ADC_GAIN_3:
395 		channel_config->gain = iadcCfgAnalogGain3x;
396 		break;
397 	case ADC_GAIN_4:
398 		channel_config->gain = iadcCfgAnalogGain4x;
399 		break;
400 	default:
401 		LOG_ERR("unsupported channel gain '%d'", channel_cfg->gain);
402 		return -ENOTSUP;
403 	}
404 
405 	/* Setup reference */
406 	switch (channel_cfg->reference) {
407 	case ADC_REF_VDD_1:
408 		channel_config->reference = iadcCfgReferenceVddx;
409 		break;
410 	case ADC_REF_INTERNAL:
411 		channel_config->reference = iadcCfgReferenceInt1V2;
412 		break;
413 #if defined(_IADC_CFG_REFSEL_VREF2P5)
414 	case ADC_REF_EXTERNAL1:
415 		channel_config->reference = iadcCfgReferenceExt2V5;
416 		break;
417 #endif
418 	case ADC_REF_EXTERNAL0:
419 		channel_config->reference = iadcCfgReferenceExt1V25;
420 		break;
421 	default:
422 		LOG_ERR("unsupported channel reference type '%d'",
423 			channel_cfg->reference);
424 		return -ENOTSUP;
425 	}
426 
427 	/* Setup GPIO xBUSALLOC registers if channel uses GPIO pin */
428 	adc_gecko_gpio_busalloc_pos(channel_config->input_positive);
429 	adc_gecko_gpio_busalloc_neg(channel_config->input_negative);
430 
431 	channel_config->initialized = true;
432 	LOG_DBG("Channel setup succeeded!");
433 
434 	return 0;
435 }
436 
adc_gecko_init(const struct device * dev)437 static int adc_gecko_init(const struct device *dev)
438 {
439 	const struct adc_gecko_config *config = dev->config;
440 	struct adc_gecko_data *data = dev->data;
441 
442 	CMU_ClockEnable(cmuClock_IADC0, true);
443 
444 	/* Select clock for IADC */
445 	CMU_ClockSelectSet(cmuClock_IADCCLK, cmuSelect_FSRCO);  /* FSRCO - 20MHz */
446 
447 	data->dev = dev;
448 
449 	config->irq_cfg_func();
450 
451 	adc_context_unlock_unconditionally(&data->ctx);
452 
453 	return 0;
454 }
455 
456 static const struct adc_driver_api api_gecko_adc_driver_api = {
457 	.channel_setup = adc_gecko_channel_setup,
458 	.read = adc_gecko_read,
459 #ifdef CONFIG_ADC_ASYNC
460 	.read_async = adc_gecko_read_async,
461 #endif
462 	.ref_internal = GECKO_INTERNAL_REFERENCE_mV,
463 };
464 
465 #define GECKO_IADC_INIT(n)						\
466 									\
467 	static void adc_gecko_config_func_##n(void);			\
468 									\
469 	const static struct adc_gecko_config adc_gecko_config_##n = {	\
470 		.base = (IADC_TypeDef *)DT_INST_REG_ADDR(n),\
471 		.irq_cfg_func = adc_gecko_config_func_##n,		\
472 	};								\
473 	static struct adc_gecko_data adc_gecko_data_##n = {		\
474 		ADC_CONTEXT_INIT_TIMER(adc_gecko_data_##n, ctx),	\
475 		ADC_CONTEXT_INIT_LOCK(adc_gecko_data_##n, ctx),	\
476 		ADC_CONTEXT_INIT_SYNC(adc_gecko_data_##n, ctx),	\
477 	};								\
478 	static void adc_gecko_config_func_##n(void)			\
479 	{								\
480 		IRQ_CONNECT(DT_INST_IRQN(n),	\
481 			    DT_INST_IRQ(n, priority), \
482 			    adc_gecko_isr, DEVICE_DT_INST_GET(n), 0);	\
483 		irq_enable(DT_INST_IRQN(n));	\
484 	}; \
485 	DEVICE_DT_INST_DEFINE(n,					 \
486 			      &adc_gecko_init, NULL,			 \
487 			      &adc_gecko_data_##n, &adc_gecko_config_##n,\
488 			      POST_KERNEL, CONFIG_ADC_INIT_PRIORITY,	 \
489 			      &api_gecko_adc_driver_api);
490 
491 DT_INST_FOREACH_STATUS_OKAY(GECKO_IADC_INIT)
492