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_adc
8
9 #include <zephyr/drivers/adc.h>
10
11 #include <em_adc.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(adc_gecko, CONFIG_ADC_LOG_LEVEL);
19
20 /* Number of channels available. */
21 #define GECKO_CHANNEL_COUNT 16
22
23 struct adc_gecko_channel_config {
24 bool initialized;
25 ADC_Ref_TypeDef reference;
26 ADC_PosSel_TypeDef input_select;
27 };
28
29 struct adc_gecko_data {
30 const struct device *dev;
31 struct adc_context ctx;
32 uint16_t *buffer;
33 uint16_t *repeat_buffer;
34 uint32_t channels;
35 uint8_t channel_id;
36 ADC_Res_TypeDef resolution;
37 struct adc_gecko_channel_config channel_config[GECKO_CHANNEL_COUNT];
38 };
39
40 struct adc_gecko_config {
41 ADC_TypeDef *base;
42 void (*irq_cfg_func)(void);
43 uint32_t frequency;
44 };
45
adc_gecko_set_config(const struct device * dev)46 static void adc_gecko_set_config(const struct device *dev)
47 {
48 struct adc_gecko_data *data = dev->data;
49 struct adc_gecko_channel_config *channel_config = NULL;
50 const struct adc_gecko_config *config = dev->config;
51 ADC_TypeDef *adc_base = (ADC_TypeDef *)config->base;
52
53 ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
54 ADC_InitSingle_TypeDef initSingle = ADC_INITSINGLE_DEFAULT;
55
56 channel_config = &data->channel_config[data->channel_id];
57
58 init.prescale = ADC_PrescaleCalc(config->frequency, 0);
59 init.timebase = ADC_TimebaseCalc(0);
60
61 initSingle.diff = false;
62 initSingle.reference = channel_config->reference;
63 initSingle.resolution = data->resolution;
64 initSingle.acqTime = adcAcqTime4;
65
66 initSingle.posSel = channel_config->input_select;
67
68 ADC_Init(adc_base, &init);
69 ADC_InitSingle(adc_base, &initSingle);
70 }
71
adc_gecko_check_buffer_size(const struct adc_sequence * sequence,uint8_t active_channels)72 static int adc_gecko_check_buffer_size(const struct adc_sequence *sequence,
73 uint8_t active_channels)
74 {
75 size_t needed_buffer_size;
76
77 needed_buffer_size = active_channels * sizeof(uint16_t);
78
79 if (sequence->options) {
80 needed_buffer_size *= (1 + sequence->options->extra_samplings);
81 }
82
83 if (sequence->buffer_size < needed_buffer_size) {
84 LOG_DBG("Provided buffer is too small (%u/%u)",
85 sequence->buffer_size, needed_buffer_size);
86 return -ENOMEM;
87 }
88
89 return 0;
90 }
91
start_read(const struct device * dev,const struct adc_sequence * sequence)92 static int start_read(const struct device *dev, const struct adc_sequence *sequence)
93 {
94
95 struct adc_gecko_data *data = dev->data;
96 uint32_t channels;
97 uint8_t channel_count;
98 uint8_t index;
99 int res;
100
101 /* Check if at least 1 channel is requested */
102 if (sequence->channels == 0) {
103 LOG_DBG("No channel requested");
104 return -EINVAL;
105 }
106
107 if (sequence->oversampling) {
108 LOG_ERR("Oversampling is not supported");
109 return -ENOTSUP;
110 }
111
112 /* Verify all requested channels are initialized and store resolution */
113 channels = sequence->channels;
114 channel_count = 0;
115 while (channels) {
116 /* Iterate through all channels and check if they are initialized */
117 index = find_lsb_set(channels) - 1;
118 if (index >= GECKO_CHANNEL_COUNT) {
119 LOG_DBG("Requested channel index not available: %d", index);
120 return -EINVAL;
121 }
122
123 if (!data->channel_config[index].initialized) {
124 LOG_DBG("Channel not initialized");
125 return -EINVAL;
126 }
127 channel_count++;
128 channels &= ~BIT(index);
129 }
130
131 res = adc_gecko_check_buffer_size(sequence, channel_count);
132 if (res < 0) {
133 return res;
134 }
135
136 data->buffer = sequence->buffer;
137
138 adc_context_start_read(&data->ctx, sequence);
139
140 res = adc_context_wait_for_completion(&data->ctx);
141
142 return res;
143 }
144
adc_gecko_start_channel(const struct device * dev)145 static void adc_gecko_start_channel(const struct device *dev)
146 {
147 const struct adc_gecko_config *config = dev->config;
148 struct adc_gecko_data *data = dev->data;
149 ADC_TypeDef *adc_base = (ADC_TypeDef *)config->base;
150
151 data->channel_id = find_lsb_set(data->channels) - 1;
152 adc_gecko_set_config(data->dev);
153
154 ADC_IntEnable(adc_base, ADC_IEN_SINGLE);
155 ADC_Start(adc_base, adcStartSingle);
156 }
157
adc_context_start_sampling(struct adc_context * ctx)158 static void adc_context_start_sampling(struct adc_context *ctx)
159 {
160 struct adc_gecko_data *data = CONTAINER_OF(ctx, struct adc_gecko_data, ctx);
161
162 data->channels = ctx->sequence.channels;
163 adc_gecko_start_channel(data->dev);
164 }
165
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)166 static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
167 {
168 struct adc_gecko_data *data = CONTAINER_OF(ctx, struct adc_gecko_data, ctx);
169
170 if (repeat_sampling) {
171 data->buffer = data->repeat_buffer;
172 }
173 }
174
adc_gecko_isr(void * arg)175 static void adc_gecko_isr(void *arg)
176 {
177 const struct device *dev = (const struct device *)arg;
178 const struct adc_gecko_config *config = dev->config;
179 struct adc_gecko_data *data = dev->data;
180 ADC_TypeDef *adc_base = config->base;
181
182 uint32_t sample = 0;
183 uint32_t flags, err;
184
185 flags = ADC_IntGet(adc_base);
186
187 __ASSERT(flags & ADC_IF_SINGLE, "unexpected ADC IRQ (flags=0x%08x)!", flags);
188
189 err = flags & (ADC_IF_EM23ERR | ADC_IF_PROGERR | ADC_IF_VREFOV | ADC_IF_SINGLEOF);
190
191 if (!err) {
192 sample = ADC_DataSingleGet(adc_base);
193 *data->buffer++ = (uint16_t)sample;
194 data->channels &= ~BIT(data->channel_id);
195
196 if (data->channels) {
197 adc_gecko_start_channel(dev);
198 } else {
199 adc_context_on_sampling_done(&data->ctx, dev);
200 }
201 } else {
202 LOG_ERR("ADC conversion error, flags=%08x", err);
203 adc_context_complete(&data->ctx, -EIO);
204 }
205 ADC_IntClear(adc_base, ADC_IF_SINGLE | err);
206 }
207
adc_gecko_read(const struct device * dev,const struct adc_sequence * sequence)208 static int adc_gecko_read(const struct device *dev,
209 const struct adc_sequence *sequence)
210 {
211 struct adc_gecko_data *data = dev->data;
212 int error;
213
214 adc_context_lock(&data->ctx, false, NULL);
215 error = start_read(dev, sequence);
216 adc_context_release(&data->ctx, error);
217
218 return error;
219 }
220
adc_gecko_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)221 static int adc_gecko_channel_setup(const struct device *dev,
222 const struct adc_channel_cfg *channel_cfg)
223 {
224 struct adc_gecko_data *data = dev->data;
225 struct adc_gecko_channel_config *channel_config = NULL;
226
227 if (channel_cfg->channel_id < GECKO_CHANNEL_COUNT) {
228 channel_config = &data->channel_config[channel_cfg->channel_id];
229 } else {
230 LOG_DBG("Requested channel index not available: %d", channel_cfg->channel_id);
231 return -EINVAL;
232 }
233
234 channel_config->initialized = false;
235
236 channel_config->input_select = channel_cfg->input_positive;
237
238 switch (channel_cfg->gain) {
239 case ADC_GAIN_1:
240 break;
241 default:
242 LOG_ERR("unsupported channel gain '%d'", channel_cfg->gain);
243 return -ENOTSUP;
244 }
245
246 switch (channel_cfg->reference) {
247 case ADC_REF_VDD_1:
248 channel_config->reference = adcRef5V;
249 break;
250 case ADC_REF_VDD_1_2:
251 channel_config->reference = adcRef2V5;
252 break;
253 case ADC_REF_VDD_1_4:
254 channel_config->reference = adcRef1V25;
255 break;
256 default:
257 LOG_ERR("unsupported channel reference type '%d'", channel_cfg->reference);
258 return -ENOTSUP;
259 }
260
261 channel_config->initialized = true;
262 return 0;
263 }
264
adc_gecko_init(const struct device * dev)265 static int adc_gecko_init(const struct device *dev)
266 {
267 const struct adc_gecko_config *config = dev->config;
268 struct adc_gecko_data *data = dev->data;
269
270 CMU_ClockEnable(cmuClock_HFPER, true);
271 CMU_ClockEnable(cmuClock_ADC0, true);
272
273 data->dev = dev;
274 data->resolution = adcRes12Bit;
275
276 config->irq_cfg_func();
277
278 adc_context_unlock_unconditionally(&data->ctx);
279
280 return 0;
281 }
282
283 static const struct adc_driver_api api_gecko_adc_driver_api = {
284 .channel_setup = adc_gecko_channel_setup,
285 .read = adc_gecko_read,
286 };
287
288 #define GECKO_ADC_INIT(n) \
289 \
290 static void adc_gecko_config_func_##n(void); \
291 \
292 const static struct adc_gecko_config adc_gecko_config_##n = { \
293 .base = (ADC_TypeDef *)DT_INST_REG_ADDR(n), \
294 .irq_cfg_func = adc_gecko_config_func_##n, \
295 .frequency = DT_INST_PROP(n, frequency), \
296 }; \
297 static struct adc_gecko_data adc_gecko_data_##n = { \
298 ADC_CONTEXT_INIT_TIMER(adc_gecko_data_##n, ctx), \
299 ADC_CONTEXT_INIT_LOCK(adc_gecko_data_##n, ctx), \
300 ADC_CONTEXT_INIT_SYNC(adc_gecko_data_##n, ctx), \
301 }; \
302 static void adc_gecko_config_func_##n(void) \
303 { \
304 IRQ_CONNECT(DT_INST_IRQN(n), \
305 DT_INST_IRQ(n, priority), \
306 adc_gecko_isr, DEVICE_DT_INST_GET(n), 0); \
307 irq_enable(DT_INST_IRQN(n)); \
308 }; \
309 DEVICE_DT_INST_DEFINE(n, \
310 &adc_gecko_init, NULL, \
311 &adc_gecko_data_##n, &adc_gecko_config_##n,\
312 POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \
313 &api_gecko_adc_driver_api);
314
315 DT_INST_FOREACH_STATUS_OKAY(GECKO_ADC_INIT)
316