1 /*
2  * Copyright 2022-2023 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_s32_gpio
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/gpio/gpio_utils.h>
12 #include <zephyr/dt-bindings/gpio/nxp-s32-gpio.h>
13 #include <zephyr/logging/log.h>
14 
15 #include <Siul2_Port_Ip.h>
16 #include <Siul2_Dio_Ip.h>
17 
18 LOG_MODULE_REGISTER(nxp_s32_gpio, CONFIG_GPIO_LOG_LEVEL);
19 
20 #ifdef CONFIG_NXP_S32_EIRQ
21 #include <zephyr/drivers/interrupt_controller/intc_eirq_nxp_s32.h>
22 #endif
23 #ifdef CONFIG_NXP_S32_WKPU
24 #include <zephyr/drivers/interrupt_controller/intc_wkpu_nxp_s32.h>
25 #endif
26 
27 #if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU)
28 #define NXP_S32_GPIO_LINE_NOT_FOUND 0xff
29 
30 struct gpio_nxp_s32_irq_map {
31 	uint8_t pin;
32 	uint8_t line;
33 } __packed;
34 
35 struct gpio_nxp_s32_irq_config {
36 	const struct device *ctrl;
37 	uint8_t map_cnt;
38 	struct gpio_nxp_s32_irq_map *map;
39 };
40 #endif
41 
42 struct gpio_nxp_s32_config {
43 	/* gpio_driver_config needs to be first */
44 	struct gpio_driver_config common;
45 
46 	Siul2_Dio_Ip_GpioType *gpio_base;
47 	Siul2_Port_Ip_PortType *port_base;
48 
49 #ifdef CONFIG_NXP_S32_EIRQ
50 	struct gpio_nxp_s32_irq_config *eirq_info;
51 #endif
52 #ifdef CONFIG_NXP_S32_WKPU
53 	struct gpio_nxp_s32_irq_config *wkpu_info;
54 #endif
55 };
56 
57 struct gpio_nxp_s32_data {
58 	/* gpio_driver_data needs to be first */
59 	struct gpio_driver_data common;
60 
61 #if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU)
62 	sys_slist_t callbacks;
63 #if defined(CONFIG_NXP_S32_WKPU)
64 	uint32_t pin_wkpu_mask;
65 #endif /* defined(CONFIG_NXP_S32_WKPU) */
66 #endif
67 };
68 
nxp_s32_gpio_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)69 static int nxp_s32_gpio_configure(const struct device *dev, gpio_pin_t pin,
70 				  gpio_flags_t flags)
71 {
72 	const struct gpio_nxp_s32_config *port_config = dev->config;
73 	Siul2_Dio_Ip_GpioType *gpio_base = port_config->gpio_base;
74 	Siul2_Port_Ip_PortType *port_base = port_config->port_base;
75 	Siul2_Port_Ip_PortPullConfig pull_config;
76 
77 	if ((flags & GPIO_SINGLE_ENDED) != 0) {
78 		return -ENOTSUP;
79 	}
80 
81 #if defined(CONFIG_NXP_S32_WKPU)
82 	struct gpio_nxp_s32_data *data = dev->data;
83 
84 	WRITE_BIT(data->pin_wkpu_mask, pin, (flags & NXP_S32_GPIO_INT_WKPU));
85 #else
86 	if (flags & NXP_S32_GPIO_INT_WKPU) {
87 		return -ENOTSUP;
88 	}
89 #endif
90 
91 	switch (flags & GPIO_DIR_MASK) {
92 	case GPIO_INPUT:
93 		Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_IN);
94 		break;
95 	case GPIO_OUTPUT:
96 		Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_OUT);
97 		break;
98 	case GPIO_INPUT | GPIO_OUTPUT:
99 		Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_IN_OUT);
100 		break;
101 	default:
102 		Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_HI_Z);
103 		break;
104 	}
105 
106 	Siul2_Port_Ip_SetOutputBuffer(port_base, pin,
107 					(flags & GPIO_OUTPUT), PORT_MUX_AS_GPIO);
108 
109 	switch (flags & (GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH | GPIO_OUTPUT_INIT_LOW)) {
110 	case GPIO_OUTPUT_HIGH:
111 		Siul2_Dio_Ip_WritePin(gpio_base, pin, 1);
112 		break;
113 	case GPIO_OUTPUT_LOW:
114 		Siul2_Dio_Ip_WritePin(gpio_base, pin, 0);
115 		break;
116 	default:
117 		break;
118 	}
119 
120 	if ((flags & GPIO_PULL_UP) != 0) {
121 		pull_config = PORT_INTERNAL_PULL_UP_ENABLED;
122 	} else if ((flags & GPIO_PULL_DOWN) != 0) {
123 		pull_config = PORT_INTERNAL_PULL_DOWN_ENABLED;
124 	} else {
125 		pull_config = PORT_INTERNAL_PULL_NOT_ENABLED;
126 	}
127 	Siul2_Port_Ip_SetPullSel(port_base, pin, pull_config);
128 
129 	return 0;
130 }
131 
nxp_s32_gpio_port_get_raw(const struct device * port,uint32_t * value)132 static int nxp_s32_gpio_port_get_raw(const struct device *port, uint32_t *value)
133 {
134 	const struct gpio_nxp_s32_config *config = port->config;
135 
136 	*value = Siul2_Dio_Ip_ReadPins(config->gpio_base);
137 
138 	return 0;
139 }
140 
nxp_s32_gpio_port_set_masked_raw(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t value)141 static int nxp_s32_gpio_port_set_masked_raw(const struct device *port,
142 					    gpio_port_pins_t mask,
143 					    gpio_port_value_t value)
144 {
145 	const struct gpio_nxp_s32_config *config = port->config;
146 	Siul2_Dio_Ip_GpioType *gpio_base = config->gpio_base;
147 	gpio_port_pins_t pins_value = Siul2_Dio_Ip_GetPinsOutput(gpio_base);
148 
149 	pins_value = (pins_value & ~mask) | (mask & value);
150 	Siul2_Dio_Ip_WritePins(gpio_base, pins_value);
151 
152 	return 0;
153 }
154 
nxp_s32_gpio_port_set_bits_raw(const struct device * port,gpio_port_pins_t pins)155 static int nxp_s32_gpio_port_set_bits_raw(const struct device *port,
156 					  gpio_port_pins_t pins)
157 {
158 	const struct gpio_nxp_s32_config *config = port->config;
159 
160 	Siul2_Dio_Ip_SetPins(config->gpio_base, pins);
161 
162 	return 0;
163 }
164 
nxp_s32_gpio_port_clear_bits_raw(const struct device * port,gpio_port_pins_t pins)165 static int nxp_s32_gpio_port_clear_bits_raw(const struct device *port,
166 					    gpio_port_pins_t pins)
167 {
168 	const struct gpio_nxp_s32_config *config = port->config;
169 
170 	Siul2_Dio_Ip_ClearPins(config->gpio_base, pins);
171 
172 	return 0;
173 }
174 
nxp_s32_gpio_port_toggle_bits(const struct device * port,gpio_port_pins_t pins)175 static int nxp_s32_gpio_port_toggle_bits(const struct device *port,
176 					 gpio_port_pins_t pins)
177 {
178 	const struct gpio_nxp_s32_config *config = port->config;
179 
180 	Siul2_Dio_Ip_TogglePins(config->gpio_base, pins);
181 
182 	return 0;
183 }
184 
185 #if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU)
186 
nxp_s32_gpio_pin_to_line(const struct gpio_nxp_s32_irq_config * irq_cfg,uint8_t pin)187 static uint8_t nxp_s32_gpio_pin_to_line(const struct gpio_nxp_s32_irq_config *irq_cfg,
188 					uint8_t pin)
189 {
190 	uint8_t i;
191 
192 	for (i = 0; i < irq_cfg->map_cnt; i++) {
193 		if (irq_cfg->map[i].pin == pin) {
194 			return irq_cfg->map[i].line;
195 		}
196 	}
197 
198 	return NXP_S32_GPIO_LINE_NOT_FOUND;
199 }
200 
nxp_s32_gpio_isr(uint8_t pin,void * arg)201 static void nxp_s32_gpio_isr(uint8_t pin, void *arg)
202 {
203 	const struct device *dev = (struct device *)arg;
204 	struct gpio_nxp_s32_data *data = dev->data;
205 
206 	gpio_fire_callbacks(&data->callbacks, dev, BIT(pin));
207 }
208 
209 #if defined(CONFIG_NXP_S32_EIRQ)
nxp_s32_gpio_eirq_get_trigger(Siul2_Icu_Ip_EdgeType * edge_type,enum gpio_int_mode mode,enum gpio_int_trig trigger)210 static int nxp_s32_gpio_eirq_get_trigger(Siul2_Icu_Ip_EdgeType *edge_type,
211 					 enum gpio_int_mode mode,
212 					 enum gpio_int_trig trigger)
213 {
214 	if (mode == GPIO_INT_MODE_DISABLED) {
215 		*edge_type = SIUL2_ICU_DISABLE;
216 		return 0;
217 	}
218 
219 	if (mode == GPIO_INT_MODE_LEVEL) {
220 		return -ENOTSUP;
221 	}
222 
223 	switch (trigger) {
224 	case GPIO_INT_TRIG_LOW:
225 		*edge_type = SIUL2_ICU_FALLING_EDGE;
226 		break;
227 	case GPIO_INT_TRIG_HIGH:
228 		*edge_type = SIUL2_ICU_RISING_EDGE;
229 		break;
230 	case GPIO_INT_TRIG_BOTH:
231 		*edge_type = SIUL2_ICU_BOTH_EDGES;
232 		break;
233 	default:
234 		return -ENOTSUP;
235 	}
236 
237 	return 0;
238 }
239 
nxp_s32_gpio_config_eirq(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)240 static int nxp_s32_gpio_config_eirq(const struct device *dev,
241 				    gpio_pin_t pin,
242 				    enum gpio_int_mode mode,
243 				    enum gpio_int_trig trig)
244 {
245 	const struct gpio_nxp_s32_config *config = dev->config;
246 	const struct gpio_nxp_s32_irq_config *irq_cfg = config->eirq_info;
247 	uint8_t irq_line;
248 	Siul2_Icu_Ip_EdgeType edge_type;
249 
250 	if (irq_cfg == NULL) {
251 		LOG_ERR("external interrupt controller not available or enabled");
252 		return -ENOTSUP;
253 	}
254 
255 	if (nxp_s32_gpio_eirq_get_trigger(&edge_type, mode, trig)) {
256 		LOG_ERR("trigger or mode not supported");
257 		return -ENOTSUP;
258 	}
259 
260 	irq_line = nxp_s32_gpio_pin_to_line(irq_cfg, pin);
261 	if (irq_line == NXP_S32_GPIO_LINE_NOT_FOUND) {
262 		if (edge_type == SIUL2_ICU_DISABLE) {
263 			return 0;
264 		}
265 		LOG_ERR("pin %d cannot be used for external interrupt", pin);
266 		return -ENOTSUP;
267 	}
268 
269 	if (edge_type == SIUL2_ICU_DISABLE) {
270 		eirq_nxp_s32_disable_interrupt(irq_cfg->ctrl, irq_line);
271 		eirq_nxp_s32_unset_callback(irq_cfg->ctrl, irq_line);
272 	} else {
273 		if (eirq_nxp_s32_set_callback(irq_cfg->ctrl, irq_line,
274 					nxp_s32_gpio_isr, pin, (void *)dev)) {
275 			LOG_ERR("pin %d is already in use", pin);
276 			return -EBUSY;
277 		}
278 		eirq_nxp_s32_enable_interrupt(irq_cfg->ctrl, irq_line, edge_type);
279 	}
280 
281 	return 0;
282 }
283 #endif /* CONFIG_NXP_S32_EIRQ */
284 
285 #if defined(CONFIG_NXP_S32_WKPU)
nxp_s32_gpio_wkpu_get_trigger(Wkpu_Ip_EdgeType * edge_type,enum gpio_int_mode mode,enum gpio_int_trig trigger)286 static int nxp_s32_gpio_wkpu_get_trigger(Wkpu_Ip_EdgeType *edge_type,
287 					 enum gpio_int_mode mode,
288 					 enum gpio_int_trig trigger)
289 {
290 	if (mode == GPIO_INT_MODE_DISABLED) {
291 		*edge_type = WKPU_IP_NONE_EDGE;
292 		return 0;
293 	}
294 
295 	if (mode == GPIO_INT_MODE_LEVEL) {
296 		return -ENOTSUP;
297 	}
298 
299 	switch (trigger) {
300 	case GPIO_INT_TRIG_LOW:
301 		*edge_type = WKPU_IP_FALLING_EDGE;
302 		break;
303 	case GPIO_INT_TRIG_HIGH:
304 		*edge_type = WKPU_IP_RISING_EDGE;
305 		break;
306 	case GPIO_INT_TRIG_BOTH:
307 		*edge_type = WKPU_IP_BOTH_EDGES;
308 		break;
309 	default:
310 		return -ENOTSUP;
311 	}
312 
313 	return 0;
314 }
315 
nxp_s32_gpio_config_wkpu(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)316 static int nxp_s32_gpio_config_wkpu(const struct device *dev,
317 				    gpio_pin_t pin,
318 				    enum gpio_int_mode mode,
319 				    enum gpio_int_trig trig)
320 {
321 	const struct gpio_nxp_s32_config *config = dev->config;
322 	const struct gpio_nxp_s32_irq_config *irq_cfg = config->wkpu_info;
323 	uint8_t irq_line;
324 	Wkpu_Ip_EdgeType edge_type;
325 
326 	if (irq_cfg == NULL) {
327 		LOG_ERR("WKPU controller not available or enabled");
328 		return -ENOTSUP;
329 	}
330 
331 	if (nxp_s32_gpio_wkpu_get_trigger(&edge_type, mode, trig)) {
332 		LOG_ERR("trigger or mode not supported");
333 		return -ENOTSUP;
334 	}
335 
336 	irq_line = nxp_s32_gpio_pin_to_line(irq_cfg, pin);
337 	if (irq_line == NXP_S32_GPIO_LINE_NOT_FOUND) {
338 		if (edge_type == WKPU_IP_NONE_EDGE) {
339 			return 0;
340 		}
341 		LOG_ERR("pin %d cannot be used for external interrupt", pin);
342 		return -ENOTSUP;
343 	}
344 
345 	if (edge_type == WKPU_IP_NONE_EDGE) {
346 		wkpu_nxp_s32_disable_interrupt(irq_cfg->ctrl, irq_line);
347 		wkpu_nxp_s32_unset_callback(irq_cfg->ctrl, irq_line);
348 	} else {
349 		if (wkpu_nxp_s32_set_callback(irq_cfg->ctrl, irq_line,
350 					nxp_s32_gpio_isr, pin, (void *)dev)) {
351 			LOG_ERR("pin %d is already in use", pin);
352 			return -EBUSY;
353 		}
354 		wkpu_nxp_s32_enable_interrupt(irq_cfg->ctrl, irq_line, edge_type);
355 	}
356 
357 	return 0;
358 }
359 #endif /* CONFIG_NXP_S32_WKPU */
360 
nxp_s32_gpio_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)361 static int nxp_s32_gpio_pin_interrupt_configure(const struct device *dev,
362 						gpio_pin_t pin,
363 						enum gpio_int_mode mode,
364 						enum gpio_int_trig trig)
365 {
366 #if defined(CONFIG_NXP_S32_WKPU)
367 	struct gpio_nxp_s32_data *data = dev->data;
368 
369 	if (data->pin_wkpu_mask & BIT(pin)) {
370 		return nxp_s32_gpio_config_wkpu(dev, pin, mode, trig);
371 	}
372 #endif
373 
374 #if defined(CONFIG_NXP_S32_EIRQ)
375 	return nxp_s32_gpio_config_eirq(dev, pin, mode, trig);
376 #endif
377 }
378 
nxp_s32_gpio_manage_callback(const struct device * dev,struct gpio_callback * cb,bool set)379 static int nxp_s32_gpio_manage_callback(const struct device *dev,
380 					struct gpio_callback *cb, bool set)
381 {
382 	struct gpio_nxp_s32_data *data = dev->data;
383 
384 	return gpio_manage_callback(&data->callbacks, cb, set);
385 }
386 #endif /* defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU) */
387 
388 #ifdef CONFIG_GPIO_GET_CONFIG
nxp_s32_gpio_pin_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * out_flags)389 static int nxp_s32_gpio_pin_get_config(const struct device *dev,
390 				       gpio_pin_t pin,
391 				       gpio_flags_t *out_flags)
392 {
393 	const struct gpio_nxp_s32_config *config = dev->config;
394 	Siul2_Dio_Ip_GpioType *gpio_base = config->gpio_base;
395 	Siul2_Port_Ip_PortType *port_base = config->port_base;
396 	Siul2_Dio_Ip_PinsChannelType pins_output;
397 	gpio_flags_t flags = 0;
398 
399 	if ((port_base->MSCR[pin] & SIUL2_MSCR_IBE_MASK) != 0) {
400 		flags |= GPIO_INPUT;
401 	}
402 
403 	if ((port_base->MSCR[pin] & SIUL2_MSCR_OBE_MASK) != 0) {
404 		flags |= GPIO_OUTPUT;
405 
406 		pins_output = Siul2_Dio_Ip_GetPinsOutput(gpio_base);
407 		if ((pins_output & BIT(pin)) != 0) {
408 			flags |= GPIO_OUTPUT_HIGH;
409 		} else {
410 			flags |= GPIO_OUTPUT_LOW;
411 		}
412 
413 #ifdef FEATURE_SIUL2_PORT_IP_HAS_OPEN_DRAIN
414 		if ((port_base->MSCR[pin] & SIUL2_MSCR_ODE_MASK) != 0) {
415 			flags |= GPIO_OPEN_DRAIN;
416 		}
417 #endif /* FEATURE_SIUL2_PORT_IP_HAS_OPEN_DRAIN */
418 	}
419 
420 	if ((port_base->MSCR[pin] & SIUL2_MSCR_PUE_MASK) != 0) {
421 		if ((port_base->MSCR[pin] & SIUL2_MSCR_PUS_MASK) != 0) {
422 			flags |= GPIO_PULL_UP;
423 		} else {
424 			flags |= GPIO_PULL_DOWN;
425 		}
426 	}
427 
428 	*out_flags = flags;
429 
430 	return 0;
431 }
432 #endif /* CONFIG_GPIO_GET_CONFIG */
433 
434 #ifdef CONFIG_GPIO_GET_DIRECTION
nxp_s32_gpio_port_get_direction(const struct device * dev,gpio_port_pins_t map,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)435 static int nxp_s32_gpio_port_get_direction(const struct device *dev,
436 					   gpio_port_pins_t map,
437 					   gpio_port_pins_t *inputs,
438 					   gpio_port_pins_t *outputs)
439 {
440 	const struct gpio_nxp_s32_config *config = dev->config;
441 	Siul2_Port_Ip_PortType *port_base = config->port_base;
442 	gpio_port_pins_t ip = 0;
443 	gpio_port_pins_t op = 0;
444 	uint32_t pin;
445 
446 	map &= config->common.port_pin_mask;
447 
448 	if (inputs != NULL) {
449 		while (map) {
450 			pin = find_lsb_set(map) - 1;
451 			ip |= (!!(port_base->MSCR[pin] & SIUL2_MSCR_IBE_MASK)) * BIT(pin);
452 			map &= ~BIT(pin);
453 		}
454 
455 		*inputs = ip;
456 	}
457 
458 	if (outputs != NULL) {
459 		while (map) {
460 			pin = find_lsb_set(map) - 1;
461 			op |= (!!(port_base->MSCR[pin] & SIUL2_MSCR_OBE_MASK)) * BIT(pin);
462 			map &= ~BIT(pin);
463 		}
464 
465 		*outputs = op;
466 	}
467 
468 	return 0;
469 }
470 #endif /* CONFIG_GPIO_GET_DIRECTION */
471 
472 static const struct gpio_driver_api gpio_nxp_s32_driver_api = {
473 	.pin_configure = nxp_s32_gpio_configure,
474 	.port_get_raw = nxp_s32_gpio_port_get_raw,
475 	.port_set_masked_raw = nxp_s32_gpio_port_set_masked_raw,
476 	.port_set_bits_raw = nxp_s32_gpio_port_set_bits_raw,
477 	.port_clear_bits_raw = nxp_s32_gpio_port_clear_bits_raw,
478 	.port_toggle_bits = nxp_s32_gpio_port_toggle_bits,
479 #if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU)
480 	.pin_interrupt_configure = nxp_s32_gpio_pin_interrupt_configure,
481 	.manage_callback = nxp_s32_gpio_manage_callback,
482 #endif
483 #ifdef CONFIG_GPIO_GET_CONFIG
484 	.pin_get_config = nxp_s32_gpio_pin_get_config,
485 #endif
486 #ifdef CONFIG_GPIO_GET_DIRECTION
487 	.port_get_direction = nxp_s32_gpio_port_get_direction,
488 #endif
489 };
490 
491 /* Calculate the port pin mask based on ngpios and gpio-reserved-ranges node
492  * properties. Multiple reserved ranges are not supported.
493  *
494  * For example, for the following gpio node definition:
495  *
496  *	gpioo: gpio@40521716 {
497  *              ...
498  *		ngpios = <14>;
499  *		gpio-reserved-ranges = <0 10>;
500  *	};
501  *
502  * the generated mask will be will be 0x3C00.
503  */
504 #define GPIO_NXP_S32_RESERVED_PIN_MASK(n)					\
505 	(GENMASK(DT_INST_PROP_BY_IDX(n, gpio_reserved_ranges, 0) +		\
506 			DT_INST_PROP_BY_IDX(n, gpio_reserved_ranges, 1) - 1,	\
507 		 DT_INST_PROP_BY_IDX(n, gpio_reserved_ranges, 0)		\
508 	))
509 
510 #define GPIO_NXP_S32_PORT_PIN_MASK(n)						\
511 	COND_CODE_1(DT_INST_NODE_HAS_PROP(n, gpio_reserved_ranges),		\
512 		(GPIO_PORT_PIN_MASK_FROM_DT_INST(n)				\
513 			& ~(GPIO_NXP_S32_RESERVED_PIN_MASK(n))),		\
514 		(GPIO_PORT_PIN_MASK_FROM_DT_INST(n)))
515 
516 #define GPIO_NXP_S32_REG_ADDR(n)						\
517 	((Siul2_Dio_Ip_GpioType *)DT_INST_REG_ADDR_BY_NAME(n, pgpdo))
518 
519 #define GPIO_NXP_S32_PORT_REG_ADDR(n)						\
520 	((Siul2_Port_Ip_PortType *)DT_INST_REG_ADDR_BY_NAME(n, mscr))
521 
522 #ifdef CONFIG_NXP_S32_EIRQ
523 #define GPIO_NXP_S32_EIRQ_NODE(n)						\
524 	DT_INST_PHANDLE(n, interrupt_parent)
525 
526 #define GPIO_NXP_S32_EIRQ_PIN_LINE(idx, n)					\
527 	DT_INST_IRQ_BY_IDX(n, idx, gpio_pin),					\
528 	DT_INST_IRQ_BY_IDX(n, idx, eirq_line)					\
529 
530 #define GPIO_NXP_S32_SET_EIRQ_INFO(n)						\
531 	BUILD_ASSERT((DT_NODE_HAS_PROP(DT_DRV_INST(n), interrupt_parent) ==	\
532 			DT_NODE_HAS_PROP(DT_DRV_INST(n), interrupts)),		\
533 			"interrupts and interrupt-parent must be set when "	\
534 			"using external interrupts");				\
535 	IF_ENABLED(DT_NODE_HAS_STATUS(GPIO_NXP_S32_EIRQ_NODE(n), okay), (	\
536 		static uint8_t gpio_nxp_s32_eirq_data_##n[] = {			\
537 			LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)),			\
538 				GPIO_NXP_S32_EIRQ_PIN_LINE, (,), n)		\
539 		};								\
540 		static struct gpio_nxp_s32_irq_config gpio_nxp_s32_eirq_##n = {	\
541 			.ctrl = DEVICE_DT_GET(GPIO_NXP_S32_EIRQ_NODE(n)),	\
542 			.map_cnt = DT_NUM_IRQS(DT_DRV_INST(n)),			\
543 			.map = (struct gpio_nxp_s32_irq_map *)			\
544 				gpio_nxp_s32_eirq_data_##n,			\
545 		};								\
546 	))
547 
548 #define GPIO_NXP_S32_GET_EIRQ_INFO(n)						\
549 	.eirq_info = UTIL_AND(DT_NODE_HAS_STATUS(GPIO_NXP_S32_EIRQ_NODE(n), okay),\
550 				&gpio_nxp_s32_eirq_##n),
551 #else
552 #define GPIO_NXP_S32_SET_EIRQ_INFO(n)
553 #define GPIO_NXP_S32_GET_EIRQ_INFO(n)
554 #endif /* CONFIG_NXP_S32_EIRQ */
555 
556 #ifdef CONFIG_NXP_S32_WKPU
557 #define GPIO_NXP_S32_WKPU_NODE(n) DT_INST_PHANDLE(n, nxp_wkpu)
558 
559 #define GPIO_NXP_S32_SET_WKPU_INFO(n)						\
560 	BUILD_ASSERT((DT_INST_NODE_HAS_PROP(n, nxp_wkpu) ==			\
561 			DT_INST_NODE_HAS_PROP(n, nxp_wkpu_interrupts)),		\
562 			"nxp,wkpu and nxp,wkpu-interrupts must be provided");	\
563 	IF_ENABLED(DT_NODE_HAS_STATUS(GPIO_NXP_S32_WKPU_NODE(n), okay), (	\
564 		static uint8_t gpio_nxp_s32_wkpu_data_##n[] =			\
565 			DT_INST_PROP(n, nxp_wkpu_interrupts);			\
566 		static struct gpio_nxp_s32_irq_config gpio_nxp_s32_wkpu_##n = {	\
567 			.ctrl = DEVICE_DT_GET(GPIO_NXP_S32_WKPU_NODE(n)),	\
568 			.map_cnt = sizeof(gpio_nxp_s32_wkpu_data_##n) /		\
569 				sizeof(struct gpio_nxp_s32_irq_map),		\
570 			.map = (struct gpio_nxp_s32_irq_map *)			\
571 				gpio_nxp_s32_wkpu_data_##n,			\
572 		};								\
573 	))
574 
575 #define GPIO_NXP_S32_GET_WKPU_INFO(n)						\
576 	.wkpu_info = UTIL_AND(DT_NODE_HAS_STATUS(GPIO_NXP_S32_WKPU_NODE(n), okay),\
577 				&gpio_nxp_s32_wkpu_##n)
578 #else
579 #define GPIO_NXP_S32_SET_WKPU_INFO(n)
580 #define GPIO_NXP_S32_GET_WKPU_INFO(n)
581 #endif /* CONFIG_NXP_S32_WKPU */
582 
583 #define GPIO_NXP_S32_DEVICE_INIT(n)						\
584 	GPIO_NXP_S32_SET_EIRQ_INFO(n)						\
585 	GPIO_NXP_S32_SET_WKPU_INFO(n)						\
586 	static const struct gpio_nxp_s32_config gpio_nxp_s32_config_##n = {	\
587 		.common = {							\
588 			.port_pin_mask = GPIO_NXP_S32_PORT_PIN_MASK(n),		\
589 		},								\
590 		.gpio_base = GPIO_NXP_S32_REG_ADDR(n),				\
591 		.port_base = GPIO_NXP_S32_PORT_REG_ADDR(n),			\
592 		GPIO_NXP_S32_GET_EIRQ_INFO(n)					\
593 		GPIO_NXP_S32_GET_WKPU_INFO(n)					\
594 	};									\
595 	static struct gpio_nxp_s32_data gpio_nxp_s32_data_##n;			\
596 	static int gpio_nxp_s32_init_##n(const struct device *dev)		\
597 	{									\
598 		return 0;							\
599 	}									\
600 	DEVICE_DT_INST_DEFINE(n,						\
601 			gpio_nxp_s32_init_##n,					\
602 			NULL,							\
603 			&gpio_nxp_s32_data_##n,					\
604 			&gpio_nxp_s32_config_##n,				\
605 			POST_KERNEL,						\
606 			CONFIG_GPIO_INIT_PRIORITY,				\
607 			&gpio_nxp_s32_driver_api);
608 
609 DT_INST_FOREACH_STATUS_OKAY(GPIO_NXP_S32_DEVICE_INIT)
610