1 /*
2  * Copyright 2023 NXP
3  * Copyright (c) 2020 Toby Firth
4  *
5  * Based on adc_mcux_adc16.c and adc_mcux_adc12.c, which are:
6  * Copyright (c) 2017-2018, NXP
7  * Copyright (c) 2019 Vestas Wind Systems A/S
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #define DT_DRV_COMPAT nxp_lpc_lpadc
13 
14 #include <errno.h>
15 #include <zephyr/drivers/adc.h>
16 #include <zephyr/sys/util.h>
17 #include <fsl_lpadc.h>
18 #include <zephyr/drivers/regulator.h>
19 
20 #include <zephyr/drivers/pinctrl.h>
21 
22 #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
23 #include <zephyr/logging/log.h>
24 #include <zephyr/irq.h>
25 LOG_MODULE_REGISTER(nxp_mcux_lpadc);
26 
27 /*
28  * Currently, no instance of the ADC IP has more than
29  * 8 channels present. Therefore, we treat channels
30  * with an index 8 or higher as a side b channel, with
31  * the channel index given by channel_num % 8
32  */
33 #define CHANNELS_PER_SIDE 0x8
34 
35 #define ADC_CONTEXT_USES_KERNEL_TIMER
36 #include "adc_context.h"
37 
38 
39 struct mcux_lpadc_config {
40 	ADC_Type *base;
41 	lpadc_reference_voltage_source_t voltage_ref;
42 	uint8_t power_level;
43 	uint32_t calibration_average;
44 	uint32_t offset_a;
45 	uint32_t offset_b;
46 	void (*irq_config_func)(const struct device *dev);
47 	const struct pinctrl_dev_config *pincfg;
48 	const struct device **ref_supplies;
49 };
50 
51 struct mcux_lpadc_data {
52 	const struct device *dev;
53 	struct adc_context ctx;
54 	uint16_t *buffer;
55 	uint16_t *repeat_buffer;
56 	uint32_t channels;
57 	lpadc_conv_command_config_t cmd_config[CONFIG_LPADC_CHANNEL_COUNT];
58 };
59 
60 
61 
mcux_lpadc_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)62 static int mcux_lpadc_channel_setup(const struct device *dev,
63 				const struct adc_channel_cfg *channel_cfg)
64 {
65 
66 
67 	struct mcux_lpadc_data *data = dev->data;
68 	lpadc_conv_command_config_t *cmd;
69 	uint8_t channel_side;
70 	uint8_t channel_num;
71 
72 	/* User may configure maximum number of active channels */
73 	if (channel_cfg->channel_id >= CONFIG_LPADC_CHANNEL_COUNT) {
74 		LOG_ERR("Channel %d is not valid", channel_cfg->channel_id);
75 		return -EINVAL;
76 	}
77 
78 	if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
79 		LOG_ERR("Invalid channel acquisition time");
80 		return -EINVAL;
81 	}
82 
83 	/* Select ADC CMD register to configure based off channel ID */
84 	cmd = &data->cmd_config[channel_cfg->channel_id];
85 
86 	/* If bit 5 of input_positive is set, then channel side B is used */
87 	channel_side = 0x20 & channel_cfg->input_positive;
88 	/* Channel number is selected by lower 4 bits of input_positive */
89 	channel_num = ADC_CMDL_ADCH(channel_cfg->input_positive);
90 
91 	LOG_DBG("Channel num: %u, channel side: %c", channel_num,
92 		channel_side == 0 ? 'A' : 'B');
93 
94 	LPADC_GetDefaultConvCommandConfig(cmd);
95 
96 	if (channel_cfg->differential) {
97 		/* Channel pairs must match in differential mode */
98 		if ((ADC_CMDL_ADCH(channel_cfg->input_positive)) !=
99 		   (ADC_CMDL_ADCH(channel_cfg->input_negative))) {
100 			return -ENOTSUP;
101 		}
102 
103 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF
104 		/* Check to see which channel is the positive input */
105 		if (channel_cfg->input_positive & 0x20) {
106 			/* Channel B is positive side */
107 			cmd->sampleChannelMode =
108 				kLPADC_SampleChannelDiffBothSideBA;
109 		} else {
110 			/* Channel A is positive side */
111 			cmd->sampleChannelMode =
112 				kLPADC_SampleChannelDiffBothSideAB;
113 		}
114 #else
115 		cmd->sampleChannelMode = kLPADC_SampleChannelDiffBothSide;
116 #endif
117 	} else if (channel_side != 0) {
118 		cmd->sampleChannelMode = kLPADC_SampleChannelSingleEndSideB;
119 	} else {
120 		/* Default value for sampleChannelMode is SideA */
121 	}
122 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
123 	/*
124 	 * The true scaling factor used by the LPADC is 30/64, instead of
125 	 * 1/2. Select 1/2 as this is the closest scaling factor available
126 	 * in Zephyr.
127 	 */
128 	if (channel_cfg->gain == ADC_GAIN_1_2) {
129 		LOG_INF("Channel gain of 30/64 selected");
130 		cmd->sampleScaleMode = kLPADC_SamplePartScale;
131 	} else if (channel_cfg->gain == ADC_GAIN_1) {
132 		cmd->sampleScaleMode = kLPADC_SampleFullScale;
133 	} else {
134 		LOG_ERR("Invalid channel gain");
135 		return -EINVAL;
136 	}
137 #else
138 	if (channel_cfg->gain != ADC_GAIN_1) {
139 		LOG_ERR("Invalid channel gain");
140 		return -EINVAL;
141 	}
142 #endif
143 
144 	if (channel_cfg->reference != ADC_REF_EXTERNAL0) {
145 		LOG_ERR("Invalid channel reference");
146 		return -EINVAL;
147 	}
148 
149 	cmd->channelNumber = channel_num;
150 	return 0;
151 }
152 
mcux_lpadc_start_read(const struct device * dev,const struct adc_sequence * sequence)153 static int mcux_lpadc_start_read(const struct device *dev,
154 		 const struct adc_sequence *sequence)
155 {
156 	const struct mcux_lpadc_config *config = dev->config;
157 	struct mcux_lpadc_data *data = dev->data;
158 	lpadc_hardware_average_mode_t hardware_average_mode;
159 	uint8_t channel, last_enabled;
160 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) \
161 	&& FSL_FEATURE_LPADC_HAS_CMDL_MODE
162 	lpadc_conversion_resolution_mode_t resolution_mode;
163 
164 	switch (sequence->resolution) {
165 	case 12:
166 	case 13:
167 		resolution_mode = kLPADC_ConversionResolutionStandard;
168 		break;
169 	case 16:
170 		resolution_mode = kLPADC_ConversionResolutionHigh;
171 		break;
172 	default:
173 		LOG_ERR("Unsupported resolution %d", sequence->resolution);
174 		return -ENOTSUP;
175 	}
176 #else
177 	/* If FSL_FEATURE_LPADC_HAS_CMDL_MODE is not defined
178 	   only 12/13 bit resolution is supported. */
179 	if (sequence->resolution != 12 && sequence->resolution != 13) {
180 		LOG_ERR("Unsupported resolution %d", sequence->resolution);
181 		return -ENOTSUP;
182 	}
183 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_MODE */
184 
185 	switch (sequence->oversampling) {
186 	case 0:
187 		hardware_average_mode = kLPADC_HardwareAverageCount1;
188 		break;
189 	case 1:
190 		hardware_average_mode = kLPADC_HardwareAverageCount2;
191 		break;
192 	case 2:
193 		hardware_average_mode = kLPADC_HardwareAverageCount4;
194 		break;
195 	case 3:
196 		hardware_average_mode = kLPADC_HardwareAverageCount8;
197 		break;
198 	case 4:
199 		hardware_average_mode = kLPADC_HardwareAverageCount16;
200 		break;
201 	case 5:
202 		hardware_average_mode = kLPADC_HardwareAverageCount32;
203 		break;
204 	case 6:
205 		hardware_average_mode = kLPADC_HardwareAverageCount64;
206 		break;
207 	case 7:
208 		hardware_average_mode = kLPADC_HardwareAverageCount128;
209 		break;
210 	default:
211 		LOG_ERR("Unsupported oversampling value %d",
212 			sequence->oversampling);
213 		return -ENOTSUP;
214 	}
215 
216 	/*
217 	 * Now, look at the selected channels to determine which ADC channels
218 	 * we need to configure, and set those channels up.
219 	 *
220 	 * Since this ADC supports chaining channels in hardware, we will
221 	 * start with the highest channel ID and work downwards, chaining
222 	 * channels as we go.
223 	 */
224 	channel = CONFIG_LPADC_CHANNEL_COUNT;
225 	last_enabled = 0;
226 	while (channel-- > 0) {
227 		if (sequence->channels & BIT(channel)) {
228 			/* Setup this channel command */
229 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) && FSL_FEATURE_LPADC_HAS_CMDL_MODE
230 			data->cmd_config[channel].conversionResolutionMode =
231 				resolution_mode;
232 #endif
233 			data->cmd_config[channel].hardwareAverageMode =
234 				hardware_average_mode;
235 			if (last_enabled) {
236 				/* Chain channel */
237 				data->cmd_config[channel].chainedNextCommandNumber =
238 					last_enabled + 1;
239 				LOG_DBG("Chaining channel %u to %u",
240 					channel, last_enabled);
241 			} else {
242 				/* End of chain */
243 				data->cmd_config[channel].chainedNextCommandNumber = 0;
244 			}
245 			last_enabled = channel;
246 			LPADC_SetConvCommandConfig(config->base,
247 				channel + 1, &data->cmd_config[channel]);
248 		}
249 	};
250 
251 	data->buffer = sequence->buffer;
252 
253 	adc_context_start_read(&data->ctx, sequence);
254 	int error = adc_context_wait_for_completion(&data->ctx);
255 
256 	return error;
257 }
258 
mcux_lpadc_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)259 static int mcux_lpadc_read_async(const struct device *dev,
260 			const struct adc_sequence *sequence,
261 			struct k_poll_signal *async)
262 {
263 	struct mcux_lpadc_data *data = dev->data;
264 	int error;
265 
266 	adc_context_lock(&data->ctx, async ? true : false, async);
267 	error = mcux_lpadc_start_read(dev, sequence);
268 	adc_context_release(&data->ctx, error);
269 
270 	return error;
271 }
272 
mcux_lpadc_read(const struct device * dev,const struct adc_sequence * sequence)273 static int mcux_lpadc_read(const struct device *dev,
274 		   const struct adc_sequence *sequence)
275 {
276 	return mcux_lpadc_read_async(dev, sequence, NULL);
277 }
278 
mcux_lpadc_start_channel(const struct device * dev)279 static void mcux_lpadc_start_channel(const struct device *dev)
280 {
281 	const struct mcux_lpadc_config *config = dev->config;
282 	struct mcux_lpadc_data *data = dev->data;
283 	lpadc_conv_trigger_config_t trigger_config;
284 	uint8_t first_channel;
285 
286 	first_channel = find_lsb_set(data->channels) - 1;
287 
288 	LOG_DBG("Starting channel %d, input %d", first_channel,
289 		data->cmd_config[first_channel].channelNumber);
290 
291 	LPADC_GetDefaultConvTriggerConfig(&trigger_config);
292 
293 	trigger_config.targetCommandId = first_channel + 1;
294 
295 	/* configures trigger0. */
296 	LPADC_SetConvTriggerConfig(config->base, 0, &trigger_config);
297 
298 	/* 1 is trigger0 mask. */
299 	LPADC_DoSoftwareTrigger(config->base, 1);
300 }
301 
adc_context_start_sampling(struct adc_context * ctx)302 static void adc_context_start_sampling(struct adc_context *ctx)
303 {
304 	struct mcux_lpadc_data *data =
305 	CONTAINER_OF(ctx, struct mcux_lpadc_data, ctx);
306 
307 	data->channels = ctx->sequence.channels;
308 	data->repeat_buffer = data->buffer;
309 
310 	mcux_lpadc_start_channel(data->dev);
311 }
312 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)313 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
314 			  bool repeat_sampling)
315 {
316 	struct mcux_lpadc_data *data =
317 		CONTAINER_OF(ctx, struct mcux_lpadc_data, ctx);
318 
319 	if (repeat_sampling) {
320 		data->buffer = data->repeat_buffer;
321 	}
322 }
323 
mcux_lpadc_isr(const struct device * dev)324 static void mcux_lpadc_isr(const struct device *dev)
325 {
326 	const struct mcux_lpadc_config *config = dev->config;
327 	struct mcux_lpadc_data *data = dev->data;
328 	ADC_Type *base = config->base;
329 
330 	lpadc_conv_result_t conv_result;
331 	lpadc_sample_channel_mode_t conv_mode;
332 	int16_t result;
333 	uint16_t channel;
334 
335 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) \
336 	&& (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
337 	LPADC_GetConvResult(base, &conv_result, 0U);
338 #else
339 	LPADC_GetConvResult(base, &conv_result);
340 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
341 
342 	channel = conv_result.commandIdSource - 1;
343 	LOG_DBG("Finished channel %d. Raw result is 0x%04x",
344 		channel, conv_result.convValue);
345 	/*
346 	 * For 12 or 13 bit resolution the the LSBs will be 0, so a bit shift
347 	 * is needed. For differential modes, the ADC conversion to
348 	 * millivolts expects to use a shift one less than the resolution.
349 	 *
350 	 * For 16 bit modes, the adc value can be left untouched. ADC
351 	 * API should treat the value as signed if the channel is
352 	 * in differential mode
353 	 */
354 	conv_mode = data->cmd_config[channel].sampleChannelMode;
355 	if (data->ctx.sequence.resolution < 15) {
356 		result = ((conv_result.convValue >> 3) & 0xFFF);
357 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF
358 		if (conv_mode == kLPADC_SampleChannelDiffBothSideAB ||
359 		    conv_mode == kLPADC_SampleChannelDiffBothSideBA) {
360 #else
361 		if (conv_mode == kLPADC_SampleChannelDiffBothSide) {
362 #endif
363 			if ((conv_result.convValue & 0x8000)) {
364 				/* 13 bit mode, MSB is sign bit. (2's complement) */
365 				result -= 0x1000;
366 			}
367 		}
368 		*data->buffer++ = result;
369 	} else {
370 		*data->buffer++ = conv_result.convValue;
371 	}
372 
373 
374 	data->channels &= ~BIT(channel);
375 
376 	/*
377 	 * Hardware will automatically continue sampling, so no need
378 	 * to issue new trigger
379 	 */
380 	if (data->channels == 0) {
381 		adc_context_on_sampling_done(&data->ctx, dev);
382 	}
383 }
384 
385 static int mcux_lpadc_init(const struct device *dev)
386 {
387 	const struct mcux_lpadc_config *config = dev->config;
388 	struct mcux_lpadc_data *data = dev->data;
389 	ADC_Type *base = config->base;
390 	lpadc_config_t adc_config;
391 	int err;
392 
393 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
394 	if (err) {
395 		return err;
396 	}
397 
398 	/* Enable necessary regulators */
399 	const struct device **regulator = config->ref_supplies;
400 
401 	while (*regulator != NULL) {
402 		err = regulator_enable(*(regulator++));
403 		if (err) {
404 			return err;
405 		}
406 	}
407 
408 	LPADC_GetDefaultConfig(&adc_config);
409 
410 	adc_config.enableAnalogPreliminary = true;
411 	adc_config.referenceVoltageSource = config->voltage_ref;
412 
413 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) \
414 	&& FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS
415 	adc_config.conversionAverageMode = config->calibration_average;
416 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */
417 
418 	adc_config.powerLevelMode = config->power_level;
419 
420 	LPADC_Init(base, &adc_config);
421 
422 	/* Do ADC calibration. */
423 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) \
424 	&& FSL_FEATURE_LPADC_HAS_CTRL_CALOFS
425 #if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) \
426 	&& FSL_FEATURE_LPADC_HAS_OFSTRIM
427 	/* Request offset calibration. */
428 #if defined(CONFIG_LPADC_DO_OFFSET_CALIBRATION) \
429 	&& CONFIG_LPADC_DO_OFFSET_CALIBRATION
430 	LPADC_DoOffsetCalibration(base);
431 #else
432 	LPADC_SetOffsetValue(base,
433 			config->offset_a,
434 			config->offset_b);
435 #endif  /* DEMO_LPADC_DO_OFFSET_CALIBRATION */
436 #endif  /* FSL_FEATURE_LPADC_HAS_OFSTRIM */
437 	/* Request gain calibration. */
438 	LPADC_DoAutoCalibration(base);
439 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */
440 
441 #if (defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) \
442 	&& FSL_FEATURE_LPADC_HAS_CFG_CALOFS)
443 	/* Do auto calibration. */
444 	LPADC_DoAutoCalibration(base);
445 #endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */
446 
447 /* Enable the watermark interrupt. */
448 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) \
449 	&& (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
450 	LPADC_EnableInterrupts(base, kLPADC_FIFO0WatermarkInterruptEnable);
451 #else
452 	LPADC_EnableInterrupts(base, kLPADC_FIFOWatermarkInterruptEnable);
453 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
454 
455 	config->irq_config_func(dev);
456 	data->dev = dev;
457 
458 	adc_context_unlock_unconditionally(&data->ctx);
459 
460 	return 0;
461 }
462 
463 static const struct adc_driver_api mcux_lpadc_driver_api = {
464 	.channel_setup = mcux_lpadc_channel_setup,
465 	.read = mcux_lpadc_read,
466 #ifdef CONFIG_ADC_ASYNC
467 	.read_async = mcux_lpadc_read_async,
468 #endif
469 };
470 
471 #define LPADC_REGULATOR_DEPENDENCY(node_id, prop, idx) \
472 	DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)),
473 
474 #define LPADC_REGULATORS_DEFINE(inst)				\
475 	static const struct device *mcux_lpadc_ref_supplies_##inst[] = {	\
476 		COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, nxp_reference_supply),	\
477 			(DT_INST_FOREACH_PROP_ELEM(inst, nxp_reference_supply,	\
478 				LPADC_REGULATOR_DEPENDENCY)), ()) NULL};
479 
480 #define LPADC_MCUX_INIT(n)						\
481 	LPADC_REGULATORS_DEFINE(n)						\
482 									\
483 	static void mcux_lpadc_config_func_##n(const struct device *dev);	\
484 									\
485 	PINCTRL_DT_INST_DEFINE(n);						\
486 	static const struct mcux_lpadc_config mcux_lpadc_config_##n = {	\
487 		.base = (ADC_Type *)DT_INST_REG_ADDR(n),	\
488 		.voltage_ref =	DT_INST_PROP(n, voltage_ref),	\
489 		.calibration_average = DT_INST_ENUM_IDX_OR(n, calibration_average, 0),	\
490 		.power_level = DT_INST_PROP(n, power_level),	\
491 		.offset_a = DT_INST_PROP(n, offset_value_a),	\
492 		.offset_b = DT_INST_PROP(n, offset_value_b),	\
493 		.irq_config_func = mcux_lpadc_config_func_##n,				\
494 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),			\
495 		.ref_supplies = mcux_lpadc_ref_supplies_##n, \
496 	};									\
497 	static struct mcux_lpadc_data mcux_lpadc_data_##n = {	\
498 		ADC_CONTEXT_INIT_TIMER(mcux_lpadc_data_##n, ctx),	\
499 		ADC_CONTEXT_INIT_LOCK(mcux_lpadc_data_##n, ctx),	\
500 		ADC_CONTEXT_INIT_SYNC(mcux_lpadc_data_##n, ctx),	\
501 	};														\
502 										\
503 	DEVICE_DT_INST_DEFINE(n,						\
504 		&mcux_lpadc_init, NULL, &mcux_lpadc_data_##n,			\
505 		&mcux_lpadc_config_##n, POST_KERNEL,				\
506 		CONFIG_ADC_INIT_PRIORITY,					\
507 		&mcux_lpadc_driver_api);							\
508 										\
509 	static void mcux_lpadc_config_func_##n(const struct device *dev)	\
510 	{									\
511 		IRQ_CONNECT(DT_INST_IRQN(n),					\
512 			DT_INST_IRQ(n, priority), mcux_lpadc_isr,	\
513 			DEVICE_DT_INST_GET(n), 0);				\
514 										\
515 		irq_enable(DT_INST_IRQN(n));					\
516 	}
517 
518 DT_INST_FOREACH_STATUS_OKAY(LPADC_MCUX_INIT)
519