1 /*
2  * Copyright (c) 2020 Seagate Technology LLC
3  * Copyright 2022 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT nxp_lpc11u6x_gpio
9 
10 /**
11  * @file
12  * @brief GPIO driver for NXP LPC11U6X SoCs
13  *
14  * This driver allows to configure the GPIOs found on the LPC11U6x MCUs.
15  *
16  * @note See the UM10732 LPC11U6x/E6x user manual for register definitions.
17  */
18 
19 #include <zephyr/drivers/clock_control.h>
20 #include <zephyr/drivers/gpio.h>
21 #include <zephyr/irq.h>
22 
23 #include <soc.h>
24 
25 #include <zephyr/drivers/gpio/gpio_utils.h>
26 
27 /* Offset from syscon base address. */
28 #define LPC11U6X_PINTSEL_REGS	0x178
29 
30 /* Offsets from GPIO base address. */
31 #define LPC11U6X_GPIO_REGS	0x2000
32 #define LPC11U6X_PINT_REGS	0x4000
33 
34 /**
35  * @brief Structure mapping the GPIO registers.
36  *
37  * @note The byte and word pin registers are not included because they are
38  *       not used by this driver. A 0x2000 offset is applied to skip them.
39  */
40 struct lpc11u6x_gpio_regs {
41 	volatile uint32_t dir[3];
42 	volatile uint32_t _unused1[29];
43 	volatile uint32_t mask[3];
44 	volatile uint32_t _unused2[29];
45 	volatile uint32_t pin[3];
46 	volatile uint32_t _unused3[29];
47 	volatile uint32_t mpin[3];
48 	volatile uint32_t _unused4[29];
49 	volatile uint32_t set[3];
50 	volatile uint32_t _unused5[29];
51 	volatile uint32_t clr[3];
52 	volatile uint32_t _unused6[29];
53 	volatile uint32_t not[3];
54 };
55 
56 /**
57  * @brief Structure mapping the PINT registers.
58  */
59 struct lpc11u6x_pint_regs {
60 	volatile uint32_t isel;
61 	volatile uint32_t ienr;
62 	volatile uint32_t sienr;
63 	volatile uint32_t cienr;
64 	volatile uint32_t ienf;
65 	volatile uint32_t sienf;
66 	volatile uint32_t cienf;
67 	volatile uint32_t rise;
68 	volatile uint32_t fall;
69 	volatile uint32_t ist;
70 	volatile uint32_t pmctrl;
71 	volatile uint32_t pmsrc;
72 	volatile uint32_t pmcfg;
73 };
74 
75 /**
76  * @brief Structure for resources and information shared between GPIO ports.
77  *
78  * This structure is included by all the per-port private configuration.
79  * It gathers all the resources and information shared between all the GPIO
80  * ports: GPIO and SYSCON registers base addresses, clock name and subsystem.
81  */
82 struct gpio_lpc11u6x_shared {
83 	const struct device *clock_dev;
84 	clock_control_subsys_t clock_subsys;
85 	uint32_t gpio_base;
86 	uint32_t syscon_base;
87 	uint8_t nirqs;
88 };
89 
90 struct gpio_lpc11u6x_config {
91 	/* gpio_driver_config needs to be first */
92 	struct gpio_driver_config common;
93 	const struct gpio_lpc11u6x_shared *shared;
94 	uint8_t port_num;
95 	uint8_t ngpios;
96 	volatile uint32_t *iocon_base;
97 };
98 
99 struct gpio_lpc11u6x_data {
100 	/* gpio_driver_data needs to be first. */
101 	struct gpio_driver_data common;
102 	sys_slist_t cb_list;
103 };
104 
gpio_lpc11u6x_pin_configure(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)105 static int gpio_lpc11u6x_pin_configure(const struct device *port,
106 				       gpio_pin_t pin, gpio_flags_t flags)
107 {
108 	const struct gpio_lpc11u6x_config *config = port->config;
109 	struct lpc11u6x_gpio_regs *gpio_regs = (struct lpc11u6x_gpio_regs *)
110 		(config->shared->gpio_base + LPC11U6X_GPIO_REGS);
111 	uint8_t port_num = config->port_num;
112 	uint32_t offset;
113 	uint32_t func;
114 
115 	if (pin >= config->ngpios) {
116 		return -EINVAL;
117 	}
118 
119 	/*
120 	 * PIO0_4 and PIO0_5 are "true" open drain pins muxed with the I2C port
121 	 * 0. They still can be configured as GPIOs but only in open drain mode
122 	 * and with no pull-down or pull-up resistor enabled.
123 	 */
124 	if (port_num == 0 && (pin == 4 || pin == 5) &&
125 		((flags & GPIO_OPEN_DRAIN) == 0 ||
126 		 (flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)))) {
127 		return -EINVAL;
128 	}
129 
130 	/*
131 	 * For PIO0_0 and PIO0_[10-15] function 1 enables GPIO mode. For all
132 	 * the other pins, function 0 must be selected.
133 	 */
134 	if (port_num == 0 && (pin == 0 || (pin >= 10 && pin <= 15))) {
135 		func = IOCON_FUNC1;
136 	} else {
137 		func = IOCON_FUNC0;
138 	}
139 
140 	if (flags & GPIO_SINGLE_ENDED) {
141 		/* Open source mode is not supported. */
142 		if (flags & GPIO_LINE_OPEN_DRAIN) {
143 			func |= IOCON_PIO_OD(1);
144 		} else {
145 			return -ENOTSUP;
146 		}
147 	}
148 
149 	if (flags & GPIO_PULL_UP) {
150 		func |= IOCON_PIO_MODE(0x2);
151 	} else if (flags & GPIO_PULL_DOWN) {
152 		func |= IOCON_PIO_MODE(0x1);
153 	} else {
154 		func |= IOCON_PIO_MODE(0x0);
155 	}
156 
157 	/* Handle 4 bytes hole between PIO2_1 and PIO2_2. */
158 	if (port_num == 2 && pin > 1) {
159 		offset = pin + 1;
160 	} else {
161 		offset = pin;
162 	}
163 	/* iocon base + offset gives configuration register for this pin */
164 	config->iocon_base[offset] = func;
165 
166 	/* Initial output value. */
167 	if (flags & GPIO_OUTPUT_INIT_HIGH) {
168 		gpio_regs->set[port_num] |= BIT(pin);
169 	}
170 
171 	if (flags & GPIO_OUTPUT_INIT_LOW) {
172 		gpio_regs->clr[port_num] |= BIT(pin);
173 	}
174 
175 	/*
176 	 * TODO: maybe configure the STARTERP0 register to allow wake-up from
177 	 * deep-sleep or power-down modes.
178 	 */
179 
180 	/* Configure GPIO direction. */
181 	WRITE_BIT(gpio_regs->dir[port_num], pin, flags & GPIO_OUTPUT);
182 
183 	return 0;
184 }
185 
gpio_lpc11u6x_port_get_raw(const struct device * port,gpio_port_value_t * value)186 static int gpio_lpc11u6x_port_get_raw(const struct device *port,
187 				      gpio_port_value_t *value)
188 {
189 	const struct gpio_lpc11u6x_config *config = port->config;
190 	struct lpc11u6x_gpio_regs *gpio_regs = (struct lpc11u6x_gpio_regs *)
191 		(config->shared->gpio_base + LPC11U6X_GPIO_REGS);
192 
193 	*value = gpio_regs->pin[config->port_num];
194 
195 	return 0;
196 }
197 
gpio_lpc11u6x_port_set_masked_raw(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t value)198 static int gpio_lpc11u6x_port_set_masked_raw(const struct device *port,
199 					     gpio_port_pins_t mask,
200 					     gpio_port_value_t value)
201 {
202 	const struct gpio_lpc11u6x_config *config = port->config;
203 	struct lpc11u6x_gpio_regs *gpio_regs = (struct lpc11u6x_gpio_regs *)
204 		(config->shared->gpio_base + LPC11U6X_GPIO_REGS);
205 	uint8_t port_num = config->port_num;
206 	uint32_t orig_mask;
207 
208 	orig_mask = gpio_regs->mask[port_num];
209 	/* Apply inverted mask (bit set to 1 masks the pin). */
210 	gpio_regs->mask[port_num] = ~mask;
211 	compiler_barrier();
212 	/* Update pins values. */
213 	gpio_regs->mpin[port_num] = value;
214 	compiler_barrier();
215 	/* Restore original mask. */
216 	gpio_regs->mask[port_num] = orig_mask;
217 	compiler_barrier();
218 
219 	return 0;
220 }
221 
gpio_lpc11u6x_port_set_bits_raw(const struct device * port,gpio_port_pins_t pins)222 static int gpio_lpc11u6x_port_set_bits_raw(const struct device *port,
223 					   gpio_port_pins_t pins)
224 {
225 	const struct gpio_lpc11u6x_config *config = port->config;
226 	struct lpc11u6x_gpio_regs *gpio_regs = (struct lpc11u6x_gpio_regs *)
227 		(config->shared->gpio_base + LPC11U6X_GPIO_REGS);
228 
229 	gpio_regs->set[config->port_num] = pins;
230 
231 	return 0;
232 }
233 
gpio_lpc11u6x_port_clear_bits_raw(const struct device * port,gpio_port_pins_t pins)234 static int gpio_lpc11u6x_port_clear_bits_raw(const struct device *port,
235 					     gpio_port_pins_t pins)
236 {
237 	const struct gpio_lpc11u6x_config *config = port->config;
238 	struct lpc11u6x_gpio_regs *gpio_regs = (struct lpc11u6x_gpio_regs *)
239 		(config->shared->gpio_base + LPC11U6X_GPIO_REGS);
240 
241 	gpio_regs->clr[config->port_num] = pins;
242 
243 	return 0;
244 }
245 
gpio_lpc11u6x_port_toggle_bits(const struct device * port,gpio_port_pins_t pins)246 static int gpio_lpc11u6x_port_toggle_bits(const struct device *port,
247 					  gpio_port_pins_t pins)
248 {
249 	const struct gpio_lpc11u6x_config *config = port->config;
250 	struct lpc11u6x_gpio_regs *gpio_regs = (struct lpc11u6x_gpio_regs *)
251 		(config->shared->gpio_base + LPC11U6X_GPIO_REGS);
252 
253 	gpio_regs->not[config->port_num] = pins;
254 
255 	return 0;
256 }
257 
258 /**
259  * @brief Attach a free interrupt line to a GPIO.
260  *
261  * @param shared   Pointer to a structure shared between all the GPIO ports.
262  * @param intpin   GPIO port and pin numbers encoded into a value compatible
263  *                 with the INTPIN register (included in the PINTSEL register).
264  *
265  * @retval >0      Number of the attached interrupt on success.
266  * @retval -EBUSY  All the interrupt lines are already attached.
267  */
268 static int
pintsel_attach(const struct gpio_lpc11u6x_shared * shared,uint8_t intpin)269 pintsel_attach(const struct gpio_lpc11u6x_shared *shared, uint8_t intpin)
270 {
271 	uint8_t irq;
272 	int ret = -EBUSY;
273 	uint32_t *pintsel_reg =
274 		(uint32_t *) (shared->syscon_base + LPC11U6X_PINTSEL_REGS);
275 
276 	for (irq = 0; irq < shared->nirqs; irq++) {
277 		/* GPIO already attached. */
278 		if ((pintsel_reg[irq] & BIT_MASK(5)) == intpin) {
279 			return irq;
280 		}
281 
282 		if (ret < 0 && (pintsel_reg[irq] & BIT_MASK(5)) == 0) {
283 			ret = irq;
284 		}
285 	}
286 	/* Attach GPIO to the first free interrupt found if any. */
287 	if (ret >= 0) {
288 		pintsel_reg[ret] = intpin;
289 	}
290 
291 	return ret;
292 }
293 
294 /**
295  * @brief Detach an interrupt line from a GPIO.
296  *
297  * @param shared   Pointer to a structure shared between all the GPIO ports.
298  * @param intpin   GPIO port and pin numbers encoded into a value compatible
299  *                 with the INTPIN register (included in the PINTSEL register).
300  *
301  * @retval >0      Number of the detached interrupt on success.
302  * @retval -EINVAL No attached interrupt found for the requested GPIO.
303  */
304 static int
pintsel_detach(const struct gpio_lpc11u6x_shared * shared,uint8_t intpin)305 pintsel_detach(const struct gpio_lpc11u6x_shared *shared, uint8_t intpin)
306 {
307 	uint8_t irq;
308 	uint32_t *pintsel_reg =
309 		(uint32_t *) (shared->syscon_base + LPC11U6X_PINTSEL_REGS);
310 
311 	for (irq = 0; irq < shared->nirqs; irq++) {
312 		if ((pintsel_reg[irq] & BIT_MASK(5)) == intpin) {
313 			pintsel_reg[irq] = 0;
314 			return irq;
315 		}
316 	}
317 	return -EINVAL;
318 }
319 
gpio_lpc11u6x_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)320 static int gpio_lpc11u6x_pin_interrupt_configure(const struct device *port,
321 						 gpio_pin_t pin,
322 						 enum gpio_int_mode mode,
323 						 enum gpio_int_trig trig)
324 {
325 	const struct gpio_lpc11u6x_config *config = port->config;
326 	struct lpc11u6x_pint_regs *pint_regs = (struct lpc11u6x_pint_regs *)
327 		(config->shared->gpio_base + LPC11U6X_PINT_REGS);
328 	uint8_t intpin;
329 	int irq;
330 
331 	if (pin >= config->ngpios) {
332 		return -EINVAL;
333 	}
334 
335 	/*
336 	 * Because the PINTSEL register only have 6 bits to encode a pin
337 	 * number, then PIO2_8 to PIO2_23 can't be attached to an interrupt
338 	 * line.
339 	 */
340 	if (config->port_num == 2 && pin > 7) {
341 		return -ENOTSUP;
342 	}
343 
344 	/*
345 	 * Convert the requested GPIO port and pin numbers into a value
346 	 * compatible with the INTPIN register (included in the PINTSEL
347 	 * register).
348 	 */
349 	intpin = pin;
350 	if (config->port_num == 1) {
351 		intpin += 24;
352 	} else if (config->port_num == 2) {
353 		intpin += 56;
354 	}
355 
356 	if (mode == GPIO_INT_MODE_DISABLED) {
357 		irq = pintsel_detach(config->shared, intpin);
358 	} else {
359 		irq = pintsel_attach(config->shared, intpin);
360 	}
361 	if (irq < 0) {
362 		return irq;
363 	}
364 
365 	switch (mode) {
366 	case GPIO_INT_MODE_DISABLED:
367 		pint_regs->isel &= ~BIT(irq);
368 		pint_regs->cienr |= BIT(irq);
369 		pint_regs->cienf |= BIT(irq);
370 		break;
371 	case GPIO_INT_MODE_EDGE:
372 		/* Select edge interrupt mode. */
373 		pint_regs->isel &= ~BIT(irq);
374 		/* Enable interrupts on falling and/or rising edges. */
375 		if (trig & GPIO_INT_TRIG_LOW) {
376 			pint_regs->sienf |= BIT(irq);
377 		} else {
378 			pint_regs->cienf |= BIT(irq);
379 		}
380 		if (trig & GPIO_INT_TRIG_HIGH) {
381 			pint_regs->sienr |= BIT(irq);
382 		} else {
383 			pint_regs->cienr |= BIT(irq);
384 		}
385 		break;
386 	case GPIO_INT_MODE_LEVEL:
387 		/* Select level interrupt mode. */
388 		pint_regs->isel |= BIT(irq);
389 		/* Set active level. */
390 		if (trig & GPIO_INT_TRIG_LOW) {
391 			pint_regs->cienf |= BIT(irq);
392 		} else {
393 			pint_regs->sienf |= BIT(irq);
394 		}
395 		/* Enable level interrupt. */
396 		pint_regs->sienr |= BIT(irq);
397 		break;
398 	default:
399 		return -ENOTSUP;
400 	}
401 
402 	/* Clear interrupt status. */
403 	pint_regs->ist |= BIT(irq);
404 
405 	return 0;
406 }
407 
gpio_lpc11u6x_manage_callback(const struct device * port,struct gpio_callback * cb,bool set)408 static int gpio_lpc11u6x_manage_callback(const struct device *port,
409 					 struct gpio_callback *cb, bool set)
410 {
411 	struct gpio_lpc11u6x_data *data = port->data;
412 
413 	return gpio_manage_callback(&data->cb_list, cb, set);
414 }
415 
gpio_lpc11u6x_get_pending_int(const struct device * dev)416 static uint32_t gpio_lpc11u6x_get_pending_int(const struct device *dev)
417 {
418 	ARG_UNUSED(dev);
419 
420 	return -ENOTSUP;
421 }
422 
gpio_lpc11u6x_isr(const void * arg)423 static void gpio_lpc11u6x_isr(const void *arg)
424 {
425 	struct gpio_lpc11u6x_shared *shared =
426 		(struct gpio_lpc11u6x_shared *)arg;
427 	struct lpc11u6x_pint_regs *pint_regs = (struct lpc11u6x_pint_regs *)
428 		(shared->gpio_base + LPC11U6X_PINT_REGS);
429 	uint32_t *pintsel_reg =
430 		(uint32_t *) (shared->syscon_base + LPC11U6X_PINTSEL_REGS);
431 	uint8_t irq;
432 	uint32_t pins[3] = { 0, 0, 0 };
433 	const struct device *port;
434 	struct gpio_lpc11u6x_data *data;
435 
436 	for (irq = 0; irq < shared->nirqs; irq++) {
437 		uint32_t intpin;
438 
439 		if ((pint_regs->ist & BIT(irq)) == 0) {
440 			continue;
441 		}
442 
443 		/* Clear interrupt status. */
444 		pint_regs->ist |= BIT(irq);
445 
446 		/*
447 		 * Look in the PINTSEL register to retrieve the "intpin" value
448 		 * attached with the requested interrupt. Extract the GPIO
449 		 * port and pin numbers from this "intpin" value and store them
450 		 * into an "active pins" mask.
451 		 */
452 		intpin = pintsel_reg[irq] & BIT_MASK(5);
453 		if (intpin < 24) {
454 			pins[0] |= BIT(intpin);
455 		} else if (intpin < 56) {
456 			pins[1] |= BIT(intpin - 24);
457 		} else {
458 			pins[2] |= BIT(intpin - 56);
459 		}
460 	}
461 	/* For each port with active pins, fire the GPIO interrupt callbacks. */
462 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio0), okay)
463 	if (pins[0]) {
464 		port = DEVICE_DT_GET(DT_NODELABEL(gpio0));
465 		data = port->data;
466 		gpio_fire_callbacks(&data->cb_list, port, pins[0]);
467 	}
468 #endif
469 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
470 	if (pins[1]) {
471 		port = DEVICE_DT_GET(DT_NODELABEL(gpio1));
472 		data = port->data;
473 		gpio_fire_callbacks(&data->cb_list, port, pins[1]);
474 	}
475 #endif
476 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio2), okay)
477 	if (pins[2]) {
478 		port = DEVICE_DT_GET(DT_NODELABEL(gpio2));
479 		data = port->data;
480 		gpio_fire_callbacks(&data->cb_list, port, pins[2]);
481 	}
482 #endif
483 }
484 
485 static const struct gpio_driver_api gpio_lpc11u6x_driver_api = {
486 	.pin_configure = gpio_lpc11u6x_pin_configure,
487 	.port_get_raw = gpio_lpc11u6x_port_get_raw,
488 	.port_set_masked_raw = gpio_lpc11u6x_port_set_masked_raw,
489 	.port_set_bits_raw = gpio_lpc11u6x_port_set_bits_raw,
490 	.port_clear_bits_raw = gpio_lpc11u6x_port_clear_bits_raw,
491 	.port_toggle_bits = gpio_lpc11u6x_port_toggle_bits,
492 	.pin_interrupt_configure = gpio_lpc11u6x_pin_interrupt_configure,
493 	.manage_callback = gpio_lpc11u6x_manage_callback,
494 	.get_pending_int = gpio_lpc11u6x_get_pending_int,
495 };
496 
497 /*
498  * Note that the first DT instance is used to initialize the resources
499  * shared between all the ports (IRQ lines, clock).
500  */
501 
502 static const struct gpio_lpc11u6x_shared gpio_lpc11u6x_shared = {
503 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
504 	.clock_subsys = (clock_control_subsys_t) DT_INST_PHA(0, clocks, clkid),
505 	.gpio_base = DT_INST_REG_ADDR_BY_IDX(0, 0),
506 	.syscon_base = DT_INST_REG_ADDR_BY_IDX(0, 1),
507 	.nirqs = DT_NUM_IRQS(DT_DRV_INST(0)),
508 };
509 
510 #define IRQ_INIT(n)							\
511 do {							                \
512 	IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, n, irq),			\
513 		    DT_INST_IRQ_BY_IDX(0, n, priority),			\
514 		    gpio_lpc11u6x_isr, &gpio_lpc11u6x_shared, 0);	\
515 	irq_enable(DT_INST_IRQ_BY_IDX(0, n, irq));			\
516 } while (false)
517 
gpio_lpc11u6x_init(const struct device * dev)518 static int gpio_lpc11u6x_init(const struct device *dev)
519 {
520 	const struct gpio_lpc11u6x_config *config = dev->config;
521 	int ret;
522 	static bool gpio_ready;
523 
524 	/* Initialize shared resources only once. */
525 	if (gpio_ready) {
526 		return 0;
527 	}
528 
529 	if (!device_is_ready(config->shared->clock_dev)) {
530 		return -ENODEV;
531 	}
532 
533 	/* Enable GPIO and PINT clocks. */
534 	ret = clock_control_on(config->shared->clock_dev, config->shared->clock_subsys);
535 	if (ret < 0) {
536 		return ret;
537 	}
538 
539 #if DT_INST_IRQ_HAS_IDX(0, 0)
540 	IRQ_INIT(0);
541 #endif
542 #if DT_INST_IRQ_HAS_IDX(0, 1)
543 	IRQ_INIT(1);
544 #endif
545 #if DT_INST_IRQ_HAS_IDX(0, 2)
546 	IRQ_INIT(2);
547 #endif
548 #if DT_INST_IRQ_HAS_IDX(0, 3)
549 	IRQ_INIT(3);
550 #endif
551 #if DT_INST_IRQ_HAS_IDX(0, 4)
552 	IRQ_INIT(4);
553 #endif
554 #if DT_INST_IRQ_HAS_IDX(0, 5)
555 	IRQ_INIT(5);
556 #endif
557 #if DT_INST_IRQ_HAS_IDX(0, 6)
558 	IRQ_INIT(6);
559 #endif
560 #if DT_INST_IRQ_HAS_IDX(0, 7)
561 	IRQ_INIT(7);
562 #endif
563 	gpio_ready = true;
564 
565 	return 0;
566 }
567 
568 #define GPIO_LPC11U6X_INIT(id)						\
569 static const struct gpio_lpc11u6x_config				\
570 			gpio_lpc11u6x_config_##id = {			\
571 	.common = {							\
572 		.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(	\
573 					DT_NODELABEL(gpio##id)),	\
574 	},								\
575 	.shared = &gpio_lpc11u6x_shared,				\
576 	.port_num = id,							\
577 	.ngpios = DT_PROP(DT_NODELABEL(gpio##id), ngpios),		\
578 	.iocon_base = (volatile uint32_t *)DT_REG_ADDR(			\
579 		DT_INST_PHANDLE(id, iocon)),				\
580 };									\
581 									\
582 static struct gpio_lpc11u6x_data gpio_lpc11u6x_data_##id;		\
583 									\
584 DEVICE_DT_DEFINE(DT_NODELABEL(gpio##id),				\
585 		    &gpio_lpc11u6x_init,				\
586 		    NULL,						\
587 		    &gpio_lpc11u6x_data_##id,				\
588 		    &gpio_lpc11u6x_config_##id,				\
589 		    PRE_KERNEL_2, CONFIG_GPIO_INIT_PRIORITY,		\
590 		    &gpio_lpc11u6x_driver_api)
591 
592 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio0), okay)
593 GPIO_LPC11U6X_INIT(0);
594 #endif
595 
596 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
597 GPIO_LPC11U6X_INIT(1);
598 #endif
599 
600 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio2), okay)
601 GPIO_LPC11U6X_INIT(2);
602 #endif
603