1 /*
2  * Copyright (c) 2024 Pierrick Curt
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 #include <zephyr/device.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/adc.h>
11 #include <zephyr/drivers/spi.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/util.h>
16 
17 #define ADC_CONTEXT_USES_KERNEL_TIMER
18 #include "adc_context.h"
19 
20 LOG_MODULE_REGISTER(ADC_AD4114, CONFIG_ADC_LOG_LEVEL);
21 
22 #define DT_DRV_COMPAT adi_ad4114_adc
23 
24 #define AD4114_CMD_READ       0x40
25 #define AD4114_CMD_WRITE      0x0
26 #define AD4114_CHAN_NUMBER    16
27 #define AD4114_ADC_RESOLUTION 24U
28 
29 enum ad4114_reg {
30 	AD4114_STATUS_REG = 0x00,
31 	AD4114_MODE_REG = 0x01,
32 	AD4114_IFMODE_REG = 0x02,
33 	AD4114_REGCHECK = 0x03,
34 	AD4114_DATA_REG = 0x04,
35 	AD4114_GPIOCON_REG = 0x06,
36 	AD4114_ID_REG = 0x07,
37 	AD4114_CHANNEL_0_REG = 0x10,
38 	AD4114_CHANNEL_1_REG = 0x11,
39 	AD4114_CHANNEL_2_REG = 0x12,
40 	AD4114_CHANNEL_3_REG = 0x13,
41 	AD4114_CHANNEL_4_REG = 0x14,
42 	AD4114_CHANNEL_5_REG = 0x15,
43 	AD4114_CHANNEL_6_REG = 0x16,
44 	AD4114_CHANNEL_7_REG = 0x17,
45 	AD4114_CHANNEL_8_REG = 0x18,
46 	AD4114_CHANNEL_9_REG = 0x19,
47 	AD4114_CHANNEL_10_REG = 0x1A,
48 	AD4114_CHANNEL_11_REG = 0x1B,
49 	AD4114_CHANNEL_12_REG = 0x1C,
50 	AD4114_CHANNEL_13_REG = 0x1D,
51 	AD4114_CHANNEL_14_REG = 0x1E,
52 	AD4114_CHANNEL_15_REG = 0x1F,
53 	AD4114_SETUPCON0_REG = 0x20,
54 	AD4114_SETUPCON1_REG = 0x21,
55 	AD4114_SETUPCON2_REG = 0x22,
56 	AD4114_SETUPCON3_REG = 0x23,
57 	AD4114_SETUPCON4_REG = 0x24,
58 	AD4114_SETUPCON5_REG = 0x25,
59 	AD4114_SETUPCON6_REG = 0x26,
60 	AD4114_SETUPCON7_REG = 0x27,
61 	AD4114_FILTCON0_REG = 0x28,
62 	AD4114_FILTCON1_REG = 0x29,
63 	AD4114_FILTCON2_REG = 0x2A,
64 	AD4114_FILTCON3_REG = 0x2B,
65 	AD4114_FILTCON4_REG = 0x2C,
66 	AD4114_FILTCON5_REG = 0x2D,
67 	AD4114_FILTCON6_REG = 0x2E,
68 	AD4114_FILTCON7_REG = 0x2F,
69 	AD4114_OFFSET0_REG = 0x30,
70 	AD4114_OFFSET1_REG = 0x31,
71 	AD4114_OFFSET2_REG = 0x32,
72 	AD4114_OFFSET3_REG = 0x33,
73 	AD4114_OFFSET4_REG = 0x34,
74 	AD4114_OFFSET5_REG = 0x35,
75 	AD4114_OFFSET6_REG = 0x36,
76 	AD4114_OFFSET7_REG = 0x37,
77 	AD4114_GAIN0_REG = 0x38,
78 	AD4114_GAIN1_REG = 0x39,
79 	AD4114_GAIN2_REG = 0x3A,
80 	AD4114_GAIN3_REG = 0x3B,
81 	AD4114_GAIN4_REG = 0x3C,
82 	AD4114_GAIN5_REG = 0x3D,
83 	AD4114_GAIN6_REG = 0x3E,
84 	AD4114_GAIN7_REG = 0x3F,
85 };
86 
87 struct adc_ad4114_config {
88 	struct spi_dt_spec spi;
89 	uint16_t resolution;
90 	uint16_t map_input[AD4114_CHAN_NUMBER];
91 };
92 
93 struct adc_ad4114_data {
94 	struct adc_context ctx;
95 	const struct device *dev;
96 	struct k_thread thread;
97 	struct k_sem sem;
98 	uint16_t channels;
99 	uint16_t channels_cfg;
100 	uint32_t *buffer;
101 	uint32_t *repeat_buffer;
102 
103 	K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_AD4114_ACQUISITION_THREAD_STACK_SIZE);
104 };
105 
ad4114_write_reg(const struct device * dev,enum ad4114_reg reg_addr,uint8_t * buffer,size_t reg_size)106 static int ad4114_write_reg(const struct device *dev, enum ad4114_reg reg_addr, uint8_t *buffer,
107 			    size_t reg_size)
108 {
109 	int ret;
110 	const struct adc_ad4114_config *config = dev->config;
111 	uint8_t buffer_tx[5] = {0}; /* One byte command, max 4 bytes data */
112 
113 	const struct spi_buf tx_buf[] = {{
114 		.buf = buffer_tx,
115 		.len = ARRAY_SIZE(buffer_tx),
116 	}};
117 	const struct spi_buf_set tx = {
118 		.buffers = tx_buf,
119 		.count = ARRAY_SIZE(tx_buf),
120 	};
121 
122 	buffer_tx[0] = AD4114_CMD_WRITE | reg_addr;
123 
124 	if (reg_size > 4) {
125 		LOG_ERR("Invalid size, max data write size is 4");
126 		return -ENOMEM;
127 	}
128 	/* Fill the data */
129 	for (uint8_t index = 0; index < reg_size; index++) {
130 		buffer_tx[1 + index] = buffer[index];
131 	}
132 
133 	ret = spi_write_dt(&config->spi, &tx);
134 	if (ret != 0) {
135 		LOG_ERR("%s: error writing register 0x%X (%d)", dev->name, reg_addr, ret);
136 		return ret;
137 	}
138 
139 	return ret;
140 }
141 
ad4114_read_reg(const struct device * dev,enum ad4114_reg reg_addr,uint8_t * buffer,size_t reg_size)142 static int ad4114_read_reg(const struct device *dev, enum ad4114_reg reg_addr, uint8_t *buffer,
143 			   size_t reg_size)
144 {
145 	int ret;
146 	const struct adc_ad4114_config *config = dev->config;
147 
148 	uint8_t buffer_tx[6] = {0};
149 	uint8_t buffer_rx[ARRAY_SIZE(buffer_tx)] = {0xFF};
150 	const struct spi_buf tx_buf[] = {{
151 		.buf = buffer_tx,
152 		.len = ARRAY_SIZE(buffer_tx),
153 	}};
154 	const struct spi_buf rx_buf[] = {{
155 		.buf = buffer_rx,
156 		.len = ARRAY_SIZE(buffer_rx),
157 	}};
158 	const struct spi_buf_set tx = {
159 		.buffers = tx_buf,
160 		.count = ARRAY_SIZE(tx_buf),
161 	};
162 	const struct spi_buf_set rx = {
163 		.buffers = rx_buf,
164 		.count = ARRAY_SIZE(rx_buf),
165 	};
166 	buffer_tx[0] = AD4114_CMD_READ | reg_addr;
167 
168 	ret = spi_transceive_dt(&config->spi, &tx, &rx);
169 	if (ret != 0) {
170 		LOG_ERR("%s: error reading register 0x%X (%d)", dev->name, reg_addr, ret);
171 		return ret;
172 	}
173 
174 	/* Copy received data in output buffer */
175 	for (uint8_t index = 0; index < reg_size; index++) {
176 		buffer[index] = buffer_rx[index + 1];
177 	}
178 
179 	return ret;
180 }
181 
adc_context_start_sampling(struct adc_context * ctx)182 static void adc_context_start_sampling(struct adc_context *ctx)
183 {
184 	struct adc_ad4114_data *data = CONTAINER_OF(ctx, struct adc_ad4114_data, ctx);
185 
186 	data->channels = ctx->sequence.channels;
187 	data->repeat_buffer = data->buffer;
188 
189 	k_sem_give(&data->sem);
190 }
191 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)192 static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
193 {
194 	struct adc_ad4114_data *data = CONTAINER_OF(ctx, struct adc_ad4114_data, ctx);
195 
196 	if (repeat_sampling) {
197 		data->buffer = data->repeat_buffer;
198 	}
199 }
200 
adc_ad4114x_validate_buffer_size(const struct device * dev,const struct adc_sequence * sequence)201 static int adc_ad4114x_validate_buffer_size(const struct device *dev,
202 					    const struct adc_sequence *sequence)
203 {
204 	uint8_t channels;
205 	size_t needed;
206 
207 	channels = POPCOUNT(sequence->channels);
208 	needed = channels * sizeof(uint32_t);
209 
210 	if (sequence->buffer_size < needed) {
211 		return -ENOMEM;
212 	}
213 
214 	return 0;
215 }
216 
adc_ad4114_start_read(const struct device * dev,const struct adc_sequence * sequence)217 static int adc_ad4114_start_read(const struct device *dev, const struct adc_sequence *sequence)
218 {
219 	struct adc_ad4114_data *data = dev->data;
220 	const struct adc_ad4114_config *config = dev->config;
221 	int ret;
222 	uint8_t write_reg[2];
223 	uint8_t status;
224 
225 	ret = adc_ad4114x_validate_buffer_size(dev, sequence);
226 	if (ret < 0) {
227 		LOG_ERR("insufficient buffer size");
228 		return ret;
229 	}
230 
231 	data->channels_cfg = sequence->channels;
232 	for (uint32_t i = 0U; i < AD4114_CHAN_NUMBER; i++) {
233 		if ((BIT(i) & sequence->channels) != 0) {
234 			write_reg[0] = 0x80 | (uint8_t)((config->map_input[i] >> 8) & 0xFF);
235 			write_reg[1] = (uint8_t)(config->map_input[i] & 0xFF);
236 			LOG_DBG("Enable channel %d with mapping %X %X, raw %X", i, write_reg[0],
237 				write_reg[1], config->map_input[i]);
238 			ad4114_write_reg(dev, AD4114_CHANNEL_0_REG + i, write_reg, 2);
239 		} else {
240 			LOG_DBG("Disable channel %d", i);
241 			write_reg[0] = 0x0;
242 			write_reg[1] = 0x0;
243 			ad4114_write_reg(dev, AD4114_CHANNEL_0_REG + i, write_reg, 2);
244 		}
245 	}
246 
247 	/* Configure the buffer */
248 	data->buffer = sequence->buffer;
249 
250 	while ((status & 0x80) != 0x80) {
251 		/* Wait for acquiistion start */
252 		ad4114_read_reg(dev, AD4114_STATUS_REG, &status, 1);
253 		/* Wait 10us between two status read */
254 		k_usleep(10);
255 	}
256 
257 	adc_context_start_read(&data->ctx, sequence);
258 
259 	return adc_context_wait_for_completion(&data->ctx);
260 }
261 
adc_ad4114_acquisition_thread(struct adc_ad4114_data * data)262 static void adc_ad4114_acquisition_thread(struct adc_ad4114_data *data)
263 {
264 	uint8_t value[4] = {0};
265 	uint32_t buffer_values[AD4114_CHAN_NUMBER];
266 	bool is_ended = false;
267 
268 	while (true) {
269 		k_sem_take(&data->sem, K_FOREVER);
270 
271 		while (data->channels != 0) {
272 			ad4114_read_reg(data->dev, AD4114_DATA_REG, value, 4);
273 			/* Check the read channel */
274 			if ((value[3] & 0xF0) != 0) {
275 				LOG_DBG("Error read on :  %X ", value[3]);
276 			} else {
277 				LOG_DBG("Success read on %d: value  %X ", value[3],
278 					(value[2] << 16 | value[1] << 8 | value[0]));
279 				/* success read, store it */
280 				buffer_values[value[3]] =
281 					(value[0] << 16 | value[1] << 8 | value[2]);
282 				WRITE_BIT(data->channels, value[3], 0);
283 				/* Disable the channel after read success */
284 				uint8_t write_reg[2] = {0};
285 
286 				ad4114_write_reg(data->dev, AD4114_CHANNEL_0_REG + value[3],
287 						 write_reg, 2);
288 			}
289 			if (data->channels == 0) {
290 				is_ended = true;
291 			}
292 			/* Wait before next status ready check: the minimal acquisition time for a
293 			 * channel is 100us. So wait 10us betwen each check to avoid to use CPU for
294 			 * nothing.
295 			 */
296 			k_usleep(10);
297 		}
298 
299 		if (is_ended) {
300 			is_ended = false;
301 			for (uint8_t i = 0U; i < AD4114_CHAN_NUMBER; i++) {
302 				if ((BIT(i) & data->channels_cfg) != 0) {
303 					*data->buffer++ = buffer_values[i];
304 					LOG_DBG("Read channel %d value :  %X ", i,
305 						buffer_values[i]);
306 				}
307 			}
308 			adc_context_on_sampling_done(&data->ctx, data->dev);
309 		}
310 		/* Wait 1ms before checking if a new sequence acquisition is asked */
311 		k_usleep(1000);
312 	}
313 }
314 
adc_ad4114_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)315 static int adc_ad4114_channel_setup(const struct device *dev,
316 				    const struct adc_channel_cfg *channel_cfg)
317 {
318 
319 	/* Todo in the futur we can manage here :
320 	 * filters
321 	 * gain
322 	 * offsets
323 	 * special configuration : we can update map_input here to override the device
324 	 * tree setup
325 	 */
326 	if (channel_cfg->channel_id >= AD4114_CHAN_NUMBER) {
327 		LOG_ERR("invalid channel id %d", channel_cfg->channel_id);
328 		return -EINVAL;
329 	}
330 	return 0;
331 }
332 
adc_ad4114_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)333 static int adc_ad4114_read_async(const struct device *dev, const struct adc_sequence *sequence,
334 				 struct k_poll_signal *async)
335 {
336 	struct adc_ad4114_data *data = dev->data;
337 	int ret;
338 
339 	adc_context_lock(&data->ctx, async ? true : false, async);
340 	ret = adc_ad4114_start_read(dev, sequence);
341 	adc_context_release(&data->ctx, ret);
342 
343 	return ret;
344 }
345 
adc_ad4114_read(const struct device * dev,const struct adc_sequence * sequence)346 static int adc_ad4114_read(const struct device *dev, const struct adc_sequence *sequence)
347 {
348 	return adc_ad4114_read_async(dev, sequence, NULL);
349 }
350 
adc_ad4114_init(const struct device * dev)351 static int adc_ad4114_init(const struct device *dev)
352 {
353 	int err;
354 	const struct adc_ad4114_config *config = dev->config;
355 	struct adc_ad4114_data *data = dev->data;
356 	uint8_t id[2] = {0};
357 	uint8_t gain[3];
358 	uint8_t write_reg[2];
359 	uint8_t status = 0;
360 	k_tid_t tid;
361 
362 	data->dev = dev;
363 	k_sem_init(&data->sem, 0, 1);
364 	adc_context_init(&data->ctx);
365 
366 	if (!spi_is_ready_dt(&config->spi)) {
367 		LOG_ERR("spi bus %s not ready", config->spi.bus->name);
368 		return -ENODEV;
369 	}
370 
371 	ad4114_read_reg(dev, AD4114_ID_REG, id, 2);
372 	/* Check that this is the expected ID : 0x30DX, where x is don’t care */
373 	if ((((id[0] << 8) | id[1]) & 0xFFF0) != 0x30D0) {
374 		LOG_ERR("Read wrong ID register 0x%X 0x%X", id[0], id[1]);
375 		return -EIO;
376 	}
377 
378 	ad4114_read_reg(dev, AD4114_STATUS_REG, &status, 1);
379 	LOG_INF("Found AD4114 with status %d", status);
380 
381 	/* Configure gain to 0x400000 */
382 	gain[0] = 0x40;
383 	gain[1] = 0x00;
384 	gain[2] = 0x00;
385 	ad4114_write_reg(dev, AD4114_GAIN0_REG, gain, 3);
386 	ad4114_write_reg(dev, AD4114_GAIN1_REG, gain, 3);
387 
388 	/* Bit 6: DATA_STAT = 1 */
389 	write_reg[0] = 0x0;
390 	write_reg[1] = 0x40;
391 	ad4114_write_reg(dev, AD4114_IFMODE_REG, write_reg, 2);
392 
393 	/* Bit 12: BI_UNIPOLARx = 0
394 	 * Bit 9:8 INBUFx = 11
395 	 */
396 	write_reg[0] = 0x3;
397 	write_reg[1] = 0x0;
398 	ad4114_write_reg(dev, AD4114_SETUPCON0_REG, write_reg, 2);
399 
400 	/* Bit 12: BI_UNIPOLARx = 1
401 	 * Bit 9:8 INBUFx = 11
402 	 */
403 	write_reg[0] = 0x13;
404 	write_reg[1] = 0x0;
405 	ad4114_write_reg(dev, AD4114_SETUPCON1_REG, write_reg, 2);
406 
407 	/* Bit 15: REF_EN = 1
408 	 * Bit 3:2: CLOCKSEL = 11
409 	 */
410 	write_reg[0] = 0x80;
411 	write_reg[1] = 0xC;
412 	ad4114_write_reg(dev, AD4114_MODE_REG, write_reg, 2);
413 
414 	tid = k_thread_create(&data->thread, data->stack, K_KERNEL_STACK_SIZEOF(data->stack),
415 			      (k_thread_entry_t)adc_ad4114_acquisition_thread, data, NULL, NULL,
416 			      CONFIG_ADC_AD4114_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT);
417 
418 	if (IS_ENABLED(CONFIG_THREAD_NAME)) {
419 		err = k_thread_name_set(tid, "adc_ad4114");
420 		if (err < 0) {
421 			return err;
422 		}
423 	}
424 
425 	adc_context_unlock_unconditionally(&data->ctx);
426 	return 0;
427 }
428 
429 static DEVICE_API(adc, adc_ad4114_api) = {
430 	.channel_setup = adc_ad4114_channel_setup,
431 	.read = adc_ad4114_read,
432 };
433 
434 #define FILL_MAP_INPUTS(node_id, prop, idx)                                                        \
435 	{                                                                                          \
436 		.key_index = DT_NODE_CHILD_IDX(node_id),                                           \
437 		.press_mv = DT_PROP_BY_IDX(node_id, prop, idx),                                    \
438 	}
439 
440 #define ADC_AD4114_DEVICE(inst)                                                                    \
441 	static struct adc_ad4114_data adc_ad4114_data_##inst;                                      \
442 	static const struct adc_ad4114_config adc_ad4114_config_##inst = {                         \
443 		.spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8), 0),                             \
444 		.resolution = AD4114_ADC_RESOLUTION,                                               \
445 		.map_input = DT_INST_PROP(inst, map_inputs),                                       \
446 	};                                                                                         \
447 	DEVICE_DT_INST_DEFINE(inst, adc_ad4114_init, NULL, &adc_ad4114_data_##inst,                \
448 			      &adc_ad4114_config_##inst, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY,    \
449 			      &adc_ad4114_api)                                                     \
450 	BUILD_ASSERT(DT_INST_PROP_LEN(inst, map_inputs) == AD4114_CHAN_NUMBER);
451 
452 DT_INST_FOREACH_STATUS_OKAY(ADC_AD4114_DEVICE)
453