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 145 static void 146 write_cfg_reg_1(struct nct_softc *sc, uint8_t reg, uint8_t value) 147 { 148 GPIO_ASSERT_LOCKED(sc); 149 bus_write_1(sc->portres, 0, reg); 150 NCT_BARRIER_WRITE(sc); 151 bus_write_1(sc->portres, 1, value); 152 NCT_BARRIER_WRITE(sc); 153 } 154 155 static uint8_t 156 read_cfg_reg_1(struct nct_softc *sc, uint8_t reg) 157 { 158 uint8_t value; 159 160 GPIO_ASSERT_LOCKED(sc); 161 bus_write_1(sc->portres, 0, reg); 162 NCT_BARRIER_READ_WRITE(sc); 163 value = bus_read_1(sc->portres, 1); 164 NCT_BARRIER_READ_WRITE(sc); 165 166 return (value); 167 } 168 169 static uint16_t 170 read_cfg_reg_2(struct nct_softc *sc, uint8_t reg) 171 { 172 uint16_t value; 173 174 value = read_cfg_reg_1(sc, reg) << 8; 175 value |= read_cfg_reg_1(sc, reg + 1); 176 177 return (value); 178 } 179 180 /* 181 * Enable extended function mode. 182 * 183 */ 184 static void 185 ext_cfg_enter(struct nct_softc *sc) 186 { 187 GPIO_ASSERT_LOCKED(sc); 188 bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER); 189 NCT_BARRIER_WRITE(sc); 190 bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER); 191 NCT_BARRIER_WRITE(sc); 192 } 193 194 /* 195 * Disable extended function mode. 196 * 197 */ 198 static void 199 ext_cfg_exit(struct nct_softc *sc) 200 { 201 GPIO_ASSERT_LOCKED(sc); 202 bus_write_1(sc->portres, 0, NCT_EXTFUNC_EXIT); 203 NCT_BARRIER_WRITE(sc); 204 } 205 206 /* 207 * Select a Logical Device. 208 */ 209 static void 210 select_ldn(struct nct_softc *sc, uint8_t ldn) 211 { 212 write_cfg_reg_1(sc, NCT_CR_LDN, ldn); 213 } 214 215 /* 216 * Get the GPIO Input/Output register address 217 * for a pin. 218 */ 219 static uint8_t 220 nct_ior_addr(uint32_t pin_num) 221 { 222 uint8_t addr; 223 224 addr = NCT_LD7_GPIO0_IOR; 225 if (pin_num > 7) 226 addr = NCT_LD7_GPIO1_IOR; 227 228 return (addr); 229 } 230 231 /* 232 * Get the GPIO Data register address for a pin. 233 */ 234 static uint8_t 235 nct_dat_addr(uint32_t pin_num) 236 { 237 uint8_t addr; 238 239 addr = NCT_LD7_GPIO0_DAT; 240 if (pin_num > 7) 241 addr = NCT_LD7_GPIO1_DAT; 242 243 return (addr); 244 } 245 246 /* 247 * Get the GPIO Inversion register address 248 * for a pin. 249 */ 250 static uint8_t 251 nct_inv_addr(uint32_t pin_num) 252 { 253 uint8_t addr; 254 255 addr = NCT_LD7_GPIO0_INV; 256 if (pin_num > 7) 257 addr = NCT_LD7_GPIO1_INV; 258 259 return (addr); 260 } 261 262 /* 263 * Get the GPIO Output Configuration/Mode 264 * register address for a pin. 265 */ 266 static uint8_t 267 nct_outcfg_addr(uint32_t pin_num) 268 { 269 uint8_t addr; 270 271 addr = NCT_LDF_GPIO0_OUTCFG; 272 if (pin_num > 7) 273 addr = NCT_LDF_GPIO1_OUTCFG; 274 275 return (addr); 276 } 277 278 /* 279 * Set a pin to output mode. 280 */ 281 static void 282 nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num) 283 { 284 uint8_t reg; 285 uint8_t ior; 286 287 reg = nct_ior_addr(pin_num); 288 select_ldn(sc, NCT_LDN_GPIO); 289 ior = read_cfg_reg_1(sc, reg); 290 ior &= ~(NCT_PIN_BIT(pin_num)); 291 write_cfg_reg_1(sc, reg, ior); 292 } 293 294 /* 295 * Set a pin to input mode. 296 */ 297 static void 298 nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num) 299 { 300 uint8_t reg; 301 uint8_t ior; 302 303 reg = nct_ior_addr(pin_num); 304 select_ldn(sc, NCT_LDN_GPIO); 305 ior = read_cfg_reg_1(sc, reg); 306 ior |= NCT_PIN_BIT(pin_num); 307 write_cfg_reg_1(sc, reg, ior); 308 } 309 310 /* 311 * Check whether a pin is configured as an input. 312 */ 313 static bool 314 nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num) 315 { 316 uint8_t reg; 317 uint8_t ior; 318 319 reg = nct_ior_addr(pin_num); 320 select_ldn(sc, NCT_LDN_GPIO); 321 ior = read_cfg_reg_1(sc, reg); 322 323 return (ior & NCT_PIN_BIT(pin_num)); 324 } 325 326 /* 327 * Write a value to an output pin. 328 */ 329 static void 330 nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data) 331 { 332 uint8_t reg; 333 uint8_t value; 334 335 reg = nct_dat_addr(pin_num); 336 select_ldn(sc, NCT_LDN_GPIO); 337 value = read_cfg_reg_1(sc, reg); 338 if (data) 339 value |= NCT_PIN_BIT(pin_num); 340 else 341 value &= ~(NCT_PIN_BIT(pin_num)); 342 343 write_cfg_reg_1(sc, reg, value); 344 } 345 346 static bool 347 nct_read_pin(struct nct_softc *sc, uint32_t pin_num) 348 { 349 uint8_t reg; 350 351 reg = nct_dat_addr(pin_num); 352 select_ldn(sc, NCT_LDN_GPIO); 353 354 return (read_cfg_reg_1(sc, reg) & NCT_PIN_BIT(pin_num)); 355 } 356 357 static void 358 nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) 359 { 360 uint8_t reg; 361 uint8_t inv; 362 363 reg = nct_inv_addr(pin_num); 364 select_ldn(sc, NCT_LDN_GPIO); 365 inv = read_cfg_reg_1(sc, reg); 366 inv |= (NCT_PIN_BIT(pin_num)); 367 write_cfg_reg_1(sc, reg, inv); 368 } 369 370 static void 371 nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num) 372 { 373 uint8_t reg; 374 uint8_t inv; 375 376 reg = nct_inv_addr(pin_num); 377 select_ldn(sc, NCT_LDN_GPIO); 378 inv = read_cfg_reg_1(sc, reg); 379 inv &= ~(NCT_PIN_BIT(pin_num)); 380 write_cfg_reg_1(sc, reg, inv); 381 } 382 383 static bool 384 nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) 385 { 386 uint8_t reg; 387 uint8_t inv; 388 389 reg = nct_inv_addr(pin_num); 390 select_ldn(sc, NCT_LDN_GPIO); 391 inv = read_cfg_reg_1(sc, reg); 392 393 return (inv & NCT_PIN_BIT(pin_num)); 394 } 395 396 static void 397 nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num) 398 { 399 uint8_t reg; 400 uint8_t outcfg; 401 402 reg = nct_outcfg_addr(pin_num); 403 select_ldn(sc, NCT_LDN_GPIO_MODE); 404 outcfg = read_cfg_reg_1(sc, reg); 405 outcfg |= (NCT_PIN_BIT(pin_num)); 406 write_cfg_reg_1(sc, reg, outcfg); 407 } 408 409 static void 410 nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num) 411 { 412 uint8_t reg; 413 uint8_t outcfg; 414 415 reg = nct_outcfg_addr(pin_num); 416 select_ldn(sc, NCT_LDN_GPIO_MODE); 417 outcfg = read_cfg_reg_1(sc, reg); 418 outcfg &= ~(NCT_PIN_BIT(pin_num)); 419 write_cfg_reg_1(sc, reg, outcfg); 420 } 421 422 static bool 423 nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num) 424 { 425 uint8_t reg; 426 uint8_t outcfg; 427 428 reg = nct_outcfg_addr(pin_num); 429 select_ldn(sc, NCT_LDN_GPIO_MODE); 430 outcfg = read_cfg_reg_1(sc, reg); 431 432 return (outcfg & NCT_PIN_BIT(pin_num)); 433 } 434 435 static void 436 nct_identify(driver_t *driver, device_t parent) 437 { 438 if (device_find_child(parent, driver->name, 0) != NULL) 439 return; 440 441 BUS_ADD_CHILD(parent, 0, driver->name, 0); 442 } 443 444 static int 445 nct_probe(device_t dev) 446 { 447 int i, j; 448 int rc; 449 struct nct_softc *sc; 450 uint16_t chipid; 451 452 /* Make sure we do not claim some ISA PNP device. */ 453 if (isa_get_logicalid(dev) != 0) 454 return (ENXIO); 455 456 sc = device_get_softc(dev); 457 458 for (i = 0; i < nitems(probe_addrs); i++) { 459 sc->rid = 0; 460 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 461 probe_addrs[i], probe_addrs[i] + 1, 2, RF_ACTIVE); 462 if (sc->portres == NULL) 463 continue; 464 465 GPIO_LOCK_INIT(sc); 466 467 GPIO_ASSERT_UNLOCKED(sc); 468 GPIO_LOCK(sc); 469 ext_cfg_enter(sc); 470 chipid = read_cfg_reg_2(sc, NCT_CR_CHIP_ID); 471 ext_cfg_exit(sc); 472 GPIO_UNLOCK(sc); 473 474 GPIO_LOCK_DESTROY(sc); 475 476 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 477 bus_delete_resource(dev, SYS_RES_IOPORT, sc->rid); 478 479 for (j = 0; j < nitems(nct_devs); j++) { 480 if (chipid == nct_devs[j].chip_id) { 481 rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, probe_addrs[i], 2); 482 if (rc != 0) { 483 device_printf(dev, "bus_set_resource failed for address 0x%02X\n", probe_addrs[i]); 484 continue; 485 } 486 device_set_desc(dev, nct_devs[j].descr); 487 return (BUS_PROBE_DEFAULT); 488 } 489 } 490 } 491 return (ENXIO); 492 } 493 494 static int 495 nct_attach(device_t dev) 496 { 497 struct nct_softc *sc; 498 int i; 499 500 sc = device_get_softc(dev); 501 502 sc->rid = 0; 503 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 504 0ul, ~0ul, 2, RF_ACTIVE); 505 if (sc->portres == NULL) { 506 device_printf(dev, "cannot allocate ioport\n"); 507 return (ENXIO); 508 } 509 510 GPIO_LOCK_INIT(sc); 511 512 GPIO_ASSERT_UNLOCKED(sc); 513 GPIO_LOCK(sc); 514 ext_cfg_enter(sc); 515 select_ldn(sc, NCT_LDN_GPIO); 516 /* Enable gpio0 and gpio1. */ 517 write_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE, 518 read_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE) | 0x03); 519 520 for (i = 0; i <= NCT_MAX_PIN; i++) { 521 struct gpio_pin *pin; 522 523 pin = &sc->pins[i]; 524 pin->gp_pin = i; 525 pin->gp_caps = NCT_GPIO_CAPS; 526 pin->gp_flags = 0; 527 528 snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%02u", i); 529 pin->gp_name[GPIOMAXNAME - 1] = '\0'; 530 531 if (nct_pin_is_input(sc, i)) 532 pin->gp_flags |= GPIO_PIN_INPUT; 533 else 534 pin->gp_flags |= GPIO_PIN_OUTPUT; 535 536 if (nct_pin_is_opendrain(sc, i)) 537 pin->gp_flags |= GPIO_PIN_OPENDRAIN; 538 else 539 pin->gp_flags |= GPIO_PIN_PUSHPULL; 540 541 if (nct_pin_is_inverted(sc, i)) 542 pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT); 543 } 544 GPIO_UNLOCK(sc); 545 546 sc->busdev = gpiobus_attach_bus(dev); 547 if (sc->busdev == NULL) { 548 GPIO_ASSERT_UNLOCKED(sc); 549 GPIO_LOCK(sc); 550 ext_cfg_exit(sc); 551 GPIO_UNLOCK(sc); 552 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 553 GPIO_LOCK_DESTROY(sc); 554 555 return (ENXIO); 556 } 557 558 return (0); 559 } 560 561 static int 562 nct_detach(device_t dev) 563 { 564 struct nct_softc *sc; 565 566 sc = device_get_softc(dev); 567 gpiobus_detach_bus(dev); 568 569 GPIO_ASSERT_UNLOCKED(sc); 570 GPIO_LOCK(sc); 571 ext_cfg_exit(sc); 572 GPIO_UNLOCK(sc); 573 574 /* Cleanup resources. */ 575 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 576 577 GPIO_LOCK_DESTROY(sc); 578 579 return (0); 580 } 581 582 static device_t 583 nct_gpio_get_bus(device_t dev) 584 { 585 struct nct_softc *sc; 586 587 sc = device_get_softc(dev); 588 589 return (sc->busdev); 590 } 591 592 static int 593 nct_gpio_pin_max(device_t dev, int *npins) 594 { 595 *npins = NCT_MAX_PIN; 596 597 return (0); 598 } 599 600 static int 601 nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value) 602 { 603 struct nct_softc *sc; 604 605 if (!NCT_IS_VALID_PIN(pin_num)) 606 return (EINVAL); 607 608 sc = device_get_softc(dev); 609 GPIO_ASSERT_UNLOCKED(sc); 610 GPIO_LOCK(sc); 611 nct_write_pin(sc, pin_num, pin_value); 612 GPIO_UNLOCK(sc); 613 614 return (0); 615 } 616 617 static int 618 nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value) 619 { 620 struct nct_softc *sc; 621 622 if (!NCT_IS_VALID_PIN(pin_num)) 623 return (EINVAL); 624 625 sc = device_get_softc(dev); 626 GPIO_ASSERT_UNLOCKED(sc); 627 GPIO_LOCK(sc); 628 *pin_value = nct_read_pin(sc, pin_num); 629 GPIO_UNLOCK(sc); 630 631 return (0); 632 } 633 634 static int 635 nct_gpio_pin_toggle(device_t dev, uint32_t pin_num) 636 { 637 struct nct_softc *sc; 638 639 if (!NCT_IS_VALID_PIN(pin_num)) 640 return (EINVAL); 641 642 sc = device_get_softc(dev); 643 GPIO_ASSERT_UNLOCKED(sc); 644 GPIO_LOCK(sc); 645 if (nct_read_pin(sc, pin_num)) 646 nct_write_pin(sc, pin_num, 0); 647 else 648 nct_write_pin(sc, pin_num, 1); 649 650 GPIO_UNLOCK(sc); 651 652 return (0); 653 } 654 655 static int 656 nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps) 657 { 658 struct nct_softc *sc; 659 660 if (!NCT_IS_VALID_PIN(pin_num)) 661 return (EINVAL); 662 663 sc = device_get_softc(dev); 664 GPIO_ASSERT_UNLOCKED(sc); 665 GPIO_LOCK(sc); 666 *caps = sc->pins[pin_num].gp_caps; 667 GPIO_UNLOCK(sc); 668 669 return (0); 670 } 671 672 static int 673 nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags) 674 { 675 struct nct_softc *sc; 676 677 if (!NCT_IS_VALID_PIN(pin_num)) 678 return (EINVAL); 679 680 sc = device_get_softc(dev); 681 GPIO_ASSERT_UNLOCKED(sc); 682 GPIO_LOCK(sc); 683 *flags = sc->pins[pin_num].gp_flags; 684 GPIO_UNLOCK(sc); 685 686 return (0); 687 } 688 689 static int 690 nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name) 691 { 692 struct nct_softc *sc; 693 694 if (!NCT_IS_VALID_PIN(pin_num)) 695 return (EINVAL); 696 697 sc = device_get_softc(dev); 698 GPIO_ASSERT_UNLOCKED(sc); 699 GPIO_LOCK(sc); 700 memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME); 701 GPIO_UNLOCK(sc); 702 703 return (0); 704 } 705 706 static int 707 nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags) 708 { 709 struct nct_softc *sc; 710 struct gpio_pin *pin; 711 712 if (!NCT_IS_VALID_PIN(pin_num)) 713 return (EINVAL); 714 715 sc = device_get_softc(dev); 716 pin = &sc->pins[pin_num]; 717 if ((flags & pin->gp_caps) != flags) 718 return (EINVAL); 719 720 GPIO_ASSERT_UNLOCKED(sc); 721 GPIO_LOCK(sc); 722 if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 723 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 724 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 725 GPIO_UNLOCK(sc); 726 return (EINVAL); 727 } 728 729 if (flags & GPIO_PIN_INPUT) 730 nct_set_pin_is_input(sc, pin_num); 731 else 732 nct_set_pin_is_output(sc, pin_num); 733 } 734 735 if (flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) { 736 if (flags & GPIO_PIN_INPUT) { 737 GPIO_UNLOCK(sc); 738 return (EINVAL); 739 } 740 741 if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) == 742 (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) { 743 GPIO_UNLOCK(sc); 744 return (EINVAL); 745 } 746 747 if (flags & GPIO_PIN_OPENDRAIN) 748 nct_set_pin_opendrain(sc, pin_num); 749 else 750 nct_set_pin_pushpull(sc, pin_num); 751 } 752 753 if (flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) { 754 if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) != 755 (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) { 756 GPIO_UNLOCK(sc); 757 return (EINVAL); 758 } 759 760 if (flags & GPIO_PIN_INVIN) 761 nct_set_pin_is_inverted(sc, pin_num); 762 else 763 nct_set_pin_not_inverted(sc, pin_num); 764 } 765 766 pin->gp_flags = flags; 767 GPIO_UNLOCK(sc); 768 769 return (0); 770 } 771 772 static device_method_t nct_methods[] = { 773 /* Device interface */ 774 DEVMETHOD(device_identify, nct_identify), 775 DEVMETHOD(device_probe, nct_probe), 776 DEVMETHOD(device_attach, nct_attach), 777 DEVMETHOD(device_detach, nct_detach), 778 779 /* GPIO */ 780 DEVMETHOD(gpio_get_bus, nct_gpio_get_bus), 781 DEVMETHOD(gpio_pin_max, nct_gpio_pin_max), 782 DEVMETHOD(gpio_pin_get, nct_gpio_pin_get), 783 DEVMETHOD(gpio_pin_set, nct_gpio_pin_set), 784 DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle), 785 DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname), 786 DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps), 787 DEVMETHOD(gpio_pin_getflags, nct_gpio_pin_getflags), 788 DEVMETHOD(gpio_pin_setflags, nct_gpio_pin_setflags), 789 790 DEVMETHOD_END 791 }; 792 793 static driver_t nct_isa_driver = { 794 "gpio", 795 nct_methods, 796 sizeof(struct nct_softc) 797 }; 798 799 static devclass_t nct_devclass; 800 801 DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL); 802 MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1); 803