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: releng/11.0/sys/dev/nctgpio/nctgpio.c 298322 2016-04-20 01:17:18Z cem $ 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 98struct 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 122static void ext_cfg_enter(struct nct_softc *); 123static void ext_cfg_exit(struct nct_softc *); 124 125/* 126 * Potential Extended Function Enable Register addresses. 127 * Same address as EFIR. 128 */ 129uint8_t probe_addrs[] = {0x2e, 0x4e}; 130 131struct 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 145static void 146write_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 155static uint8_t 156read_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 169static uint16_t 170read_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 */ 184static void 185ext_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 */ 198static void 199ext_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 */ 209static void 210select_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 */ 219static uint8_t 220nct_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 */ 234static uint8_t 235nct_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 */ 250static uint8_t 251nct_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 */ 266static uint8_t 267nct_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 */ 281static void 282nct_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 */ 297static void 298nct_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 */ 313static bool 314nct_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 */ 329static void 330nct_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 346static bool 347nct_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 357static void 358nct_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 370static void 371nct_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 383static bool 384nct_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 396static void 397nct_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 409static void 410nct_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 422static bool 423nct_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 435static void 436nct_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 444static int 445nct_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 494static int 495nct_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 561static int 562nct_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 582static device_t 583nct_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 592static int 593nct_gpio_pin_max(device_t dev, int *npins) 594{ 595 *npins = NCT_MAX_PIN; 596 597 return (0); 598} 599 600static int 601nct_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 617static int 618nct_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 634static int 635nct_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 655static int 656nct_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 672static int 673nct_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 689static int 690nct_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 706static int 707nct_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 772static 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 793static driver_t nct_isa_driver = { 794 "gpio", 795 nct_methods, 796 sizeof(struct nct_softc) 797}; 798 799static devclass_t nct_devclass; 800 801DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL); 802MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1); 803