1 /*
2  * Copyright (c) 2021 Pavlo Hamov <pasha.gamov@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_cc32xx_adc
8 
9 #include <errno.h>
10 
11 #include <zephyr/drivers/adc.h>
12 #include <zephyr/device.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/init.h>
15 #include <soc.h>
16 
17 /* Driverlib includes */
18 #include <inc/hw_types.h>
19 #include <driverlib/pin.h>
20 #include <driverlib/rom.h>
21 #include <driverlib/rom_map.h>
22 #include <driverlib/prcm.h>
23 #include <driverlib/adc.h>
24 
25 #define CHAN_COUNT 4
26 
27 #define ADC_CONTEXT_USES_KERNEL_TIMER
28 #include "adc_context.h"
29 
30 #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
31 #include <zephyr/logging/log.h>
32 #include <zephyr/irq.h>
33 LOG_MODULE_REGISTER(adc_cc32xx);
34 
35 #define ISR_MASK (ADC_DMA_DONE | ADC_FIFO_OVERFLOW | ADC_FIFO_UNDERFLOW	\
36 		  | ADC_FIFO_EMPTY | ADC_FIFO_FULL)
37 
38 struct adc_cc32xx_data {
39 	struct adc_context ctx;
40 	const struct device *dev;
41 	uint16_t *buffer;
42 	uint16_t *repeat_buffer;
43 	uint32_t channels;
44 	uint8_t offset[CHAN_COUNT];
45 	size_t active_channels;
46 };
47 
48 struct adc_cc32xx_cfg {
49 	unsigned long base;
50 	void (*irq_cfg_func)(void);
51 };
52 
53 static const int s_chPin[CHAN_COUNT] = {
54 	PIN_57,
55 	PIN_58,
56 	PIN_59,
57 	PIN_60,
58 };
59 
60 static const int s_channel[CHAN_COUNT] = {
61 	ADC_CH_0,
62 	ADC_CH_1,
63 	ADC_CH_2,
64 	ADC_CH_3,
65 };
66 
start_sampling(unsigned long base,int ch)67 static inline void start_sampling(unsigned long base, int ch)
68 {
69 	MAP_ADCChannelEnable(base, ch);
70 	for (int i = 0; i < 5; i++) {
71 		while (!MAP_ADCFIFOLvlGet(base, ch)) {
72 		}
73 		MAP_ADCFIFORead(base, ch);
74 	}
75 	MAP_ADCIntClear(base, ch, ISR_MASK);
76 	MAP_ADCIntEnable(base, ch, ISR_MASK);
77 }
78 
adc_context_start_sampling(struct adc_context * ctx)79 static void adc_context_start_sampling(struct adc_context *ctx)
80 {
81 	struct adc_cc32xx_data *data =
82 		CONTAINER_OF(ctx, struct adc_cc32xx_data, ctx);
83 	const struct adc_cc32xx_cfg *config = data->dev->config;
84 
85 	data->channels = ctx->sequence.channels;
86 	data->repeat_buffer = data->buffer;
87 
88 	for (int i = 0; i < CHAN_COUNT; ++i) {
89 		if (ctx->sequence.channels & BIT(i)) {
90 			start_sampling(config->base, s_channel[i]);
91 		}
92 	}
93 }
94 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat)95 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
96 					      bool repeat)
97 {
98 	struct adc_cc32xx_data *data =
99 		CONTAINER_OF(ctx, struct adc_cc32xx_data, ctx);
100 
101 	if (repeat) {
102 		data->buffer = data->repeat_buffer;
103 	} else {
104 		data->buffer += data->active_channels;
105 	}
106 }
107 
adc_cc32xx_init(const struct device * dev)108 static int adc_cc32xx_init(const struct device *dev)
109 {
110 	struct adc_cc32xx_data *data = dev->data;
111 	const struct adc_cc32xx_cfg *config = dev->config;
112 
113 	data->dev = dev;
114 
115 	LOG_DBG("Initializing....");
116 
117 	for (int i = 0; i < CHAN_COUNT; ++i) {
118 		const int ch = s_channel[i];
119 
120 		MAP_ADCIntDisable(config->base, ch, ISR_MASK);
121 		MAP_ADCChannelDisable(config->base, ch);
122 		MAP_ADCDMADisable(config->base, ch);
123 		MAP_ADCIntClear(config->base, ch, ISR_MASK);
124 	}
125 	MAP_ADCEnable(config->base);
126 	config->irq_cfg_func();
127 
128 	adc_context_unlock_unconditionally(&data->ctx);
129 	return 0;
130 }
131 
adc_cc32xx_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)132 static int adc_cc32xx_channel_setup(const struct device *dev,
133 				    const struct adc_channel_cfg *channel_cfg)
134 {
135 	const struct adc_cc32xx_cfg *config = dev->config;
136 	const uint8_t ch = channel_cfg->channel_id;
137 
138 	if (ch >= CHAN_COUNT) {
139 		LOG_ERR("Channel %d is not supported, max %d", ch, CHAN_COUNT);
140 		return -EINVAL;
141 	}
142 
143 	if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
144 		LOG_ERR("Acquisition time is not valid");
145 		return -EINVAL;
146 	}
147 
148 	if (channel_cfg->differential) {
149 		LOG_ERR("Differential channels are not supported");
150 		return -EINVAL;
151 	}
152 
153 	if (channel_cfg->gain != ADC_GAIN_1) {
154 		LOG_ERR("Gain is not valid");
155 		return -EINVAL;
156 	}
157 
158 	if (channel_cfg->reference != ADC_REF_INTERNAL) {
159 		LOG_ERR("Reference is not valid");
160 		return -EINVAL;
161 	}
162 
163 	LOG_DBG("Setup %d", ch);
164 
165 	MAP_ADCChannelDisable(config->base, s_channel[ch]);
166 	MAP_ADCIntDisable(config->base, s_channel[ch], ISR_MASK);
167 	MAP_PinDirModeSet(s_chPin[ch], PIN_DIR_MODE_IN);
168 	MAP_PinTypeADC(s_chPin[ch], PIN_MODE_255);
169 
170 	return 0;
171 }
172 
cc32xx_read(const struct device * dev,const struct adc_sequence * sequence,bool asynchronous,struct k_poll_signal * sig)173 static int cc32xx_read(const struct device *dev,
174 		       const struct adc_sequence *sequence,
175 		       bool asynchronous,
176 		       struct k_poll_signal *sig)
177 {
178 	struct adc_cc32xx_data *data = dev->data;
179 	int rv;
180 	size_t exp_size;
181 
182 	if (sequence->resolution != 12) {
183 		LOG_ERR("Only 12 Resolution is supported, but %d got",
184 			sequence->resolution);
185 		return -EINVAL;
186 	}
187 
188 	data->active_channels = 0;
189 	for (int i = 0; i < CHAN_COUNT; ++i) {
190 		if (!(sequence->channels & BIT(i))) {
191 			continue;
192 		}
193 		data->offset[i] = data->active_channels++;
194 	}
195 	exp_size = data->active_channels * sizeof(uint16_t);
196 	if (sequence->options) {
197 		exp_size *= (1 + sequence->options->extra_samplings);
198 	}
199 
200 	if (sequence->buffer_size < exp_size) {
201 		LOG_ERR("Required buffer size is %u, but %u got",
202 			exp_size, sequence->buffer_size);
203 		return -ENOMEM;
204 	}
205 
206 	data->buffer = sequence->buffer;
207 
208 	adc_context_lock(&data->ctx, asynchronous, sig);
209 	adc_context_start_read(&data->ctx, sequence);
210 	rv = adc_context_wait_for_completion(&data->ctx);
211 	adc_context_release(&data->ctx, rv);
212 	return rv;
213 }
214 
adc_cc32xx_read(const struct device * dev,const struct adc_sequence * sequence)215 static int adc_cc32xx_read(const struct device *dev,
216 			   const struct adc_sequence *sequence)
217 {
218 	return cc32xx_read(dev, sequence, false, NULL);
219 }
220 
221 #ifdef CONFIG_ADC_ASYNC
adc_cc32xx_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)222 static int adc_cc32xx_read_async(const struct device *dev,
223 				 const struct adc_sequence *sequence,
224 				 struct k_poll_signal *async)
225 {
226 	return cc32xx_read(dev, sequence, true, async);
227 }
228 #endif
229 
adc_cc32xx_isr(const struct device * dev,int no)230 static void adc_cc32xx_isr(const struct device *dev, int no)
231 {
232 	const struct adc_cc32xx_cfg *config = dev->config;
233 	struct adc_cc32xx_data *data = dev->data;
234 	const int chan = s_channel[no];
235 	unsigned long mask = MAP_ADCIntStatus(config->base, chan);
236 	int cnt = 0;
237 	int rv = 0;
238 
239 	MAP_ADCIntClear(config->base, chan, mask);
240 
241 	if ((mask & ADC_FIFO_EMPTY) || !(mask & ADC_FIFO_FULL)) {
242 		return;
243 	}
244 
245 	while (MAP_ADCFIFOLvlGet(config->base, chan)) {
246 		rv += (MAP_ADCFIFORead(config->base, chan) >> 2) & 0x0FFF;
247 		cnt++;
248 	}
249 
250 	*(data->buffer + data->offset[no]) = rv / cnt;
251 	data->channels &= ~BIT(no);
252 
253 	MAP_ADCIntDisable(config->base, chan, ISR_MASK);
254 	MAP_ADCChannelDisable(config->base, chan);
255 
256 	LOG_DBG("ISR %d, 0x%lX %d %d", chan, mask, rv, cnt);
257 	if (!data->channels) {
258 		adc_context_on_sampling_done(&data->ctx, dev);
259 	}
260 }
261 
adc_cc32xx_isr_ch0(const struct device * dev)262 static void adc_cc32xx_isr_ch0(const struct device *dev)
263 {
264 	adc_cc32xx_isr(dev, 0);
265 }
266 
adc_cc32xx_isr_ch1(const struct device * dev)267 static void adc_cc32xx_isr_ch1(const struct device *dev)
268 {
269 	adc_cc32xx_isr(dev, 1);
270 }
271 
adc_cc32xx_isr_ch2(const struct device * dev)272 static void adc_cc32xx_isr_ch2(const struct device *dev)
273 {
274 	adc_cc32xx_isr(dev, 2);
275 }
276 
adc_cc32xx_isr_ch3(const struct device * dev)277 static void adc_cc32xx_isr_ch3(const struct device *dev)
278 {
279 	adc_cc32xx_isr(dev, 3);
280 }
281 
282 static const struct adc_driver_api cc32xx_driver_api = {
283 	.channel_setup = adc_cc32xx_channel_setup,
284 	.read = adc_cc32xx_read,
285 #ifdef CONFIG_ADC_ASYNC
286 	.read_async = adc_cc32xx_read_async,
287 #endif
288 	.ref_internal = 1467,
289 };
290 
291 #define cc32xx_ADC_IRQ_CONNECT(index, chan)			       \
292 	do {							       \
293 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(index, chan, irq),      \
294 			    DT_INST_IRQ_BY_IDX(index, chan, priority), \
295 			    adc_cc32xx_isr_ch##chan,		       \
296 			    DEVICE_DT_INST_GET(index), 0);	       \
297 		irq_enable(DT_INST_IRQ_BY_IDX(index, chan, irq));      \
298 	} while (false)
299 
300 #define cc32xx_ADC_INIT(index)							 \
301 										 \
302 	static void adc_cc32xx_cfg_func_##index(void);				 \
303 										 \
304 	static const struct adc_cc32xx_cfg adc_cc32xx_cfg_##index = {		 \
305 		.base = DT_INST_REG_ADDR(index),				 \
306 		.irq_cfg_func = adc_cc32xx_cfg_func_##index,			 \
307 	};									 \
308 	static struct adc_cc32xx_data adc_cc32xx_data_##index = {		 \
309 		ADC_CONTEXT_INIT_TIMER(adc_cc32xx_data_##index, ctx),		 \
310 		ADC_CONTEXT_INIT_LOCK(adc_cc32xx_data_##index, ctx),		 \
311 		ADC_CONTEXT_INIT_SYNC(adc_cc32xx_data_##index, ctx),		 \
312 	};									 \
313 										 \
314 	DEVICE_DT_INST_DEFINE(index,						 \
315 			      &adc_cc32xx_init, NULL, &adc_cc32xx_data_##index,	 \
316 			      &adc_cc32xx_cfg_##index, POST_KERNEL,		 \
317 			      CONFIG_ADC_INIT_PRIORITY,				 \
318 			      &cc32xx_driver_api);				 \
319 										 \
320 	static void adc_cc32xx_cfg_func_##index(void)				 \
321 	{									 \
322 		cc32xx_ADC_IRQ_CONNECT(index, 0);				 \
323 		cc32xx_ADC_IRQ_CONNECT(index, 1);				 \
324 		cc32xx_ADC_IRQ_CONNECT(index, 2);				 \
325 		cc32xx_ADC_IRQ_CONNECT(index, 3);				 \
326 	}
327 
328 DT_INST_FOREACH_STATUS_OKAY(cc32xx_ADC_INIT)
329