Home | History | Annotate | Line # | Download | only in ic
      1 /*	$NetBSD: sc16is7xx.c,v 1.1 2025/10/24 23:16:11 brad Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2025 Brad Spencer <brad (at) anduin.eldar.org>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include "opt_fdt.h"
     20 
     21 #include <sys/cdefs.h>
     22 __KERNEL_RCSID(0, "$NetBSD: sc16is7xx.c,v 1.1 2025/10/24 23:16:11 brad Exp $");
     23 
     24 /* Common driver for the frontend to the NXP SC16IS7xx UART bridge */
     25 
     26 #include <sys/param.h>
     27 #include <sys/systm.h>
     28 #include <sys/kernel.h>
     29 #include <sys/kthread.h>
     30 #include <sys/device.h>
     31 #include <sys/module.h>
     32 #include <sys/sysctl.h>
     33 #include <sys/mutex.h>
     34 #include <sys/pool.h>
     35 #include <sys/proc.h>
     36 #include <sys/workqueue.h>
     37 
     38 #ifdef FDT
     39 #include <dev/fdt/fdtvar.h>
     40 #endif
     41 
     42 #include <dev/ic/sc16is7xxreg.h>
     43 #include <dev/ic/sc16is7xxvar.h>
     44 #include <dev/ic/sc16is7xx_ttyvar.h>
     45 
     46 const struct device_compatible_entry sc16is7xx_compat_data[] = {
     47 	{.compat = "nxp,sc16is740"},
     48 	{.compat = "nxp,sc16is741"},
     49 	{.compat = "nxp,sc16is750"},
     50 	{.compat = "nxp,sc16is752"},
     51 	{.compat = "nxp,sc16is760"},
     52 	{.compat = "nxp,sc16is762"},
     53 
     54 	DEVICE_COMPAT_EOL
     55 };
     56 
     57 void sc16is7xx_attach(struct sc16is7xx_sc *);
     58 static int sc16is7xx_verify_poll(SYSCTLFN_ARGS);
     59 static int sc16is7xx_verify_freq_sysctl(SYSCTLFN_ARGS);
     60 void sc16is7xx_thread(void *);
     61 
     62 /* Artifical interrupts and the like */
     63 
     64 static void
     65 sc16is7xx_comintr(struct sc16is7xx_sc *sc)
     66 {
     67 	struct sc16is7xx_tty_softc *csc;
     68 
     69 	for (int i = 0; i <= 1; i++){
     70 		if (sc->sc_ttydevchannel[i] != NULL) {
     71 			csc = device_private(sc->sc_ttydevchannel[i]);
     72 			if (csc != NULL)
     73 				comintr(&csc->sc_com);
     74 		}
     75 	}
     76 }
     77 
     78 void
     79 sc16is7xx_thread(void *arg)
     80 {
     81 	struct sc16is7xx_sc *sc = arg;
     82 
     83 	while (sc->sc_thread_run) {
     84 		sc16is7xx_comintr(sc);
     85 
     86 		kpause(device_xname(sc->sc_dev), false, mstohz(sc->sc_poll), NULL);
     87 	}
     88 	kthread_exit(0);
     89 }
     90 
     91 #ifdef FDT
     92 /* This song and dance is needed because:
     93 
     94    sc16is7xx_intr is entered in a hard interrupt context.  It is not
     95    allowed to call workqueue_enqueue() and can't call comintr()
     96    because that might need to talk to the I2C or SPI bus, allocate
     97    memory, or otherwise wait.
     98 
     99    sc16is7xx_softintr wasn't able to call comintr() directly as that
    100    resulted in a panic.
    101 
    102    Hence..  sc16is7xx_comintr() and then comintr() needed to be
    103    entered from a thread or a workqueue worker.
    104 */
    105 
    106 static void
    107 sc16is7xx_wq(struct work *wk, void *arg)
    108 {
    109 	struct sc16is7xx_sc *sc = arg;
    110 
    111 
    112 	sc16is7xx_comintr(sc);
    113 
    114 	pool_cache_put(sc->sc_wk_pool, wk);
    115 }
    116 
    117 static void
    118 sc16is7xx_softintr(void *arg)
    119 {
    120 	struct sc16is7xx_sc *sc = arg;
    121 	int *wk;
    122 
    123 	/* This is a little strange, but ensures that there is unique work to
    124 	 * be done.  See workqueue(9) about "A work must not be enqueued again
    125 	 * until the callback is called by the workqueue framework."
    126 	 *
    127 	 * If one tries to use a variable from the stack here you will panic if
    128 	 * there are a number of interrupts coming in quickly.  kmem_alloc()
    129 	 * also panic'ed.  This is running in a interrupt context, although it
    130 	 * is soft and kmem(9) didn't like that.
    131 	 *
    132 	 * There could be a lot of interrupts going on if the there is a lot to
    133 	 * receive or transmit.
    134 	 *
    135 	 * It may be possble to get clever and send a couple of work items, one
    136 	 * for each possible channel. */
    137 
    138 	wk = pool_cache_get(sc->sc_wk_pool, PR_NOWAIT);
    139 
    140 	if (wk != NULL) {
    141 		workqueue_enqueue(sc->sc_wq, (struct work *)wk, NULL);
    142 	}
    143 }
    144 
    145 static int
    146 sc16is7xx_intr(void *arg)
    147 {
    148 	struct sc16is7xx_sc *sc = arg;
    149 
    150 	softint_schedule(sc->sc_sih);
    151 
    152 	return 1;
    153 }
    154 #endif
    155 
    156 /* GPIO */
    157 
    158 static uint32_t
    159 sc16is7xx_to_gpio_flags(struct sc16is7xx_sc *sc, int pin, int nc,
    160     uint8_t iocontrol, uint8_t iodir)
    161 {
    162 	int f = 0;
    163 
    164 	if (pin <= 3) {
    165 		if (nc == 2) {
    166 			if (iocontrol & SC16IS7XX_IOCONTROL_3_0)
    167 				f = GPIO_PIN_ALT0;
    168 		}
    169 		if (f == 0) {
    170 			if (iodir & (1 << pin))
    171 				f = GPIO_PIN_OUTPUT;
    172 			else
    173 				f = GPIO_PIN_INPUT;
    174 		}
    175 	} else {
    176 		if (iocontrol & SC16IS7XX_IOCONTROL_7_4)
    177 			f = GPIO_PIN_ALT0;
    178 		else if (iodir & (1 << pin))
    179 			f = GPIO_PIN_OUTPUT;
    180 		else
    181 			f = GPIO_PIN_INPUT;
    182 	}
    183 
    184 	return f;
    185 }
    186 
    187 static int
    188 sc16is7xx_gpio_pin_read(void *arg, int pin)
    189 {
    190 	struct sc16is7xx_sc *sc = arg;
    191 	uint8_t r;
    192 	int rr = GPIO_PIN_LOW, error;
    193 
    194 	error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOSTATE, 1, &r, 1);
    195 	if (!error && (r & (1 << pin)))
    196 		rr = GPIO_PIN_HIGH;
    197 
    198 	return rr;
    199 }
    200 
    201 static void
    202 sc16is7xx_gpio_pin_write(void *arg, int pin, int value)
    203 {
    204 	struct sc16is7xx_sc *sc = arg;
    205 	uint8_t r;
    206 	int error;
    207 
    208 	error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOSTATE, 1, &r, 1);
    209 	if (!error) {
    210 		if (value)
    211 			r |= (1 << pin);
    212 		else
    213 			r &= ~(1 << pin);
    214 		error = sc->sc_funcs->write_reg(sc, SC16IS7XX_REGISTER_IOSTATE, 1, &r, 1);
    215 	}
    216 }
    217 
    218 static void
    219 sc16is7xx_gpio_ctl_alt0(struct sc16is7xx_sc *sc, uint8_t bank_mask,
    220     int low_pin, int high_pin, uint32_t flags)
    221 {
    222 	int error;
    223 	uint8_t iocontrol;
    224 
    225 	error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 1, &iocontrol, 1);
    226 	if (!error) {
    227 		iocontrol |= bank_mask;
    228 		error = sc->sc_funcs->write_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 1, &iocontrol, 1);
    229 		if (!error) {
    230 			for (int i = low_pin; i <= high_pin; i++)
    231 				sc->sc_gpio_pins[i].pin_flags = flags;
    232 		}
    233 	}
    234 }
    235 
    236 static void
    237 sc16is7xx_gpio_ctl_inout(struct sc16is7xx_sc *sc, uint8_t bank_mask,
    238     int low_pin, int high_pin, int a_pin, uint32_t flags)
    239 {
    240 	int error;
    241 	uint8_t iocontrol, iodir;
    242 
    243 	error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 1, &iocontrol, 1);
    244 	if (!error) {
    245 		iocontrol &= ~bank_mask;
    246 		error = sc->sc_funcs->write_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 1, &iocontrol, 1);
    247 		if (!error) {
    248 			error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IODIR, 1, &iodir, 1);
    249 			if (flags & GPIO_PIN_OUTPUT)
    250 				iodir |= (1 << a_pin);
    251 			if (flags & GPIO_PIN_INPUT)
    252 				iodir &= ~(1 << a_pin);
    253 			error = sc->sc_funcs->write_reg(sc, SC16IS7XX_REGISTER_IODIR, 1, &iodir, 1);
    254 			if (!error) {
    255 				for (int i = low_pin; i <= high_pin; i++)
    256 					sc->sc_gpio_pins[i].pin_flags = sc16is7xx_to_gpio_flags(sc, i, sc->sc_num_channels, iocontrol, iodir);
    257 			}
    258 		}
    259 	}
    260 }
    261 
    262 static void
    263 sc16is7xx_gpio_pin_ctl(void *arg, int pin, int flags)
    264 {
    265 	struct sc16is7xx_sc *sc = arg;
    266 	uint8_t bank_mask;
    267 	int low_pin, high_pin;
    268 
    269 	if (pin <= 3) {
    270 		bank_mask = SC16IS7XX_IOCONTROL_3_0;
    271 		low_pin = 0;
    272 		high_pin = 3;
    273 	} else {
    274 		bank_mask = SC16IS7XX_IOCONTROL_7_4;
    275 		low_pin = 4;
    276 		high_pin = SC16IS7XX_NPINS - 1;
    277 	}
    278 
    279 	if (flags & GPIO_PIN_ALT0) {
    280 		sc16is7xx_gpio_ctl_alt0(sc, bank_mask, low_pin, high_pin, flags);
    281 	} else {
    282 		sc16is7xx_gpio_ctl_inout(sc, bank_mask, low_pin, high_pin, pin, flags);
    283 	}
    284 }
    285 /* sysctl */
    286 
    287 int
    288 sc16is7xx_verify_poll(SYSCTLFN_ARGS)
    289 {
    290 	int error, t;
    291 	struct sysctlnode node;
    292 
    293 	node = *rnode;
    294 	t = *(int *)rnode->sysctl_data;
    295 	node.sysctl_data = &t;
    296 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    297 	if (error || newp == NULL)
    298 		return error;
    299 
    300 	if (t < 1)
    301 		return EINVAL;
    302 
    303 	*(int *)rnode->sysctl_data = t;
    304 
    305 	return 0;
    306 }
    307 
    308 int
    309 sc16is7xx_verify_freq_sysctl(SYSCTLFN_ARGS)
    310 {
    311 	struct sc16is7xx_sc *sc;
    312 	struct sc16is7xx_tty_softc *csc;
    313 	int error, t;
    314 	struct sysctlnode node;
    315 
    316 	node = *rnode;
    317 	sc = node.sysctl_data;
    318 	t = sc->sc_frequency;
    319 	node.sysctl_data = &t;
    320 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    321 	if (error || newp == NULL)
    322 		return error;
    323 
    324 	if (t < 1)
    325 		return EINVAL;
    326 
    327 	sc->sc_frequency = t;
    328 
    329 	for (int i = 0; i <= 1; i++){
    330 		if (sc->sc_ttydevchannel[i] != NULL) {
    331 			csc = device_private(sc->sc_ttydevchannel[i]);
    332 			if (csc != NULL)
    333 				csc->sc_com.sc_frequency = sc->sc_frequency;
    334 		}
    335 	}
    336 
    337 	return 0;
    338 }
    339 
    340 static int
    341 sc16is7xx_sysctl_init(struct sc16is7xx_sc *sc)
    342 {
    343 	int error;
    344 	const struct sysctlnode *cnode;
    345 	int sysctlroot_num;
    346 
    347 	if ((error = sysctl_createv(&sc->sc_sc16is7xx_log, 0, NULL, &cnode,
    348 	    0, CTLTYPE_NODE, device_xname(sc->sc_dev),
    349 	    SYSCTL_DESCR("sc16ix7xx controls"), NULL, 0, NULL, 0, CTL_HW,
    350 	    CTL_CREATE, CTL_EOL)) != 0)
    351 		return error;
    352 
    353 	sysctlroot_num = cnode->sysctl_num;
    354 
    355 	if ((error = sysctl_createv(&sc->sc_sc16is7xx_log, 0, NULL, &cnode,
    356 	    CTLFLAG_READWRITE, CTLTYPE_INT, "frequency",
    357 	    SYSCTL_DESCR("Frequency of the oscillator in Hz"), sc16is7xx_verify_freq_sysctl, 0,
    358 	    (void *)sc, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
    359 	    CTL_EOL)) != 0)
    360 		return error;
    361 
    362 	if ((error = sysctl_createv(&sc->sc_sc16is7xx_log, 0, NULL, &cnode,
    363 	    CTLFLAG_READWRITE, CTLTYPE_INT, "poll",
    364 	    SYSCTL_DESCR("In polling mode, how often to check the status register in ms"), sc16is7xx_verify_poll, 0,
    365 	    &sc->sc_poll, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
    366 	    CTL_EOL)) != 0)
    367 		return error;
    368 
    369 	return 0;
    370 }
    371 /* attach, detach and such */
    372 
    373 static int
    374 sc16is7xx_print(void *aux, const char *pnp)
    375 {
    376 	struct sc16is7xx_tty_attach_args *aa = aux;
    377 
    378 	if (pnp)
    379 		aprint_normal("PNP = %s", pnp);
    380 	aprint_normal(" channel %d", aa->aa_channel);
    381 	return (UNCONF);
    382 }
    383 
    384 void
    385 sc16is7xx_attach(struct sc16is7xx_sc *sc)
    386 {
    387 	int error;
    388 	char chip_type[SC16IS7XX_TYPE_STRINGLEN];
    389 	int num_channels;
    390 	int num_gpio;
    391 	uint8_t buf[1];
    392 	uint8_t iocontrol_reg;
    393 	struct sc16is7xx_tty_attach_args aa;
    394 	int reset_count = 0;
    395 
    396 	aprint_normal("\n");
    397 
    398 	sc->sc_frequency = SC16IS7XX_DEFAULT_FREQUENCY;
    399 	sc->sc_poll = SC16IS7XX_DEFAULT_POLL;
    400 	sc->sc_thread_run = false;
    401 	sc->sc_thread = NULL;
    402 	sc->sc_wq = NULL;
    403 	sc->sc_ih = NULL;
    404 	sc->sc_sih = NULL;
    405 
    406 	if ((error = sc16is7xx_sysctl_init(sc)) != 0) {
    407 		aprint_error_dev(sc->sc_dev, "Can't setup sysctl tree (%d)\n", error);
    408 		goto out;
    409 	}
    410 
    411 	/* Reset of the chip is a little odd.  Setting the SRESET bit is the
    412 	 * only write that will NACK.  So, an expected error will result in
    413 	 * that case.  Just ignore the error and read a few times to make sure
    414 	 * that the reset is done.  After the reset, one must delay at least
    415 	 * 3us before trying to talk to the chip again. */
    416 	error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 0, &iocontrol_reg, 1);
    417 	if (!error) {
    418 		iocontrol_reg |= SC16IS7XX_IOCONTROL_SRESET;
    419 		sc->sc_funcs->write_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 0, &iocontrol_reg, 1);
    420 		delay(5);
    421 		do {
    422 			error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 0, &iocontrol_reg, 1);
    423 			if (!error) {
    424 				if (iocontrol_reg & SC16IS7XX_IOCONTROL_SRESET) {
    425 					delay(2);
    426 				}
    427 				reset_count++;
    428 			}
    429 		} while ((iocontrol_reg & SC16IS7XX_IOCONTROL_SRESET) &&
    430 		    (reset_count < 100) &&
    431 		    (!error));
    432 	}
    433 	if (!error) {
    434 		if (iocontrol_reg & SC16IS7XX_IOCONTROL_SRESET) {
    435 			aprint_error_dev(sc->sc_dev,
    436 			    "Chip did not reset in time.  reset_count=%d\n", reset_count);
    437 		}
    438 	} else {
    439 		aprint_error_dev(sc->sc_dev,
    440 		    "Error reseting chip: error=%d, reset_count=%d\n",
    441 		    error, reset_count);
    442 	}
    443 
    444 	/* After a reset, the LCR register will be 0x1d.  If this isn't the
    445 	 * case with channel 1, then channel 1 does not exist and this is a
    446 	 * single UART chip, that is a SC16IS740, SC16IS750 or SC16IS760 and
    447 	 * not a SC16IS752 or SC16IS762.
    448 	 *
    449 	 * There does not appear to be a way to distinguish a SC16IS740 /
    450 	 * SC16IS741 from a SC16IS750 / SC16IS760.  The GPIO registers exist in
    451 	 * both varients and appear to behave the same.  Obviously the physical
    452 	 * pins are missing from the SC16IS74x branch of the family.  A bit
    453 	 * more detail is available if you have a system with FDT.
    454 	 *
    455 	 * */
    456 
    457 	num_channels = 1;
    458 	num_gpio = SC16IS7XX_NPINS;
    459 	strncpy(chip_type, "UNKNOWN", SC16IS7XX_TYPE_STRINGLEN);
    460 
    461 	error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_LCR, 1, buf, 1);
    462 	if (!error) {
    463 		if (buf[0] == 0x1d) {
    464 			strncpy(chip_type, "SC16IS752/SC16IS762", SC16IS7XX_TYPE_STRINGLEN);
    465 			num_channels = 2;
    466 		} else {
    467 			strncpy(chip_type, "SC16IS740/SC16IS741/SC16IS750/SC16IS760", SC16IS7XX_TYPE_STRINGLEN);
    468 		}
    469 	}
    470 	sc->sc_num_channels = num_channels;
    471 
    472 	aprint_normal_dev(sc->sc_dev, "NXP %s\n", chip_type);
    473 
    474 	sc->sc_ttydevchannel[0] = sc->sc_ttydevchannel[1] = NULL;
    475 
    476 	sc->sc_wk_pool = pool_cache_init(sizeof(int), 0, 0, 0, "sc16pool", NULL, IPL_SOFTSERIAL, NULL, NULL, NULL);
    477 
    478 	bool use_polling = true;
    479 
    480 #ifdef FDT
    481 
    482 	error = workqueue_create(&sc->sc_wq, device_xname(sc->sc_dev),
    483 	    sc16is7xx_wq, sc, PRI_SOFTSERIAL, IPL_SOFTSERIAL, WQ_MPSAFE);
    484 	if (error) {
    485 		aprint_error_dev(sc->sc_dev,
    486 		    "Could not create workqueue: %d\n",
    487 		    error);
    488 	}
    489 	if (!error &&
    490 	    devhandle_type(device_handle(sc->sc_dev)) == DEVHANDLE_TYPE_OF) {
    491 		char intrstr[128];
    492 
    493 		sc->sc_phandle = devhandle_to_of(device_handle(sc->sc_dev));
    494 
    495 		if (!of_hasprop(sc->sc_phandle, "gpio-controller")) {
    496 			num_gpio = 0;
    497 
    498 			/* If there is an indication that the GPIO is not
    499 			 * desired, turn the pins into modem control pins. */
    500 			error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 1, &iocontrol_reg, 1);
    501 			if (error)
    502 				goto out;
    503 			if (num_channels == 2)
    504 				iocontrol_reg |= SC16IS7XX_IOCONTROL_7_4 | SC16IS7XX_IOCONTROL_3_0;
    505 			else
    506 				iocontrol_reg |= SC16IS7XX_IOCONTROL_7_4;	/* No strictly correct
    507 										 * for the SC16IS74x */
    508 			error = sc->sc_funcs->write_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 1, &iocontrol_reg, 1);
    509 			if (error)
    510 				goto out;
    511 		}
    512 		if (fdtbus_intr_str(sc->sc_phandle, 0,
    513 		    intrstr, sizeof(intrstr))) {
    514 
    515 			aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr);
    516 
    517 			sc->sc_ih = fdtbus_intr_establish(sc->sc_phandle, 0, IPL_VM, 0,
    518 			    sc16is7xx_intr, sc);
    519 
    520 			if (sc->sc_ih == NULL) {
    521 				aprint_error_dev(sc->sc_dev,
    522 				    "unable to establish interrupt\n");
    523 			} else {
    524 				sc->sc_sih =
    525 				    softint_establish(SOFTINT_SERIAL, sc16is7xx_softintr, sc);
    526 				if (sc->sc_sih == NULL) {
    527 					aprint_error_dev(sc->sc_dev,
    528 					    "unable to establish soft interrupt\n");
    529 					fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih);
    530 					sc->sc_ih = NULL;
    531 				} else {
    532 					use_polling = false;
    533 				}
    534 			}
    535 		}
    536 		const u_int * cf;
    537 		int len;
    538 		cf = fdtbus_get_prop(sc->sc_phandle, "clock-frequency", &len);
    539 		if (cf != NULL && len > 0) {
    540 			sc->sc_frequency = be32toh(cf[0]);
    541 		}
    542 	}
    543 
    544 #endif
    545 
    546 	if (use_polling) {
    547 		aprint_normal_dev(sc->sc_dev, "polling for interrupts\n");
    548 
    549 		sc->sc_thread_run = true;
    550 		error = kthread_create(PRI_SOFTSERIAL, KTHREAD_MUSTJOIN | KTHREAD_MPSAFE, NULL,
    551 		    sc16is7xx_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev));
    552 		if (error) {
    553 			aprint_error_dev(sc->sc_dev,
    554 			    "Could not create kernel thread for polling: %d\n",
    555 			    error);
    556 			sc->sc_thread_run = false;
    557 		}
    558 	}
    559 	for (int i = 0; i < num_channels; i++){
    560 		aa.aa_channel = i;
    561 
    562 		sc->sc_ttydevchannel[i] = config_found(sc->sc_dev, &aa, sc16is7xx_print,
    563 		    CFARGS(.submatch = config_stdsubmatch,
    564 		    .iattr = "sc16is7xxbus"));
    565 
    566 	}
    567 
    568 	if (num_gpio > 0) {
    569 		struct gpiobus_attach_args gba;
    570 		uint8_t iodir_reg;
    571 		int c = 3;
    572 
    573 		if (num_channels == 2)
    574 			c = -1;
    575 
    576 		error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IOCONTROL, 1, &iocontrol_reg, 1);
    577 		if (error)
    578 			goto out;
    579 		error = sc->sc_funcs->read_reg(sc, SC16IS7XX_REGISTER_IODIR, 1, &iodir_reg, 1);
    580 		if (error)
    581 			goto out;
    582 
    583 		for (int i = 0; i < num_gpio; i++){
    584 			sc->sc_gpio_pins[i].pin_num = i;
    585 			sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT;
    586 			sc->sc_gpio_pins[i].pin_caps |= GPIO_PIN_OUTPUT;
    587 			if (i > c)
    588 				sc->sc_gpio_pins[i].pin_caps |= GPIO_PIN_ALT0;
    589 			sc->sc_gpio_pins[i].pin_flags =
    590 			    sc16is7xx_to_gpio_flags(sc, i, num_channels, iocontrol_reg, iodir_reg);
    591 			sc->sc_gpio_pins[i].pin_intrcaps = 0;
    592 			snprintf(sc->sc_gpio_pins[i].pin_defname, 4, "GP%d", i);
    593 		}
    594 
    595 		sc->sc_gpio_gc.gp_cookie = sc;
    596 		sc->sc_gpio_gc.gp_pin_read = sc16is7xx_gpio_pin_read;
    597 		sc->sc_gpio_gc.gp_pin_write = sc16is7xx_gpio_pin_write;
    598 		sc->sc_gpio_gc.gp_pin_ctl = sc16is7xx_gpio_pin_ctl;
    599 
    600 		gba.gba_gc = &sc->sc_gpio_gc;
    601 		gba.gba_pins = sc->sc_gpio_pins;
    602 		gba.gba_npins = SC16IS7XX_NPINS;
    603 
    604 		sc->sc_gpio_dev = config_found(sc->sc_dev, &gba, gpiobus_print,
    605 		    CFARGS(.iattr = "gpiobus"));
    606 	}
    607 
    608 out:
    609 
    610 	return;
    611 }
    612 
    613 int
    614 sc16is7xx_detach(struct sc16is7xx_sc *sc, int flags)
    615 {
    616 	int err = 0;
    617 
    618 	err = config_detach_children(sc->sc_dev, flags);
    619 
    620 	if (sc->sc_thread &&
    621 	    sc->sc_thread_run) {
    622 		sc->sc_thread_run = false;
    623 		kthread_join(sc->sc_thread);
    624 	}
    625 #ifdef FDT
    626 	if (sc->sc_ih != NULL)
    627 		fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih);
    628 
    629 	if (sc->sc_sih != NULL)
    630 		softint_disestablish(sc->sc_sih);
    631 #endif
    632 
    633 	pool_cache_destroy(sc->sc_wk_pool);
    634 
    635 	sysctl_teardown(&sc->sc_sc16is7xx_log);
    636 
    637 	return err;
    638 }
    639