1 /*
2 * Copyright (c) 2019 Vestas Wind Systems A/S
3 * Copyright (c) 2020 Innoseis BV
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7 #include <zephyr/device.h>
8 #include <zephyr/devicetree.h>
9 #include <zephyr/drivers/adc.h>
10 #include <zephyr/logging/log.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <zephyr/sys/util.h>
15
16 #define ADC_CONTEXT_USES_KERNEL_TIMER 1
17 #include "adc_context.h"
18
19 #define DT_DRV_COMPAT ti_ads1119
20
21 LOG_MODULE_REGISTER(ADS1119, CONFIG_ADC_LOG_LEVEL);
22
23
24 #define ADS1119_CONFIG_VREF(x) ((x) & BIT(0))
25 #define ADS1119_CONFIG_CM(x) ((x) & BIT(1))
26 #define ADS1119_CONFIG_DR(x) ((x) & (BIT_MASK(2) << 2))
27 #define ADS1119_CONFIG_GAIN(x) ((x) & BIT(4))
28 #define ADS1119_CONFIG_MUX(x) ((x) & (BIT_MASK(3) << 5))
29
30 #define ADS1119_STATUS_MASK_ID BIT_MASK(7)
31 #define ADS1119_STATUS_MASK_READY BIT(7)
32
33 #define ADS1119_REG_SHIFT 2
34
35 #define ADS1119_RESOLUTION 16
36 #define ADS1119_REF_INTERNAL 2048
37
38 enum ads1119_cmd {
39 ADS1119_CMD_RESET = 0x06,
40 ADS1119_CMD_START_SYNC = 0x08,
41 ADS1119_CMD_POWER_DOWN = 0x02,
42 ADS1119_CMD_READ_DATA = 0x10,
43 ADS1119_CMD_READ_REG = 0x20,
44 ADS1119_CMD_WRITE_REG = 0x40,
45 };
46
47 enum ads1119_reg {
48 ADS1119_REG_CONFIG = 0 << ADS1119_REG_SHIFT,
49 ADS1119_REG_STATUS = 1 << ADS1119_REG_SHIFT,
50 };
51
52 enum {
53 ADS1119_CONFIG_VREF_INTERNAL = 0,
54 ADS1119_CONFIG_VREF_EXTERNAL = 1,
55 };
56
57 enum {
58 ADS1119_CONFIG_MUX_DIFF_0_1 = 0,
59 ADS1119_CONFIG_MUX_DIFF_2_3 = 1,
60 ADS1119_CONFIG_MUX_DIFF_1_2 = 2,
61 ADS1119_CONFIG_MUX_SINGLE_0 = 3,
62 ADS1119_CONFIG_MUX_SINGLE_1 = 4,
63 ADS1119_CONFIG_MUX_SINGLE_2 = 5,
64 ADS1119_CONFIG_MUX_SINGLE_3 = 6,
65 ADS1119_CONFIG_MUX_SHORTED = 7,
66 };
67
68 enum {
69 ADS1119_CONFIG_DR_20 = 0,
70 ADS1119_CONFIG_DR_90 = 1,
71 ADS1119_CONFIG_DR_330 = 2,
72 ADS1119_CONFIG_DR_1000 = 3,
73 ADS1119_CONFIG_DR_DEFAULT = ADS1119_CONFIG_DR_20,
74 };
75
76 enum {
77 ADS1119_CONFIG_GAIN_1 = 0,
78 ADS1119_CONFIG_GAIN_4 = 1,
79 };
80
81 enum {
82 ADS1119_CONFIG_CM_SINGLE = 0,
83 ADS1119_CONFIG_CM_CONTINUOUS = 1,
84 };
85
86 struct ads1119_config {
87 const struct i2c_dt_spec bus;
88 #if CONFIG_ADC_ASYNC
89 k_thread_stack_t *stack;
90 #endif
91 };
92
93 struct ads1119_data {
94 struct adc_context ctx;
95 k_timeout_t ready_time;
96 struct k_sem acq_sem;
97 int16_t *buffer;
98 int16_t *buffer_ptr;
99 #if CONFIG_ADC_ASYNC
100 struct k_thread thread;
101 #endif
102 bool differential;
103 };
104
ads1119_read_reg(const struct device * dev,enum ads1119_reg reg_addr,uint8_t * reg_val)105 static int ads1119_read_reg(const struct device *dev, enum ads1119_reg reg_addr, uint8_t *reg_val)
106 {
107 const struct ads1119_config *config = dev->config;
108
109 return i2c_reg_read_byte_dt(&config->bus, ADS1119_CMD_READ_REG | reg_addr, reg_val);
110 }
111
ads1119_write_reg(const struct device * dev,uint8_t reg)112 static int ads1119_write_reg(const struct device *dev, uint8_t reg)
113 {
114 const struct ads1119_config *config = dev->config;
115
116 return i2c_reg_write_byte_dt(&config->bus, ADS1119_CMD_WRITE_REG, reg);
117 }
118
ads1119_acq_time_to_dr(const struct device * dev,uint16_t acq_time)119 static inline int ads1119_acq_time_to_dr(const struct device *dev,
120 uint16_t acq_time)
121 {
122 struct ads1119_data *data = dev->data;
123 int odr = -EINVAL;
124 uint16_t acq_value = ADC_ACQ_TIME_VALUE(acq_time);
125 uint16_t ready_time_us = 0;
126
127 if (acq_time == ADC_ACQ_TIME_DEFAULT) {
128 acq_value = ADS1119_CONFIG_DR_DEFAULT;
129 } else if (ADC_ACQ_TIME_UNIT(acq_time) != ADC_ACQ_TIME_TICKS) {
130 return -EINVAL;
131 }
132
133 switch (acq_value) {
134 case ADS1119_CONFIG_DR_20:
135 odr = ADS1119_CONFIG_DR_20;
136 ready_time_us = (1000*1000) / 20;
137 break;
138 case ADS1119_CONFIG_DR_90:
139 odr = ADS1119_CONFIG_DR_90;
140 ready_time_us = (1000*1000) / 90;
141 break;
142 case ADS1119_CONFIG_DR_330:
143 odr = ADS1119_CONFIG_DR_330;
144 ready_time_us = (1000*1000) / 330;
145 break;
146 case ADS1119_CONFIG_DR_1000:
147 odr = ADS1119_CONFIG_DR_1000;
148 ready_time_us = (1000*1000) / 1000;
149 break;
150 default:
151 break;
152 }
153
154 /* As per datasheet acquisition time is a bit longer wait a bit more
155 * to ensure data ready at first try
156 */
157 data->ready_time = K_USEC(ready_time_us + 10);
158
159 return odr;
160 }
161
ads1119_send_start_read(const struct device * dev)162 static int ads1119_send_start_read(const struct device *dev)
163 {
164 const struct ads1119_config *config = dev->config;
165 const uint8_t cmd = ADS1119_CMD_START_SYNC;
166
167 return i2c_write_dt(&config->bus, &cmd, sizeof(cmd));
168 }
169
ads1119_wait_data_ready(const struct device * dev)170 static int ads1119_wait_data_ready(const struct device *dev)
171 {
172 int rc;
173 struct ads1119_data *data = dev->data;
174
175 k_sleep(data->ready_time);
176 uint8_t status = 0;
177
178 rc = ads1119_read_reg(dev, ADS1119_REG_STATUS, &status);
179 if (rc != 0) {
180 return rc;
181 }
182
183 while ((status & ADS1119_STATUS_MASK_READY) == 0) {
184
185 k_sleep(K_USEC(100));
186 rc = ads1119_read_reg(dev, ADS1119_REG_STATUS, &status);
187 if (rc != 0) {
188 return rc;
189 }
190 }
191
192 return 0;
193 }
194
ads1119_read_sample(const struct device * dev,uint16_t * buff)195 static int ads1119_read_sample(const struct device *dev, uint16_t *buff)
196 {
197 int res;
198 uint8_t rx_bytes[2];
199 const struct ads1119_config *config = dev->config;
200 const uint8_t cmd = ADS1119_CMD_READ_DATA;
201
202 res = i2c_write_read_dt(&config->bus,
203 &cmd, sizeof(cmd),
204 rx_bytes, sizeof(rx_bytes));
205
206 *buff = sys_get_be16(rx_bytes);
207 return res;
208 }
209
ads1119_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)210 static int ads1119_channel_setup(const struct device *dev,
211 const struct adc_channel_cfg *channel_cfg)
212 {
213 struct ads1119_data *data = dev->data;
214 uint8_t config = 0;
215 int dr = 0;
216
217 if (channel_cfg->channel_id != 0) {
218 return -EINVAL;
219 }
220
221 switch (channel_cfg->reference) {
222 case ADC_REF_EXTERNAL0:
223 config |= ADS1119_CONFIG_VREF(ADS1119_CONFIG_VREF_EXTERNAL);
224 break;
225 case ADC_REF_INTERNAL:
226 config |= ADS1119_CONFIG_VREF(ADS1119_CONFIG_VREF_INTERNAL);
227 break;
228 default:
229 return -EINVAL;
230 }
231
232 if (channel_cfg->differential) {
233 if (channel_cfg->input_positive == 0 && channel_cfg->input_negative == 1) {
234 config |= ADS1119_CONFIG_MUX(ADS1119_CONFIG_MUX_DIFF_0_1);
235 } else if (channel_cfg->input_positive == 1 && channel_cfg->input_negative == 2) {
236 config |= ADS1119_CONFIG_MUX(ADS1119_CONFIG_MUX_DIFF_1_2);
237 } else if (channel_cfg->input_positive == 2 && channel_cfg->input_negative == 3) {
238 config |= ADS1119_CONFIG_MUX(ADS1119_CONFIG_MUX_DIFF_2_3);
239 } else {
240 return -EINVAL;
241 }
242 } else {
243 if (channel_cfg->input_positive == 0) {
244 config |= ADS1119_CONFIG_MUX(ADS1119_CONFIG_MUX_SINGLE_0);
245 } else if (channel_cfg->input_positive == 1) {
246 config |= ADS1119_CONFIG_MUX(ADS1119_CONFIG_MUX_SINGLE_1);
247 } else if (channel_cfg->input_positive == 2) {
248 config |= ADS1119_CONFIG_MUX(ADS1119_CONFIG_MUX_SINGLE_2);
249 } else if (channel_cfg->input_positive == 3) {
250 config |= ADS1119_CONFIG_MUX(ADS1119_CONFIG_MUX_SINGLE_3);
251 } else {
252 return -EINVAL;
253 }
254 }
255 data->differential = channel_cfg->differential;
256
257 dr = ads1119_acq_time_to_dr(dev, channel_cfg->acquisition_time);
258 if (dr < 0) {
259 return dr;
260 }
261
262 config |= ADS1119_CONFIG_DR(dr);
263
264 switch (channel_cfg->gain) {
265 case ADC_GAIN_1:
266 config |= ADS1119_CONFIG_GAIN(ADS1119_CONFIG_GAIN_1);
267 break;
268 case ADC_GAIN_4:
269 config |= ADS1119_CONFIG_GAIN(ADS1119_CONFIG_GAIN_4);
270 break;
271 default:
272 return -EINVAL;
273 }
274
275 config |= ADS1119_CONFIG_CM(ADS1119_CONFIG_CM_SINGLE); /* Only single shot supported */
276
277 return ads1119_write_reg(dev, config);
278 }
279
280
ads1119_validate_buffer_size(const struct adc_sequence * sequence)281 static int ads1119_validate_buffer_size(const struct adc_sequence *sequence)
282 {
283 size_t needed = sizeof(int16_t);
284
285 if (sequence->options) {
286 needed *= (1 + sequence->options->extra_samplings);
287 }
288
289 if (sequence->buffer_size < needed) {
290 return -ENOMEM;
291 }
292
293 return 0;
294 }
295
ads1119_validate_sequence(const struct device * dev,const struct adc_sequence * sequence)296 static int ads1119_validate_sequence(const struct device *dev, const struct adc_sequence *sequence)
297 {
298 const struct ads1119_data *data = dev->data;
299 const uint8_t resolution = data->differential ? ADS1119_RESOLUTION : ADS1119_RESOLUTION - 1;
300
301 if (sequence->resolution != resolution) {
302 return -EINVAL;
303 }
304
305 if (sequence->channels != BIT(0)) {
306 return -EINVAL;
307 }
308
309 if (sequence->oversampling) {
310 return -EINVAL;
311 }
312
313 return ads1119_validate_buffer_size(sequence);
314 }
315
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)316 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
317 bool repeat_sampling)
318 {
319 struct ads1119_data *data = CONTAINER_OF(ctx,
320 struct ads1119_data,
321 ctx);
322
323 if (repeat_sampling) {
324 data->buffer = data->buffer_ptr;
325 }
326 }
327
adc_context_start_sampling(struct adc_context * ctx)328 static void adc_context_start_sampling(struct adc_context *ctx)
329 {
330 struct ads1119_data *data = CONTAINER_OF(ctx,
331 struct ads1119_data, ctx);
332
333 data->buffer_ptr = data->buffer;
334 k_sem_give(&data->acq_sem);
335 }
336
ads1119_adc_start_read(const struct device * dev,const struct adc_sequence * sequence,bool wait)337 static int ads1119_adc_start_read(const struct device *dev,
338 const struct adc_sequence *sequence,
339 bool wait)
340 {
341 int rc;
342 struct ads1119_data *data = dev->data;
343
344 rc = ads1119_validate_sequence(dev, sequence);
345 if (rc != 0) {
346 return rc;
347 }
348
349 data->buffer = sequence->buffer;
350
351 adc_context_start_read(&data->ctx, sequence);
352
353 if (wait) {
354 rc = adc_context_wait_for_completion(&data->ctx);
355 }
356 return rc;
357 }
358
ads1119_adc_perform_read(const struct device * dev)359 static int ads1119_adc_perform_read(const struct device *dev)
360 {
361 int rc;
362 struct ads1119_data *data = dev->data;
363
364 k_sem_take(&data->acq_sem, K_FOREVER);
365
366 rc = ads1119_send_start_read(dev);
367 if (rc) {
368 adc_context_complete(&data->ctx, rc);
369 return rc;
370 }
371
372 rc = ads1119_wait_data_ready(dev);
373 if (rc != 0) {
374 adc_context_complete(&data->ctx, rc);
375 return rc;
376 }
377
378 rc = ads1119_read_sample(dev, data->buffer);
379 if (rc != 0) {
380 adc_context_complete(&data->ctx, rc);
381 return rc;
382 }
383 data->buffer++;
384
385 adc_context_on_sampling_done(&data->ctx, dev);
386
387 return rc;
388 }
389
390 #if CONFIG_ADC_ASYNC
ads1119_adc_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)391 static int ads1119_adc_read_async(const struct device *dev,
392 const struct adc_sequence *sequence,
393 struct k_poll_signal *async)
394 {
395 int rc;
396 struct ads1119_data *data = dev->data;
397
398 adc_context_lock(&data->ctx, true, async);
399 rc = ads1119_adc_start_read(dev, sequence, true);
400 adc_context_release(&data->ctx, rc);
401
402 return rc;
403 }
ads1119_read(const struct device * dev,const struct adc_sequence * sequence)404 static int ads1119_read(const struct device *dev,
405 const struct adc_sequence *sequence)
406 {
407 int rc;
408 struct ads1119_data *data = dev->data;
409
410 adc_context_lock(&data->ctx, false, NULL);
411 rc = ads1119_adc_start_read(dev, sequence, true);
412 adc_context_release(&data->ctx, rc);
413
414 return rc;
415 }
416 #else
ads1119_read(const struct device * dev,const struct adc_sequence * sequence)417 static int ads1119_read(const struct device *dev,
418 const struct adc_sequence *sequence)
419 {
420 int rc;
421 struct ads1119_data *data = dev->data;
422
423 adc_context_lock(&data->ctx, false, NULL);
424 rc = ads1119_adc_start_read(dev, sequence, false);
425
426 while (rc == 0 && k_sem_take(&data->ctx.sync, K_NO_WAIT) != 0) {
427 rc = ads1119_adc_perform_read(dev);
428 }
429
430 adc_context_release(&data->ctx, rc);
431 return rc;
432 }
433 #endif
434
435 #if CONFIG_ADC_ASYNC
ads1119_acquisition_thread(void * p1,void * p2,void * p3)436 static void ads1119_acquisition_thread(void *p1, void *p2, void *p3)
437 {
438 ARG_UNUSED(p2);
439 ARG_UNUSED(p3);
440
441 const struct device *dev = p1;
442 while (true) {
443 ads1119_adc_perform_read(dev);
444 }
445 }
446 #endif
447
ads1119_init(const struct device * dev)448 static int ads1119_init(const struct device *dev)
449 {
450 int rc;
451 uint8_t status;
452 const struct ads1119_config *config = dev->config;
453 struct ads1119_data *data = dev->data;
454
455 adc_context_init(&data->ctx);
456
457 k_sem_init(&data->acq_sem, 0, 1);
458
459 if (!device_is_ready(config->bus.bus)) {
460 return -ENODEV;
461 }
462
463 rc = ads1119_read_reg(dev, ADS1119_REG_STATUS, &status);
464 if (rc) {
465 LOG_ERR("Could not get %s status", dev->name);
466 return rc;
467 }
468
469 #if CONFIG_ADC_ASYNC
470 k_tid_t tid =
471 k_thread_create(&data->thread, config->stack,
472 CONFIG_ADC_ADS1119_ACQUISITION_THREAD_STACK_SIZE,
473 ads1119_acquisition_thread,
474 (void *)dev, NULL, NULL,
475 CONFIG_ADC_ADS1119_ASYNC_THREAD_INIT_PRIO,
476 0, K_NO_WAIT);
477 k_thread_name_set(tid, "adc_ads1119");
478 #endif
479 adc_context_unlock_unconditionally(&data->ctx);
480
481 return rc;
482 }
483
484 static const struct adc_driver_api api = {
485 .channel_setup = ads1119_channel_setup,
486 .read = ads1119_read,
487 .ref_internal = ADS1119_REF_INTERNAL,
488 #ifdef CONFIG_ADC_ASYNC
489 .read_async = ads1119_adc_read_async,
490 #endif
491 };
492 #define ADC_ADS1119_INST_DEFINE(n) \
493 IF_ENABLED(CONFIG_ADC_ASYNC, \
494 (static \
495 K_KERNEL_STACK_DEFINE(thread_stack_##n, \
496 CONFIG_ADC_ADS1119_ACQUISITION_THREAD_STACK_SIZE);)) \
497 static const struct ads1119_config config_##n = { \
498 .bus = I2C_DT_SPEC_GET(DT_DRV_INST(n)), \
499 IF_ENABLED(CONFIG_ADC_ASYNC, (.stack = thread_stack_##n)) \
500 }; \
501 static struct ads1119_data data_##n; \
502 DEVICE_DT_INST_DEFINE(n, ads1119_init, \
503 NULL, &data_##n, &config_##n, \
504 POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \
505 &api);
506
507 DT_INST_FOREACH_STATUS_OKAY(ADC_ADS1119_INST_DEFINE);
508