1 /* TI ADS7052 ADC
2  *
3  * Copyright (c) 2023 Google, LLC
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT ti_ads7052
9 
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/adc.h>
12 #include <zephyr/drivers/spi.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/kernel.h>
15 
16 LOG_MODULE_REGISTER(adc_ads7052);
17 
18 #define ADC_CONTEXT_USES_KERNEL_TIMER
19 #include "adc_context.h"
20 
21 #define ADS7052_RESOLUTION 14U
22 
23 struct ads7052_config {
24 	struct spi_dt_spec bus;
25 	uint8_t channels;
26 };
27 
28 struct ads7052_data {
29 	struct adc_context ctx;
30 	const struct device *dev;
31 	uint16_t *buffer;
32 	uint16_t *repeat_buffer;
33 	uint8_t channels;
34 	struct k_thread thread;
35 	struct k_sem sem;
36 
37 	K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_ADS7052_ACQUISITION_THREAD_STACK_SIZE);
38 };
39 
adc_ads7052_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)40 static int adc_ads7052_channel_setup(const struct device *dev,
41 				     const struct adc_channel_cfg *channel_cfg)
42 {
43 	const struct ads7052_config *config = dev->config;
44 
45 	if (channel_cfg->gain != ADC_GAIN_1) {
46 		LOG_ERR("unsupported channel gain '%d'", channel_cfg->gain);
47 		return -ENOTSUP;
48 	}
49 
50 	if (channel_cfg->reference != ADC_REF_VDD_1) {
51 		LOG_ERR("unsupported channel reference '%d'", channel_cfg->reference);
52 		return -ENOTSUP;
53 	}
54 
55 	if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
56 		LOG_ERR("unsupported acquisition_time '%d'", channel_cfg->acquisition_time);
57 		return -ENOTSUP;
58 	}
59 
60 	if (channel_cfg->channel_id >= config->channels) {
61 		LOG_ERR("unsupported channel id '%d'", channel_cfg->channel_id);
62 		return -ENOTSUP;
63 	}
64 	return 0;
65 }
66 
ads7052_validate_buffer_size(const struct device * dev,const struct adc_sequence * sequence)67 static int ads7052_validate_buffer_size(const struct device *dev,
68 					const struct adc_sequence *sequence)
69 {
70 	uint8_t channels = 0;
71 	size_t needed;
72 
73 	channels = POPCOUNT(sequence->channels);
74 
75 	needed = channels * sizeof(uint16_t);
76 	if (sequence->options) {
77 		needed *= (1 + sequence->options->extra_samplings);
78 	}
79 
80 	if (sequence->buffer_size < needed) {
81 		return -ENOMEM;
82 	}
83 
84 	return 0;
85 }
86 
87 /**
88  * @brief Send ADS7052 Offset calibration request
89  *
90  * On power-up, the host must provide 24 SCLKs in the first serial transfer to enter the OFFCAL
91  * state. During normal operation, the host must provide 64 SCLKs in the serial transfer frame to
92  * enter the OFFCAL state.
93  */
ads7052_send_calibration(const struct device * dev,bool power_up)94 static int ads7052_send_calibration(const struct device *dev, bool power_up)
95 {
96 	const struct ads7052_config *config = dev->config;
97 	int err;
98 	uint8_t sclks_needed = power_up ? 24 : 64;
99 	uint8_t num_bytes = sclks_needed / 8;
100 	uint8_t tx_bytes[8] = {0};
101 
102 	const struct spi_buf tx_buf = {.buf = tx_bytes, .len = num_bytes};
103 	const struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1};
104 
105 	err = spi_write_dt(&config->bus, &tx);
106 
107 	return err;
108 }
109 
ads7052_start_read(const struct device * dev,const struct adc_sequence * sequence)110 static int ads7052_start_read(const struct device *dev, const struct adc_sequence *sequence)
111 {
112 	const struct ads7052_config *config = dev->config;
113 	struct ads7052_data *data = dev->data;
114 	int err;
115 
116 	if (sequence->resolution != ADS7052_RESOLUTION) {
117 		LOG_ERR("unsupported resolution %d", sequence->resolution);
118 		return -ENOTSUP;
119 	}
120 
121 	if (find_msb_set(sequence->channels) > config->channels) {
122 		LOG_ERR("unsupported channels in mask: 0x%08x", sequence->channels);
123 		return -ENOTSUP;
124 	}
125 
126 	if (sequence->calibrate) {
127 		ads7052_send_calibration(dev, false);
128 	}
129 
130 	err = ads7052_validate_buffer_size(dev, sequence);
131 	if (err) {
132 		LOG_ERR("buffer size too small");
133 		return err;
134 	}
135 
136 	data->buffer = sequence->buffer;
137 	adc_context_start_read(&data->ctx, sequence);
138 
139 	return adc_context_wait_for_completion(&data->ctx);
140 }
141 
adc_ads7052_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)142 static int adc_ads7052_read_async(const struct device *dev, const struct adc_sequence *sequence,
143 				  struct k_poll_signal *async)
144 {
145 	struct ads7052_data *data = dev->data;
146 	int error;
147 
148 	adc_context_lock(&data->ctx, async ? true : false, async);
149 	error = ads7052_start_read(dev, sequence);
150 	adc_context_release(&data->ctx, error);
151 
152 	return error;
153 }
154 
adc_ads7052_read(const struct device * dev,const struct adc_sequence * sequence)155 static int adc_ads7052_read(const struct device *dev, const struct adc_sequence *sequence)
156 {
157 	return adc_ads7052_read_async(dev, sequence, NULL);
158 }
159 
adc_context_start_sampling(struct adc_context * ctx)160 static void adc_context_start_sampling(struct adc_context *ctx)
161 {
162 	struct ads7052_data *data = CONTAINER_OF(ctx, struct ads7052_data, ctx);
163 
164 	data->channels = ctx->sequence.channels;
165 	data->repeat_buffer = data->buffer;
166 
167 	k_sem_give(&data->sem);
168 }
169 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)170 static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
171 {
172 	struct ads7052_data *data = CONTAINER_OF(ctx, struct ads7052_data, ctx);
173 
174 	if (repeat_sampling) {
175 		data->buffer = data->repeat_buffer;
176 	}
177 }
178 
179 /**
180  *  @brief Get a 14-bit integer from raw ADC data.
181  *
182  *  @param src Location of the big-endian 14-bit integer to get.
183  *
184  *  @return 14-bit integer in host endianness.
185  */
ads7052_get_be14(const uint8_t src[2])186 static inline int ads7052_get_be14(const uint8_t src[2])
187 {
188 	return ((src[0] & 0x7F) << 7) | (src[1] >> 1);
189 }
190 
191 /**
192  * @brief Read ADS7052 over SPI interface
193  *
194  * A leading 0 is output on the SDO pin on the CS falling edge.
195  * The most significant bit (MSB) of the output data is launched on the SDO pin on the rising edge
196  * after the first SCLK falling edge. Subsequent output bits are launched on the subsequent rising
197  * edges provided on SCLK. When all 14 output bits are shifted out, the device outputs 0's on the
198  * subsequent SCLK rising edges. The device enters the ACQ state after 18 clocks and a minimum time
199  * of tACQ must be provided for acquiring the next sample. If the device is provided with less than
200  * 18 SCLK falling edges in the present serial transfer frame, the device provides an invalid
201  * conversion result in the next serial transfer frame
202  */
ads7052_read_channel(const struct device * dev,uint8_t channel,uint16_t * result)203 static int ads7052_read_channel(const struct device *dev, uint8_t channel, uint16_t *result)
204 {
205 	const struct ads7052_config *config = dev->config;
206 	int err;
207 	uint8_t rx_bytes[3];
208 	const struct spi_buf rx_buf[1] = {{.buf = rx_bytes, .len = sizeof(rx_bytes)}};
209 	const struct spi_buf_set rx = {.buffers = rx_buf, .count = ARRAY_SIZE(rx_buf)};
210 
211 	err = spi_read_dt(&config->bus, &rx);
212 	if (err) {
213 		return err;
214 	}
215 
216 	*result = ads7052_get_be14(rx_bytes);
217 	*result &= BIT_MASK(ADS7052_RESOLUTION);
218 
219 	return 0;
220 }
221 
ads7052_acquisition_thread(void * p1,void * p2,void * p3)222 static void ads7052_acquisition_thread(void *p1, void *p2, void *p3)
223 {
224 	ARG_UNUSED(p2);
225 	ARG_UNUSED(p3);
226 
227 	struct ads7052_data *data = p1;
228 	uint16_t result = 0;
229 	uint8_t channel;
230 	int err = 0;
231 
232 	err = ads7052_send_calibration(data->dev, true);
233 	if (err) {
234 		LOG_ERR("failed to send powerup sequence (err %d)", err);
235 	}
236 
237 	while (true) {
238 		k_sem_take(&data->sem, K_FOREVER);
239 
240 		while (data->channels != 0) {
241 			channel = find_lsb_set(data->channels) - 1;
242 
243 			LOG_DBG("reading channel %d", channel);
244 
245 			err = ads7052_read_channel(data->dev, channel, &result);
246 			if (err) {
247 				LOG_ERR("failed to read channel %d (err %d)", channel, err);
248 				adc_context_complete(&data->ctx, err);
249 				break;
250 			}
251 
252 			LOG_DBG("read channel %d, result = %d", channel, result);
253 
254 			*data->buffer++ = result;
255 			WRITE_BIT(data->channels, channel, 0);
256 		}
257 
258 		adc_context_on_sampling_done(&data->ctx, data->dev);
259 	}
260 }
261 
adc_ads7052_init(const struct device * dev)262 static int adc_ads7052_init(const struct device *dev)
263 {
264 	const struct ads7052_config *config = dev->config;
265 	struct ads7052_data *data = dev->data;
266 
267 	data->dev = dev;
268 
269 	adc_context_init(&data->ctx);
270 	k_sem_init(&data->sem, 0, 1);
271 
272 	if (!spi_is_ready_dt(&config->bus)) {
273 		LOG_ERR("SPI bus %s not ready", config->bus.bus->name);
274 		return -ENODEV;
275 	}
276 
277 	k_thread_create(&data->thread, data->stack,
278 			K_KERNEL_STACK_SIZEOF(data->stack),
279 			ads7052_acquisition_thread, data, NULL, NULL,
280 			CONFIG_ADC_ADS7052_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT);
281 
282 	adc_context_unlock_unconditionally(&data->ctx);
283 
284 	return 0;
285 }
286 
287 static const struct adc_driver_api ads7052_api = {
288 	.channel_setup = adc_ads7052_channel_setup,
289 	.read = adc_ads7052_read,
290 #ifdef CONFIG_ADC_ASYNC
291 	.read_async = adc_ads7052_read_async,
292 #endif
293 };
294 
295 #define ADC_ADS7052_SPI_CFG \
296 	SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_TRANSFER_MSB
297 
298 #define ADC_ADS7052_INIT(n)                                                                        \
299                                                                                                    \
300 	static const struct ads7052_config ads7052_cfg_##n = {                                     \
301 		.bus = SPI_DT_SPEC_INST_GET(n, ADC_ADS7052_SPI_CFG, 1U),                           \
302 		.channels = 1,                                                                     \
303 	};                                                                                         \
304                                                                                                    \
305 	static struct ads7052_data ads7052_data_##n = {                                            \
306 		ADC_CONTEXT_INIT_TIMER(ads7052_data_##n, ctx),                                     \
307 		ADC_CONTEXT_INIT_LOCK(ads7052_data_##n, ctx),                                      \
308 		ADC_CONTEXT_INIT_SYNC(ads7052_data_##n, ctx),                                      \
309 	};                                                                                         \
310                                                                                                    \
311 	DEVICE_DT_INST_DEFINE(n, adc_ads7052_init, NULL, &ads7052_data_##n, &ads7052_cfg_##n,      \
312 			      POST_KERNEL, CONFIG_ADC_ADS7052_INIT_PRIORITY, &ads7052_api);
313 
314 DT_INST_FOREACH_STATUS_OKAY(ADC_ADS7052_INIT)
315