1 /*
2  * Copyright (c) 2023 Grinn
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT adi_ad5592_adc
7 
8 #include <zephyr/drivers/adc.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/sys/byteorder.h>
11 
12 #include <zephyr/drivers/mfd/ad5592.h>
13 
14 #define ADC_CONTEXT_USES_KERNEL_TIMER
15 #include "adc_context.h"
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(adc_ad5592, CONFIG_ADC_LOG_LEVEL);
19 
20 #define AD5592_ADC_RESOLUTION 12U
21 #define AD5592_ADC_MAX_VAL 4096
22 
23 struct adc_ad5592_config {
24 	const struct device *mfd_dev;
25 };
26 
27 struct adc_ad5592_data {
28 	struct adc_context ctx;
29 	const struct device *dev;
30 	uint8_t adc_conf;
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_AD5592_ACQUISITION_THREAD_STACK_SIZE);
38 };
39 
adc_ad5592_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)40 static int adc_ad5592_channel_setup(const struct device *dev,
41 				    const struct adc_channel_cfg *channel_cfg)
42 {
43 	const struct adc_ad5592_config *config = dev->config;
44 	struct adc_ad5592_data *data = dev->data;
45 
46 	if (channel_cfg->channel_id >= AD5592_PIN_MAX) {
47 		LOG_ERR("invalid channel id %d", channel_cfg->channel_id);
48 		return -EINVAL;
49 	}
50 
51 	data->adc_conf |= BIT(channel_cfg->channel_id);
52 
53 	return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_ADC_CONFIG, data->adc_conf);
54 }
55 
adc_ad5592_validate_buffer_size(const struct device * dev,const struct adc_sequence * sequence)56 static int adc_ad5592_validate_buffer_size(const struct device *dev,
57 					   const struct adc_sequence *sequence)
58 {
59 	uint8_t channels;
60 	size_t needed;
61 
62 	channels = POPCOUNT(sequence->channels);
63 	needed = channels * sizeof(uint16_t);
64 
65 	if (sequence->buffer_size < needed) {
66 		return -ENOMEM;
67 	}
68 
69 	return 0;
70 }
71 
adc_ad5592_start_read(const struct device * dev,const struct adc_sequence * sequence)72 static int adc_ad5592_start_read(const struct device *dev, const struct adc_sequence *sequence)
73 {
74 	struct adc_ad5592_data *data = dev->data;
75 	int ret;
76 
77 	if (sequence->resolution != AD5592_ADC_RESOLUTION) {
78 		LOG_ERR("invalid resolution %d", sequence->resolution);
79 		return -EINVAL;
80 	}
81 
82 	if (find_msb_set(sequence->channels) > AD5592_PIN_MAX) {
83 		LOG_ERR("invalid channels in mask: 0x%08x", sequence->channels);
84 		return -EINVAL;
85 	}
86 
87 	ret = adc_ad5592_validate_buffer_size(dev, sequence);
88 	if (ret < 0) {
89 		LOG_ERR("insufficient buffer size");
90 		return ret;
91 	}
92 
93 	data->buffer = sequence->buffer;
94 	adc_context_start_read(&data->ctx, sequence);
95 
96 	return adc_context_wait_for_completion(&data->ctx);
97 }
98 
adc_ad5592_read_channel(const struct device * dev,uint8_t channel,uint16_t * result)99 static int adc_ad5592_read_channel(const struct device *dev, uint8_t channel, uint16_t *result)
100 {
101 	const struct adc_ad5592_config *config = dev->config;
102 	uint16_t val;
103 	int ret;
104 
105 	ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_SEQ_ADC, BIT(channel));
106 	if (ret < 0) {
107 		return ret;
108 	}
109 
110 	/*
111 	 * Invalid data:
112 	 * See Figure 46. Single-Channel ADC Conversion Sequence.
113 	 * The first conversion result always returns invalid data.
114 	 */
115 	(void) mfd_ad5592_read_raw(config->mfd_dev, &val);
116 
117 	ret = mfd_ad5592_read_raw(config->mfd_dev, &val);
118 	if (ret < 0) {
119 		return ret;
120 	}
121 
122 	val = sys_be16_to_cpu(val);
123 	if (channel >= 1) {
124 		val -= channel * AD5592_ADC_MAX_VAL;
125 	}
126 
127 	*result = val;
128 
129 	return 0;
130 }
131 
adc_context_start_sampling(struct adc_context * ctx)132 static void adc_context_start_sampling(struct adc_context *ctx)
133 {
134 	struct adc_ad5592_data *data = CONTAINER_OF(ctx, struct adc_ad5592_data, ctx);
135 
136 	data->channels = ctx->sequence.channels;
137 	data->repeat_buffer = data->buffer;
138 
139 	k_sem_give(&data->sem);
140 }
141 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)142 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
143 					      bool repeat_sampling)
144 {
145 	struct adc_ad5592_data *data = CONTAINER_OF(ctx, struct adc_ad5592_data, ctx);
146 
147 	if (repeat_sampling) {
148 		data->buffer = data->repeat_buffer;
149 	}
150 }
151 
adc_ad5592_acquisition_thread(struct adc_ad5592_data * data)152 static void adc_ad5592_acquisition_thread(struct adc_ad5592_data *data)
153 {
154 	uint16_t result;
155 	uint8_t channel;
156 	int ret;
157 
158 	while (true) {
159 		k_sem_take(&data->sem, K_FOREVER);
160 
161 		while (data->channels != 0) {
162 			channel = find_lsb_set(data->channels) - 1;
163 
164 			ret = adc_ad5592_read_channel(data->dev, channel, &result);
165 			if (ret < 0) {
166 				LOG_ERR("failed to read channel %d (ret %d)", channel, ret);
167 				adc_context_complete(&data->ctx, ret);
168 				break;
169 			}
170 
171 			*data->buffer++ = result;
172 			WRITE_BIT(data->channels, channel, 0);
173 		}
174 
175 		adc_context_on_sampling_done(&data->ctx, data->dev);
176 	}
177 }
178 
adc_ad5592_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)179 static int adc_ad5592_read_async(const struct device *dev,
180 				 const struct adc_sequence *sequence,
181 				 struct k_poll_signal *async)
182 {
183 	struct adc_ad5592_data *data = dev->data;
184 	int ret;
185 
186 	adc_context_lock(&data->ctx, async ? true : false, async);
187 	ret = adc_ad5592_start_read(dev, sequence);
188 	adc_context_release(&data->ctx, ret);
189 
190 	return ret;
191 }
192 
adc_ad5592_read(const struct device * dev,const struct adc_sequence * sequence)193 static int adc_ad5592_read(const struct device *dev,
194 			   const struct adc_sequence *sequence)
195 {
196 	return adc_ad5592_read_async(dev, sequence, NULL);
197 }
198 
adc_ad5592_init(const struct device * dev)199 static int adc_ad5592_init(const struct device *dev)
200 {
201 	const struct adc_ad5592_config *config = dev->config;
202 	struct adc_ad5592_data *data = dev->data;
203 	k_tid_t tid;
204 	int ret;
205 
206 	if (!device_is_ready(config->mfd_dev)) {
207 		return -ENODEV;
208 	}
209 
210 	ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_PD_REF_CTRL, AD5592_EN_REF);
211 	if (ret < 0) {
212 		return ret;
213 	}
214 
215 	data->dev = dev;
216 
217 	k_sem_init(&data->sem, 0, 1);
218 	adc_context_init(&data->ctx);
219 
220 	tid = k_thread_create(&data->thread, data->stack,
221 			K_KERNEL_STACK_SIZEOF(data->stack),
222 			(k_thread_entry_t)adc_ad5592_acquisition_thread, data, NULL, NULL,
223 			CONFIG_ADC_AD5592_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT);
224 
225 	ret = k_thread_name_set(tid, "adc_ad5592");
226 	if (ret < 0) {
227 		return ret;
228 	}
229 
230 	adc_context_unlock_unconditionally(&data->ctx);
231 
232 	return 0;
233 }
234 
235 static const struct adc_driver_api adc_ad5592_api = {
236 	.channel_setup = adc_ad5592_channel_setup,
237 	.read = adc_ad5592_read,
238 #ifdef CONFIG_ADC_ASYNC
239 	.read_async = adc_ad5592_read_async,
240 #endif
241 };
242 
243 #define ADC_AD5592_DEFINE(inst)							\
244 	static const struct adc_ad5592_config adc_ad5592_config##inst = {	\
245 		.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)),			\
246 	};									\
247 										\
248 	static struct adc_ad5592_data adc_ad5592_data##inst;			\
249 										\
250 	DEVICE_DT_INST_DEFINE(inst, adc_ad5592_init, NULL,			\
251 			      &adc_ad5592_data##inst, &adc_ad5592_config##inst, \
252 			      POST_KERNEL, CONFIG_MFD_INIT_PRIORITY,		\
253 			      &adc_ad5592_api);
254 
255 DT_INST_FOREACH_STATUS_OKAY(ADC_AD5592_DEFINE)
256