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