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