1 /*- 2 * Copyright (c) 2016 Daniel Wyatt <Daniel.Wyatt@gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 * 28 */ 29 30 /* 31 * Nuvoton GPIO driver. 32 * 33 */ 34 35 #include <sys/cdefs.h> 36 37 #include <sys/param.h> 38 #include <sys/kernel.h> 39 #include <sys/systm.h> 40 #include <sys/bus.h> 41 #include <sys/eventhandler.h> 42 #include <sys/lock.h> 43 44 #include <sys/module.h> 45 #include <sys/rman.h> 46 #include <sys/gpio.h> 47 48 #include <isa/isavar.h> 49 50 #include <machine/bus.h> 51 #include <machine/resource.h> 52 53 #include <dev/gpio/gpiobusvar.h> 54 55 #include "gpio_if.h" 56 57 /* 58 * Global configuration registers (CR). 59 */ 60 #define NCT_CR_LDN 0x07 /* Logical Device Number */ 61 #define NCT_CR_CHIP_ID 0x20 /* Chip ID */ 62 #define NCT_CR_CHIP_ID_H 0x20 /* Chip ID (high byte) */ 63 #define NCT_CR_CHIP_ID_L 0x21 /* Chip ID (low byte) */ 64 #define NCT_CR_OPT_1 0x26 /* Global Options (1) */ 65 66 /* Logical Device Numbers. */ 67 #define NCT_LDN_GPIO 0x07 68 #define NCT_LDN_GPIO_CFG 0x08 69 #define NCT_LDN_GPIO_MODE 0x0f 70 71 /* Logical Device 7 */ 72 #define NCT_LD7_GPIO_ENABLE 0x30 73 #define NCT_LD7_GPIO0_IOR 0xe0 74 #define NCT_LD7_GPIO0_DAT 0xe1 75 #define NCT_LD7_GPIO0_INV 0xe2 76 #define NCT_LD7_GPIO0_DST 0xe3 77 #define NCT_LD7_GPIO1_IOR 0xe4 78 #define NCT_LD7_GPIO1_DAT 0xe5 79 #define NCT_LD7_GPIO1_INV 0xe6 80 #define NCT_LD7_GPIO1_DST 0xe7 81 82 /* Logical Device F */ 83 #define NCT_LDF_GPIO0_OUTCFG 0xe0 84 #define NCT_LDF_GPIO1_OUTCFG 0xe1 85 86 #define NCT_EXTFUNC_ENTER 0x87 87 #define NCT_EXTFUNC_EXIT 0xaa 88 89 #define NCT_MAX_PIN 15 90 #define NCT_IS_VALID_PIN(_p) ((_p) >= 0 && (_p) <= NCT_MAX_PIN) 91 92 #define NCT_PIN_BIT(_p) (1 << ((_p) % 8)) 93 94 #define NCT_GPIO_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ 95 GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \ 96 GPIO_PIN_INVIN | GPIO_PIN_INVOUT) 97 98 struct nct_softc { 99 device_t dev; 100 device_t busdev; 101 struct mtx mtx; 102 struct resource *portres; 103 int rid; 104 struct gpio_pin pins[NCT_MAX_PIN + 1]; 105 }; 106 107 #define GPIO_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \ 108 device_get_nameunit(dev), NULL, MTX_DEF) 109 #define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx) 110 #define GPIO_LOCK(_sc) mtx_lock(&(_sc)->mtx) 111 #define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) 112 #define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED) 113 #define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED) 114 115 #define NCT_BARRIER_WRITE(_sc) \ 116 bus_barrier((_sc)->portres, 0, 2, BUS_SPACE_BARRIER_WRITE) 117 118 #define NCT_BARRIER_READ_WRITE(_sc) \ 119 bus_barrier((_sc)->portres, 0, 2, \ 120 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) 121 122 static void ext_cfg_enter(struct nct_softc *); 123 static void ext_cfg_exit(struct nct_softc *); 124 125 /* 126 * Potential Extended Function Enable Register addresses. 127 * Same address as EFIR. 128 */ 129 uint8_t probe_addrs[] = {0x2e, 0x4e}; 130 131 struct nuvoton_vendor_device_id { 132 uint16_t chip_id; 133 const char * descr; 134 } nct_devs[] = { 135 { 136 .chip_id = 0x1061, 137 .descr = "Nuvoton NCT5104D", 138 }, 139 { 140 .chip_id = 0xc452, 141 .descr = "Nuvoton NCT5104D (PC-Engines APU)", 142 }, 143 { 144 .chip_id = 0xc453, 145 .descr = "Nuvoton NCT5104D (PC-Engines APU3)", 146 }, 147 }; 148 149 static void 150 write_cfg_reg_1(struct nct_softc *sc, uint8_t reg, uint8_t value) 151 { 152 GPIO_ASSERT_LOCKED(sc); 153 bus_write_1(sc->portres, 0, reg); 154 NCT_BARRIER_WRITE(sc); 155 bus_write_1(sc->portres, 1, value); 156 NCT_BARRIER_WRITE(sc); 157 } 158 159 static uint8_t 160 read_cfg_reg_1(struct nct_softc *sc, uint8_t reg) 161 { 162 uint8_t value; 163 164 GPIO_ASSERT_LOCKED(sc); 165 bus_write_1(sc->portres, 0, reg); 166 NCT_BARRIER_READ_WRITE(sc); 167 value = bus_read_1(sc->portres, 1); 168 NCT_BARRIER_READ_WRITE(sc); 169 170 return (value); 171 } 172 173 static uint16_t 174 read_cfg_reg_2(struct nct_softc *sc, uint8_t reg) 175 { 176 uint16_t value; 177 178 value = read_cfg_reg_1(sc, reg) << 8; 179 value |= read_cfg_reg_1(sc, reg + 1); 180 181 return (value); 182 } 183 184 /* 185 * Enable extended function mode. 186 * 187 */ 188 static void 189 ext_cfg_enter(struct nct_softc *sc) 190 { 191 GPIO_ASSERT_LOCKED(sc); 192 bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER); 193 NCT_BARRIER_WRITE(sc); 194 bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER); 195 NCT_BARRIER_WRITE(sc); 196 } 197 198 /* 199 * Disable extended function mode. 200 * 201 */ 202 static void 203 ext_cfg_exit(struct nct_softc *sc) 204 { 205 GPIO_ASSERT_LOCKED(sc); 206 bus_write_1(sc->portres, 0, NCT_EXTFUNC_EXIT); 207 NCT_BARRIER_WRITE(sc); 208 } 209 210 /* 211 * Select a Logical Device. 212 */ 213 static void 214 select_ldn(struct nct_softc *sc, uint8_t ldn) 215 { 216 write_cfg_reg_1(sc, NCT_CR_LDN, ldn); 217 } 218 219 /* 220 * Get the GPIO Input/Output register address 221 * for a pin. 222 */ 223 static uint8_t 224 nct_ior_addr(uint32_t pin_num) 225 { 226 uint8_t addr; 227 228 addr = NCT_LD7_GPIO0_IOR; 229 if (pin_num > 7) 230 addr = NCT_LD7_GPIO1_IOR; 231 232 return (addr); 233 } 234 235 /* 236 * Get the GPIO Data register address for a pin. 237 */ 238 static uint8_t 239 nct_dat_addr(uint32_t pin_num) 240 { 241 uint8_t addr; 242 243 addr = NCT_LD7_GPIO0_DAT; 244 if (pin_num > 7) 245 addr = NCT_LD7_GPIO1_DAT; 246 247 return (addr); 248 } 249 250 /* 251 * Get the GPIO Inversion register address 252 * for a pin. 253 */ 254 static uint8_t 255 nct_inv_addr(uint32_t pin_num) 256 { 257 uint8_t addr; 258 259 addr = NCT_LD7_GPIO0_INV; 260 if (pin_num > 7) 261 addr = NCT_LD7_GPIO1_INV; 262 263 return (addr); 264 } 265 266 /* 267 * Get the GPIO Output Configuration/Mode 268 * register address for a pin. 269 */ 270 static uint8_t 271 nct_outcfg_addr(uint32_t pin_num) 272 { 273 uint8_t addr; 274 275 addr = NCT_LDF_GPIO0_OUTCFG; 276 if (pin_num > 7) 277 addr = NCT_LDF_GPIO1_OUTCFG; 278 279 return (addr); 280 } 281 282 /* 283 * Set a pin to output mode. 284 */ 285 static void 286 nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num) 287 { 288 uint8_t reg; 289 uint8_t ior; 290 291 reg = nct_ior_addr(pin_num); 292 select_ldn(sc, NCT_LDN_GPIO); 293 ior = read_cfg_reg_1(sc, reg); 294 ior &= ~(NCT_PIN_BIT(pin_num)); 295 write_cfg_reg_1(sc, reg, ior); 296 } 297 298 /* 299 * Set a pin to input mode. 300 */ 301 static void 302 nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num) 303 { 304 uint8_t reg; 305 uint8_t ior; 306 307 reg = nct_ior_addr(pin_num); 308 select_ldn(sc, NCT_LDN_GPIO); 309 ior = read_cfg_reg_1(sc, reg); 310 ior |= NCT_PIN_BIT(pin_num); 311 write_cfg_reg_1(sc, reg, ior); 312 } 313 314 /* 315 * Check whether a pin is configured as an input. 316 */ 317 static bool 318 nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num) 319 { 320 uint8_t reg; 321 uint8_t ior; 322 323 reg = nct_ior_addr(pin_num); 324 select_ldn(sc, NCT_LDN_GPIO); 325 ior = read_cfg_reg_1(sc, reg); 326 327 return (ior & NCT_PIN_BIT(pin_num)); 328 } 329 330 /* 331 * Write a value to an output pin. 332 */ 333 static void 334 nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data) 335 { 336 uint8_t reg; 337 uint8_t value; 338 339 reg = nct_dat_addr(pin_num); 340 select_ldn(sc, NCT_LDN_GPIO); 341 value = read_cfg_reg_1(sc, reg); 342 if (data) 343 value |= NCT_PIN_BIT(pin_num); 344 else 345 value &= ~(NCT_PIN_BIT(pin_num)); 346 347 write_cfg_reg_1(sc, reg, value); 348 } 349 350 static bool 351 nct_read_pin(struct nct_softc *sc, uint32_t pin_num) 352 { 353 uint8_t reg; 354 355 reg = nct_dat_addr(pin_num); 356 select_ldn(sc, NCT_LDN_GPIO); 357 358 return (read_cfg_reg_1(sc, reg) & NCT_PIN_BIT(pin_num)); 359 } 360 361 static void 362 nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) 363 { 364 uint8_t reg; 365 uint8_t inv; 366 367 reg = nct_inv_addr(pin_num); 368 select_ldn(sc, NCT_LDN_GPIO); 369 inv = read_cfg_reg_1(sc, reg); 370 inv |= (NCT_PIN_BIT(pin_num)); 371 write_cfg_reg_1(sc, reg, inv); 372 } 373 374 static void 375 nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num) 376 { 377 uint8_t reg; 378 uint8_t inv; 379 380 reg = nct_inv_addr(pin_num); 381 select_ldn(sc, NCT_LDN_GPIO); 382 inv = read_cfg_reg_1(sc, reg); 383 inv &= ~(NCT_PIN_BIT(pin_num)); 384 write_cfg_reg_1(sc, reg, inv); 385 } 386 387 static bool 388 nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) 389 { 390 uint8_t reg; 391 uint8_t inv; 392 393 reg = nct_inv_addr(pin_num); 394 select_ldn(sc, NCT_LDN_GPIO); 395 inv = read_cfg_reg_1(sc, reg); 396 397 return (inv & NCT_PIN_BIT(pin_num)); 398 } 399 400 static void 401 nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num) 402 { 403 uint8_t reg; 404 uint8_t outcfg; 405 406 reg = nct_outcfg_addr(pin_num); 407 select_ldn(sc, NCT_LDN_GPIO_MODE); 408 outcfg = read_cfg_reg_1(sc, reg); 409 outcfg |= (NCT_PIN_BIT(pin_num)); 410 write_cfg_reg_1(sc, reg, outcfg); 411 } 412 413 static void 414 nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num) 415 { 416 uint8_t reg; 417 uint8_t outcfg; 418 419 reg = nct_outcfg_addr(pin_num); 420 select_ldn(sc, NCT_LDN_GPIO_MODE); 421 outcfg = read_cfg_reg_1(sc, reg); 422 outcfg &= ~(NCT_PIN_BIT(pin_num)); 423 write_cfg_reg_1(sc, reg, outcfg); 424 } 425 426 static bool 427 nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num) 428 { 429 uint8_t reg; 430 uint8_t outcfg; 431 432 reg = nct_outcfg_addr(pin_num); 433 select_ldn(sc, NCT_LDN_GPIO_MODE); 434 outcfg = read_cfg_reg_1(sc, reg); 435 436 return (outcfg & NCT_PIN_BIT(pin_num)); 437 } 438 439 static void 440 nct_identify(driver_t *driver, device_t parent) 441 { 442 if (device_find_child(parent, driver->name, 0) != NULL) 443 return; 444 445 BUS_ADD_CHILD(parent, 0, driver->name, 0); 446 } 447 448 static int 449 nct_probe(device_t dev) 450 { 451 int i, j; 452 int rc; 453 struct nct_softc *sc; 454 uint16_t chipid; 455 456 /* Make sure we do not claim some ISA PNP device. */ 457 if (isa_get_logicalid(dev) != 0) 458 return (ENXIO); 459 460 sc = device_get_softc(dev); 461 462 for (i = 0; i < nitems(probe_addrs); i++) { 463 sc->rid = 0; 464 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 465 probe_addrs[i], probe_addrs[i] + 1, 2, RF_ACTIVE); 466 if (sc->portres == NULL) 467 continue; 468 469 GPIO_LOCK_INIT(sc); 470 471 GPIO_ASSERT_UNLOCKED(sc); 472 GPIO_LOCK(sc); 473 ext_cfg_enter(sc); 474 chipid = read_cfg_reg_2(sc, NCT_CR_CHIP_ID); 475 ext_cfg_exit(sc); 476 GPIO_UNLOCK(sc); 477 478 GPIO_LOCK_DESTROY(sc); 479 480 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 481 bus_delete_resource(dev, SYS_RES_IOPORT, sc->rid); 482 483 for (j = 0; j < nitems(nct_devs); j++) { 484 if (chipid == nct_devs[j].chip_id) { 485 rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, probe_addrs[i], 2); 486 if (rc != 0) { 487 device_printf(dev, "bus_set_resource failed for address 0x%02X\n", probe_addrs[i]); 488 continue; 489 } 490 device_set_desc(dev, nct_devs[j].descr); 491 return (BUS_PROBE_DEFAULT); 492 } 493 } 494 } 495 return (ENXIO); 496 } 497 498 static int 499 nct_attach(device_t dev) 500 { 501 struct nct_softc *sc; 502 int i; 503 504 sc = device_get_softc(dev); 505 506 sc->rid = 0; 507 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 508 0ul, ~0ul, 2, RF_ACTIVE); 509 if (sc->portres == NULL) { 510 device_printf(dev, "cannot allocate ioport\n"); 511 return (ENXIO); 512 } 513 514 GPIO_LOCK_INIT(sc); 515 516 GPIO_ASSERT_UNLOCKED(sc); 517 GPIO_LOCK(sc); 518 ext_cfg_enter(sc); 519 select_ldn(sc, NCT_LDN_GPIO); 520 /* Enable gpio0 and gpio1. */ 521 write_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE, 522 read_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE) | 0x03); 523 524 for (i = 0; i <= NCT_MAX_PIN; i++) { 525 struct gpio_pin *pin; 526 527 pin = &sc->pins[i]; 528 pin->gp_pin = i; 529 pin->gp_caps = NCT_GPIO_CAPS; 530 pin->gp_flags = 0; 531 532 snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%02u", i); 533 pin->gp_name[GPIOMAXNAME - 1] = '\0'; 534 535 if (nct_pin_is_input(sc, i)) 536 pin->gp_flags |= GPIO_PIN_INPUT; 537 else 538 pin->gp_flags |= GPIO_PIN_OUTPUT; 539 540 if (nct_pin_is_opendrain(sc, i)) 541 pin->gp_flags |= GPIO_PIN_OPENDRAIN; 542 else 543 pin->gp_flags |= GPIO_PIN_PUSHPULL; 544 545 if (nct_pin_is_inverted(sc, i)) 546 pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT); 547 } 548 GPIO_UNLOCK(sc); 549 550 sc->busdev = gpiobus_attach_bus(dev); 551 if (sc->busdev == NULL) { 552 GPIO_ASSERT_UNLOCKED(sc); 553 GPIO_LOCK(sc); 554 ext_cfg_exit(sc); 555 GPIO_UNLOCK(sc); 556 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 557 GPIO_LOCK_DESTROY(sc); 558 559 return (ENXIO); 560 } 561 562 return (0); 563 } 564 565 static int 566 nct_detach(device_t dev) 567 { 568 struct nct_softc *sc; 569 570 sc = device_get_softc(dev); 571 gpiobus_detach_bus(dev); 572 573 GPIO_ASSERT_UNLOCKED(sc); 574 GPIO_LOCK(sc); 575 ext_cfg_exit(sc); 576 GPIO_UNLOCK(sc); 577 578 /* Cleanup resources. */ 579 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 580 581 GPIO_LOCK_DESTROY(sc); 582 583 return (0); 584 } 585 586 static device_t 587 nct_gpio_get_bus(device_t dev) 588 { 589 struct nct_softc *sc; 590 591 sc = device_get_softc(dev); 592 593 return (sc->busdev); 594 } 595 596 static int 597 nct_gpio_pin_max(device_t dev, int *npins) 598 { 599 *npins = NCT_MAX_PIN; 600 601 return (0); 602 } 603 604 static int 605 nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value) 606 { 607 struct nct_softc *sc; 608 609 if (!NCT_IS_VALID_PIN(pin_num)) 610 return (EINVAL); 611 612 sc = device_get_softc(dev); 613 GPIO_ASSERT_UNLOCKED(sc); 614 GPIO_LOCK(sc); 615 nct_write_pin(sc, pin_num, pin_value); 616 GPIO_UNLOCK(sc); 617 618 return (0); 619 } 620 621 static int 622 nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value) 623 { 624 struct nct_softc *sc; 625 626 if (!NCT_IS_VALID_PIN(pin_num)) 627 return (EINVAL); 628 629 sc = device_get_softc(dev); 630 GPIO_ASSERT_UNLOCKED(sc); 631 GPIO_LOCK(sc); 632 *pin_value = nct_read_pin(sc, pin_num); 633 GPIO_UNLOCK(sc); 634 635 return (0); 636 } 637 638 static int 639 nct_gpio_pin_toggle(device_t dev, uint32_t pin_num) 640 { 641 struct nct_softc *sc; 642 643 if (!NCT_IS_VALID_PIN(pin_num)) 644 return (EINVAL); 645 646 sc = device_get_softc(dev); 647 GPIO_ASSERT_UNLOCKED(sc); 648 GPIO_LOCK(sc); 649 if (nct_read_pin(sc, pin_num)) 650 nct_write_pin(sc, pin_num, 0); 651 else 652 nct_write_pin(sc, pin_num, 1); 653 654 GPIO_UNLOCK(sc); 655 656 return (0); 657 } 658 659 static int 660 nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps) 661 { 662 struct nct_softc *sc; 663 664 if (!NCT_IS_VALID_PIN(pin_num)) 665 return (EINVAL); 666 667 sc = device_get_softc(dev); 668 GPIO_ASSERT_UNLOCKED(sc); 669 GPIO_LOCK(sc); 670 *caps = sc->pins[pin_num].gp_caps; 671 GPIO_UNLOCK(sc); 672 673 return (0); 674 } 675 676 static int 677 nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags) 678 { 679 struct nct_softc *sc; 680 681 if (!NCT_IS_VALID_PIN(pin_num)) 682 return (EINVAL); 683 684 sc = device_get_softc(dev); 685 GPIO_ASSERT_UNLOCKED(sc); 686 GPIO_LOCK(sc); 687 *flags = sc->pins[pin_num].gp_flags; 688 GPIO_UNLOCK(sc); 689 690 return (0); 691 } 692 693 static int 694 nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name) 695 { 696 struct nct_softc *sc; 697 698 if (!NCT_IS_VALID_PIN(pin_num)) 699 return (EINVAL); 700 701 sc = device_get_softc(dev); 702 GPIO_ASSERT_UNLOCKED(sc); 703 GPIO_LOCK(sc); 704 memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME); 705 GPIO_UNLOCK(sc); 706 707 return (0); 708 } 709 710 static int 711 nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags) 712 { 713 struct nct_softc *sc; 714 struct gpio_pin *pin; 715 716 if (!NCT_IS_VALID_PIN(pin_num)) 717 return (EINVAL); 718 719 sc = device_get_softc(dev); 720 pin = &sc->pins[pin_num]; 721 if ((flags & pin->gp_caps) != flags) 722 return (EINVAL); 723 724 GPIO_ASSERT_UNLOCKED(sc); 725 GPIO_LOCK(sc); 726 if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 727 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 728 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 729 GPIO_UNLOCK(sc); 730 return (EINVAL); 731 } 732 733 if (flags & GPIO_PIN_INPUT) 734 nct_set_pin_is_input(sc, pin_num); 735 else 736 nct_set_pin_is_output(sc, pin_num); 737 } 738 739 if (flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) { 740 if (flags & GPIO_PIN_INPUT) { 741 GPIO_UNLOCK(sc); 742 return (EINVAL); 743 } 744 745 if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) == 746 (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) { 747 GPIO_UNLOCK(sc); 748 return (EINVAL); 749 } 750 751 if (flags & GPIO_PIN_OPENDRAIN) 752 nct_set_pin_opendrain(sc, pin_num); 753 else 754 nct_set_pin_pushpull(sc, pin_num); 755 } 756 757 if (flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) { 758 if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) != 759 (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) { 760 GPIO_UNLOCK(sc); 761 return (EINVAL); 762 } 763 764 if (flags & GPIO_PIN_INVIN) 765 nct_set_pin_is_inverted(sc, pin_num); 766 else 767 nct_set_pin_not_inverted(sc, pin_num); 768 } 769 770 pin->gp_flags = flags; 771 GPIO_UNLOCK(sc); 772 773 return (0); 774 } 775 776 static device_method_t nct_methods[] = { 777 /* Device interface */ 778 DEVMETHOD(device_identify, nct_identify), 779 DEVMETHOD(device_probe, nct_probe), 780 DEVMETHOD(device_attach, nct_attach), 781 DEVMETHOD(device_detach, nct_detach), 782 783 /* GPIO */ 784 DEVMETHOD(gpio_get_bus, nct_gpio_get_bus), 785 DEVMETHOD(gpio_pin_max, nct_gpio_pin_max), 786 DEVMETHOD(gpio_pin_get, nct_gpio_pin_get), 787 DEVMETHOD(gpio_pin_set, nct_gpio_pin_set), 788 DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle), 789 DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname), 790 DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps), 791 DEVMETHOD(gpio_pin_getflags, nct_gpio_pin_getflags), 792 DEVMETHOD(gpio_pin_setflags, nct_gpio_pin_setflags), 793 794 DEVMETHOD_END 795 }; 796 797 static driver_t nct_isa_driver = { 798 "gpio", 799 nct_methods, 800 sizeof(struct nct_softc) 801 }; 802 803 static devclass_t nct_devclass; 804 805 DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL); 806 MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1); 807