1 /*
2  * Copyright (c) 2019 Vestas Wind Systems A/S
3  *
4  * Based on adc_mcux_adc16.c, which is:
5  * Copyright (c) 2017-2018, NXP
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 
10 #define DT_DRV_COMPAT nxp_kinetis_adc12
11 
12 #include <zephyr/drivers/adc.h>
13 #include <fsl_adc12.h>
14 #include <zephyr/drivers/pinctrl.h>
15 
16 #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
17 #include <zephyr/logging/log.h>
18 #include <zephyr/irq.h>
19 LOG_MODULE_REGISTER(adc_mcux_adc12);
20 
21 #define ADC_CONTEXT_USES_KERNEL_TIMER
22 #include "adc_context.h"
23 
24 struct mcux_adc12_config {
25 	ADC_Type *base;
26 	adc12_clock_source_t clock_src;
27 	adc12_clock_divider_t clock_div;
28 	adc12_reference_voltage_source_t ref_src;
29 	uint32_t sample_clk_count;
30 	void (*irq_config_func)(const struct device *dev);
31 	const struct pinctrl_dev_config *pincfg;
32 };
33 
34 struct mcux_adc12_data {
35 	const struct device *dev;
36 	struct adc_context ctx;
37 	uint16_t *buffer;
38 	uint16_t *repeat_buffer;
39 	uint32_t channels;
40 	uint8_t channel_id;
41 };
42 
mcux_adc12_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)43 static int mcux_adc12_channel_setup(const struct device *dev,
44 				    const struct adc_channel_cfg *channel_cfg)
45 {
46 	uint8_t channel_id = channel_cfg->channel_id;
47 
48 	if (channel_id > (ADC_SC1_ADCH_MASK >> ADC_SC1_ADCH_SHIFT)) {
49 		LOG_ERR("Invalid channel %d", channel_id);
50 		return -EINVAL;
51 	}
52 
53 	if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
54 		LOG_ERR("Unsupported channel acquisition time");
55 		return -ENOTSUP;
56 	}
57 
58 	if (channel_cfg->differential) {
59 		LOG_ERR("Differential channels are not supported");
60 		return -ENOTSUP;
61 	}
62 
63 	if (channel_cfg->gain != ADC_GAIN_1) {
64 		LOG_ERR("Unsupported channel gain %d", channel_cfg->gain);
65 		return -ENOTSUP;
66 	}
67 
68 	if (channel_cfg->reference != ADC_REF_INTERNAL) {
69 		LOG_ERR("Unsupported channel reference");
70 		return -ENOTSUP;
71 	}
72 
73 	return 0;
74 }
75 
mcux_adc12_start_read(const struct device * dev,const struct adc_sequence * sequence)76 static int mcux_adc12_start_read(const struct device *dev,
77 				 const struct adc_sequence *sequence)
78 {
79 	const struct mcux_adc12_config *config = dev->config;
80 	struct mcux_adc12_data *data = dev->data;
81 	adc12_hardware_average_mode_t mode;
82 	adc12_resolution_t resolution;
83 	ADC_Type *base = config->base;
84 	int error;
85 	uint32_t tmp32;
86 
87 	switch (sequence->resolution) {
88 	case 8:
89 		resolution = kADC12_Resolution8Bit;
90 		break;
91 	case 10:
92 		resolution = kADC12_Resolution10Bit;
93 		break;
94 	case 12:
95 		resolution = kADC12_Resolution12Bit;
96 		break;
97 	default:
98 		LOG_ERR("Unsupported resolution %d", sequence->resolution);
99 		return -ENOTSUP;
100 	}
101 
102 	tmp32 = base->CFG1 & ~(ADC_CFG1_MODE_MASK);
103 	tmp32 |= ADC_CFG1_MODE(resolution);
104 	base->CFG1 = tmp32;
105 
106 	switch (sequence->oversampling) {
107 	case 0:
108 		mode = kADC12_HardwareAverageDisabled;
109 		break;
110 	case 2:
111 		mode = kADC12_HardwareAverageCount4;
112 		break;
113 	case 3:
114 		mode = kADC12_HardwareAverageCount8;
115 		break;
116 	case 4:
117 		mode = kADC12_HardwareAverageCount16;
118 		break;
119 	case 5:
120 		mode = kADC12_HardwareAverageCount32;
121 		break;
122 	default:
123 		LOG_ERR("Unsupported oversampling value %d",
124 			sequence->oversampling);
125 		return -ENOTSUP;
126 	}
127 	ADC12_SetHardwareAverage(config->base, mode);
128 
129 	data->buffer = sequence->buffer;
130 	adc_context_start_read(&data->ctx, sequence);
131 	error = adc_context_wait_for_completion(&data->ctx);
132 
133 	return error;
134 }
135 
mcux_adc12_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)136 static int mcux_adc12_read_async(const struct device *dev,
137 				 const struct adc_sequence *sequence,
138 				 struct k_poll_signal *async)
139 {
140 	struct mcux_adc12_data *data = dev->data;
141 	int error;
142 
143 	adc_context_lock(&data->ctx, async ? true : false, async);
144 	error = mcux_adc12_start_read(dev, sequence);
145 	adc_context_release(&data->ctx, error);
146 
147 	return error;
148 }
149 
mcux_adc12_read(const struct device * dev,const struct adc_sequence * sequence)150 static int mcux_adc12_read(const struct device *dev,
151 			   const struct adc_sequence *sequence)
152 {
153 	return mcux_adc12_read_async(dev, sequence, NULL);
154 }
155 
mcux_adc12_start_channel(const struct device * dev)156 static void mcux_adc12_start_channel(const struct device *dev)
157 {
158 	const struct mcux_adc12_config *config = dev->config;
159 	struct mcux_adc12_data *data = dev->data;
160 
161 	adc12_channel_config_t channel_config;
162 	uint32_t channel_group = 0U;
163 
164 	data->channel_id = find_lsb_set(data->channels) - 1;
165 
166 	LOG_DBG("Starting channel %d", data->channel_id);
167 	channel_config.enableInterruptOnConversionCompleted = true;
168 	channel_config.channelNumber = data->channel_id;
169 	ADC12_SetChannelConfig(config->base, channel_group, &channel_config);
170 }
171 
adc_context_start_sampling(struct adc_context * ctx)172 static void adc_context_start_sampling(struct adc_context *ctx)
173 {
174 	struct mcux_adc12_data *data =
175 		CONTAINER_OF(ctx, struct mcux_adc12_data, ctx);
176 
177 	data->channels = ctx->sequence.channels;
178 	data->repeat_buffer = data->buffer;
179 
180 	mcux_adc12_start_channel(data->dev);
181 }
182 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)183 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
184 					      bool repeat_sampling)
185 {
186 	struct mcux_adc12_data *data =
187 		CONTAINER_OF(ctx, struct mcux_adc12_data, ctx);
188 
189 	if (repeat_sampling) {
190 		data->buffer = data->repeat_buffer;
191 	}
192 }
193 
mcux_adc12_isr(const struct device * dev)194 static void mcux_adc12_isr(const struct device *dev)
195 {
196 	const struct mcux_adc12_config *config = dev->config;
197 	struct mcux_adc12_data *data = dev->data;
198 	ADC_Type *base = config->base;
199 	uint32_t channel_group = 0U;
200 	uint16_t result;
201 
202 	result = ADC12_GetChannelConversionValue(base, channel_group);
203 	LOG_DBG("Finished channel %d. Result is 0x%04x",
204 		data->channel_id, result);
205 
206 	*data->buffer++ = result;
207 	data->channels &= ~BIT(data->channel_id);
208 
209 	if (data->channels) {
210 		mcux_adc12_start_channel(dev);
211 	} else {
212 		adc_context_on_sampling_done(&data->ctx, dev);
213 	}
214 }
215 
mcux_adc12_init(const struct device * dev)216 static int mcux_adc12_init(const struct device *dev)
217 {
218 	const struct mcux_adc12_config *config = dev->config;
219 	struct mcux_adc12_data *data = dev->data;
220 	ADC_Type *base = config->base;
221 	adc12_config_t adc_config;
222 	int err;
223 
224 	ADC12_GetDefaultConfig(&adc_config);
225 
226 	adc_config.referenceVoltageSource = config->ref_src;
227 	adc_config.clockSource = config->clock_src;
228 	adc_config.clockDivider = config->clock_div;
229 	adc_config.sampleClockCount = config->sample_clk_count;
230 	adc_config.resolution = kADC12_Resolution12Bit;
231 	adc_config.enableContinuousConversion = false;
232 
233 	ADC12_Init(base, &adc_config);
234 	ADC12_DoAutoCalibration(base);
235 	ADC12_EnableHardwareTrigger(base, false);
236 
237 	config->irq_config_func(dev);
238 	data->dev = dev;
239 
240 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
241 	if (err) {
242 		return err;
243 	}
244 
245 	adc_context_unlock_unconditionally(&data->ctx);
246 
247 	return 0;
248 }
249 
250 static const struct adc_driver_api mcux_adc12_driver_api = {
251 	.channel_setup = mcux_adc12_channel_setup,
252 	.read = mcux_adc12_read,
253 #ifdef CONFIG_ADC_ASYNC
254 	.read_async = mcux_adc12_read_async,
255 #endif
256 };
257 
258 #define ASSERT_WITHIN_RANGE(val, min, max, str) \
259 	BUILD_ASSERT(val >= min && val <= max, str)
260 #define ASSERT_ADC12_CLK_DIV_VALID(val, str) \
261 	BUILD_ASSERT(val == 1 || val == 2 || val == 4 || val == 8, str)
262 #define TO_ADC12_CLOCK_SRC(val) _DO_CONCAT(kADC12_ClockSourceAlt, val)
263 #define TO_ADC12_CLOCK_DIV(val) _DO_CONCAT(kADC12_ClockDivider, val)
264 
265 #define ADC12_REF_SRC(n)						\
266 	COND_CODE_1(DT_INST_PROP(0, alternate_voltage_reference),	\
267 				 (kADC12_ReferenceVoltageSourceValt),	\
268 				 (kADC12_ReferenceVoltageSourceVref))
269 
270 #define ACD12_MCUX_INIT(n)						\
271 	static void mcux_adc12_config_func_##n(const struct device *dev); \
272 									\
273 	PINCTRL_DT_INST_DEFINE(n);					\
274 									\
275 	ASSERT_WITHIN_RANGE(DT_INST_PROP(n, clk_source), 0, 3,		\
276 			    "Invalid clock source");			\
277 	ASSERT_ADC12_CLK_DIV_VALID(DT_INST_PROP(n, clk_divider),	\
278 				   "Invalid clock divider");		\
279 	ASSERT_WITHIN_RANGE(DT_INST_PROP(n, sample_time), 2, 256,	\
280 			    "Invalid sample time");			\
281 	static const struct mcux_adc12_config mcux_adc12_config_##n = {	\
282 		.base = (ADC_Type *)DT_INST_REG_ADDR(n),		\
283 		.clock_src = TO_ADC12_CLOCK_SRC(DT_INST_PROP(n, clk_source)),\
284 		.clock_div =						\
285 			TO_ADC12_CLOCK_DIV(DT_INST_PROP(n, clk_divider)),\
286 		.ref_src = ADC12_REF_SRC(n),				\
287 		.sample_clk_count = DT_INST_PROP(n, sample_time),	\
288 		.irq_config_func = mcux_adc12_config_func_##n,		\
289 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),		\
290 	};								\
291 									\
292 	static struct mcux_adc12_data mcux_adc12_data_##n = {		\
293 		ADC_CONTEXT_INIT_TIMER(mcux_adc12_data_##n, ctx),	\
294 		ADC_CONTEXT_INIT_LOCK(mcux_adc12_data_##n, ctx),	\
295 		ADC_CONTEXT_INIT_SYNC(mcux_adc12_data_##n, ctx),	\
296 	};								\
297 									\
298 	DEVICE_DT_INST_DEFINE(n, &mcux_adc12_init,			\
299 			    NULL, &mcux_adc12_data_##n,			\
300 			    &mcux_adc12_config_##n, POST_KERNEL,	\
301 			    CONFIG_ADC_INIT_PRIORITY,			\
302 			    &mcux_adc12_driver_api);			\
303 									\
304 	static void mcux_adc12_config_func_##n(const struct device *dev) \
305 	{								\
306 		IRQ_CONNECT(DT_INST_IRQN(n),				\
307 			    DT_INST_IRQ(n, priority), mcux_adc12_isr,	\
308 			    DEVICE_DT_INST_GET(n), 0);			\
309 									\
310 		irq_enable(DT_INST_IRQN(n));				\
311 	}
312 
313 DT_INST_FOREACH_STATUS_OKAY(ACD12_MCUX_INIT)
314