1 /*
2 * Copyright (c) 2020 Vestas Wind Systems A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief ADC driver for the MCP3204/MCP3208 ADCs.
10 */
11
12 #include <zephyr/drivers/adc.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/spi.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/logging/log.h>
17 #include <zephyr/sys/byteorder.h>
18 #include <zephyr/sys/util.h>
19
20 LOG_MODULE_REGISTER(adc_mcp320x, CONFIG_ADC_LOG_LEVEL);
21
22 #define ADC_CONTEXT_USES_KERNEL_TIMER
23 #include "adc_context.h"
24
25 #define MCP320X_RESOLUTION 12U
26
27 struct mcp320x_config {
28 struct spi_dt_spec bus;
29 uint8_t channels;
30 };
31
32 struct mcp320x_data {
33 struct adc_context ctx;
34 const struct device *dev;
35 uint16_t *buffer;
36 uint16_t *repeat_buffer;
37 uint8_t channels;
38 uint8_t differential;
39 struct k_thread thread;
40 struct k_sem sem;
41
42 K_KERNEL_STACK_MEMBER(stack,
43 CONFIG_ADC_MCP320X_ACQUISITION_THREAD_STACK_SIZE);
44 };
45
mcp320x_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)46 static int mcp320x_channel_setup(const struct device *dev,
47 const struct adc_channel_cfg *channel_cfg)
48 {
49 const struct mcp320x_config *config = dev->config;
50 struct mcp320x_data *data = dev->data;
51
52 if (channel_cfg->gain != ADC_GAIN_1) {
53 LOG_ERR("unsupported channel gain '%d'", channel_cfg->gain);
54 return -ENOTSUP;
55 }
56
57 if (channel_cfg->reference != ADC_REF_EXTERNAL0) {
58 LOG_ERR("unsupported channel reference '%d'",
59 channel_cfg->reference);
60 return -ENOTSUP;
61 }
62
63 if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
64 LOG_ERR("unsupported acquisition_time '%d'",
65 channel_cfg->acquisition_time);
66 return -ENOTSUP;
67 }
68
69 if (channel_cfg->channel_id >= config->channels) {
70 LOG_ERR("unsupported channel id '%d'", channel_cfg->channel_id);
71 return -ENOTSUP;
72 }
73
74 WRITE_BIT(data->differential, channel_cfg->channel_id,
75 channel_cfg->differential);
76
77 return 0;
78 }
79
mcp320x_validate_buffer_size(const struct device * dev,const struct adc_sequence * sequence)80 static int mcp320x_validate_buffer_size(const struct device *dev,
81 const struct adc_sequence *sequence)
82 {
83 const struct mcp320x_config *config = dev->config;
84 uint8_t channels = 0;
85 size_t needed;
86 uint32_t mask;
87
88 for (mask = BIT(config->channels - 1); mask != 0; mask >>= 1) {
89 if (mask & sequence->channels) {
90 channels++;
91 }
92 }
93
94 needed = channels * sizeof(uint16_t);
95 if (sequence->options) {
96 needed *= (1 + sequence->options->extra_samplings);
97 }
98
99 if (sequence->buffer_size < needed) {
100 return -ENOMEM;
101 }
102
103 return 0;
104 }
105
mcp320x_start_read(const struct device * dev,const struct adc_sequence * sequence)106 static int mcp320x_start_read(const struct device *dev,
107 const struct adc_sequence *sequence)
108 {
109 const struct mcp320x_config *config = dev->config;
110 struct mcp320x_data *data = dev->data;
111 int err;
112
113 if (sequence->resolution != MCP320X_RESOLUTION) {
114 LOG_ERR("unsupported resolution %d", sequence->resolution);
115 return -ENOTSUP;
116 }
117
118 if (find_msb_set(sequence->channels) > config->channels) {
119 LOG_ERR("unsupported channels in mask: 0x%08x",
120 sequence->channels);
121 return -ENOTSUP;
122 }
123
124 err = mcp320x_validate_buffer_size(dev, sequence);
125 if (err) {
126 LOG_ERR("buffer size too small");
127 return err;
128 }
129
130 data->buffer = sequence->buffer;
131 adc_context_start_read(&data->ctx, sequence);
132
133 return adc_context_wait_for_completion(&data->ctx);
134 }
135
mcp320x_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)136 static int mcp320x_read_async(const struct device *dev,
137 const struct adc_sequence *sequence,
138 struct k_poll_signal *async)
139 {
140 struct mcp320x_data *data = dev->data;
141 int err;
142
143 adc_context_lock(&data->ctx, async ? true : false, async);
144 err = mcp320x_start_read(dev, sequence);
145 adc_context_release(&data->ctx, err);
146
147 return err;
148 }
149
mcp320x_read(const struct device * dev,const struct adc_sequence * sequence)150 static int mcp320x_read(const struct device *dev,
151 const struct adc_sequence *sequence)
152 {
153 return mcp320x_read_async(dev, sequence, NULL);
154 }
155
adc_context_start_sampling(struct adc_context * ctx)156 static void adc_context_start_sampling(struct adc_context *ctx)
157 {
158 struct mcp320x_data *data = CONTAINER_OF(ctx, struct mcp320x_data, ctx);
159
160 data->channels = ctx->sequence.channels;
161 data->repeat_buffer = data->buffer;
162
163 k_sem_give(&data->sem);
164 }
165
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)166 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
167 bool repeat_sampling)
168 {
169 struct mcp320x_data *data = CONTAINER_OF(ctx, struct mcp320x_data, ctx);
170
171 if (repeat_sampling) {
172 data->buffer = data->repeat_buffer;
173 }
174 }
175
mcp320x_read_channel(const struct device * dev,uint8_t channel,uint16_t * result)176 static int mcp320x_read_channel(const struct device *dev, uint8_t channel,
177 uint16_t *result)
178 {
179 const struct mcp320x_config *config = dev->config;
180 struct mcp320x_data *data = dev->data;
181 uint8_t tx_bytes[2];
182 uint8_t rx_bytes[2];
183 int err;
184 const struct spi_buf tx_buf[2] = {
185 {
186 .buf = tx_bytes,
187 .len = sizeof(tx_bytes)
188 },
189 {
190 .buf = NULL,
191 .len = 1
192 }
193 };
194 const struct spi_buf rx_buf[2] = {
195 {
196 .buf = NULL,
197 .len = 1
198 },
199 {
200 .buf = rx_bytes,
201 .len = sizeof(rx_bytes)
202 }
203 };
204 const struct spi_buf_set tx = {
205 .buffers = tx_buf,
206 .count = ARRAY_SIZE(tx_buf)
207 };
208 const struct spi_buf_set rx = {
209 .buffers = rx_buf,
210 .count = ARRAY_SIZE(rx_buf)
211 };
212
213 /*
214 * Configuration bits consists of: 5 dummy bits + start bit +
215 * SGL/#DIFF bit + D2 + D1 + D0 + 6 dummy bits
216 */
217 tx_bytes[0] = BIT(2) | channel >> 2;
218 tx_bytes[1] = channel << 6;
219
220 if ((data->differential & BIT(channel)) == 0) {
221 tx_bytes[0] |= BIT(1);
222 }
223
224 err = spi_transceive_dt(&config->bus, &tx, &rx);
225 if (err) {
226 return err;
227 }
228
229 *result = sys_get_be16(rx_bytes);
230 *result &= BIT_MASK(MCP320X_RESOLUTION);
231
232 return 0;
233 }
234
mcp320x_acquisition_thread(struct mcp320x_data * data)235 static void mcp320x_acquisition_thread(struct mcp320x_data *data)
236 {
237 uint16_t result = 0;
238 uint8_t channel;
239 int err;
240
241 while (true) {
242 k_sem_take(&data->sem, K_FOREVER);
243
244 while (data->channels) {
245 channel = find_lsb_set(data->channels) - 1;
246
247 LOG_DBG("reading channel %d", channel);
248
249 err = mcp320x_read_channel(data->dev, channel, &result);
250 if (err) {
251 LOG_ERR("failed to read channel %d (err %d)",
252 channel, err);
253 adc_context_complete(&data->ctx, err);
254 break;
255 }
256
257 LOG_DBG("read channel %d, result = %d", channel,
258 result);
259
260 *data->buffer++ = result;
261 WRITE_BIT(data->channels, channel, 0);
262 }
263
264 adc_context_on_sampling_done(&data->ctx, data->dev);
265 }
266 }
267
mcp320x_init(const struct device * dev)268 static int mcp320x_init(const struct device *dev)
269 {
270 const struct mcp320x_config *config = dev->config;
271 struct mcp320x_data *data = dev->data;
272
273 data->dev = dev;
274
275 k_sem_init(&data->sem, 0, 1);
276
277 if (!spi_is_ready_dt(&config->bus)) {
278 LOG_ERR("SPI bus is not ready");
279 return -ENODEV;
280 }
281
282 k_thread_create(&data->thread, data->stack,
283 CONFIG_ADC_MCP320X_ACQUISITION_THREAD_STACK_SIZE,
284 (k_thread_entry_t)mcp320x_acquisition_thread,
285 data, NULL, NULL,
286 CONFIG_ADC_MCP320X_ACQUISITION_THREAD_PRIO,
287 0, K_NO_WAIT);
288
289 adc_context_unlock_unconditionally(&data->ctx);
290
291 return 0;
292 }
293
294 static const struct adc_driver_api mcp320x_adc_api = {
295 .channel_setup = mcp320x_channel_setup,
296 .read = mcp320x_read,
297 #ifdef CONFIG_ADC_ASYNC
298 .read_async = mcp320x_read_async,
299 #endif
300 };
301
302 #define INST_DT_MCP320X(inst, t) DT_INST(inst, microchip_mcp##t)
303
304 #define MCP320X_DEVICE(t, n, ch) \
305 static struct mcp320x_data mcp##t##_data_##n = { \
306 ADC_CONTEXT_INIT_TIMER(mcp##t##_data_##n, ctx), \
307 ADC_CONTEXT_INIT_LOCK(mcp##t##_data_##n, ctx), \
308 ADC_CONTEXT_INIT_SYNC(mcp##t##_data_##n, ctx), \
309 }; \
310 static const struct mcp320x_config mcp##t##_config_##n = { \
311 .bus = SPI_DT_SPEC_GET(INST_DT_MCP320X(n, t), \
312 SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | \
313 SPI_WORD_SET(8), 0), \
314 .channels = ch, \
315 }; \
316 DEVICE_DT_DEFINE(INST_DT_MCP320X(n, t), \
317 &mcp320x_init, NULL, \
318 &mcp##t##_data_##n, \
319 &mcp##t##_config_##n, POST_KERNEL, \
320 CONFIG_ADC_INIT_PRIORITY, \
321 &mcp320x_adc_api)
322
323 /*
324 * MCP3204: 4 channels
325 */
326 #define MCP3204_DEVICE(n) MCP320X_DEVICE(3204, n, 4)
327
328 /*
329 * MCP3208: 8 channels
330 */
331 #define MCP3208_DEVICE(n) MCP320X_DEVICE(3208, n, 8)
332
333 #define CALL_WITH_ARG(arg, expr) expr(arg)
334
335 #define INST_DT_MCP320X_FOREACH(t, inst_expr) \
336 LISTIFY(DT_NUM_INST_STATUS_OKAY(microchip_mcp##t), \
337 CALL_WITH_ARG, (;), inst_expr)
338
339 INST_DT_MCP320X_FOREACH(3204, MCP3204_DEVICE);
340 INST_DT_MCP320X_FOREACH(3208, MCP3208_DEVICE);
341