1 /*
2  * Copyright (c) 2020 Vestas Wind Systems A/S
3  * Copyright 2022, 2024 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT nxp_kinetis_acmp
9 
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/sensor.h>
12 #include <zephyr/drivers/sensor/mcux_acmp.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/kernel.h>
15 #include <fsl_acmp.h>
16 #include <zephyr/drivers/pinctrl.h>
17 #include <zephyr/irq.h>
18 
19 LOG_MODULE_REGISTER(mcux_acmp, CONFIG_SENSOR_LOG_LEVEL);
20 
21 #define MCUX_ACMP_DAC_LEVELS 256
22 #define MCUX_ACMP_INPUT_CHANNELS 8
23 
24 /*
25  * Ensure the underlying MCUX definitions match the driver shim
26  * assumptions. This saves us from converting between integers and
27  * MCUX enumerations for sensor attributes.
28  */
29 #if MCUX_ACMP_HAS_OFFSET
30 BUILD_ASSERT(kACMP_OffsetLevel0 == 0);
31 BUILD_ASSERT(kACMP_OffsetLevel1 == 1);
32 #endif /* MCUX_ACMP_HAS_OFFSET */
33 BUILD_ASSERT(kACMP_HysteresisLevel0 == 0);
34 BUILD_ASSERT(kACMP_HysteresisLevel1 == 1);
35 BUILD_ASSERT(kACMP_HysteresisLevel2 == 2);
36 BUILD_ASSERT(kACMP_HysteresisLevel3 == 3);
37 BUILD_ASSERT(kACMP_VrefSourceVin1 == 0);
38 BUILD_ASSERT(kACMP_VrefSourceVin2 == 1);
39 #if MCUX_ACMP_HAS_INPSEL || MCUX_ACMP_HAS_INNSEL
40 BUILD_ASSERT(kACMP_PortInputFromDAC == 0);
41 BUILD_ASSERT(kACMP_PortInputFromMux == 1);
42 #endif /* MCUX_ACMP_HAS_INPSEL || MCUX_ACMP_HAS_INNSEL */
43 
44 /*
45  * prop New property name
46  * depr Deprecated property name
47  */
48 #define MCUX_ACMP_DT_INST_PROP(inst, prop, depr)						\
49 	COND_CODE_1(										\
50 		DT_INST_NODE_HAS_PROP(inst, prop),						\
51 		(DT_INST_PROP(inst, prop)),							\
52 		(DT_INST_PROP(inst, depr))							\
53 	)
54 
55 /*
56  * prop New property name
57  * depr Deprecated property name
58  */
59 #define MCUX_ACMP_DT_INST_PROP_OR(inst, prop, depr, default_value)				\
60 	COND_CODE_1(										\
61 		DT_INST_NODE_HAS_PROP(inst, prop) || DT_INST_NODE_HAS_PROP(inst, depr),		\
62 		(MCUX_ACMP_DT_INST_PROP(inst, prop, depr)),					\
63 		(default_value)									\
64 	)
65 
66 #define MCUX_ACMP_DT_INST_ENABLE_SAMPLE(inst) \
67 	MCUX_ACMP_DT_INST_PROP(inst, filter_enable_sample, nxp_enable_sample)
68 
69 #define MCUX_ACMP_DT_INST_FILTER_COUNT(inst) \
70 	MCUX_ACMP_DT_INST_PROP_OR(inst, filter_count, nxp_filter_count, 0)
71 
72 #define MCUX_ACMP_DT_INST_FILTER_PERIOD(inst) \
73 	MCUX_ACMP_DT_INST_PROP_OR(inst, filter_period, nxp_filter_period, 0)
74 
75 #define MCUX_ACMP_DT_INST_HIGH_SPEED(inst) \
76 	MCUX_ACMP_DT_INST_PROP(inst, enable_high_speed_mode, nxp_high_speed_mode)
77 
78 #define MCUX_ACMP_DT_INST_USE_UNFILTERED_MODE(inst) \
79 	MCUX_ACMP_DT_INST_PROP(inst, use_unfiltered_output, nxp_use_unfiltered_output)
80 
81 #define MCUX_ACMP_DT_INST_USE_ENABLE_PIN_OUT(inst) \
82 	MCUX_ACMP_DT_INST_PROP(inst, enable_pin_out, nxp_enable_output_pin)
83 
84 #define MCUX_ACMP_DT_INST_ENABLE_WINDOW_MODE(inst) \
85 	MCUX_ACMP_DT_INST_PROP(inst, enable_window_mode, nxp_window_mode)
86 
87 struct mcux_acmp_config {
88 	CMP_Type *base;
89 	acmp_filter_config_t filter;
90 	const struct pinctrl_dev_config *pincfg;
91 #ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER
92 	void (*irq_config_func)(const struct device *dev);
93 #endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */
94 	bool high_speed : 1;
95 	bool unfiltered : 1;
96 	bool output : 1;
97 	bool window : 1;
98 };
99 
100 struct mcux_acmp_data {
101 	acmp_config_t config;
102 	acmp_channel_config_t channels;
103 	acmp_dac_config_t dac;
104 #if MCUX_ACMP_HAS_DISCRETE_MODE
105 	acmp_discrete_mode_config_t discrete_config;
106 #endif
107 #ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER
108 	const struct device *dev;
109 	sensor_trigger_handler_t rising_handler;
110 	const struct sensor_trigger *rising_trigger;
111 	sensor_trigger_handler_t falling_handler;
112 	const struct sensor_trigger *falling_trigger;
113 	struct k_work work;
114 	volatile uint32_t status;
115 #endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */
116 	bool cout;
117 };
118 
mcux_acmp_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)119 static int mcux_acmp_attr_set(const struct device *dev,
120 			      enum sensor_channel chan,
121 			      enum sensor_attribute attr,
122 			      const struct sensor_value *val)
123 {
124 	const struct mcux_acmp_config *config = dev->config;
125 	struct mcux_acmp_data *data = dev->data;
126 	int32_t val1;
127 
128 	__ASSERT_NO_MSG(val != NULL);
129 
130 	if ((int16_t)chan != SENSOR_CHAN_MCUX_ACMP_OUTPUT) {
131 		return -ENOTSUP;
132 	}
133 
134 	if (val->val2 != 0) {
135 		return -EINVAL;
136 	}
137 	val1 = val->val1;
138 
139 	switch ((int16_t)attr) {
140 #if MCUX_ACMP_HAS_OFFSET
141 	case SENSOR_ATTR_MCUX_ACMP_OFFSET_LEVEL:
142 		if (val1 >= kACMP_OffsetLevel0 &&
143 		    val1 <= kACMP_OffsetLevel1) {
144 			LOG_DBG("offset = %d", val1);
145 			data->config.offsetMode = val1;
146 			ACMP_Init(config->base, &data->config);
147 			ACMP_Enable(config->base, true);
148 		} else {
149 			return -EINVAL;
150 		}
151 		break;
152 #endif /* MCUX_ACMP_HAS_OFFSET */
153 #if MCUX_ACMP_HAS_HYSTCTR
154 	case SENSOR_ATTR_MCUX_ACMP_HYSTERESIS_LEVEL:
155 		if (val1 >= kACMP_HysteresisLevel0 &&
156 		    val1 <= kACMP_HysteresisLevel3) {
157 			LOG_DBG("hysteresis = %d", val1);
158 			data->config.hysteresisMode = val1;
159 			ACMP_Init(config->base, &data->config);
160 			ACMP_Enable(config->base, true);
161 		} else {
162 			return -EINVAL;
163 		}
164 		break;
165 #endif /* MCUX_ACMP_HAS_HYSTCTR */
166 	case SENSOR_ATTR_MCUX_ACMP_DAC_VOLTAGE_REFERENCE:
167 		if (val1 >= kACMP_VrefSourceVin1 &&
168 		    val1 <= kACMP_VrefSourceVin2) {
169 			LOG_DBG("vref = %d", val1);
170 			data->dac.referenceVoltageSource = val1;
171 			ACMP_SetDACConfig(config->base, &data->dac);
172 		} else {
173 			return -EINVAL;
174 		}
175 		break;
176 	case SENSOR_ATTR_MCUX_ACMP_DAC_VALUE:
177 		if (val1 >= 0 && val1 < MCUX_ACMP_DAC_LEVELS) {
178 			LOG_DBG("dac = %d", val1);
179 			data->dac.DACValue = val1;
180 			ACMP_SetDACConfig(config->base, &data->dac);
181 		} else {
182 			return -EINVAL;
183 		}
184 		break;
185 #if MCUX_ACMP_HAS_INPSEL
186 	case SENSOR_ATTR_MCUX_ACMP_POSITIVE_PORT_INPUT:
187 		if (val1 >= kACMP_PortInputFromDAC &&
188 		    val1 <= kACMP_PortInputFromMux) {
189 			LOG_DBG("pport = %d", val1);
190 			data->channels.positivePortInput = val1;
191 			ACMP_SetChannelConfig(config->base, &data->channels);
192 		} else {
193 			return -EINVAL;
194 		}
195 		break;
196 #endif /* MCUX_ACMP_HAS_INPSEL */
197 	case SENSOR_ATTR_MCUX_ACMP_POSITIVE_MUX_INPUT:
198 		if (val1 >= 0 && val1 < MCUX_ACMP_INPUT_CHANNELS) {
199 			LOG_DBG("pmux = %d", val1);
200 			data->channels.plusMuxInput = val1;
201 			ACMP_SetChannelConfig(config->base, &data->channels);
202 		} else {
203 			return -EINVAL;
204 		}
205 		break;
206 #if MCUX_ACMP_HAS_INNSEL
207 	case SENSOR_ATTR_MCUX_ACMP_NEGATIVE_PORT_INPUT:
208 		if (val1 >= kACMP_PortInputFromDAC &&
209 		    val1 <= kACMP_PortInputFromMux) {
210 			LOG_DBG("nport = %d", val1);
211 			data->channels.negativePortInput = val1;
212 			ACMP_SetChannelConfig(config->base, &data->channels);
213 		} else {
214 			return -EINVAL;
215 		}
216 		break;
217 #endif /* MCUX_ACMP_HAS_INNSEL */
218 	case SENSOR_ATTR_MCUX_ACMP_NEGATIVE_MUX_INPUT:
219 		if (val1 >= 0 && val1 < MCUX_ACMP_INPUT_CHANNELS) {
220 			LOG_DBG("nmux = %d", val1);
221 			data->channels.minusMuxInput = val1;
222 			ACMP_SetChannelConfig(config->base, &data->channels);
223 		} else {
224 			return -EINVAL;
225 		}
226 		break;
227 #if MCUX_ACMP_HAS_DISCRETE_MODE
228 	case SENSOR_ATTR_MCUX_ACMP_POSITIVE_DISCRETE_MODE:
229 		if (val1 <= 1 && val1 >= 0) {
230 			LOG_DBG("pdiscrete = %d", val1);
231 			data->discrete_config.enablePositiveChannelDiscreteMode = val1;
232 			ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
233 		} else {
234 			return -EINVAL;
235 		}
236 		break;
237 	case SENSOR_ATTR_MCUX_ACMP_NEGATIVE_DISCRETE_MODE:
238 		if (val1 <= 1 && val1 >= 0) {
239 			LOG_DBG("ndiscrete = %d", val1);
240 			data->discrete_config.enableNegativeChannelDiscreteMode = val1;
241 			ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
242 		} else {
243 			return -EINVAL;
244 		}
245 		break;
246 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_CLOCK:
247 		if (val1 <= kACMP_DiscreteClockFast && val1 >= kACMP_DiscreteClockSlow) {
248 			LOG_DBG("discreteClk = %d", val1);
249 			data->discrete_config.clockSource = val1;
250 			ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
251 		} else {
252 			return -EINVAL;
253 		}
254 		break;
255 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_ENABLE_RESISTOR_DIVIDER:
256 		if (val1 <= 1 && val1 >= 0) {
257 			LOG_DBG("discreteClk = %d", val1);
258 			data->discrete_config.enableResistorDivider = val1;
259 			ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
260 		} else {
261 			return -EINVAL;
262 		}
263 		break;
264 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_SAMPLE_TIME:
265 		if (val1 <= kACMP_DiscreteSampleTimeAs256T &&
266 		    val1 >= kACMP_DiscreteSampleTimeAs1T) {
267 			LOG_DBG("discrete sampleTime = %d", val1);
268 			data->discrete_config.sampleTime = val1;
269 			ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
270 		} else {
271 			return -EINVAL;
272 		}
273 		break;
274 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_PHASE1_TIME:
275 		if (val1 <= kACMP_DiscretePhaseTimeAlt7 && val1 >= kACMP_DiscretePhaseTimeAlt0) {
276 			LOG_DBG("discrete phase1Time = %d", val1);
277 			data->discrete_config.phase1Time = val1;
278 			ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
279 		} else {
280 			return -EINVAL;
281 		}
282 		break;
283 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_PHASE2_TIME:
284 		if (val1 <= kACMP_DiscretePhaseTimeAlt7 && val1 >= kACMP_DiscretePhaseTimeAlt0) {
285 			LOG_DBG("discrete phase2Time = %d", val1);
286 			data->discrete_config.phase2Time = val1;
287 			ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
288 		} else {
289 			return -EINVAL;
290 		}
291 		break;
292 #endif /* MCUX_ACMP_HAS_DISCRETE_MODE */
293 	default:
294 		return -ENOTSUP;
295 	}
296 
297 	return 0;
298 }
299 
mcux_acmp_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)300 static int mcux_acmp_attr_get(const struct device *dev,
301 			      enum sensor_channel chan,
302 			      enum sensor_attribute attr,
303 			      struct sensor_value *val)
304 {
305 	struct mcux_acmp_data *data = dev->data;
306 
307 	__ASSERT_NO_MSG(val != NULL);
308 
309 	if ((int16_t)chan != SENSOR_CHAN_MCUX_ACMP_OUTPUT) {
310 		return -ENOTSUP;
311 	}
312 
313 	switch ((int16_t)attr) {
314 #if MCUX_ACMP_HAS_OFFSET
315 	case SENSOR_ATTR_MCUX_ACMP_OFFSET_LEVEL:
316 		val->val1 = data->config.offsetMode;
317 		break;
318 #endif /* MCUX_ACMP_HAS_OFFSET */
319 #if MCUX_ACMP_HAS_HYSTCTR
320 	case SENSOR_ATTR_MCUX_ACMP_HYSTERESIS_LEVEL:
321 		val->val1 = data->config.hysteresisMode;
322 		break;
323 #endif /* MCUX_ACMP_HAS_HYSTCTR */
324 	case SENSOR_ATTR_MCUX_ACMP_DAC_VOLTAGE_REFERENCE:
325 		val->val1 = data->dac.referenceVoltageSource;
326 		break;
327 	case SENSOR_ATTR_MCUX_ACMP_DAC_VALUE:
328 		val->val1 = data->dac.DACValue;
329 		break;
330 #if MCUX_ACMP_HAS_INPSEL
331 	case SENSOR_ATTR_MCUX_ACMP_POSITIVE_PORT_INPUT:
332 		val->val1 = data->channels.positivePortInput;
333 		break;
334 #endif /* MCUX_ACMP_HAS_INPSEL */
335 	case SENSOR_ATTR_MCUX_ACMP_POSITIVE_MUX_INPUT:
336 		val->val1 = data->channels.plusMuxInput;
337 		break;
338 #if MCUX_ACMP_HAS_INNSEL
339 	case SENSOR_ATTR_MCUX_ACMP_NEGATIVE_PORT_INPUT:
340 		val->val1 = data->channels.negativePortInput;
341 		break;
342 #endif /* MCUX_ACMP_HAS_INNSEL */
343 	case SENSOR_ATTR_MCUX_ACMP_NEGATIVE_MUX_INPUT:
344 		val->val1 = data->channels.minusMuxInput;
345 		break;
346 #if MCUX_ACMP_HAS_DISCRETE_MODE
347 	case SENSOR_ATTR_MCUX_ACMP_POSITIVE_DISCRETE_MODE:
348 		val->val1 = data->discrete_config.enablePositiveChannelDiscreteMode;
349 		break;
350 	case SENSOR_ATTR_MCUX_ACMP_NEGATIVE_DISCRETE_MODE:
351 		val->val1 = data->discrete_config.enableNegativeChannelDiscreteMode;
352 		break;
353 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_CLOCK:
354 		val->val1 = data->discrete_config.clockSource;
355 		break;
356 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_ENABLE_RESISTOR_DIVIDER:
357 		val->val1 = data->discrete_config.enableResistorDivider;
358 		break;
359 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_SAMPLE_TIME:
360 		val->val1 = data->discrete_config.sampleTime;
361 		break;
362 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_PHASE1_TIME:
363 		val->val1 = data->discrete_config.phase1Time;
364 		break;
365 	case SENSOR_ATTR_MCUX_ACMP_DISCRETE_PHASE2_TIME:
366 		val->val1 = data->discrete_config.phase2Time;
367 		break;
368 #endif /* MCUX_ACMP_HAS_DISCRETE_MODE */
369 	default:
370 		return -ENOTSUP;
371 	}
372 
373 	val->val2 = 0;
374 
375 	return 0;
376 }
377 
mcux_acmp_sample_fetch(const struct device * dev,enum sensor_channel chan)378 static int mcux_acmp_sample_fetch(const struct device *dev,
379 				     enum sensor_channel chan)
380 {
381 	const struct mcux_acmp_config *config = dev->config;
382 	struct mcux_acmp_data *data = dev->data;
383 	uint32_t status;
384 
385 	__ASSERT_NO_MSG(val != NULL);
386 
387 	if (chan != SENSOR_CHAN_ALL &&
388 	    (int16_t)chan != SENSOR_CHAN_MCUX_ACMP_OUTPUT) {
389 		return -ENOTSUP;
390 	}
391 
392 	status = ACMP_GetStatusFlags(config->base);
393 	data->cout = status & kACMP_OutputAssertEventFlag;
394 
395 	return 0;
396 }
397 
mcux_acmp_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)398 static int mcux_acmp_channel_get(const struct device *dev,
399 				    enum sensor_channel chan,
400 				    struct sensor_value *val)
401 {
402 	struct mcux_acmp_data *data = dev->data;
403 
404 	__ASSERT_NO_MSG(val != NULL);
405 
406 	if ((int16_t)chan != SENSOR_CHAN_MCUX_ACMP_OUTPUT) {
407 		return -ENOTSUP;
408 	}
409 
410 	val->val1 = data->cout ? 1 : 0;
411 	val->val2 = 0;
412 
413 	return 0;
414 }
415 
416 #ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER
mcux_acmp_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)417 static int mcux_acmp_trigger_set(const struct device *dev,
418 				 const struct sensor_trigger *trig,
419 				 sensor_trigger_handler_t handler)
420 {
421 	struct mcux_acmp_data *data = dev->data;
422 
423 	__ASSERT_NO_MSG(trig != NULL);
424 
425 	if ((int16_t)trig->chan != SENSOR_CHAN_MCUX_ACMP_OUTPUT) {
426 		return -ENOTSUP;
427 	}
428 
429 	switch ((int16_t)trig->type) {
430 	case SENSOR_TRIG_MCUX_ACMP_OUTPUT_RISING:
431 		data->rising_handler = handler;
432 		data->rising_trigger = trig;
433 		break;
434 	case SENSOR_TRIG_MCUX_ACMP_OUTPUT_FALLING:
435 		data->falling_handler = handler;
436 		data->falling_trigger = trig;
437 		break;
438 	default:
439 		return -ENOTSUP;
440 	}
441 
442 	return 0;
443 }
444 
mcux_acmp_trigger_work_handler(struct k_work * item)445 static void mcux_acmp_trigger_work_handler(struct k_work *item)
446 {
447 	const struct sensor_trigger *trigger;
448 	struct mcux_acmp_data *data =
449 		CONTAINER_OF(item, struct mcux_acmp_data, work);
450 	sensor_trigger_handler_t handler = NULL;
451 
452 	if (data->status & kACMP_OutputRisingEventFlag) {
453 		handler = data->rising_handler;
454 		trigger = data->rising_trigger;
455 	} else if (data->status & kACMP_OutputFallingEventFlag) {
456 		handler = data->falling_handler;
457 		trigger = data->falling_trigger;
458 	}
459 
460 	if (handler) {
461 		handler(data->dev, trigger);
462 	}
463 }
464 
mcux_acmp_isr(const struct device * dev)465 static void mcux_acmp_isr(const struct device *dev)
466 {
467 	const struct mcux_acmp_config *config = dev->config;
468 	struct mcux_acmp_data *data = dev->data;
469 
470 	data->status = ACMP_GetStatusFlags(config->base);
471 	ACMP_ClearStatusFlags(config->base, data->status);
472 
473 	LOG_DBG("isr status = 0x%08x", data->status);
474 
475 	k_work_submit(&data->work);
476 }
477 #endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */
478 
mcux_acmp_init(const struct device * dev)479 static int mcux_acmp_init(const struct device *dev)
480 {
481 	const struct mcux_acmp_config *config = dev->config;
482 	struct mcux_acmp_data *data = dev->data;
483 	int err;
484 
485 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
486 	if (err) {
487 		return err;
488 	}
489 
490 	ACMP_GetDefaultConfig(&data->config);
491 	data->config.enableHighSpeed = config->high_speed;
492 	data->config.useUnfilteredOutput = config->unfiltered;
493 	data->config.enablePinOut = config->output;
494 	ACMP_Init(config->base, &data->config);
495 
496 #if MCUX_ACMP_HAS_DISCRETE_MODE
497 	ACMP_GetDefaultDiscreteModeConfig(&data->discrete_config);
498 	ACMP_SetDiscreteModeConfig(config->base, &data->discrete_config);
499 #endif
500 
501 	ACMP_EnableWindowMode(config->base, config->window);
502 	ACMP_SetFilterConfig(config->base, &config->filter);
503 	ACMP_SetChannelConfig(config->base, &data->channels);
504 
505 	/* Disable DAC */
506 	ACMP_SetDACConfig(config->base, NULL);
507 
508 #ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER
509 	data->dev = dev;
510 	k_work_init(&data->work, mcux_acmp_trigger_work_handler);
511 
512 	config->irq_config_func(dev);
513 	ACMP_EnableInterrupts(config->base,
514 			      kACMP_OutputRisingInterruptEnable |
515 			      kACMP_OutputFallingInterruptEnable);
516 #endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */
517 
518 	ACMP_Enable(config->base, true);
519 
520 	return 0;
521 }
522 
523 static DEVICE_API(sensor, mcux_acmp_driver_api) = {
524 	.attr_set = mcux_acmp_attr_set,
525 	.attr_get = mcux_acmp_attr_get,
526 #ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER
527 	.trigger_set = mcux_acmp_trigger_set,
528 #endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */
529 	.sample_fetch = mcux_acmp_sample_fetch,
530 	.channel_get = mcux_acmp_channel_get,
531 };
532 
533 #define MCUX_ACMP_DECLARE_CONFIG(n, config_func_init)			\
534 static const struct mcux_acmp_config mcux_acmp_config_##n = {		\
535 	.base = (CMP_Type *)DT_INST_REG_ADDR(n),			\
536 	.filter = {							\
537 		.enableSample = MCUX_ACMP_DT_INST_ENABLE_SAMPLE(n),	\
538 		.filterCount = MCUX_ACMP_DT_INST_FILTER_COUNT(n),	\
539 		.filterPeriod = MCUX_ACMP_DT_INST_FILTER_PERIOD(n),	\
540 	},								\
541 	.high_speed = MCUX_ACMP_DT_INST_HIGH_SPEED(n),			\
542 	.unfiltered = MCUX_ACMP_DT_INST_USE_UNFILTERED_MODE(n),		\
543 	.output = MCUX_ACMP_DT_INST_USE_ENABLE_PIN_OUT(n),		\
544 	.window = MCUX_ACMP_DT_INST_ENABLE_WINDOW_MODE(n),		\
545 	.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),			\
546 	config_func_init						\
547 }
548 
549 #ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER
550 #define MCUX_ACMP_CONFIG_FUNC(n)					\
551 	static void mcux_acmp_config_func_##n(const struct device *dev) \
552 	{								\
553 		IRQ_CONNECT(DT_INST_IRQN(n),				\
554 			    DT_INST_IRQ(n, priority),			\
555 			    mcux_acmp_isr,				\
556 			    DEVICE_DT_INST_GET(n), 0);			\
557 		irq_enable(DT_INST_IRQN(n));				\
558 	}
559 #define MCUX_ACMP_CONFIG_FUNC_INIT(n)					\
560 	.irq_config_func = mcux_acmp_config_func_##n
561 #define MCUX_ACMP_INIT_CONFIG(n)					\
562 	MCUX_ACMP_DECLARE_CONFIG(n, MCUX_ACMP_CONFIG_FUNC_INIT(n))
563 #else /* !CONFIG_SENSOR_MCUX_ACMP_TRIGGER */
564 #define MCUX_ACMP_CONFIG_FUNC(n)
565 #define MCUX_ACMP_CONFIG_FUNC_INIT
566 #define MCUX_ACMP_INIT_CONFIG(n)					\
567 	MCUX_ACMP_DECLARE_CONFIG(n, MCUX_ACMP_CONFIG_FUNC_INIT)
568 #endif /* !CONFIG_SENSOR_MCUX_ACMP_TRIGGER */
569 
570 #define MCUX_ACMP_INIT(n)						\
571 	static struct mcux_acmp_data mcux_acmp_data_##n;		\
572 									\
573 	static const struct mcux_acmp_config mcux_acmp_config_##n;	\
574 									\
575 	PINCTRL_DT_INST_DEFINE(n);					\
576 									\
577 	SENSOR_DEVICE_DT_INST_DEFINE(n, &mcux_acmp_init,		\
578 			      NULL,					\
579 			      &mcux_acmp_data_##n,			\
580 			      &mcux_acmp_config_##n, POST_KERNEL,	\
581 			      CONFIG_SENSOR_INIT_PRIORITY,		\
582 			      &mcux_acmp_driver_api);			\
583 	MCUX_ACMP_CONFIG_FUNC(n)					\
584 	MCUX_ACMP_INIT_CONFIG(n);
585 
586 DT_INST_FOREACH_STATUS_OKAY(MCUX_ACMP_INIT)
587