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 #include <sys/cdefs.h> 35 36 #include <sys/param.h> 37 #include <sys/kernel.h> 38 #include <sys/systm.h> 39 #include <sys/bus.h> 40 #include <sys/eventhandler.h> 41 #include <sys/lock.h> 42 43 #include <sys/module.h> 44 #include <sys/gpio.h> 45 46 #include <machine/bus.h> 47 48 #include <dev/gpio/gpiobusvar.h> 49 #include <dev/superio/superio.h> 50 51 #include "gpio_if.h" 52 53 #define NCT_PPOD_LDN 0xf /* LDN used to select Push-Pull/Open-Drain */ 54 55 /* Direct access through GPIO register table */ 56 #define NCT_IO_GSR 0 /* Group Select */ 57 #define NCT_IO_IOR 1 /* I/O */ 58 #define NCT_IO_DAT 2 /* Data */ 59 #define NCT_IO_INV 3 /* Inversion */ 60 #define NCT_IO_DST 4 /* Status */ 61 62 #define NCT_MAX_GROUP 9 63 #define NCT_MAX_PIN 75 64 65 #define NCT_PIN_IS_VALID(_sc, _p) ((_p) < (_sc)->npins) 66 #define NCT_PIN_GROUP(_sc, _p) ((_sc)->pinmap[(_p)].group) 67 #define NCT_PIN_GRPNUM(_sc, _p) ((_sc)->pinmap[(_p)].grpnum) 68 #define NCT_PIN_BIT(_sc, _p) ((_sc)->pinmap[(_p)].bit) 69 #define NCT_PIN_BITMASK(_p) (1 << ((_p) & 7)) 70 71 #define NCT_GPIO_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ 72 GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \ 73 GPIO_PIN_INVIN | GPIO_PIN_INVOUT) 74 75 #define NCT_PREFER_INDIRECT_CHANNEL 2 76 77 #define NCT_VERBOSE_PRINTF(dev, ...) \ 78 do { \ 79 if (__predict_false(bootverbose)) \ 80 device_printf(dev, __VA_ARGS__); \ 81 } while (0) 82 83 /* 84 * Note that the values are important. 85 * They match actual register offsets. 86 */ 87 typedef enum { 88 REG_IOR = 0, 89 REG_DAT = 1, 90 REG_INV = 2, 91 } reg_t; 92 93 struct nct_gpio_group { 94 uint32_t caps; 95 uint8_t enable_ldn; 96 uint8_t enable_reg; 97 uint8_t enable_mask; 98 uint8_t data_ldn; 99 uint8_t iobase; 100 uint8_t ppod_reg; /* Push-Pull/Open-Drain */ 101 uint8_t grpnum; 102 uint8_t pinbits[8]; 103 uint8_t npins; 104 }; 105 106 struct nct_softc { 107 device_t dev; 108 device_t busdev; 109 struct mtx mtx; 110 struct resource *iores; 111 int iorid; 112 int curgrp; 113 struct { 114 uint8_t ior[NCT_MAX_GROUP + 1]; /* direction, 1: input 0: output */ 115 uint8_t out[NCT_MAX_GROUP + 1]; /* output value */ 116 uint8_t out_known[NCT_MAX_GROUP + 1]; /* whether out is valid */ 117 uint8_t inv[NCT_MAX_GROUP + 1]; /* inversion, 1: inverted */ 118 } cache; 119 struct gpio_pin pins[NCT_MAX_PIN + 1]; 120 struct nct_device *nctdevp; 121 int npins; /* Total number of pins */ 122 123 /* Lookup tables */ 124 struct { 125 struct nct_gpio_group *group; 126 uint8_t grpnum; 127 uint8_t bit; 128 } pinmap[NCT_MAX_PIN+1]; 129 struct nct_gpio_group *grpmap[NCT_MAX_GROUP+1]; 130 }; 131 132 #define GPIO_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \ 133 device_get_nameunit(dev), NULL, MTX_DEF) 134 #define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx) 135 #define GPIO_LOCK(_sc) mtx_lock(&(_sc)->mtx) 136 #define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) 137 #define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED) 138 #define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED) 139 140 #define GET_BIT(v, b) (((v) >> (b)) & 1) 141 142 /* 143 * For most devices there are several GPIO devices, we attach only to one of 144 * them and use the rest without attaching. 145 */ 146 struct nct_device { 147 uint16_t devid; 148 int extid; 149 const char *descr; 150 int ngroups; 151 struct nct_gpio_group groups[NCT_MAX_GROUP + 1]; 152 } nct_devices[] = { 153 { 154 .devid = 0xa025, 155 .descr = "GPIO on Winbond 83627DHG IC ver. 5", 156 .ngroups = 5, 157 .groups = { 158 { 159 .grpnum = 2, 160 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 161 .enable_ldn = 0x09, 162 .enable_reg = 0x30, 163 .enable_mask = 0x01, 164 .data_ldn = 0x09, 165 .ppod_reg = 0xe0, /* FIXME Need to check for this group. */ 166 .caps = NCT_GPIO_CAPS, 167 .npins = 8, 168 .iobase = 0xe3, 169 }, 170 { 171 .grpnum = 3, 172 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 173 .enable_ldn = 0x09, 174 .enable_reg = 0x30, 175 .enable_mask = 0x02, 176 .data_ldn = 0x09, 177 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 178 .caps = NCT_GPIO_CAPS, 179 .npins = 8, 180 .iobase = 0xf0, 181 }, 182 { 183 .grpnum = 4, 184 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 185 .enable_ldn = 0x09, 186 .enable_reg = 0x30, 187 .enable_mask = 0x04, 188 .data_ldn = 0x09, 189 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 190 .caps = NCT_GPIO_CAPS, 191 .npins = 8, 192 .iobase = 0xf4, 193 }, 194 { 195 .grpnum = 5, 196 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 197 .enable_ldn = 0x09, 198 .enable_reg = 0x30, 199 .enable_mask = 0x08, 200 .data_ldn = 0x09, 201 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 202 .caps = NCT_GPIO_CAPS, 203 .npins = 8, 204 .iobase = 0xe0, 205 }, 206 { 207 .grpnum = 6, 208 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 209 .enable_ldn = 0x07, 210 .enable_reg = 0x30, 211 .enable_mask = 0x01, 212 .data_ldn = 0x07, 213 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 214 .caps = NCT_GPIO_CAPS, 215 .npins = 8, 216 .iobase = 0xf4, 217 }, 218 }, 219 }, 220 { 221 .devid = 0x1061, 222 .descr = "GPIO on Nuvoton NCT5104D", 223 .ngroups = 2, 224 .groups = { 225 { 226 .grpnum = 0, 227 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 228 .enable_ldn = 0x07, 229 .enable_reg = 0x30, 230 .enable_mask = 0x01, 231 .data_ldn = 0x07, 232 .ppod_reg = 0xe0, 233 .caps = NCT_GPIO_CAPS, 234 .npins = 8, 235 .iobase = 0xe0, 236 }, 237 { 238 .grpnum = 1, 239 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 240 .enable_ldn = 0x07, 241 .enable_reg = 0x30, 242 .enable_mask = 0x02, 243 .data_ldn = 0x07, 244 .ppod_reg = 0xe1, 245 .caps = NCT_GPIO_CAPS, 246 .npins = 8, 247 .iobase = 0xe4, 248 }, 249 }, 250 }, 251 { 252 .devid = 0xc452, /* FIXME Conflict with Nuvoton NCT6106D. See NetBSD's nct_match. */ 253 .descr = "GPIO on Nuvoton NCT5104D (PC-Engines APU)", 254 .ngroups = 2, 255 .groups = { 256 { 257 .grpnum = 0, 258 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 259 .enable_ldn = 0x07, 260 .enable_reg = 0x30, 261 .enable_mask = 0x01, 262 .data_ldn = 0x07, 263 .ppod_reg = 0xe0, 264 .caps = NCT_GPIO_CAPS, 265 .npins = 8, 266 .iobase = 0xe0, 267 }, 268 { 269 .grpnum = 1, 270 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 271 .enable_ldn = 0x07, 272 .enable_reg = 0x30, 273 .enable_mask = 0x02, 274 .data_ldn = 0x07, 275 .ppod_reg = 0xe1, 276 .caps = NCT_GPIO_CAPS, 277 .npins = 8, 278 .iobase = 0xe4, 279 }, 280 }, 281 }, 282 { 283 .devid = 0xc453, 284 .descr = "GPIO on Nuvoton NCT5104D (PC-Engines APU3)", 285 .ngroups = 2, 286 .groups = { 287 { 288 .grpnum = 0, 289 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 290 .enable_ldn = 0x07, 291 .enable_reg = 0x30, 292 .enable_mask = 0x01, 293 .data_ldn = 0x07, 294 .ppod_reg = 0xe0, 295 .caps = NCT_GPIO_CAPS, 296 .npins = 8, 297 .iobase = 0xe0, 298 }, 299 { 300 .grpnum = 1, 301 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 302 .enable_ldn = 0x07, 303 .enable_reg = 0x30, 304 .enable_mask = 0x02, 305 .data_ldn = 0x07, 306 .ppod_reg = 0xe1, 307 .caps = NCT_GPIO_CAPS, 308 .npins = 8, 309 .iobase = 0xe4, 310 }, 311 }, 312 }, 313 { 314 .devid = 0xd42a, 315 .extid = 1, 316 .descr = "GPIO on Nuvoton NCT6796D-E", 317 .ngroups = 10, 318 .groups = { 319 { 320 .grpnum = 0, 321 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 322 .enable_ldn = 0x08, 323 .enable_reg = 0x30, 324 .enable_mask = 0x02, 325 .data_ldn = 0x08, 326 .ppod_reg = 0xe0, /* FIXME Need to check for this group. */ 327 .caps = NCT_GPIO_CAPS, 328 .npins = 8, 329 .iobase = 0xe0, 330 }, 331 { 332 .grpnum = 1, 333 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 334 .enable_ldn = 0x08, 335 .enable_reg = 0x30, 336 .enable_mask = 0x80, 337 .data_ldn = 0x08, 338 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 339 .caps = NCT_GPIO_CAPS, 340 .npins = 8, 341 .iobase = 0xf0, 342 }, 343 { 344 .grpnum = 2, 345 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 346 .enable_ldn = 0x09, 347 .enable_reg = 0x30, 348 .enable_mask = 0x01, 349 .data_ldn = 0x09, 350 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 351 .caps = NCT_GPIO_CAPS, 352 .npins = 8, 353 .iobase = 0xe0, 354 }, 355 { 356 .grpnum = 3, 357 .pinbits = { 0, 1, 2, 3, 4, 5, 6 }, 358 .enable_ldn = 0x09, 359 .enable_reg = 0x30, 360 .enable_mask = 0x02, 361 .data_ldn = 0x09, 362 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 363 .caps = NCT_GPIO_CAPS, 364 .npins = 7, 365 .iobase = 0xe4, 366 }, 367 { 368 .grpnum = 4, 369 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 370 .enable_ldn = 0x09, 371 .enable_reg = 0x30, 372 .enable_mask = 0x04, 373 .data_ldn = 0x09, 374 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 375 .caps = NCT_GPIO_CAPS, 376 .npins = 8, 377 .iobase = 0xf0, /* FIXME Page 344 say "F0~F2, E8", 378 not "F0~F3". */ 379 }, 380 { 381 .grpnum = 5, 382 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 383 .enable_ldn = 0x09, 384 .enable_reg = 0x30, 385 .enable_mask = 0x08, 386 .data_ldn = 0x09, 387 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 388 .caps = NCT_GPIO_CAPS, 389 .npins = 8, 390 .iobase = 0xf4, 391 }, 392 { 393 .grpnum = 6, 394 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 395 .enable_ldn = 0x07, 396 .enable_reg = 0x30, 397 .enable_mask = 0x01, 398 .data_ldn = 0x07, 399 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 400 .caps = NCT_GPIO_CAPS, 401 .npins = 8, 402 .iobase = 0xf4, 403 }, 404 { 405 .grpnum = 7, 406 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 407 .enable_ldn = 0x07, 408 .enable_reg = 0x30, 409 .enable_mask = 0x02, 410 .data_ldn = 0x07, 411 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 412 .caps = NCT_GPIO_CAPS, 413 .npins = 8, 414 .iobase = 0xe0, 415 }, 416 { 417 .grpnum = 8, 418 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 419 .enable_ldn = 0x07, 420 .enable_reg = 0x30, 421 .enable_mask = 0x04, 422 .data_ldn = 0x07, 423 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 424 .caps = NCT_GPIO_CAPS, 425 .npins = 8, 426 .iobase = 0xe4, 427 }, 428 { 429 .grpnum = 9, 430 .pinbits = { 0, 1, 2, 3 }, 431 .enable_ldn = 0x07, 432 .enable_reg = 0x30, 433 .enable_mask = 0x08, 434 .data_ldn = 0x07, 435 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 436 .caps = NCT_GPIO_CAPS, 437 .npins = 4, 438 .iobase = 0xe8, 439 }, 440 }, 441 }, 442 { 443 .devid = 0xd42a, 444 .extid = 2, 445 .descr = "GPIO on Nuvoton NCT5585D", 446 .ngroups = 6, 447 .groups = { 448 { 449 .grpnum = 2, 450 .pinbits = { 0, 1, 2, 3, 4, 5, 6 }, 451 .enable_ldn = 0x09, 452 .enable_reg = 0x30, 453 .enable_mask = 0x01, 454 .data_ldn = 0x09, 455 .ppod_reg = 0xe1, 456 .caps = NCT_GPIO_CAPS, 457 .npins = 7, 458 .iobase = 0xe0, 459 }, 460 { 461 .grpnum = 3, 462 .pinbits = { 1, 2, 3 }, 463 .enable_ldn = 0x09, 464 .enable_reg = 0x30, 465 .enable_mask = 0x02, 466 .data_ldn = 0x09, 467 .ppod_reg = 0xe2, 468 .caps = NCT_GPIO_CAPS, 469 .npins = 3, 470 .iobase = 0xe4, 471 }, 472 { 473 .grpnum = 5, 474 .pinbits = { 0, 2, 6, 7 }, 475 .enable_ldn = 0x09, 476 .enable_reg = 0x30, 477 .enable_mask = 0x08, 478 .data_ldn = 0x09, 479 .ppod_reg = 0xe4, 480 .caps = NCT_GPIO_CAPS, 481 .npins = 4, 482 .iobase = 0xf4, 483 }, 484 { 485 .grpnum = 7, 486 .pinbits = { 4 }, 487 .enable_ldn = 0x07, 488 .enable_reg = 0x30, 489 .enable_mask = 0x02, 490 .data_ldn = 0x07, 491 .ppod_reg = 0xe6, 492 .caps = NCT_GPIO_CAPS, 493 .npins = 1, 494 .iobase = 0xe0, 495 }, 496 { 497 .grpnum = 8, 498 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 499 .enable_ldn = 0x07, 500 .enable_reg = 0x30, 501 .enable_mask = 0x04, 502 .data_ldn = 0x07, 503 .ppod_reg = 0xe7, 504 .caps = NCT_GPIO_CAPS, 505 .npins = 8, 506 .iobase = 0xe4, 507 }, 508 { 509 .grpnum = 9, 510 .pinbits = { 0, 2 }, 511 .enable_ldn = 0x07, 512 .enable_reg = 0x30, 513 .enable_mask = 0x08, 514 .data_ldn = 0x07, 515 .ppod_reg = 0xea, 516 .caps = NCT_GPIO_CAPS, 517 .npins = 2, 518 .iobase = 0xe8, 519 }, 520 }, 521 }, 522 { 523 .devid = 0xc562, 524 .descr = "GPIO on Nuvoton NCT6779D", 525 .ngroups = 9, 526 .groups = { 527 { 528 .grpnum = 0, 529 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 530 .enable_ldn = 0x08, 531 .enable_reg = 0x30, 532 .enable_mask = 0x01, 533 .data_ldn = 0x08, 534 .ppod_reg = 0xe0, /* FIXME Need to check for this group. */ 535 .caps = NCT_GPIO_CAPS, 536 .npins = 8, 537 .iobase = 0xe0, 538 }, 539 { 540 .grpnum = 1, 541 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 542 .enable_ldn = 0x09, 543 .enable_reg = 0x30, 544 .enable_mask = 0x01, 545 .data_ldn = 0x08, 546 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 547 .caps = NCT_GPIO_CAPS, 548 .npins = 8, 549 .iobase = 0xf0, 550 }, 551 { 552 .grpnum = 2, 553 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 554 .enable_ldn = 0x09, 555 .enable_reg = 0x30, 556 .enable_mask = 0x01, 557 .data_ldn = 0x09, 558 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 559 .caps = NCT_GPIO_CAPS, 560 .npins = 8, 561 .iobase = 0xe0, 562 }, 563 { 564 .grpnum = 3, 565 .pinbits = { 0, 1, 2, 3, 4, 5, 6 }, 566 .enable_ldn = 0x09, 567 .enable_reg = 0x30, 568 .enable_mask = 0x02, 569 .data_ldn = 0x09, 570 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 571 .caps = NCT_GPIO_CAPS, 572 .npins = 7, 573 .iobase = 0xe4, 574 }, 575 { 576 .grpnum = 4, 577 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 578 .enable_ldn = 0x09, 579 .enable_reg = 0x30, 580 .enable_mask = 0x04, 581 .data_ldn = 0x09, 582 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 583 .caps = NCT_GPIO_CAPS, 584 .npins = 8, 585 .iobase = 0xf0, 586 }, 587 { 588 .grpnum = 5, 589 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 590 .enable_ldn = 0x09, 591 .enable_reg = 0x30, 592 .enable_mask = 0x08, 593 .data_ldn = 0x09, 594 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 595 .caps = NCT_GPIO_CAPS, 596 .npins = 8, 597 .iobase = 0xf4, 598 }, 599 { 600 .grpnum = 6, 601 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 602 .enable_ldn = 0x09, 603 .enable_reg = 0x30, 604 .enable_mask = 0x01, 605 .data_ldn = 0x07, 606 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 607 .caps = NCT_GPIO_CAPS, 608 .npins = 8, 609 .iobase = 0xf4, 610 }, 611 { 612 .grpnum = 7, 613 .pinbits = { 0, 1, 2, 3, 4, 5, 6 }, 614 .enable_ldn = 0x09, 615 .enable_reg = 0x30, 616 .enable_mask = 0x02, 617 .data_ldn = 0x07, 618 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 619 .caps = NCT_GPIO_CAPS, 620 .npins = 7, 621 .iobase = 0xe0, 622 }, 623 { 624 .grpnum = 8, 625 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 626 .enable_ldn = 0x09, 627 .enable_reg = 0x30, 628 .enable_mask = 0x04, 629 .data_ldn = 0x07, 630 .ppod_reg = 0xe1, /* FIXME Need to check for this group. */ 631 .caps = NCT_GPIO_CAPS, 632 .npins = 8, 633 .iobase = 0xe4, 634 }, 635 }, 636 }, 637 { 638 .devid = 0xd282, 639 .descr = "GPIO on Nuvoton NCT6112D/NCT6114D/NCT6116D", 640 .ngroups = 9, 641 .groups = { 642 { 643 .grpnum = 0, 644 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 645 .enable_ldn = 0x07, 646 .enable_reg = 0x30, 647 .enable_mask = 0x01, 648 .data_ldn = 0x07, 649 .ppod_reg = 0xe0, 650 .caps = NCT_GPIO_CAPS, 651 .npins = 8, 652 .iobase = 0xe0, 653 }, 654 { 655 .grpnum = 1, 656 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 657 .enable_ldn = 0x07, 658 .enable_reg = 0x30, 659 .enable_mask = 0x02, 660 .data_ldn = 0x07, 661 .ppod_reg = 0xe1, 662 .caps = NCT_GPIO_CAPS, 663 .npins = 8, 664 .iobase = 0xe4, 665 }, 666 { 667 .grpnum = 2, 668 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 669 .enable_ldn = 0x07, 670 .enable_reg = 0x30, 671 .enable_mask = 0x04, 672 .data_ldn = 0x07, 673 .ppod_reg = 0xe1, 674 .caps = NCT_GPIO_CAPS, 675 .npins = 8, 676 .iobase = 0xe8, 677 }, 678 { 679 .grpnum = 3, 680 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 681 .enable_ldn = 0x07, 682 .enable_reg = 0x30, 683 .enable_mask = 0x08, 684 .data_ldn = 0x07, 685 .ppod_reg = 0xe1, 686 .caps = NCT_GPIO_CAPS, 687 .npins = 8, 688 .iobase = 0xec, 689 }, 690 { 691 .grpnum = 4, 692 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 693 .enable_ldn = 0x07, 694 .enable_reg = 0x30, 695 .enable_mask = 0x10, 696 .data_ldn = 0x07, 697 .ppod_reg = 0xe1, 698 .caps = NCT_GPIO_CAPS, 699 .npins = 8, 700 .iobase = 0xf0, 701 }, 702 { 703 .grpnum = 5, 704 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 705 .enable_ldn = 0x07, 706 .enable_reg = 0x30, 707 .enable_mask = 0x20, 708 .data_ldn = 0x07, 709 .ppod_reg = 0xe1, 710 .caps = NCT_GPIO_CAPS, 711 .npins = 8, 712 .iobase = 0xf4, 713 }, 714 { 715 .grpnum = 6, 716 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 717 .enable_ldn = 0x07, 718 .enable_reg = 0x30, 719 .enable_mask = 0x40, 720 .data_ldn = 0x07, 721 .ppod_reg = 0xe1, 722 .caps = NCT_GPIO_CAPS, 723 .npins = 8, 724 .iobase = 0xf8, 725 }, 726 { 727 .grpnum = 7, 728 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 729 .enable_ldn = 0x07, 730 .enable_reg = 0x30, 731 .enable_mask = 0x80, 732 .data_ldn = 0x07, 733 .ppod_reg = 0xe1, 734 .caps = NCT_GPIO_CAPS, 735 .npins = 8, 736 .iobase = 0xfc, 737 }, 738 { 739 .grpnum = 8, 740 .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, 741 .enable_ldn = 0x09, 742 .enable_reg = 0x30, 743 .enable_mask = 0x01, 744 .data_ldn = 0x09, 745 .ppod_reg = 0xe1, 746 .caps = NCT_GPIO_CAPS, 747 .npins = 8, 748 .iobase = 0xf0, 749 }, 750 }, 751 }, 752 }; 753 754 static const char * 755 io2str(uint8_t ioport) 756 { 757 switch (ioport) { 758 case NCT_IO_GSR: return ("grpsel"); 759 case NCT_IO_IOR: return ("io"); 760 case NCT_IO_DAT: return ("data"); 761 case NCT_IO_INV: return ("inv"); 762 case NCT_IO_DST: return ("status"); 763 default: return ("?"); 764 } 765 } 766 767 static void 768 nct_io_set_group(struct nct_softc *sc, uint8_t grpnum) 769 { 770 GPIO_ASSERT_LOCKED(sc); 771 772 if (grpnum == sc->curgrp) 773 return; 774 775 NCT_VERBOSE_PRINTF(sc->dev, "write %s 0x%x ioport %d\n", 776 io2str(NCT_IO_GSR), grpnum, NCT_IO_GSR); 777 bus_write_1(sc->iores, NCT_IO_GSR, grpnum); 778 sc->curgrp = grpnum; 779 } 780 781 static uint8_t 782 nct_io_read(struct nct_softc *sc, uint8_t grpnum, uint8_t reg) 783 { 784 uint8_t val; 785 786 nct_io_set_group(sc, grpnum); 787 788 val = bus_read_1(sc->iores, reg); 789 NCT_VERBOSE_PRINTF(sc->dev, "read %s 0x%x ioport %d\n", 790 io2str(reg), val, reg); 791 return (val); 792 } 793 794 static void 795 nct_io_write(struct nct_softc *sc, uint8_t grpnum, uint8_t reg, uint8_t val) 796 { 797 nct_io_set_group(sc, grpnum); 798 799 NCT_VERBOSE_PRINTF(sc->dev, "write %s 0x%x ioport %d\n", 800 io2str(reg), val, reg); 801 bus_write_1(sc->iores, reg, val); 802 } 803 804 static uint8_t 805 nct_get_ioreg(struct nct_softc *sc, reg_t reg, uint8_t grpnum) 806 { 807 uint8_t iobase; 808 809 if (sc->iores != NULL) 810 iobase = NCT_IO_IOR; 811 else 812 iobase = sc->grpmap[grpnum]->iobase; 813 return (iobase + reg); 814 } 815 816 static const char * 817 reg2str(reg_t reg) 818 { 819 switch (reg) { 820 case REG_IOR: return ("io"); 821 case REG_DAT: return ("data"); 822 case REG_INV: return ("inv"); 823 default: return ("?"); 824 } 825 } 826 827 static uint8_t 828 nct_read_reg(struct nct_softc *sc, reg_t reg, uint8_t grpnum) 829 { 830 struct nct_gpio_group *gp; 831 uint8_t ioreg; 832 uint8_t val; 833 834 ioreg = nct_get_ioreg(sc, reg, grpnum); 835 836 if (sc->iores != NULL) 837 return (nct_io_read(sc, grpnum, ioreg)); 838 839 gp = sc->grpmap[grpnum]; 840 val = superio_ldn_read(sc->dev, gp->data_ldn, ioreg); 841 NCT_VERBOSE_PRINTF(sc->dev, "read %s 0x%x from group GPIO%u ioreg 0x%x\n", 842 reg2str(reg), val, grpnum, ioreg); 843 return (val); 844 } 845 846 static int 847 nct_get_pin_cache(struct nct_softc *sc, uint32_t pin_num, uint8_t *cache) 848 { 849 uint8_t bit; 850 uint8_t group; 851 uint8_t val; 852 853 KASSERT(NCT_PIN_IS_VALID(sc, pin_num), ("%s: invalid pin number %d", 854 __func__, pin_num)); 855 856 group = NCT_PIN_GRPNUM(sc, pin_num); 857 bit = NCT_PIN_BIT(sc, pin_num); 858 val = cache[group]; 859 return (GET_BIT(val, bit)); 860 } 861 862 static void 863 nct_write_reg(struct nct_softc *sc, reg_t reg, uint8_t grpnum, uint8_t val) 864 { 865 struct nct_gpio_group *gp; 866 uint8_t ioreg; 867 868 ioreg = nct_get_ioreg(sc, reg, grpnum); 869 870 if (sc->iores != NULL) { 871 nct_io_write(sc, grpnum, ioreg, val); 872 return; 873 } 874 875 gp = sc->grpmap[grpnum]; 876 superio_ldn_write(sc->dev, gp->data_ldn, ioreg, val); 877 878 NCT_VERBOSE_PRINTF(sc->dev, "write %s 0x%x to group GPIO%u ioreg 0x%x\n", 879 reg2str(reg), val, grpnum, ioreg); 880 } 881 882 static void 883 nct_set_pin_reg(struct nct_softc *sc, reg_t reg, uint32_t pin_num, bool val) 884 { 885 uint8_t *cache; 886 uint8_t bit; 887 uint8_t bitval; 888 uint8_t group; 889 uint8_t mask; 890 891 KASSERT(NCT_PIN_IS_VALID(sc, pin_num), 892 ("%s: invalid pin number %d", __func__, pin_num)); 893 KASSERT(reg == REG_IOR || reg == REG_INV, 894 ("%s: unsupported register %d", __func__, reg)); 895 896 group = NCT_PIN_GRPNUM(sc, pin_num); 897 bit = NCT_PIN_BIT(sc, pin_num); 898 mask = (uint8_t)1 << bit; 899 bitval = (uint8_t)val << bit; 900 901 if (reg == REG_IOR) 902 cache = &sc->cache.ior[group]; 903 else 904 cache = &sc->cache.inv[group]; 905 if ((*cache & mask) == bitval) 906 return; 907 *cache &= ~mask; 908 *cache |= bitval; 909 nct_write_reg(sc, reg, group, *cache); 910 } 911 912 /* 913 * Set a pin to input (val is true) or output (val is false) mode. 914 */ 915 static void 916 nct_set_pin_input(struct nct_softc *sc, uint32_t pin_num, bool val) 917 { 918 nct_set_pin_reg(sc, REG_IOR, pin_num, val); 919 } 920 921 /* 922 * Check whether a pin is configured as an input. 923 */ 924 static bool 925 nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num) 926 { 927 return (nct_get_pin_cache(sc, pin_num, sc->cache.ior)); 928 } 929 930 /* 931 * Set a pin to inverted (val is true) or normal (val is false) mode. 932 */ 933 static void 934 nct_set_pin_inverted(struct nct_softc *sc, uint32_t pin_num, bool val) 935 { 936 nct_set_pin_reg(sc, REG_INV, pin_num, val); 937 } 938 939 static bool 940 nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) 941 { 942 return (nct_get_pin_cache(sc, pin_num, sc->cache.inv)); 943 } 944 945 /* 946 * Write a value to an output pin. 947 * NB: the hardware remembers last output value across switching from 948 * output mode to input mode and back. 949 * Writes to a pin in input mode are not allowed here as they cannot 950 * have any effect and would corrupt the output value cache. 951 */ 952 static void 953 nct_write_pin(struct nct_softc *sc, uint32_t pin_num, bool val) 954 { 955 uint8_t bit; 956 uint8_t group; 957 958 KASSERT(!nct_pin_is_input(sc, pin_num), ("attempt to write input pin")); 959 group = NCT_PIN_GRPNUM(sc, pin_num); 960 bit = NCT_PIN_BIT(sc, pin_num); 961 962 if (GET_BIT(sc->cache.out_known[group], bit) && 963 GET_BIT(sc->cache.out[group], bit) == val) { 964 /* The pin is already in requested state. */ 965 return; 966 } 967 sc->cache.out_known[group] |= 1 << bit; 968 if (val) 969 sc->cache.out[group] |= 1 << bit; 970 else 971 sc->cache.out[group] &= ~(1 << bit); 972 nct_write_reg(sc, REG_DAT, group, sc->cache.out[group]); 973 } 974 975 static bool 976 nct_get_pin_reg(struct nct_softc *sc, reg_t reg, uint32_t pin_num) 977 { 978 uint8_t bit; 979 uint8_t group; 980 uint8_t val; 981 bool b; 982 983 KASSERT(NCT_PIN_IS_VALID(sc, pin_num), ("%s: invalid pin number %d", 984 __func__, pin_num)); 985 986 group = NCT_PIN_GRPNUM(sc, pin_num); 987 bit = NCT_PIN_BIT(sc, pin_num); 988 val = nct_read_reg(sc, reg, group); 989 b = GET_BIT(val, bit); 990 991 if (__predict_false(bootverbose)) { 992 if (nct_pin_is_input(sc, pin_num)) 993 NCT_VERBOSE_PRINTF(sc->dev, "read %d from input pin %u<GPIO%u%u>\n", 994 b, pin_num, group, bit); 995 else 996 NCT_VERBOSE_PRINTF(sc->dev, 997 "read %d from output pin %u<GPIO%u%u>, cache miss\n", 998 b, pin_num, group, bit); 999 } 1000 1001 return (b); 1002 } 1003 1004 /* 1005 * NB: state of an input pin cannot be cached, of course. 1006 * For an output we can either take the value from the cache if it's valid 1007 * or read the state from the hadrware and cache it. 1008 */ 1009 static bool 1010 nct_read_pin(struct nct_softc *sc, uint32_t pin_num) 1011 { 1012 uint8_t bit; 1013 uint8_t group; 1014 bool val; 1015 1016 if (nct_pin_is_input(sc, pin_num)) { 1017 return (nct_get_pin_reg(sc, REG_DAT, pin_num)); 1018 } 1019 1020 group = NCT_PIN_GRPNUM(sc, pin_num); 1021 bit = NCT_PIN_BIT(sc, pin_num); 1022 1023 if (GET_BIT(sc->cache.out_known[group], bit)) { 1024 val = GET_BIT(sc->cache.out[group], bit); 1025 1026 NCT_VERBOSE_PRINTF(sc->dev, 1027 "read %d from output pin %u<GPIO%u%u>, cache hit\n", 1028 val, pin_num, group, bit); 1029 1030 return (val); 1031 } 1032 1033 val = nct_get_pin_reg(sc, REG_DAT, pin_num); 1034 sc->cache.out_known[group] |= 1 << bit; 1035 if (val) 1036 sc->cache.out[group] |= 1 << bit; 1037 else 1038 sc->cache.out[group] &= ~(1 << bit); 1039 return (val); 1040 } 1041 1042 /* FIXME Incorret for NCT5585D and probably other chips. */ 1043 static uint8_t 1044 nct_ppod_reg(struct nct_softc *sc, uint32_t pin_num) 1045 { 1046 uint8_t group = NCT_PIN_GRPNUM(sc, pin_num); 1047 1048 return (sc->grpmap[group]->ppod_reg); 1049 } 1050 1051 /* 1052 * NB: PP/OD can be configured only via configuration registers. 1053 * Also, the registers are in a different logical device. 1054 * So, this is a special case. No caching too. 1055 */ 1056 static void 1057 nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num) 1058 { 1059 uint8_t reg; 1060 uint8_t outcfg; 1061 1062 reg = nct_ppod_reg(sc, pin_num); 1063 outcfg = superio_ldn_read(sc->dev, NCT_PPOD_LDN, reg); 1064 outcfg |= NCT_PIN_BITMASK(pin_num); 1065 superio_ldn_write(sc->dev, 0xf, reg, outcfg); 1066 } 1067 1068 static void 1069 nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num) 1070 { 1071 uint8_t reg; 1072 uint8_t outcfg; 1073 1074 reg = nct_ppod_reg(sc, pin_num); 1075 outcfg = superio_ldn_read(sc->dev, NCT_PPOD_LDN, reg); 1076 outcfg &= ~NCT_PIN_BITMASK(pin_num); 1077 superio_ldn_write(sc->dev, 0xf, reg, outcfg); 1078 } 1079 1080 static bool 1081 nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num) 1082 { 1083 uint8_t reg; 1084 uint8_t outcfg; 1085 1086 reg = nct_ppod_reg(sc, pin_num); 1087 outcfg = superio_ldn_read(sc->dev, NCT_PPOD_LDN, reg); 1088 return (outcfg & NCT_PIN_BITMASK(pin_num)); 1089 } 1090 1091 static struct nct_device * 1092 nct_lookup_device(device_t dev) 1093 { 1094 struct nct_device *nctdevp; 1095 uint16_t devid; 1096 int i, extid; 1097 1098 devid = superio_devid(dev); 1099 extid = superio_extid(dev); 1100 for (i = 0, nctdevp = nct_devices; i < nitems(nct_devices); i++, nctdevp++) { 1101 if (devid == nctdevp->devid && nctdevp->extid == extid) 1102 return (nctdevp); 1103 } 1104 return (NULL); 1105 } 1106 1107 static int 1108 nct_probe(device_t dev) 1109 { 1110 struct nct_device *nctdevp; 1111 uint8_t ldn; 1112 1113 ldn = superio_get_ldn(dev); 1114 1115 if (superio_vendor(dev) != SUPERIO_VENDOR_NUVOTON) { 1116 NCT_VERBOSE_PRINTF(dev, "ldn 0x%x not a Nuvoton device\n", ldn); 1117 return (ENXIO); 1118 } 1119 if (superio_get_type(dev) != SUPERIO_DEV_GPIO) { 1120 NCT_VERBOSE_PRINTF(dev, "ldn 0x%x not a GPIO device\n", ldn); 1121 return (ENXIO); 1122 } 1123 1124 nctdevp = nct_lookup_device(dev); 1125 if (nctdevp == NULL) { 1126 NCT_VERBOSE_PRINTF(dev, "ldn 0x%x not supported\n", ldn); 1127 return (ENXIO); 1128 } 1129 device_set_desc(dev, nctdevp->descr); 1130 return (BUS_PROBE_DEFAULT); 1131 } 1132 1133 static int 1134 nct_attach(device_t dev) 1135 { 1136 struct nct_softc *sc; 1137 struct nct_gpio_group *gp; 1138 uint32_t pin_num; 1139 uint8_t v; 1140 int flags, i, g; 1141 1142 sc = device_get_softc(dev); 1143 sc->dev = dev; 1144 sc->nctdevp = nct_lookup_device(dev); 1145 1146 flags = 0; 1147 (void)resource_int_value(device_get_name(dev), device_get_unit(dev), "flags", &flags); 1148 1149 if ((flags & NCT_PREFER_INDIRECT_CHANNEL) == 0) { 1150 uint16_t iobase; 1151 device_t dev_8; 1152 1153 /* 1154 * As strange as it may seem, I/O port base is configured in the 1155 * Logical Device 8 which is primarily used for WDT, but also plays 1156 * a role in GPIO configuration. 1157 */ 1158 iobase = 0; 1159 dev_8 = superio_find_dev(device_get_parent(dev), SUPERIO_DEV_WDT, 8); 1160 if (dev_8 != NULL) 1161 iobase = superio_get_iobase(dev_8); 1162 if (iobase != 0 && iobase != 0xffff) { 1163 int err; 1164 1165 NCT_VERBOSE_PRINTF(dev, "iobase %#x\n", iobase); 1166 sc->curgrp = -1; 1167 sc->iorid = 0; 1168 err = bus_set_resource(dev, SYS_RES_IOPORT, sc->iorid, 1169 iobase, 7); /* FIXME NCT6796D-E have 8 registers according to table 18.3. */ 1170 if (err == 0) { 1171 sc->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 1172 &sc->iorid, RF_ACTIVE); 1173 if (sc->iores == NULL) { 1174 device_printf(dev, "can't map i/o space, " 1175 "iobase=%#x\n", iobase); 1176 } 1177 } else { 1178 device_printf(dev, 1179 "failed to set io port resource at %#x\n", iobase); 1180 } 1181 } 1182 } 1183 NCT_VERBOSE_PRINTF(dev, "iores %p %s channel\n", 1184 sc->iores, (sc->iores ? "direct" : "indirect")); 1185 1186 /* Enable GPIO groups */ 1187 for (g = 0, gp = sc->nctdevp->groups; g < sc->nctdevp->ngroups; g++, gp++) { 1188 NCT_VERBOSE_PRINTF(dev, 1189 "GPIO%d: %d pins, enable with mask 0x%x via ldn 0x%x reg 0x%x\n", 1190 gp->grpnum, gp->npins, gp->enable_mask, gp->enable_ldn, 1191 gp->enable_reg); 1192 v = superio_ldn_read(dev, gp->enable_ldn, gp->enable_reg); 1193 v |= gp->enable_mask; 1194 superio_ldn_write(dev, gp->enable_ldn, gp->enable_reg, v); 1195 } 1196 1197 GPIO_LOCK_INIT(sc); 1198 GPIO_LOCK(sc); 1199 1200 pin_num = 0; 1201 sc->npins = 0; 1202 for (g = 0, gp = sc->nctdevp->groups; g < sc->nctdevp->ngroups; g++, gp++) { 1203 1204 sc->grpmap[gp->grpnum] = gp; 1205 1206 /* 1207 * Caching input values is meaningless as an input can be changed at any 1208 * time by an external agent. But outputs are controlled by this 1209 * driver, so it can cache their state. Also, the hardware remembers 1210 * the output state of a pin when the pin is switched to input mode and 1211 * then back to output mode. So, the cache stays valid. 1212 * The only problem is with pins that are in input mode at the attach 1213 * time. For them the output state is not known until it is set by the 1214 * driver for the first time. 1215 * 'out' and 'out_known' bits form a tri-state output cache: 1216 * |-----+-----------+---------| 1217 * | out | out_known | cache | 1218 * |-----+-----------+---------| 1219 * | X | 0 | invalid | 1220 * | 0 | 1 | 0 | 1221 * | 1 | 1 | 1 | 1222 * |-----+-----------+---------| 1223 */ 1224 sc->cache.inv[gp->grpnum] = nct_read_reg(sc, REG_INV, gp->grpnum); 1225 sc->cache.ior[gp->grpnum] = nct_read_reg(sc, REG_IOR, gp->grpnum); 1226 sc->cache.out[gp->grpnum] = nct_read_reg(sc, REG_DAT, gp->grpnum); 1227 sc->cache.out_known[gp->grpnum] = ~sc->cache.ior[gp->grpnum]; 1228 1229 sc->npins += gp->npins; 1230 for (i = 0; i < gp->npins; i++, pin_num++) { 1231 struct gpio_pin *pin; 1232 1233 sc->pinmap[pin_num].group = gp; 1234 sc->pinmap[pin_num].grpnum = gp->grpnum; 1235 sc->pinmap[pin_num].bit = gp->pinbits[i]; 1236 1237 pin = &sc->pins[pin_num]; 1238 pin->gp_pin = pin_num; 1239 pin->gp_caps = gp->caps; 1240 pin->gp_flags = 0; 1241 1242 snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%u%u", 1243 gp->grpnum, gp->pinbits[i]); 1244 1245 if (nct_pin_is_input(sc, pin_num)) 1246 pin->gp_flags |= GPIO_PIN_INPUT; 1247 else 1248 pin->gp_flags |= GPIO_PIN_OUTPUT; 1249 1250 if (nct_pin_is_opendrain(sc, pin_num)) 1251 pin->gp_flags |= GPIO_PIN_OPENDRAIN; 1252 else 1253 pin->gp_flags |= GPIO_PIN_PUSHPULL; 1254 1255 if (nct_pin_is_inverted(sc, pin_num)) 1256 pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT); 1257 } 1258 } 1259 NCT_VERBOSE_PRINTF(dev, "%d pins available\n", sc->npins); 1260 1261 GPIO_UNLOCK(sc); 1262 1263 sc->busdev = gpiobus_attach_bus(dev); 1264 if (sc->busdev == NULL) { 1265 device_printf(dev, "failed to attach to gpiobus\n"); 1266 GPIO_LOCK_DESTROY(sc); 1267 return (ENXIO); 1268 } 1269 1270 return (0); 1271 } 1272 1273 static int 1274 nct_detach(device_t dev) 1275 { 1276 struct nct_softc *sc; 1277 1278 sc = device_get_softc(dev); 1279 gpiobus_detach_bus(dev); 1280 1281 if (sc->iores != NULL) 1282 bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->iores); 1283 GPIO_ASSERT_UNLOCKED(sc); 1284 GPIO_LOCK_DESTROY(sc); 1285 1286 return (0); 1287 } 1288 1289 static device_t 1290 nct_gpio_get_bus(device_t dev) 1291 { 1292 struct nct_softc *sc; 1293 1294 sc = device_get_softc(dev); 1295 1296 return (sc->busdev); 1297 } 1298 1299 static int 1300 nct_gpio_pin_max(device_t dev, int *maxpin) 1301 { 1302 struct nct_softc *sc; 1303 1304 sc = device_get_softc(dev); 1305 *maxpin = sc->npins - 1; 1306 return (0); 1307 } 1308 1309 static int 1310 nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value) 1311 { 1312 struct nct_softc *sc; 1313 1314 sc = device_get_softc(dev); 1315 1316 if (!NCT_PIN_IS_VALID(sc, pin_num)) 1317 return (EINVAL); 1318 1319 GPIO_LOCK(sc); 1320 if ((sc->pins[pin_num].gp_flags & GPIO_PIN_OUTPUT) == 0) { 1321 GPIO_UNLOCK(sc); 1322 return (EINVAL); 1323 } 1324 nct_write_pin(sc, pin_num, pin_value); 1325 GPIO_UNLOCK(sc); 1326 1327 return (0); 1328 } 1329 1330 static int 1331 nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value) 1332 { 1333 struct nct_softc *sc; 1334 1335 sc = device_get_softc(dev); 1336 1337 if (!NCT_PIN_IS_VALID(sc, pin_num)) 1338 return (EINVAL); 1339 1340 GPIO_ASSERT_UNLOCKED(sc); 1341 GPIO_LOCK(sc); 1342 *pin_value = nct_read_pin(sc, pin_num); 1343 GPIO_UNLOCK(sc); 1344 1345 return (0); 1346 } 1347 1348 static int 1349 nct_gpio_pin_toggle(device_t dev, uint32_t pin_num) 1350 { 1351 struct nct_softc *sc; 1352 1353 sc = device_get_softc(dev); 1354 1355 if (!NCT_PIN_IS_VALID(sc, pin_num)) 1356 return (EINVAL); 1357 1358 GPIO_ASSERT_UNLOCKED(sc); 1359 GPIO_LOCK(sc); 1360 if ((sc->pins[pin_num].gp_flags & GPIO_PIN_OUTPUT) == 0) { 1361 GPIO_UNLOCK(sc); 1362 return (EINVAL); 1363 } 1364 if (nct_read_pin(sc, pin_num)) 1365 nct_write_pin(sc, pin_num, 0); 1366 else 1367 nct_write_pin(sc, pin_num, 1); 1368 1369 GPIO_UNLOCK(sc); 1370 1371 return (0); 1372 } 1373 1374 static int 1375 nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps) 1376 { 1377 struct nct_softc *sc; 1378 1379 sc = device_get_softc(dev); 1380 1381 if (!NCT_PIN_IS_VALID(sc, pin_num)) 1382 return (EINVAL); 1383 1384 GPIO_ASSERT_UNLOCKED(sc); 1385 GPIO_LOCK(sc); 1386 *caps = sc->pins[pin_num].gp_caps; 1387 GPIO_UNLOCK(sc); 1388 1389 return (0); 1390 } 1391 1392 static int 1393 nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags) 1394 { 1395 struct nct_softc *sc; 1396 1397 sc = device_get_softc(dev); 1398 1399 if (!NCT_PIN_IS_VALID(sc, pin_num)) 1400 return (EINVAL); 1401 1402 GPIO_ASSERT_UNLOCKED(sc); 1403 GPIO_LOCK(sc); 1404 *flags = sc->pins[pin_num].gp_flags; 1405 GPIO_UNLOCK(sc); 1406 1407 return (0); 1408 } 1409 1410 static int 1411 nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name) 1412 { 1413 struct nct_softc *sc; 1414 1415 sc = device_get_softc(dev); 1416 1417 if (!NCT_PIN_IS_VALID(sc, pin_num)) 1418 return (EINVAL); 1419 1420 GPIO_ASSERT_UNLOCKED(sc); 1421 GPIO_LOCK(sc); 1422 memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME); 1423 GPIO_UNLOCK(sc); 1424 1425 return (0); 1426 } 1427 1428 static int 1429 nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags) 1430 { 1431 struct nct_softc *sc; 1432 struct gpio_pin *pin; 1433 1434 sc = device_get_softc(dev); 1435 1436 if (!NCT_PIN_IS_VALID(sc, pin_num)) 1437 return (EINVAL); 1438 1439 pin = &sc->pins[pin_num]; 1440 if ((flags & pin->gp_caps) != flags) 1441 return (EINVAL); 1442 1443 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 1444 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 1445 return (EINVAL); 1446 } 1447 if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) == 1448 (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) { 1449 return (EINVAL); 1450 } 1451 if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) == 1452 (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) { 1453 return (EINVAL); 1454 } 1455 1456 GPIO_ASSERT_UNLOCKED(sc); 1457 GPIO_LOCK(sc); 1458 1459 /* input or output */ 1460 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 0) { 1461 nct_set_pin_input(sc, pin_num, (flags & GPIO_PIN_INPUT) != 0); 1462 pin->gp_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT); 1463 pin->gp_flags |= flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT); 1464 } 1465 1466 /* invert */ 1467 if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) != 0) { 1468 nct_set_pin_inverted(sc, pin_num, 1); 1469 pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT); 1470 } else { 1471 nct_set_pin_inverted(sc, pin_num, 0); 1472 pin->gp_flags &= ~(GPIO_PIN_INVIN | GPIO_PIN_INVOUT); 1473 } 1474 1475 /* Open drain or push pull */ 1476 if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) != 0) { 1477 if (flags & GPIO_PIN_OPENDRAIN) 1478 nct_set_pin_opendrain(sc, pin_num); 1479 else 1480 nct_set_pin_pushpull(sc, pin_num); 1481 pin->gp_flags &= ~(GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL); 1482 pin->gp_flags |= 1483 flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL); 1484 } 1485 GPIO_UNLOCK(sc); 1486 1487 return (0); 1488 } 1489 1490 static device_method_t nct_methods[] = { 1491 /* Device interface */ 1492 DEVMETHOD(device_probe, nct_probe), 1493 DEVMETHOD(device_attach, nct_attach), 1494 DEVMETHOD(device_detach, nct_detach), 1495 1496 /* GPIO */ 1497 DEVMETHOD(gpio_get_bus, nct_gpio_get_bus), 1498 DEVMETHOD(gpio_pin_max, nct_gpio_pin_max), 1499 DEVMETHOD(gpio_pin_get, nct_gpio_pin_get), 1500 DEVMETHOD(gpio_pin_set, nct_gpio_pin_set), 1501 DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle), 1502 DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname), 1503 DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps), 1504 DEVMETHOD(gpio_pin_getflags, nct_gpio_pin_getflags), 1505 DEVMETHOD(gpio_pin_setflags, nct_gpio_pin_setflags), 1506 1507 DEVMETHOD_END 1508 }; 1509 1510 static driver_t nct_driver = { 1511 "gpio", 1512 nct_methods, 1513 sizeof(struct nct_softc) 1514 }; 1515 1516 DRIVER_MODULE(nctgpio, superio, nct_driver, NULL, NULL); 1517 MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1); 1518 MODULE_DEPEND(nctgpio, superio, 1, 1, 1); 1519 MODULE_VERSION(nctgpio, 1); 1520