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