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