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