1 /* $NetBSD: wbsio.c,v 1.24 2018/04/25 08:29:45 yamaguchi Exp $ */ 2 /* $OpenBSD: wbsio.c,v 1.10 2015/03/14 03:38:47 jsg Exp $ */ 3 /* 4 * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Winbond LPC Super I/O driver. 21 */ 22 23 #include <sys/cdefs.h> 24 #include <sys/param.h> 25 #include <sys/device.h> 26 #include <sys/kernel.h> 27 #include <sys/module.h> 28 #include <sys/systm.h> 29 #include <sys/mutex.h> 30 #include <sys/gpio.h> 31 32 #include <sys/bus.h> 33 34 #include <dev/isa/isareg.h> 35 #include <dev/isa/isavar.h> 36 #include <dev/isa/wbsioreg.h> 37 #include <dev/sysmon/sysmonvar.h> 38 39 /* Don't use gpio for now in the module */ 40 #if !defined(_MODULE) && defined(WBSIO_GPIO) 41 #include "gpio.h" 42 #endif 43 44 #if NGPIO > 0 45 #include <dev/gpio/gpiovar.h> 46 #endif 47 48 struct wbsio_softc { 49 device_t sc_dev; 50 device_t sc_lm_dev; 51 #if NGPIO > 0 52 device_t sc_gpio_dev; 53 #endif 54 55 bus_space_tag_t sc_iot; 56 bus_space_handle_t sc_ioh; 57 kmutex_t sc_conf_lock; 58 59 struct isa_attach_args sc_ia; 60 struct isa_io sc_io; 61 62 #if NGPIO > 0 63 bus_space_handle_t sc_gpio_ioh; 64 kmutex_t sc_gpio_lock; 65 struct gpio_chipset_tag sc_gpio_gc; 66 struct gpio_pin sc_gpio_pins[WBSIO_GPIO_NPINS]; 67 bool sc_gpio_rt; 68 #endif 69 70 struct sysmon_wdog sc_smw; 71 bool sc_smw_valid; 72 }; 73 74 static const struct wbsio_product { 75 uint16_t id; 76 bool idis12bits; 77 const char *str; 78 } wbsio_products[] = { 79 { WBSIO_ID_W83627HF, false, "W83627HF" }, 80 { WBSIO_ID_W83697HF, false, "W83697HF" }, 81 { WBSIO_ID_W83637HF, false, "W83637HF" }, 82 { WBSIO_ID_W83627THF, false, "W83627THF" }, 83 { WBSIO_ID_W83687THF, false, "W83687THF" }, 84 { WBSIO_ID_W83627DHG, true, "W83627DHG" }, 85 { WBSIO_ID_W83627DHGP, true, "W83627DHG-P" }, 86 { WBSIO_ID_W83627EHF, true, "W83627EHF" }, 87 { WBSIO_ID_W83627SF, true, "W83627SF" }, 88 { WBSIO_ID_W83627UHG, true, "W83627UHG" }, 89 { WBSIO_ID_W83667HG, true, "W83667HG" }, 90 { WBSIO_ID_W83667HGB, true, "W83667HGB" }, 91 { WBSIO_ID_W83697UG, true, "W83697UG" }, 92 { WBSIO_ID_NCT6775F, true, "NCT6775F" }, 93 { WBSIO_ID_NCT6776F, true, "NCT6776F" }, 94 { WBSIO_ID_NCT5104D, true, "NCT5104D or 610[246]D" }, 95 { WBSIO_ID_NCT6779D, true, "NCT6779D" }, 96 { WBSIO_ID_NCT6791D, true, "NCT6791D" }, 97 { WBSIO_ID_NCT6792D, true, "NCT6792D" }, 98 { WBSIO_ID_NCT6793D, true, "NCT6793D" }, 99 { WBSIO_ID_NCT6795D, true, "NCT6795D" }, 100 { WBSIO_ID_NCT6796D, true, "NCT6796D" }, 101 }; 102 103 static const struct wbsio_product *wbsio_lookup(uint8_t id, uint8_t rev); 104 static int wbsio_match(device_t, cfdata_t, void *); 105 static void wbsio_attach(device_t, device_t, void *); 106 static int wbsio_detach(device_t, int); 107 static int wbsio_rescan(device_t, const char *, const int *); 108 static void wbsio_childdet(device_t, device_t); 109 static int wbsio_print(void *, const char *); 110 static int wbsio_search(device_t, cfdata_t, const int *, void *); 111 static bool wbsio_suspend(device_t, const pmf_qual_t *); 112 #if NGPIO > 0 113 static int wbsio_gpio_search(device_t, cfdata_t, const int *, void *); 114 static int wbsio_gpio_rt_init(struct wbsio_softc *); 115 static int wbsio_gpio_rt_read(struct wbsio_softc *, int, int); 116 static void wbsio_gpio_rt_write(struct wbsio_softc *, int, int, int); 117 static int wbsio_gpio_rt_pin_read(void *, int); 118 static void wbsio_gpio_rt_pin_write(void *, int, int); 119 static void wbsio_gpio_rt_pin_ctl(void *, int, int); 120 static void wbsio_gpio_enable_nct6779d(device_t); 121 static void wbsio_gpio_pinconfig_nct6779d(device_t); 122 #endif 123 static void wbsio_wdog_attach(device_t); 124 static int wbsio_wdog_detach(device_t); 125 static int wbsio_wdog_setmode(struct sysmon_wdog *); 126 static int wbsio_wdog_tickle(struct sysmon_wdog *); 127 static void wbsio_wdog_setcounter(struct wbsio_softc *, uint8_t); 128 static void wbsio_wdog_clear_timeout(struct wbsio_softc *); 129 130 CFATTACH_DECL2_NEW(wbsio, sizeof(struct wbsio_softc), 131 wbsio_match, wbsio_attach, wbsio_detach, NULL, 132 wbsio_rescan, wbsio_childdet); 133 134 static __inline void 135 wbsio_conf_enable(kmutex_t *lock, bus_space_tag_t iot, bus_space_handle_t ioh) 136 { 137 if (lock) 138 mutex_enter(lock); 139 140 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC); 141 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC); 142 } 143 144 static __inline void 145 wbsio_conf_disable(kmutex_t *lock, bus_space_tag_t iot, bus_space_handle_t ioh) 146 { 147 148 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_DS_MAGIC); 149 150 if (lock) 151 mutex_exit(lock); 152 } 153 154 static __inline uint8_t 155 wbsio_conf_read(bus_space_tag_t iot, bus_space_handle_t ioh, uint8_t index) 156 { 157 bus_space_write_1(iot, ioh, WBSIO_INDEX, index); 158 return (bus_space_read_1(iot, ioh, WBSIO_DATA)); 159 } 160 161 static __inline void 162 wbsio_conf_write(bus_space_tag_t iot, bus_space_handle_t ioh, uint8_t index, 163 uint8_t data) 164 { 165 bus_space_write_1(iot, ioh, WBSIO_INDEX, index); 166 bus_space_write_1(iot, ioh, WBSIO_DATA, data); 167 } 168 169 static const struct wbsio_product * 170 wbsio_lookup(uint8_t id, uint8_t rev) 171 { 172 uint16_t wid = ((uint16_t)id << 4) | (rev >> 4); 173 int i; 174 175 for (i = 0; i < __arraycount(wbsio_products); i++) { 176 if (wbsio_products[i].idis12bits) { 177 if (wbsio_products[i].id == wid) 178 return &wbsio_products[i]; 179 } else { 180 if (wbsio_products[i].id == id) 181 return &wbsio_products[i]; 182 } 183 } 184 185 /* Not found */ 186 return NULL; 187 } 188 189 int 190 wbsio_match(device_t parent, cfdata_t match, void *aux) 191 { 192 struct isa_attach_args *ia = aux; 193 const struct wbsio_product *product; 194 bus_space_tag_t iot; 195 bus_space_handle_t ioh; 196 uint8_t id, rev; 197 198 /* Must supply an address */ 199 if (ia->ia_nio < 1) 200 return 0; 201 202 if (ISA_DIRECT_CONFIG(ia)) 203 return 0; 204 205 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 206 return 0; 207 208 /* Match by device ID */ 209 iot = ia->ia_iot; 210 if (bus_space_map(iot, ia->ia_io[0].ir_addr, WBSIO_IOSIZE, 0, &ioh)) 211 return 0; 212 wbsio_conf_enable(NULL, iot, ioh); 213 id = wbsio_conf_read(iot, ioh, WBSIO_ID); 214 rev = wbsio_conf_read(iot, ioh, WBSIO_REV); 215 aprint_debug("wbsio_probe: id 0x%02x, rev 0x%02x\n", id, rev); 216 wbsio_conf_disable(NULL, iot, ioh); 217 bus_space_unmap(iot, ioh, WBSIO_IOSIZE); 218 219 if ((product = wbsio_lookup(id, rev)) == NULL) 220 return 0; 221 222 ia->ia_nio = 1; 223 ia->ia_io[0].ir_size = WBSIO_IOSIZE; 224 ia->ia_niomem = 0; 225 ia->ia_nirq = 0; 226 ia->ia_ndrq = 0; 227 return 1; 228 } 229 230 void 231 wbsio_attach(device_t parent, device_t self, void *aux) 232 { 233 struct wbsio_softc *sc = device_private(self); 234 struct isa_attach_args *ia = aux; 235 const struct wbsio_product *product; 236 const char *desc; 237 const char *vendor; 238 uint8_t id, rev; 239 240 sc->sc_dev = self; 241 242 sc->sc_ia = *ia; 243 244 /* Map ISA I/O space */ 245 sc->sc_iot = ia->ia_iot; 246 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 247 WBSIO_IOSIZE, 0, &sc->sc_ioh)) { 248 aprint_error(": can't map i/o space\n"); 249 return; 250 } 251 252 mutex_init(&sc->sc_conf_lock, MUTEX_DEFAULT, IPL_NONE); 253 254 /* Enter configuration mode */ 255 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 256 257 /* Read device ID */ 258 id = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID); 259 /* Read device revision */ 260 rev = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV); 261 262 /* Escape from configuration mode */ 263 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 264 265 if ((product = wbsio_lookup(id, rev)) == NULL) { 266 aprint_error_dev(self, "Unknown device. Failed to attach\n"); 267 return; 268 } 269 if (product->idis12bits) 270 rev &= 0x0f; /* Revision is low 4bits */ 271 272 desc = product->str; 273 if (desc[0] == 'W') 274 vendor = "Winbond"; 275 else 276 vendor = "Nuvoton"; 277 aprint_naive("\n"); 278 aprint_normal(": %s LPC Super I/O %s rev ", vendor, desc); 279 if (product->idis12bits) { 280 /* Revision filed is 4bit only */ 281 aprint_normal("%c\n", 'A' + rev); 282 } else 283 aprint_normal("0x%02x\n", rev); 284 285 if (!pmf_device_register(self, wbsio_suspend, NULL)) 286 aprint_error_dev(self, "couldn't establish power handler\n"); 287 288 sc->sc_smw_valid = false; 289 wbsio_rescan(self, "wbsio", NULL); 290 291 #if NGPIO > 0 292 293 wbsio_rescan(self, "gpiobus", NULL); 294 #endif 295 } 296 297 int 298 wbsio_detach(device_t self, int flags) 299 { 300 struct wbsio_softc *sc = device_private(self); 301 int rc; 302 303 if ((rc = wbsio_wdog_detach(self)) != 0) 304 return rc; 305 306 if ((rc = config_detach_children(self, flags)) != 0) 307 return rc; 308 bus_space_unmap(sc->sc_iot, sc->sc_ioh, WBSIO_IOSIZE); 309 pmf_device_deregister(self); 310 311 #if NGPIO > 0 312 if (sc->sc_gpio_dev) { 313 bus_space_unmap(sc->sc_iot, sc->sc_gpio_ioh, 314 WBSIO_GPIO_IOSIZE); 315 } 316 317 if (sc->sc_gpio_rt) { 318 mutex_destroy(&sc->sc_gpio_lock); 319 } 320 #endif 321 322 mutex_destroy(&sc->sc_conf_lock); 323 return 0; 324 } 325 326 int 327 wbsio_rescan(device_t self, const char *ifattr, const int *locators) 328 { 329 330 #if NGPIO > 0 331 if (ifattr_match(ifattr, "gpiobus")) { 332 config_search_loc(wbsio_gpio_search, self, 333 ifattr, locators, NULL); 334 return 0; 335 } 336 #endif 337 config_search_loc(wbsio_search, self, ifattr, locators, NULL); 338 339 wbsio_wdog_attach(self); 340 341 return 0; 342 } 343 344 void 345 wbsio_childdet(device_t self, device_t child) 346 { 347 struct wbsio_softc *sc = device_private(self); 348 349 if (sc->sc_lm_dev == child) 350 sc->sc_lm_dev = NULL; 351 } 352 353 static int 354 wbsio_search(device_t parent, cfdata_t cf, const int *slocs, void *aux) 355 { 356 struct wbsio_softc *sc = device_private(parent); 357 const struct wbsio_product *product; 358 uint16_t iobase; 359 uint16_t devid; 360 uint8_t reg0, reg1, rev; 361 362 /* Enter configuration mode */ 363 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 364 365 /* Select HM logical device */ 366 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_HM); 367 368 /* 369 * The address should be 8-byte aligned, but it seems some 370 * BIOSes ignore this. They get away with it, because 371 * Apparently the hardware simply ignores the lower three 372 * bits. We do the same here. 373 */ 374 reg0 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_LSB); 375 reg1 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_MSB); 376 377 /* Escape from configuration mode */ 378 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 379 380 iobase = (reg1 << 8) | (reg0 & ~0x7); 381 382 if (iobase == 0) 383 return -1; 384 385 /* Enter configuration mode */ 386 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 387 /* Read device ID and revision */ 388 devid = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID); 389 rev = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV); 390 /* Escape from configuration mode */ 391 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 392 393 if ((product = wbsio_lookup(devid, rev)) == NULL) { 394 aprint_error_dev(parent, "%s: Unknown device.\n", __func__); 395 return -1; 396 } 397 if (product->idis12bits) 398 devid = (devid << 4) | (rev >> 4); 399 400 sc->sc_ia.ia_nio = 1; 401 sc->sc_ia.ia_io = &sc->sc_io; 402 sc->sc_ia.ia_io[0].ir_addr = iobase; 403 sc->sc_ia.ia_io[0].ir_size = 8; 404 sc->sc_ia.ia_niomem = 0; 405 sc->sc_ia.ia_nirq = 0; 406 sc->sc_ia.ia_ndrq = 0; 407 /* Store device-id to ia_aux */ 408 sc->sc_ia.ia_aux = (void *)(uintptr_t)devid; 409 sc->sc_lm_dev = config_attach(parent, cf, &sc->sc_ia, wbsio_print); 410 411 return 0; 412 } 413 414 int 415 wbsio_print(void *aux, const char *pnp) 416 { 417 struct isa_attach_args *ia = aux; 418 419 if (pnp) 420 aprint_normal("%s", pnp); 421 if (ia->ia_io[0].ir_size) 422 aprint_normal(" port 0x%x", ia->ia_io[0].ir_addr); 423 if (ia->ia_io[0].ir_size > 1) 424 aprint_normal("-0x%x", ia->ia_io[0].ir_addr + 425 ia->ia_io[0].ir_size - 1); 426 return (UNCONF); 427 } 428 429 static bool 430 wbsio_suspend(device_t self, const pmf_qual_t *qual) 431 { 432 struct wbsio_softc *sc = device_private(self); 433 434 if (sc->sc_smw_valid) { 435 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) 436 != WDOG_MODE_DISARMED) 437 return false; 438 } 439 440 return true; 441 } 442 443 #if NGPIO > 0 444 static int 445 wbsio_gpio_search(device_t parent, cfdata_t cf, const int *slocs, void *aux) 446 { 447 struct wbsio_softc *sc = device_private(parent); 448 const struct wbsio_product *product; 449 struct gpiobus_attach_args gba; 450 uint16_t devid; 451 uint8_t rev; 452 int i; 453 454 /* Enter configuration mode */ 455 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 456 /* Read device ID and revision */ 457 devid = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID); 458 rev = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV); 459 /* Escape from configuration mode */ 460 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 461 462 if ((product = wbsio_lookup(devid, rev)) == NULL) { 463 aprint_error_dev(parent, "%s: Unknown device.\n", __func__); 464 return -1; 465 } 466 467 sc->sc_gpio_rt = false; 468 469 switch (product->id) { 470 case WBSIO_ID_NCT6779D: 471 wbsio_gpio_enable_nct6779d(parent); 472 sc->sc_gpio_rt = true; 473 break; 474 default: 475 aprint_error_dev(parent, "%s's GPIO is not supported yet\n", 476 product->str); 477 return -1; 478 } 479 480 if (sc->sc_gpio_rt) { 481 if (wbsio_gpio_rt_init(sc) != 0) { 482 sc->sc_gpio_rt = false; 483 return -1; 484 } 485 sc->sc_gpio_gc.gp_cookie = sc; 486 sc->sc_gpio_gc.gp_pin_read = wbsio_gpio_rt_pin_read; 487 sc->sc_gpio_gc.gp_pin_write = wbsio_gpio_rt_pin_write; 488 sc->sc_gpio_gc.gp_pin_ctl = wbsio_gpio_rt_pin_ctl; 489 } else { 490 aprint_error_dev(parent, 491 "GPIO indirect access is not supported\n"); 492 return -1; 493 } 494 495 for (i = 0; i < WBSIO_GPIO_NPINS; i++) { 496 sc->sc_gpio_pins[i].pin_num = i; 497 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | 498 GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | GPIO_PIN_INVOUT; 499 500 /* safe defaults */ 501 sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INPUT; 502 sc->sc_gpio_pins[i].pin_state = GPIO_PIN_LOW; 503 sc->sc_gpio_gc.gp_pin_ctl(sc, i, sc->sc_gpio_pins[i].pin_flags); 504 sc->sc_gpio_gc.gp_pin_write(sc, i, sc->sc_gpio_pins[i].pin_state); 505 } 506 507 switch (product->id) { 508 case WBSIO_ID_NCT6779D: 509 wbsio_gpio_pinconfig_nct6779d(parent); 510 break; 511 } 512 513 gba.gba_gc = &sc->sc_gpio_gc; 514 gba.gba_pins = sc->sc_gpio_pins; 515 gba.gba_npins = WBSIO_GPIO_NPINS; 516 517 sc->sc_gpio_dev = config_attach(parent, cf, &gba, gpiobus_print); 518 519 return 0; 520 } 521 522 static int 523 wbsio_gpio_rt_init(struct wbsio_softc *sc) 524 { 525 uint16_t iobase; 526 uint8_t reg0, reg1; 527 528 /* Enter configuration mode */ 529 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 530 531 /* Get GPIO Register Table address */ 532 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_GPIO0); 533 reg0 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_GPIO_ADDR_LSB); 534 reg1 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_GPIO_ADDR_MSB); 535 iobase = (reg1 << 8) | (reg0 & ~0x7); 536 537 /* Escape from configuration mode */ 538 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 539 540 if (bus_space_map(sc->sc_iot, iobase, WBSIO_GPIO_IOSIZE, 541 0, &sc->sc_gpio_ioh)) { 542 aprint_error_dev(sc->sc_dev, 543 "can't map gpio to i/o space\n"); 544 return -1; 545 } 546 547 aprint_normal_dev(sc->sc_dev, "GPIO: port 0x%x-0x%x\n", 548 iobase, iobase + WBSIO_GPIO_IOSIZE); 549 550 mutex_init(&sc->sc_gpio_lock, MUTEX_DEFAULT, IPL_VM); 551 552 return 0; 553 } 554 555 static int 556 wbsio_gpio_rt_read(struct wbsio_softc *sc, int port, int reg) 557 { 558 int v; 559 560 mutex_enter(&sc->sc_gpio_lock); 561 562 bus_space_write_1(sc->sc_iot, sc->sc_gpio_ioh, 563 WBSIO_GPIO_GSR, port); 564 v = bus_space_read_1(sc->sc_iot, sc->sc_gpio_ioh, reg); 565 566 mutex_exit(&sc->sc_gpio_lock); 567 568 return v; 569 } 570 571 static void 572 wbsio_gpio_rt_write(struct wbsio_softc *sc, int port, int reg, int value) 573 { 574 575 mutex_enter(&sc->sc_gpio_lock); 576 577 bus_space_write_1(sc->sc_iot, sc->sc_gpio_ioh, 578 WBSIO_GPIO_GSR, port); 579 bus_space_write_1(sc->sc_iot, sc->sc_gpio_ioh, 580 reg, value); 581 582 mutex_exit(&sc->sc_gpio_lock); 583 } 584 585 static int 586 wbsio_gpio_rt_pin_read(void *aux, int pin) 587 { 588 struct wbsio_softc *sc = (struct wbsio_softc *)aux; 589 int port, shift, data; 590 591 port = (pin >> 3) & 0x07; 592 shift = pin & 0x07; 593 594 data = wbsio_gpio_rt_read(sc, port, WBSIO_GPIO_DAT); 595 596 return ((data >> shift) & 0x01); 597 } 598 599 static void 600 wbsio_gpio_rt_pin_write(void *aux, int pin, int v) 601 { 602 struct wbsio_softc *sc = (struct wbsio_softc *)aux; 603 int port, shift, data; 604 605 port = (pin >> 3) & 0x07; 606 shift = pin & 0x07; 607 608 data = wbsio_gpio_rt_read(sc, port, WBSIO_GPIO_DAT); 609 610 if (v == 0) 611 data &= ~(1 << shift); 612 else if (v == 1) 613 data |= (1 << shift); 614 615 wbsio_gpio_rt_write(sc, port, WBSIO_GPIO_DAT, data); 616 } 617 618 static void 619 wbsio_gpio_rt_pin_ctl(void *aux, int pin, int flags) 620 { 621 struct wbsio_softc *sc = (struct wbsio_softc *)aux; 622 uint8_t ior, inv; 623 int port, shift; 624 625 port = (pin >> 3) & 0x07; 626 shift = pin & 0x07; 627 628 ior = wbsio_gpio_rt_read(sc, port, WBSIO_GPIO_IOR); 629 inv = wbsio_gpio_rt_read(sc, port, WBSIO_GPIO_INV); 630 631 if (flags & GPIO_PIN_INPUT) { 632 ior |= (1 << shift); 633 inv &= ~(1 << shift); 634 } else if (flags & GPIO_PIN_OUTPUT) { 635 ior &= ~(1 << shift); 636 inv &= ~(1 << shift); 637 } else if (flags & GPIO_PIN_INVIN) { 638 ior |= (1 << shift); 639 inv |= (1 << shift); 640 } else if (flags & GPIO_PIN_INVOUT) { 641 ior &= ~(1 << shift); 642 inv |= (1 << shift); 643 } 644 645 wbsio_gpio_rt_write(sc, port, WBSIO_GPIO_IOR, ior); 646 wbsio_gpio_rt_write(sc, port, WBSIO_GPIO_INV, inv); 647 } 648 649 static void 650 wbsio_gpio_enable_nct6779d(device_t parent) 651 { 652 struct wbsio_softc *sc = device_private(parent); 653 uint8_t reg, conf; 654 655 /* Enter configuration mode */ 656 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 657 658 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_GPIO0); 659 reg = WBSIO_GPIO_CONF; 660 conf = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, reg); 661 /* Activate Register Table access */ 662 conf |= WBSIO_GPIO_BASEADDR; 663 664 conf |= WBSIO_GPIO0_ENABLE; 665 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, reg, conf); 666 667 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_GPIO1); 668 reg = WBSIO_GPIO_CONF; 669 conf = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, reg); 670 conf |= WBSIO_GPIO1_ENABLE; 671 conf |= WBSIO_GPIO2_ENABLE; 672 conf |= WBSIO_GPIO3_ENABLE; 673 conf |= WBSIO_GPIO4_ENABLE; 674 conf |= WBSIO_GPIO5_ENABLE; 675 conf |= WBSIO_GPIO6_ENABLE; 676 conf |= WBSIO_GPIO7_ENABLE; 677 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, reg, conf); 678 679 /* Escape from configuration mode */ 680 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 681 } 682 683 static void 684 wbsio_gpio_pinconfig_nct6779d(device_t parent) 685 { 686 struct wbsio_softc *sc = device_private(parent); 687 uint8_t sfr, mfs0, mfs1, mfs2, mfs3; 688 uint8_t mfs4, mfs5, mfs6, gopt2, hm_conf; 689 690 /* Enter configuration mode */ 691 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 692 693 /* Strapping Function Result */ 694 sfr = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_SFR); 695 sfr &= ~(WBSIO_SFR_LPT | WBSIO_SFR_DSW | WBSIO_SFR_AMDPWR); 696 697 /* Read current configuration */ 698 mfs0 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_MFS0); 699 mfs1 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_MFS1); 700 mfs2 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_MFS2); 701 mfs3 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_MFS3); 702 mfs4 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_MFS4); 703 mfs5 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_MFS5); 704 mfs6 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_MFS6); 705 gopt2 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_GOPT2); 706 707 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_HM); 708 hm_conf = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_CONF); 709 710 /* GPIO0 pin configs */ 711 mfs2 |= WBSIO_NCT6779D_MFS2_GP00; 712 mfs2 |= WBSIO_NCT6779D_MFS2_GP01; 713 mfs2 |= WBSIO_NCT6779D_MFS2_GP02; 714 mfs2 &= ~WBSIO_NCT6779D_MFS2_GP03_MASK; 715 mfs2 |= WBSIO_NCT6779D_MFS2_GP04; 716 mfs2 |= WBSIO_NCT6779D_MFS2_GP05; 717 mfs2 |= WBSIO_NCT6779D_MFS2_GP06; 718 mfs3 &= ~WBSIO_NCT6779D_MFS3_GP07_MASK; 719 720 /* GPIO1 pin configs */ 721 mfs4 |= WBSIO_NCT6779D_MFS4_GP10_GP17; 722 723 /* GPIO2 pin configs */ 724 mfs4 |= WBSIO_NCT6779D_MFS4_GP20_GP21; 725 mfs4 |= WBSIO_NCT6779D_MFS4_GP22_GP23; 726 mfs1 &= ~WBSIO_NCT6779D_MFS1_GP24_MASK; 727 gopt2 &= ~WBSIO_NCT6779D_GOPT2_GP24_MASK; 728 mfs4 &= ~WBSIO_NCT6779D_MFS4_GP25_MASK; 729 gopt2 &= ~WBSIO_NCT6779D_GOPT2_GP25_MASK; 730 mfs6 |= WBSIO_NCT6779D_MFS6_GP26; 731 mfs6 &= ~WBSIO_NCT6779D_MFS6_GP27_MASK; 732 733 /* GPIO3 pin configs */ 734 mfs0 &= ~WBSIO_NCT6779D_MFS0_GP30_MASK; 735 mfs0 |= WBSIO_NCT6779D_MFS0_GP30; 736 mfs1 &= ~WBSIO_NCT6779D_MFS1_GP31_MASK; 737 mfs0 |= WBSIO_NCT6779D_MFS0_GP31; 738 mfs1 &= ~WBSIO_NCT6779D_MFS1_GP32_MASK; 739 mfs0 |= WBSIO_NCT6779D_MFS0_GP32; 740 mfs6 &= ~WBSIO_NCT6779D_MFS6_GP33_MASK; 741 mfs6 |= WBSIO_NCT6779D_MFS6_GP33; 742 /* GP34, 35 and 36 are enabled by LPT_EN=0 */ 743 /* GP37 is not existed */ 744 745 /* GPIO4 pin configs */ 746 mfs1 |= WBSIO_NCT6779D_MFS1_GP40; 747 /* GP41 to GP46 requires LPT_EN=0 */ 748 mfs0 &= ~WBSIO_NCT6779D_MFS0_GP41_MASK; 749 mfs0 |= WBSIO_NCT6779D_MFS0_GP41; 750 mfs1 |= WBSIO_NCT6779D_MFS1_GP42; 751 mfs1 |= WBSIO_NCT6779D_MFS1_GP42; 752 gopt2 |= WBSIO_NCT6779D_GOPT2_GP43; 753 mfs1 &= ~WBSIO_NCT6779D_MFS1_GP44_GP45_MASK; 754 gopt2 &= ~WBSIO_NCT6779D_GOPT2_GP46_MASK; 755 mfs1 |= WBSIO_NCT6779D_MFS1_GP47; 756 757 /* GPIO5 pin configs */ 758 /* GP50 to GP55 requires DSW_EN=0 */ 759 hm_conf &= ~WBSIO_NCT6779D_HM_GP50_MASK; 760 /* GP51 is enabled by DSW_EN=0 */ 761 hm_conf &= ~WBSIO_NCT6779D_HM_GP52_MASK; 762 /* GP53 and GP54 are enabled by DSW_EN=0 */ 763 hm_conf &= ~WBSIO_NCT6779D_HM_GP55_MASK; 764 /* GP56 and GP57 are enabled by AMDPWR_EN=0 */ 765 766 /* GPIO6 pin configs are shared with GP43 */ 767 768 /* GPIO7 pin configs */ 769 /* GP70 to GP73 are enabled by TEST_MODE_EN */ 770 mfs5 |= WBSIO_NCT6779D_MFS5_GP74; 771 mfs5 |= WBSIO_NCT6779D_MFS5_GP75; 772 mfs5 |= WBSIO_NCT6779D_MFS5_GP76; 773 /* GP77 is not existed */ 774 775 /* Write all pin configs */ 776 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_SFR, sfr); 777 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_MFS0, mfs0); 778 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_MFS1, mfs1); 779 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_MFS2, mfs2); 780 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_MFS3, mfs3); 781 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_MFS4, mfs4); 782 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_MFS5, mfs5); 783 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_MFS6, mfs6); 784 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_GOPT2, gopt2); 785 786 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_HM); 787 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_HM_CONF, hm_conf); 788 789 /* Escape from configuration mode */ 790 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 791 } 792 793 #endif /* NGPIO > 0 */ 794 795 static void 796 wbsio_wdog_attach(device_t self) 797 { 798 struct wbsio_softc *sc = device_private(self); 799 const struct wbsio_product *product; 800 uint8_t gpio, mode; 801 uint16_t devid; 802 uint8_t rev; 803 804 if (sc->sc_smw_valid) 805 return; /* watchdog already attached */ 806 807 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 808 devid = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID); 809 rev = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV); 810 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 811 812 if ((product = wbsio_lookup(devid, rev)) == NULL) { 813 return; 814 } 815 816 switch (product->id) { 817 case WBSIO_ID_NCT6779D: 818 break; 819 default: 820 /* WDT is not supoorted */ 821 return; 822 } 823 824 wbsio_wdog_setcounter(sc, WBSIO_WDT_CNTR_STOP); 825 826 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 827 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_GPIO0); 828 829 gpio = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_GPIO_CONF); 830 mode = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_WDT_MODE); 831 832 gpio |= WBSIO_GPIO0_WDT1; 833 834 mode &= ~WBSIO_WDT_MODE_FASTER; 835 mode &= ~WBSIO_WDT_MODE_MINUTES; 836 mode &= ~WBSIO_WDT_MODE_KBCRST; 837 mode &= ~WBSIO_WDT_MODE_LEVEL; 838 839 /* initialize WDT mode */ 840 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_WDT_MODE, mode); 841 /* Activate WDT1 function */ 842 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_GPIO_CONF, gpio); 843 844 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 845 846 sc->sc_smw.smw_name = device_xname(self); 847 sc->sc_smw.smw_cookie = sc; 848 sc->sc_smw.smw_setmode = wbsio_wdog_setmode; 849 sc->sc_smw.smw_tickle = wbsio_wdog_tickle; 850 sc->sc_smw.smw_period = WBSIO_WDT_CNTR_MAX; 851 852 if (sysmon_wdog_register(&sc->sc_smw)) 853 aprint_error_dev(self, "couldn't register with sysmon\n"); 854 else 855 sc->sc_smw_valid = true; 856 } 857 858 static int 859 wbsio_wdog_detach(device_t self) 860 { 861 struct wbsio_softc *sc = device_private(self); 862 int error; 863 864 error = 0; 865 866 if (sc->sc_smw_valid) { 867 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) 868 != WDOG_MODE_DISARMED) 869 return EBUSY; 870 871 error = sysmon_wdog_unregister(&sc->sc_smw); 872 } 873 874 if (!error) 875 sc->sc_smw_valid = false; 876 877 return error; 878 } 879 880 static int 881 wbsio_wdog_setmode(struct sysmon_wdog *smw) 882 { 883 884 switch(smw->smw_mode & WDOG_MODE_MASK) { 885 case WDOG_MODE_DISARMED: 886 wbsio_wdog_setcounter(smw->smw_cookie, WBSIO_WDT_CNTR_STOP); 887 wbsio_wdog_clear_timeout(smw->smw_cookie); 888 break; 889 default: 890 if (smw->smw_period > WBSIO_WDT_CNTR_MAX 891 || smw->smw_period == 0) 892 return EINVAL; 893 894 wbsio_wdog_setcounter(smw->smw_cookie, smw->smw_period); 895 } 896 897 return 0; 898 } 899 900 static void 901 wbsio_wdog_setcounter(struct wbsio_softc *sc, uint8_t period) 902 { 903 904 KASSERT(!mutex_owned(&sc->sc_conf_lock)); 905 906 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 907 908 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_GPIO0); 909 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_WDT_CNTR, period); 910 911 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_GPIO0); 912 913 914 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 915 } 916 917 static void 918 wbsio_wdog_clear_timeout(struct wbsio_softc *sc) 919 { 920 uint8_t st; 921 922 KASSERT(!mutex_owned(&sc->sc_conf_lock)); 923 924 wbsio_conf_enable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 925 926 st = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_WDT_STAT); 927 st &= ~WBSIO_WDT_STAT_TIMEOUT; 928 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_WDT_STAT, st); 929 930 wbsio_conf_disable(&sc->sc_conf_lock, sc->sc_iot, sc->sc_ioh); 931 } 932 933 static int 934 wbsio_wdog_tickle(struct sysmon_wdog *smw) 935 { 936 937 wbsio_wdog_setcounter(smw->smw_cookie, smw->smw_period); 938 939 return 0; 940 } 941 942 943 MODULE(MODULE_CLASS_DRIVER, wbsio, "sysmon_wdog"); 944 945 #ifdef _MODULE 946 #include "ioconf.c" 947 #endif 948 949 static int 950 wbsio_modcmd(modcmd_t cmd, void *opaque) 951 { 952 switch (cmd) { 953 case MODULE_CMD_INIT: 954 #ifdef _MODULE 955 return config_init_component(cfdriver_ioconf_wbsio, 956 cfattach_ioconf_wbsio, cfdata_ioconf_wbsio); 957 #else 958 return 0; 959 #endif 960 case MODULE_CMD_FINI: 961 #ifdef _MODULE 962 return config_fini_component(cfdriver_ioconf_wbsio, 963 cfattach_ioconf_wbsio, cfdata_ioconf_wbsio); 964 #else 965 return 0; 966 #endif 967 default: 968 return ENOTTY; 969 } 970 } 971