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