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