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(void * p1,void * p2,void * p3)235 static void mcp320x_acquisition_thread(void *p1, void *p2, void *p3)
236 {
237 	ARG_UNUSED(p2);
238 	ARG_UNUSED(p3);
239 
240 	struct mcp320x_data *data = p1;
241 	uint16_t result = 0;
242 	uint8_t channel;
243 	int err;
244 
245 	while (true) {
246 		k_sem_take(&data->sem, K_FOREVER);
247 
248 		while (data->channels) {
249 			channel = find_lsb_set(data->channels) - 1;
250 
251 			LOG_DBG("reading channel %d", channel);
252 
253 			err = mcp320x_read_channel(data->dev, channel, &result);
254 			if (err) {
255 				LOG_ERR("failed to read channel %d (err %d)",
256 					channel, err);
257 				adc_context_complete(&data->ctx, err);
258 				break;
259 			}
260 
261 			LOG_DBG("read channel %d, result = %d", channel,
262 				result);
263 
264 			*data->buffer++ = result;
265 			WRITE_BIT(data->channels, channel, 0);
266 		}
267 
268 		adc_context_on_sampling_done(&data->ctx, data->dev);
269 	}
270 }
271 
mcp320x_init(const struct device * dev)272 static int mcp320x_init(const struct device *dev)
273 {
274 	const struct mcp320x_config *config = dev->config;
275 	struct mcp320x_data *data = dev->data;
276 
277 	data->dev = dev;
278 
279 	k_sem_init(&data->sem, 0, 1);
280 
281 	if (!spi_is_ready_dt(&config->bus)) {
282 		LOG_ERR("SPI bus is not ready");
283 		return -ENODEV;
284 	}
285 
286 	k_thread_create(&data->thread, data->stack,
287 			K_KERNEL_STACK_SIZEOF(data->stack),
288 			mcp320x_acquisition_thread,
289 			data, NULL, NULL,
290 			CONFIG_ADC_MCP320X_ACQUISITION_THREAD_PRIO,
291 			0, K_NO_WAIT);
292 
293 	adc_context_unlock_unconditionally(&data->ctx);
294 
295 	return 0;
296 }
297 
298 static const struct adc_driver_api mcp320x_adc_api = {
299 	.channel_setup = mcp320x_channel_setup,
300 	.read = mcp320x_read,
301 #ifdef CONFIG_ADC_ASYNC
302 	.read_async = mcp320x_read_async,
303 #endif
304 };
305 
306 #define INST_DT_MCP320X(inst, t) DT_INST(inst, microchip_mcp##t)
307 
308 #define MCP320X_DEVICE(t, n, ch) \
309 	static struct mcp320x_data mcp##t##_data_##n = { \
310 		ADC_CONTEXT_INIT_TIMER(mcp##t##_data_##n, ctx), \
311 		ADC_CONTEXT_INIT_LOCK(mcp##t##_data_##n, ctx), \
312 		ADC_CONTEXT_INIT_SYNC(mcp##t##_data_##n, ctx), \
313 	}; \
314 	static const struct mcp320x_config mcp##t##_config_##n = { \
315 		.bus = SPI_DT_SPEC_GET(INST_DT_MCP320X(n, t), \
316 					 SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | \
317 					 SPI_WORD_SET(8), 0), \
318 		.channels = ch, \
319 	}; \
320 	DEVICE_DT_DEFINE(INST_DT_MCP320X(n, t), \
321 			 &mcp320x_init, NULL, \
322 			 &mcp##t##_data_##n, \
323 			 &mcp##t##_config_##n, POST_KERNEL, \
324 			 CONFIG_ADC_INIT_PRIORITY, \
325 			 &mcp320x_adc_api)
326 
327 /*
328  * MCP3204: 4 channels
329  */
330 #define MCP3204_DEVICE(n) MCP320X_DEVICE(3204, n, 4)
331 
332 /*
333  * MCP3208: 8 channels
334  */
335 #define MCP3208_DEVICE(n) MCP320X_DEVICE(3208, n, 8)
336 
337 #define CALL_WITH_ARG(arg, expr) expr(arg)
338 
339 #define INST_DT_MCP320X_FOREACH(t, inst_expr)			\
340 	LISTIFY(DT_NUM_INST_STATUS_OKAY(microchip_mcp##t),	\
341 		CALL_WITH_ARG, (;), inst_expr)
342 
343 INST_DT_MCP320X_FOREACH(3204, MCP3204_DEVICE);
344 INST_DT_MCP320X_FOREACH(3208, MCP3208_DEVICE);
345