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