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