1 /*
2  * Copyright (c) 2021 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nuvoton_nct38xx_gpio_port
8 
9 #include "gpio_nct38xx.h"
10 #include <zephyr/drivers/gpio/gpio_utils.h>
11 
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_DECLARE(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL);
15 
16 /* Driver config */
17 struct gpio_nct38xx_port_config {
18 	/* gpio_driver_config needs to be first */
19 	struct gpio_driver_config common;
20 	/* NCT38XX controller dev */
21 	const struct device *nct38xx_dev;
22 	/* GPIO port index */
23 	uint8_t gpio_port;
24 	/* GPIO port 0 pinmux mask */
25 	uint8_t pinmux_mask;
26 };
27 
28 /* Driver data */
29 struct gpio_nct38xx_port_data {
30 	/* gpio_driver_data needs to be first */
31 	struct gpio_driver_data common;
32 	/* GPIO callback list */
33 	sys_slist_t cb_list_gpio;
34 	/* lock GPIO register access */
35 	struct k_sem lock;
36 };
37 
38 /* GPIO api functions */
gpio_nct38xx_pin_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)39 static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
40 {
41 	const struct gpio_nct38xx_port_config *const config = dev->config;
42 	struct gpio_nct38xx_port_data *const data = dev->data;
43 	uint32_t mask = BIT(pin);
44 	uint8_t reg, new_reg;
45 	int ret;
46 
47 	/* Don't support simultaneous in/out mode */
48 	if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
49 		return -ENOTSUP;
50 	}
51 
52 	/* Don't support "open source" mode */
53 	if (((flags & GPIO_SINGLE_ENDED) != 0) && ((flags & GPIO_LINE_OPEN_DRAIN) == 0)) {
54 		return -ENOTSUP;
55 	}
56 
57 	/* Don't support pull-up/pull-down */
58 	if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
59 		return -ENOTSUP;
60 	}
61 
62 	k_sem_take(&data->lock, K_FOREVER);
63 
64 	/* Pin multiplexing */
65 	if (config->gpio_port == 0) {
66 		ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, &reg);
67 		if (ret < 0) {
68 			goto done;
69 		}
70 
71 		new_reg = reg | mask;
72 		/* NCT3807 bit3 must be set to 0 */
73 		new_reg &= config->pinmux_mask;
74 
75 		ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, reg,
76 					 new_reg);
77 		if (ret < 0) {
78 			goto done;
79 		}
80 	}
81 
82 	/* Configure pin as input. */
83 	if (flags & GPIO_INPUT) {
84 		ret = nct38xx_reg_read_byte(config->nct38xx_dev,
85 					    NCT38XX_REG_GPIO_DIR(config->gpio_port), &reg);
86 		if (ret < 0) {
87 			goto done;
88 		}
89 		new_reg = reg & ~mask;
90 		ret = nct38xx_reg_update(config->nct38xx_dev,
91 					 NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
92 
93 		k_sem_give(&data->lock);
94 		return ret;
95 	}
96 
97 	/* Select open drain 0:push-pull 1:open-drain */
98 	ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
99 				    &reg);
100 	if (ret < 0) {
101 		goto done;
102 	}
103 	if (flags & GPIO_OPEN_DRAIN) {
104 		new_reg = reg | mask;
105 	} else {
106 		new_reg = reg & ~mask;
107 	}
108 	ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
109 				 reg, new_reg);
110 	if (ret < 0) {
111 		goto done;
112 	}
113 
114 	/* Set level 0:low 1:high */
115 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
116 				    NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
117 				    &reg);
118 	if (ret < 0) {
119 		goto done;
120 	}
121 	if (flags & GPIO_OUTPUT_INIT_HIGH) {
122 		new_reg = reg | mask;
123 	} else if (flags & GPIO_OUTPUT_INIT_LOW) {
124 		new_reg = reg & ~mask;
125 	}
126 	ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
127 				 reg, new_reg);
128 	if (ret < 0) {
129 		goto done;
130 	}
131 
132 	/* Configure pin as output, if requested 0:input 1:output */
133 	if (flags & GPIO_OUTPUT) {
134 		ret = nct38xx_reg_read_byte(config->nct38xx_dev,
135 					    NCT38XX_REG_GPIO_DIR(config->gpio_port), &reg);
136 		if (ret < 0) {
137 			goto done;
138 		}
139 		new_reg = reg | mask;
140 		ret = nct38xx_reg_update(config->nct38xx_dev,
141 					 NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
142 	}
143 
144 done:
145 	k_sem_give(&data->lock);
146 	return ret;
147 }
148 
149 #ifdef CONFIG_GPIO_GET_CONFIG
gpio_nct38xx_pin_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * flags)150 int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *flags)
151 {
152 	const struct gpio_nct38xx_port_config *const config = dev->config;
153 	struct gpio_nct38xx_port_data *const data = dev->data;
154 	uint32_t mask = BIT(pin);
155 	uint8_t reg;
156 	int ret;
157 
158 	k_sem_take(&data->lock, K_FOREVER);
159 
160 	if (config->gpio_port == 0) {
161 		if (mask & (~config->common.port_pin_mask)) {
162 			ret = -ENOTSUP;
163 			goto done;
164 		}
165 
166 		ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, &reg);
167 		if (ret < 0) {
168 			goto done;
169 		}
170 
171 		if ((mask & config->pinmux_mask) && (mask & (~reg))) {
172 			*flags = GPIO_DISCONNECTED;
173 			goto done;
174 		}
175 	}
176 
177 	ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port),
178 				    &reg);
179 	if (ret < 0) {
180 		goto done;
181 	}
182 
183 	if (reg & mask) {
184 		/* Output */
185 		*flags = GPIO_OUTPUT;
186 
187 		/* 0 - push-pull, 1 - open-drain */
188 		ret = nct38xx_reg_read_byte(config->nct38xx_dev,
189 					    NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), &reg);
190 		if (ret < 0) {
191 			goto done;
192 		}
193 
194 		if (mask & reg) {
195 			*flags |= GPIO_OPEN_DRAIN;
196 		}
197 
198 		/* Output value */
199 		ret = nct38xx_reg_read_byte(config->nct38xx_dev,
200 					    NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
201 		if (ret < 0) {
202 			goto done;
203 		}
204 
205 		if (mask & reg) {
206 			*flags |= GPIO_OUTPUT_HIGH;
207 		} else {
208 			*flags |= GPIO_OUTPUT_LOW;
209 		}
210 	} else {
211 		/* Input */
212 		*flags = GPIO_INPUT;
213 	}
214 
215 done:
216 	k_sem_give(&data->lock);
217 	return ret;
218 }
219 #endif /* CONFIG_GPIO_GET_CONFIG */
220 
gpio_nct38xx_port_get_raw(const struct device * dev,gpio_port_value_t * value)221 static int gpio_nct38xx_port_get_raw(const struct device *dev, gpio_port_value_t *value)
222 {
223 	const struct gpio_nct38xx_port_config *const config = dev->config;
224 
225 	return nct38xx_reg_read_byte(config->nct38xx_dev,
226 				     NCT38XX_REG_GPIO_DATA_IN(config->gpio_port), (uint8_t *)value);
227 }
228 
gpio_nct38xx_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)229 static int gpio_nct38xx_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
230 					    gpio_port_value_t value)
231 {
232 	const struct gpio_nct38xx_port_config *const config = dev->config;
233 	struct gpio_nct38xx_port_data *const data = dev->data;
234 	uint8_t reg, new_reg;
235 	int ret;
236 
237 	k_sem_take(&data->lock, K_FOREVER);
238 
239 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
240 				    NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
241 	if (ret < 0) {
242 		goto done;
243 	}
244 	new_reg = ((reg & ~mask) | (value & mask));
245 	ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
246 				 reg, new_reg);
247 
248 done:
249 	k_sem_give(&data->lock);
250 
251 	return ret;
252 }
253 
gpio_nct38xx_port_set_bits_raw(const struct device * dev,gpio_port_pins_t mask)254 static int gpio_nct38xx_port_set_bits_raw(const struct device *dev, gpio_port_pins_t mask)
255 {
256 	const struct gpio_nct38xx_port_config *const config = dev->config;
257 	struct gpio_nct38xx_port_data *const data = dev->data;
258 	uint8_t reg, new_reg;
259 	int ret;
260 
261 	k_sem_take(&data->lock, K_FOREVER);
262 
263 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
264 				    NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
265 	if (ret < 0) {
266 		goto done;
267 	}
268 	new_reg = reg | mask;
269 	ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
270 				 reg, new_reg);
271 
272 done:
273 	k_sem_give(&data->lock);
274 
275 	return ret;
276 }
277 
gpio_nct38xx_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t mask)278 static int gpio_nct38xx_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t mask)
279 {
280 	const struct gpio_nct38xx_port_config *const config = dev->config;
281 	struct gpio_nct38xx_port_data *const data = dev->data;
282 	uint8_t reg, new_reg;
283 	int ret;
284 
285 	k_sem_take(&data->lock, K_FOREVER);
286 
287 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
288 				    NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
289 	if (ret < 0) {
290 		goto done;
291 	}
292 	new_reg = reg & ~mask;
293 	ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
294 				 reg, new_reg);
295 
296 done:
297 	k_sem_give(&data->lock);
298 
299 	return ret;
300 }
301 
gpio_nct38xx_port_toggle_bits(const struct device * dev,gpio_port_pins_t mask)302 static int gpio_nct38xx_port_toggle_bits(const struct device *dev, gpio_port_pins_t mask)
303 {
304 	const struct gpio_nct38xx_port_config *const config = dev->config;
305 	struct gpio_nct38xx_port_data *const data = dev->data;
306 	uint8_t reg, new_reg;
307 	int ret;
308 
309 	k_sem_take(&data->lock, K_FOREVER);
310 
311 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
312 				    NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
313 	if (ret < 0) {
314 		goto done;
315 	}
316 	new_reg = reg ^ mask;
317 	ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
318 				 reg, new_reg);
319 
320 done:
321 	k_sem_give(&data->lock);
322 
323 	return ret;
324 }
325 
gpio_nct38xx_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)326 static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
327 						enum gpio_int_mode mode, enum gpio_int_trig trig)
328 {
329 	const struct gpio_nct38xx_port_config *const config = dev->config;
330 	struct gpio_nct38xx_port_data *const data = dev->data;
331 	uint8_t reg, new_reg, rise, new_rise, fall, new_fall;
332 	int ret;
333 	uint32_t mask = BIT(pin);
334 
335 	k_sem_take(&data->lock, K_FOREVER);
336 
337 	/* Disable irq before configuring them */
338 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
339 				    NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &reg);
340 	if (ret < 0) {
341 		goto done;
342 	}
343 	new_reg = reg & ~mask;
344 	ret = nct38xx_reg_update(config->nct38xx_dev,
345 				 NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
346 	if (ret < 0) {
347 		goto done;
348 	}
349 
350 	/* Configure and enable interrupt? */
351 	if (mode == GPIO_INT_MODE_DISABLED) {
352 		goto done;
353 	}
354 
355 	/* set edge register */
356 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
357 				    NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), &rise);
358 	if (ret < 0) {
359 		goto done;
360 	}
361 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
362 				    NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), &fall);
363 	if (ret < 0) {
364 		goto done;
365 	}
366 
367 	if (mode == GPIO_INT_MODE_EDGE) {
368 		if (trig == GPIO_INT_TRIG_LOW) {
369 			new_rise = rise & ~mask;
370 			new_fall = fall | mask;
371 		} else if (trig == GPIO_INT_TRIG_HIGH) {
372 			new_rise = rise | mask;
373 			new_fall = fall & ~mask;
374 		} else if (trig == GPIO_INT_TRIG_BOTH) {
375 			new_rise = rise | mask;
376 			new_fall = fall | mask;
377 		} else {
378 			LOG_ERR("Invalid interrupt trigger type %d", trig);
379 			return -EINVAL;
380 		}
381 	} else {
382 		/* level mode */
383 		new_rise = rise & ~mask;
384 		new_fall = fall & ~mask;
385 	}
386 
387 	ret = nct38xx_reg_update(config->nct38xx_dev,
388 				 NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), rise, new_rise);
389 	if (ret < 0) {
390 		goto done;
391 	}
392 
393 	ret = nct38xx_reg_update(config->nct38xx_dev,
394 				 NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), fall, new_fall);
395 	if (ret < 0) {
396 		goto done;
397 	}
398 
399 	if (mode == GPIO_INT_MODE_LEVEL) {
400 		/* set active high/low */
401 		ret = nct38xx_reg_read_byte(config->nct38xx_dev,
402 					    NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), &reg);
403 		if (ret < 0) {
404 			goto done;
405 		}
406 
407 		if (trig == GPIO_INT_TRIG_LOW) {
408 			new_reg = reg & ~mask;
409 		} else if (trig == GPIO_INT_TRIG_HIGH) {
410 			new_reg = reg | mask;
411 		} else {
412 			LOG_ERR("Invalid interrupt trigger type %d", trig);
413 			ret = -EINVAL;
414 			goto done;
415 		}
416 		ret = nct38xx_reg_update(config->nct38xx_dev,
417 					 NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), reg,
418 					 new_reg);
419 
420 		if (ret < 0) {
421 			goto done;
422 		}
423 	}
424 
425 	/* Clear pending bit */
426 	ret = nct38xx_reg_write_byte(config->nct38xx_dev,
427 				     NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), mask);
428 	if (ret < 0) {
429 		goto done;
430 	}
431 
432 	/* Enable it after configuration is completed */
433 	ret = nct38xx_reg_read_byte(config->nct38xx_dev,
434 				    NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &reg);
435 	if (ret < 0) {
436 		goto done;
437 	}
438 	new_reg = reg | mask;
439 	ret = nct38xx_reg_update(config->nct38xx_dev,
440 				 NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
441 
442 done:
443 	k_sem_give(&data->lock);
444 
445 	return ret;
446 }
447 
gpio_nct38xx_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)448 static int gpio_nct38xx_manage_callback(const struct device *dev, struct gpio_callback *callback,
449 					bool set)
450 {
451 	struct gpio_nct38xx_port_data *const data = dev->data;
452 
453 	return gpio_manage_callback(&data->cb_list_gpio, callback, set);
454 }
455 
456 #ifdef CONFIG_GPIO_GET_DIRECTION
gpio_nct38xx_port_get_direction(const struct device * dev,gpio_port_pins_t mask,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)457 static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_pins_t mask,
458 					   gpio_port_pins_t *inputs, gpio_port_pins_t *outputs)
459 {
460 	const struct gpio_nct38xx_port_config *const config = dev->config;
461 	struct gpio_nct38xx_port_data *const data = dev->data;
462 	uint8_t dir_reg;
463 	int ret;
464 
465 	k_sem_take(&data->lock, K_FOREVER);
466 
467 	if (config->gpio_port == 0) {
468 		uint8_t enabled_gpios;
469 		/* Remove the disabled GPIOs from the mask */
470 		ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL,
471 					    &enabled_gpios);
472 		mask &= (enabled_gpios & config->common.port_pin_mask);
473 
474 		if (ret < 0) {
475 			goto done;
476 		}
477 	}
478 
479 	/* Read direction register, 0 - input, 1 - output */
480 	ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port),
481 				    &dir_reg);
482 	if (ret < 0) {
483 		goto done;
484 	}
485 
486 	if (inputs) {
487 		*inputs = mask & (~dir_reg);
488 	}
489 
490 	if (outputs) {
491 		*outputs = mask & dir_reg;
492 	}
493 
494 done:
495 	k_sem_give(&data->lock);
496 	return ret;
497 }
498 #endif /* CONFIG_GPIO_GET_DIRECTION */
499 
gpio_nct38xx_dispatch_port_isr(const struct device * dev)500 int gpio_nct38xx_dispatch_port_isr(const struct device *dev)
501 {
502 	const struct gpio_nct38xx_port_config *const config = dev->config;
503 	struct gpio_nct38xx_port_data *const data = dev->data;
504 	uint8_t alert_pins, mask;
505 	int ret;
506 
507 	do {
508 		k_sem_take(&data->lock, K_FOREVER);
509 		ret = nct38xx_reg_read_byte(config->nct38xx_dev,
510 					    NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
511 					    &alert_pins);
512 		if (ret < 0) {
513 			k_sem_give(&data->lock);
514 			return ret;
515 		}
516 
517 		ret = nct38xx_reg_read_byte(config->nct38xx_dev,
518 					    NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &mask);
519 		if (ret < 0) {
520 			k_sem_give(&data->lock);
521 			return ret;
522 		}
523 		alert_pins &= mask;
524 		if (alert_pins) {
525 			ret = nct38xx_reg_write_byte(config->nct38xx_dev,
526 						     NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
527 						     alert_pins);
528 			if (ret < 0) {
529 				k_sem_give(&data->lock);
530 				return ret;
531 			}
532 		}
533 		k_sem_give(&data->lock);
534 
535 		gpio_fire_callbacks(&data->cb_list_gpio, dev, alert_pins);
536 
537 		/*
538 		 * Vendor defined alert is generated if at least one STATn bit
539 		 * changes from 0 to 1. We should guarantee the STATn bit is
540 		 * clear to 0 before leaving isr.
541 		 */
542 	} while (alert_pins);
543 
544 	return 0;
545 }
546 
547 static const struct gpio_driver_api gpio_nct38xx_driver = {
548 	.pin_configure = gpio_nct38xx_pin_config,
549 #ifdef CONFIG_GPIO_GET_CONFIG
550 	.pin_get_config = gpio_nct38xx_pin_get_config,
551 #endif /* CONFIG_GPIO_GET_CONFIG */
552 	.port_get_raw = gpio_nct38xx_port_get_raw,
553 	.port_set_masked_raw = gpio_nct38xx_port_set_masked_raw,
554 	.port_set_bits_raw = gpio_nct38xx_port_set_bits_raw,
555 	.port_clear_bits_raw = gpio_nct38xx_port_clear_bits_raw,
556 	.port_toggle_bits = gpio_nct38xx_port_toggle_bits,
557 	.pin_interrupt_configure = gpio_nct38xx_pin_interrupt_configure,
558 	.manage_callback = gpio_nct38xx_manage_callback,
559 #ifdef CONFIG_GPIO_GET_DIRECTION
560 	.port_get_direction = gpio_nct38xx_port_get_direction,
561 #endif /* CONFIG_GPIO_GET_DIRECTION */
562 };
563 
gpio_nct38xx_port_init(const struct device * dev)564 static int gpio_nct38xx_port_init(const struct device *dev)
565 {
566 	const struct gpio_nct38xx_port_config *const config = dev->config;
567 	struct gpio_nct38xx_port_data *const data = dev->data;
568 
569 	if (!device_is_ready(config->nct38xx_dev)) {
570 		LOG_ERR("%s is not ready", config->nct38xx_dev->name);
571 		return -ENODEV;
572 	}
573 
574 	k_sem_init(&data->lock, 1, 1);
575 
576 	return 0;
577 }
578 
579 /* NCT38XX GPIO port driver must be initialized after NCT38XX GPIO driver */
580 BUILD_ASSERT(CONFIG_GPIO_NCT38XX_PORT_INIT_PRIORITY > CONFIG_GPIO_NCT38XX_INIT_PRIORITY);
581 
582 #define GPIO_NCT38XX_PORT_DEVICE_INSTANCE(inst)                                                    \
583 	static const struct gpio_nct38xx_port_config gpio_nct38xx_port_cfg_##inst = {              \
584 		.common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) &                \
585 					    DT_INST_PROP(inst, pin_mask)},                         \
586 		.nct38xx_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)),                                \
587 		.gpio_port = DT_INST_REG_ADDR(inst),                                               \
588 		.pinmux_mask = COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pinmux_mask),               \
589 					   (DT_INST_PROP(inst, pinmux_mask)), (0)),                \
590 	};                                                                                         \
591 	BUILD_ASSERT(                                                                              \
592 		!(DT_INST_REG_ADDR(inst) == 0 && !(DT_INST_NODE_HAS_PROP(inst, pinmux_mask))),     \
593 		"Port 0 should assign pinmux_mask property.");                                     \
594 	static struct gpio_nct38xx_port_data gpio_nct38xx_port_data_##inst;                        \
595 	DEVICE_DT_INST_DEFINE(inst, gpio_nct38xx_port_init, NULL, &gpio_nct38xx_port_data_##inst,  \
596 			      &gpio_nct38xx_port_cfg_##inst, POST_KERNEL,                          \
597 			      CONFIG_GPIO_NCT38XX_PORT_INIT_PRIORITY, &gpio_nct38xx_driver);
598 
599 DT_INST_FOREACH_STATUS_OKAY(GPIO_NCT38XX_PORT_DEVICE_INSTANCE)
600