1 /* $NetBSD: ichlpcib.c,v 1.21 2009/09/27 18:27:01 jakllsch Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Minoura Makoto and Matthew R. Green. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Intel I/O Controller Hub (ICHn) LPC Interface Bridge driver 34 * 35 * LPC Interface Bridge is basically a pcib (PCI-ISA Bridge), but has 36 * some power management and monitoring functions. 37 * Currently we support the watchdog timer, SpeedStep (on some systems) 38 * and the power management timer. 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.21 2009/09/27 18:27:01 jakllsch Exp $"); 43 44 #include <sys/types.h> 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/device.h> 48 #include <sys/sysctl.h> 49 #include <sys/timetc.h> 50 #include <sys/gpio.h> 51 #include <machine/bus.h> 52 53 #include <dev/pci/pcivar.h> 54 #include <dev/pci/pcireg.h> 55 #include <dev/pci/pcidevs.h> 56 57 #include <dev/gpio/gpiovar.h> 58 #include <dev/sysmon/sysmonvar.h> 59 60 #include <dev/ic/acpipmtimer.h> 61 #include <dev/ic/i82801lpcreg.h> 62 #include <dev/ic/hpetreg.h> 63 #include <dev/ic/hpetvar.h> 64 65 #include "hpet.h" 66 #include "pcibvar.h" 67 #include "gpio.h" 68 69 #define LPCIB_GPIO_NPINS 64 70 71 struct lpcib_softc { 72 /* we call pcibattach() which assumes this starts like this: */ 73 struct pcib_softc sc_pcib; 74 75 struct pci_attach_args sc_pa; 76 int sc_has_rcba; 77 int sc_has_ich5_hpet; 78 79 /* RCBA */ 80 bus_space_tag_t sc_rcbat; 81 bus_space_handle_t sc_rcbah; 82 pcireg_t sc_rcba_reg; 83 84 /* Watchdog variables. */ 85 struct sysmon_wdog sc_smw; 86 bus_space_tag_t sc_iot; 87 bus_space_handle_t sc_ioh; 88 bus_size_t sc_iosize; 89 90 #if NHPET > 0 91 /* HPET variables. */ 92 uint32_t sc_hpet_reg; 93 #endif 94 95 #if NGPIO > 0 96 device_t sc_gpiobus; 97 kmutex_t sc_gpio_mtx; 98 bus_space_tag_t sc_gpio_iot; 99 bus_space_handle_t sc_gpio_ioh; 100 bus_size_t sc_gpio_ios; 101 struct gpio_chipset_tag sc_gpio_gc; 102 gpio_pin_t sc_gpio_pins[LPCIB_GPIO_NPINS]; 103 #endif 104 105 /* Speedstep */ 106 pcireg_t sc_pmcon_orig; 107 108 /* Power management */ 109 pcireg_t sc_pirq[2]; 110 pcireg_t sc_pmcon; 111 pcireg_t sc_fwhsel2; 112 113 /* Child devices */ 114 device_t sc_hpetbus; 115 acpipmtimer_t sc_pmtimer; 116 pcireg_t sc_acpi_cntl; 117 118 struct sysctllog *sc_log; 119 }; 120 121 static int lpcibmatch(device_t, cfdata_t, void *); 122 static void lpcibattach(device_t, device_t, void *); 123 static int lpcibdetach(device_t, int); 124 static void lpcibchilddet(device_t, device_t); 125 static int lpcibrescan(device_t, const char *, const int *); 126 static bool lpcib_suspend(device_t PMF_FN_PROTO); 127 static bool lpcib_resume(device_t PMF_FN_PROTO); 128 static bool lpcib_shutdown(device_t, int); 129 130 static void pmtimer_configure(device_t); 131 static int pmtimer_unconfigure(device_t, int); 132 133 static void tcotimer_configure(device_t); 134 static int tcotimer_unconfigure(device_t, int); 135 static int tcotimer_setmode(struct sysmon_wdog *); 136 static int tcotimer_tickle(struct sysmon_wdog *); 137 static void tcotimer_stop(struct lpcib_softc *); 138 static void tcotimer_start(struct lpcib_softc *); 139 static void tcotimer_status_reset(struct lpcib_softc *); 140 static int tcotimer_disable_noreboot(device_t); 141 142 static void speedstep_configure(device_t); 143 static void speedstep_unconfigure(device_t); 144 static int speedstep_sysctl_helper(SYSCTLFN_ARGS); 145 146 #if NHPET > 0 147 static void lpcib_hpet_configure(device_t); 148 static int lpcib_hpet_unconfigure(device_t, int); 149 #endif 150 151 #if NGPIO > 0 152 static void lpcib_gpio_configure(device_t); 153 static int lpcib_gpio_unconfigure(device_t, int); 154 static int lpcib_gpio_pin_read(void *, int); 155 static void lpcib_gpio_pin_write(void *, int, int); 156 static void lpcib_gpio_pin_ctl(void *, int, int); 157 #endif 158 159 struct lpcib_softc *speedstep_cookie; /* XXX */ 160 161 CFATTACH_DECL2_NEW(ichlpcib, sizeof(struct lpcib_softc), 162 lpcibmatch, lpcibattach, lpcibdetach, NULL, lpcibrescan, lpcibchilddet); 163 164 static struct lpcib_device { 165 pcireg_t vendor, product; 166 int has_rcba; 167 int has_ich5_hpet; 168 } lpcib_devices[] = { 169 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_LPC, 0, 0 }, 170 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_LPC, 0, 0 }, 171 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BAM_LPC, 0, 0 }, 172 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_LPC, 0, 0 }, 173 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CAM_LPC, 0, 0 }, 174 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_LPC, 0, 0 }, 175 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_ISA, 0, 0 }, 176 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_LPC, 0, 1 }, 177 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FB_LPC, 1, 0 }, 178 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FBM_LPC, 1, 0 }, 179 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801G_LPC, 1, 0 }, 180 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GBM_LPC, 1, 0 }, 181 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GHM_LPC, 1, 0 }, 182 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_LPC, 1, 0 }, 183 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HEM_LPC, 1, 0 }, 184 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HH_LPC, 1, 0 }, 185 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HO_LPC, 1, 0 }, 186 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HBM_LPC, 1, 0 }, 187 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IH_LPC, 1, 0 }, 188 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IO_LPC, 1, 0 }, 189 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IR_LPC, 1, 0 }, 190 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IEM_LPC, 1, 0 }, 191 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IB_LPC, 1, 0 }, 192 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_63XXESB_LPC, 1, 0 }, 193 194 { 0, 0, 0, 0 }, 195 }; 196 197 /* 198 * Autoconf callbacks. 199 */ 200 static int 201 lpcibmatch(device_t parent, cfdata_t match, void *aux) 202 { 203 struct pci_attach_args *pa = aux; 204 struct lpcib_device *lpcib_dev; 205 206 /* We are ISA bridge, of course */ 207 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE || 208 PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA) 209 return 0; 210 211 for (lpcib_dev = lpcib_devices; lpcib_dev->vendor; ++lpcib_dev) { 212 if (PCI_VENDOR(pa->pa_id) == lpcib_dev->vendor && 213 PCI_PRODUCT(pa->pa_id) == lpcib_dev->product) 214 return 10; 215 } 216 217 return 0; 218 } 219 220 static void 221 lpcibattach(device_t parent, device_t self, void *aux) 222 { 223 struct pci_attach_args *pa = aux; 224 struct lpcib_softc *sc = device_private(self); 225 struct lpcib_device *lpcib_dev; 226 227 sc->sc_pa = *pa; 228 229 for (lpcib_dev = lpcib_devices; lpcib_dev->vendor; ++lpcib_dev) { 230 if (PCI_VENDOR(pa->pa_id) != lpcib_dev->vendor || 231 PCI_PRODUCT(pa->pa_id) != lpcib_dev->product) 232 continue; 233 sc->sc_has_rcba = lpcib_dev->has_rcba; 234 sc->sc_has_ich5_hpet = lpcib_dev->has_ich5_hpet; 235 break; 236 } 237 238 pcibattach(parent, self, aux); 239 240 /* 241 * Part of our I/O registers are used as ACPI PM regs. 242 * Since our ACPI subsystem accesses the I/O space directly so far, 243 * we do not have to bother bus_space I/O map confliction. 244 */ 245 if (pci_mapreg_map(pa, LPCIB_PCI_PMBASE, PCI_MAPREG_TYPE_IO, 0, 246 &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_iosize)) { 247 aprint_error_dev(self, "can't map power management i/o space"); 248 return; 249 } 250 251 sc->sc_pmcon_orig = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 252 LPCIB_PCI_GEN_PMCON_1); 253 254 /* For ICH6 and later, always enable RCBA */ 255 if (sc->sc_has_rcba) { 256 pcireg_t rcba; 257 258 sc->sc_rcbat = sc->sc_pa.pa_memt; 259 260 rcba = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 261 LPCIB_RCBA); 262 if ((rcba & LPCIB_RCBA_EN) == 0) { 263 aprint_error_dev(self, "RCBA is not enabled"); 264 return; 265 } 266 rcba &= ~LPCIB_RCBA_EN; 267 268 if (bus_space_map(sc->sc_rcbat, rcba, LPCIB_RCBA_SIZE, 0, 269 &sc->sc_rcbah)) { 270 aprint_error_dev(self, "RCBA could not be mapped"); 271 return; 272 } 273 } 274 275 /* Set up the power management timer. */ 276 pmtimer_configure(self); 277 278 /* Set up the TCO (watchdog). */ 279 tcotimer_configure(self); 280 281 /* Set up SpeedStep. */ 282 speedstep_configure(self); 283 284 #if NHPET > 0 285 /* Set up HPET. */ 286 lpcib_hpet_configure(self); 287 #endif 288 289 #if NGPIO > 0 290 /* Set up GPIO */ 291 lpcib_gpio_configure(self); 292 #endif 293 294 /* Install power handler */ 295 if (!pmf_device_register1(self, lpcib_suspend, lpcib_resume, 296 lpcib_shutdown)) 297 aprint_error_dev(self, "couldn't establish power handler\n"); 298 } 299 300 static void 301 lpcibchilddet(device_t self, device_t child) 302 { 303 struct lpcib_softc *sc = device_private(self); 304 uint32_t val; 305 306 #if NGPIO > 0 307 if (sc->sc_gpiobus == child) { 308 sc->sc_gpiobus = NULL; 309 return; 310 } 311 #endif 312 if (sc->sc_hpetbus != child) { 313 pcibchilddet(self, child); 314 return; 315 } 316 sc->sc_hpetbus = NULL; 317 if (sc->sc_has_ich5_hpet) { 318 val = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 319 LPCIB_PCI_GEN_CNTL); 320 switch (val & LPCIB_ICH5_HPTC_WIN_MASK) { 321 case LPCIB_ICH5_HPTC_0000: 322 case LPCIB_ICH5_HPTC_1000: 323 case LPCIB_ICH5_HPTC_2000: 324 case LPCIB_ICH5_HPTC_3000: 325 break; 326 default: 327 return; 328 } 329 val &= ~LPCIB_ICH5_HPTC_EN; 330 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 331 LPCIB_PCI_GEN_CNTL, val); 332 } else if (sc->sc_has_rcba) { 333 val = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 334 LPCIB_RCBA_HPTC); 335 switch (val & LPCIB_RCBA_HPTC_WIN_MASK) { 336 case LPCIB_RCBA_HPTC_0000: 337 case LPCIB_RCBA_HPTC_1000: 338 case LPCIB_RCBA_HPTC_2000: 339 case LPCIB_RCBA_HPTC_3000: 340 break; 341 default: 342 return; 343 } 344 val &= ~LPCIB_RCBA_HPTC_EN; 345 bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC, 346 val); 347 } 348 } 349 350 #if NHPET > 0 || NGPIO > 0 351 /* XXX share this with sys/arch/i386/pci/elan520.c */ 352 static bool 353 ifattr_match(const char *snull, const char *t) 354 { 355 return (snull == NULL) || strcmp(snull, t) == 0; 356 } 357 #endif 358 359 static int 360 lpcibrescan(device_t self, const char *ifattr, const int *locators) 361 { 362 #if NHPET > 0 || NGPIO > 0 363 struct lpcib_softc *sc = device_private(self); 364 #endif 365 366 #if NHPET > 0 367 if (ifattr_match(ifattr, "hpetichbus") && sc->sc_hpetbus == NULL) 368 lpcib_hpet_configure(self); 369 #endif 370 371 #if NGPIO > 0 372 if (ifattr_match(ifattr, "gpiobus") && sc->sc_gpiobus == NULL) 373 lpcib_gpio_configure(self); 374 #endif 375 376 return pcibrescan(self, ifattr, locators); 377 } 378 379 static int 380 lpcibdetach(device_t self, int flags) 381 { 382 struct lpcib_softc *sc = device_private(self); 383 int rc; 384 385 pmf_device_deregister(self); 386 387 #if NHPET > 0 388 if ((rc = lpcib_hpet_unconfigure(self, flags)) != 0) 389 return rc; 390 #endif 391 392 #if NGPIO > 0 393 if ((rc = lpcib_gpio_unconfigure(self, flags)) != 0) 394 return rc; 395 #endif 396 397 /* Set up SpeedStep. */ 398 speedstep_unconfigure(self); 399 400 if ((rc = tcotimer_unconfigure(self, flags)) != 0) 401 return rc; 402 403 if ((rc = pmtimer_unconfigure(self, flags)) != 0) 404 return rc; 405 406 if (sc->sc_has_rcba) 407 bus_space_unmap(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_SIZE); 408 409 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); 410 411 return pcibdetach(self, flags); 412 } 413 414 static bool 415 lpcib_shutdown(device_t dv, int howto) 416 { 417 struct lpcib_softc *sc = device_private(dv); 418 419 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 420 LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon_orig); 421 422 return true; 423 } 424 425 static bool 426 lpcib_suspend(device_t dv PMF_FN_ARGS) 427 { 428 struct lpcib_softc *sc = device_private(dv); 429 pci_chipset_tag_t pc = sc->sc_pcib.sc_pc; 430 pcitag_t tag = sc->sc_pcib.sc_tag; 431 432 /* capture PIRQ routing control registers */ 433 sc->sc_pirq[0] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQA_ROUT); 434 sc->sc_pirq[1] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQE_ROUT); 435 436 sc->sc_pmcon = pci_conf_read(pc, tag, LPCIB_PCI_GEN_PMCON_1); 437 sc->sc_fwhsel2 = pci_conf_read(pc, tag, LPCIB_PCI_GEN_STA); 438 439 if (sc->sc_has_rcba) { 440 sc->sc_rcba_reg = pci_conf_read(pc, tag, LPCIB_RCBA); 441 #if NHPET > 0 442 sc->sc_hpet_reg = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 443 LPCIB_RCBA_HPTC); 444 #endif 445 } else if (sc->sc_has_ich5_hpet) { 446 #if NHPET > 0 447 sc->sc_hpet_reg = pci_conf_read(pc, tag, LPCIB_PCI_GEN_CNTL); 448 #endif 449 } 450 451 return true; 452 } 453 454 static bool 455 lpcib_resume(device_t dv PMF_FN_ARGS) 456 { 457 struct lpcib_softc *sc = device_private(dv); 458 pci_chipset_tag_t pc = sc->sc_pcib.sc_pc; 459 pcitag_t tag = sc->sc_pcib.sc_tag; 460 461 /* restore PIRQ routing control registers */ 462 pci_conf_write(pc, tag, LPCIB_PCI_PIRQA_ROUT, sc->sc_pirq[0]); 463 pci_conf_write(pc, tag, LPCIB_PCI_PIRQE_ROUT, sc->sc_pirq[1]); 464 465 pci_conf_write(pc, tag, LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon); 466 pci_conf_write(pc, tag, LPCIB_PCI_GEN_STA, sc->sc_fwhsel2); 467 468 if (sc->sc_has_rcba) { 469 pci_conf_write(pc, tag, LPCIB_RCBA, sc->sc_rcba_reg); 470 #if NHPET > 0 471 bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC, 472 sc->sc_hpet_reg); 473 #endif 474 } else if (sc->sc_has_ich5_hpet) { 475 #if NHPET > 0 476 pci_conf_write(pc, tag, LPCIB_PCI_GEN_CNTL, sc->sc_hpet_reg); 477 #endif 478 } 479 480 return true; 481 } 482 483 /* 484 * Initialize the power management timer. 485 */ 486 static void 487 pmtimer_configure(device_t self) 488 { 489 struct lpcib_softc *sc = device_private(self); 490 pcireg_t control; 491 492 /* 493 * Check if power management I/O space is enabled and enable the ACPI_EN 494 * bit if it's disabled. 495 */ 496 control = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 497 LPCIB_PCI_ACPI_CNTL); 498 sc->sc_acpi_cntl = control; 499 if ((control & LPCIB_PCI_ACPI_CNTL_EN) == 0) { 500 control |= LPCIB_PCI_ACPI_CNTL_EN; 501 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 502 LPCIB_PCI_ACPI_CNTL, control); 503 } 504 505 /* Attach our PM timer with the generic acpipmtimer function */ 506 sc->sc_pmtimer = acpipmtimer_attach(self, sc->sc_iot, sc->sc_ioh, 507 LPCIB_PM1_TMR, 0); 508 } 509 510 static int 511 pmtimer_unconfigure(device_t self, int flags) 512 { 513 struct lpcib_softc *sc = device_private(self); 514 int rc; 515 516 if (sc->sc_pmtimer != NULL && 517 (rc = acpipmtimer_detach(sc->sc_pmtimer, flags)) != 0) 518 return rc; 519 520 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 521 LPCIB_PCI_ACPI_CNTL, sc->sc_acpi_cntl); 522 523 return 0; 524 } 525 526 /* 527 * Initialize the watchdog timer. 528 */ 529 static void 530 tcotimer_configure(device_t self) 531 { 532 struct lpcib_softc *sc = device_private(self); 533 uint32_t ioreg; 534 unsigned int period; 535 536 /* Explicitly stop the TCO timer. */ 537 tcotimer_stop(sc); 538 539 /* 540 * Enable TCO timeout SMI only if the hardware reset does not 541 * work. We don't know what the SMBIOS does. 542 */ 543 ioreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LPCIB_SMI_EN); 544 ioreg &= ~LPCIB_SMI_EN_TCO_EN; 545 546 /* 547 * Clear the No Reboot (NR) bit. If this fails, enabling the TCO_EN bit 548 * in the SMI_EN register is the last chance. 549 */ 550 if (tcotimer_disable_noreboot(self)) { 551 ioreg |= LPCIB_SMI_EN_TCO_EN; 552 } 553 if ((ioreg & LPCIB_SMI_EN_GBL_SMI_EN) != 0) { 554 bus_space_write_4(sc->sc_iot, sc->sc_ioh, LPCIB_SMI_EN, ioreg); 555 } 556 557 /* Reset the watchdog status registers. */ 558 tcotimer_status_reset(sc); 559 560 /* 561 * Register the driver with the sysmon watchdog framework. 562 */ 563 sc->sc_smw.smw_name = device_xname(self); 564 sc->sc_smw.smw_cookie = sc; 565 sc->sc_smw.smw_setmode = tcotimer_setmode; 566 sc->sc_smw.smw_tickle = tcotimer_tickle; 567 if (sc->sc_has_rcba) 568 period = LPCIB_TCOTIMER2_MAX_TICK; 569 else 570 period = LPCIB_TCOTIMER_MAX_TICK; 571 sc->sc_smw.smw_period = lpcib_tcotimer_tick_to_second(period); 572 573 if (sysmon_wdog_register(&sc->sc_smw)) { 574 aprint_error_dev(self, "unable to register TCO timer" 575 "as a sysmon watchdog device.\n"); 576 return; 577 } 578 579 aprint_verbose_dev(self, "TCO (watchdog) timer configured.\n"); 580 } 581 582 static int 583 tcotimer_unconfigure(device_t self, int flags) 584 { 585 struct lpcib_softc *sc = device_private(self); 586 int rc; 587 588 if ((rc = sysmon_wdog_unregister(&sc->sc_smw)) != 0) { 589 if (rc == ERESTART) 590 rc = EINTR; 591 return rc; 592 } 593 594 /* Explicitly stop the TCO timer. */ 595 tcotimer_stop(sc); 596 597 /* XXX Set No Reboot? */ 598 599 return 0; 600 } 601 602 603 /* 604 * Sysmon watchdog callbacks. 605 */ 606 static int 607 tcotimer_setmode(struct sysmon_wdog *smw) 608 { 609 struct lpcib_softc *sc = smw->smw_cookie; 610 unsigned int period; 611 uint16_t ich6period = 0; 612 uint8_t ich5period = 0; 613 614 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 615 /* Stop the TCO timer. */ 616 tcotimer_stop(sc); 617 } else { 618 /* 619 * ICH6 or newer are limited to 2s min and 613s max. 620 * ICH5 or older are limited to 4s min and 39s max. 621 */ 622 period = lpcib_tcotimer_second_to_tick(smw->smw_period); 623 if (sc->sc_has_rcba) { 624 if (period < LPCIB_TCOTIMER2_MIN_TICK || 625 period > LPCIB_TCOTIMER2_MAX_TICK) 626 return EINVAL; 627 } else { 628 if (period < LPCIB_TCOTIMER_MIN_TICK || 629 period > LPCIB_TCOTIMER_MAX_TICK) 630 return EINVAL; 631 } 632 633 /* Stop the TCO timer, */ 634 tcotimer_stop(sc); 635 636 /* set the timeout, */ 637 if (sc->sc_has_rcba) { 638 /* ICH6 or newer */ 639 ich6period = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 640 LPCIB_TCO_TMR2); 641 ich6period &= 0xfc00; 642 bus_space_write_2(sc->sc_iot, sc->sc_ioh, 643 LPCIB_TCO_TMR2, ich6period | period); 644 } else { 645 /* ICH5 or older */ 646 ich5period = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 647 LPCIB_TCO_TMR); 648 ich5period &= 0xc0; 649 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 650 LPCIB_TCO_TMR, ich5period | period); 651 } 652 653 /* and start/reload the timer. */ 654 tcotimer_start(sc); 655 tcotimer_tickle(smw); 656 } 657 658 return 0; 659 } 660 661 static int 662 tcotimer_tickle(struct sysmon_wdog *smw) 663 { 664 struct lpcib_softc *sc = smw->smw_cookie; 665 666 /* any value is allowed */ 667 if (sc->sc_has_rcba) 668 bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO_RLD, 1); 669 else 670 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_TCO_RLD, 1); 671 672 return 0; 673 } 674 675 static void 676 tcotimer_stop(struct lpcib_softc *sc) 677 { 678 uint16_t ioreg; 679 680 ioreg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT); 681 ioreg |= LPCIB_TCO1_CNT_TCO_TMR_HLT; 682 bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT, ioreg); 683 } 684 685 static void 686 tcotimer_start(struct lpcib_softc *sc) 687 { 688 uint16_t ioreg; 689 690 ioreg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT); 691 ioreg &= ~LPCIB_TCO1_CNT_TCO_TMR_HLT; 692 bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT, ioreg); 693 } 694 695 static void 696 tcotimer_status_reset(struct lpcib_softc *sc) 697 { 698 bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_STS, 699 LPCIB_TCO1_STS_TIMEOUT); 700 bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO2_STS, 701 LPCIB_TCO2_STS_BOOT_STS); 702 bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO2_STS, 703 LPCIB_TCO2_STS_SECONDS_TO_STS); 704 } 705 706 /* 707 * Clear the No Reboot (NR) bit, this enables reboots when the timer 708 * reaches the timeout for the second time. 709 */ 710 static int 711 tcotimer_disable_noreboot(device_t self) 712 { 713 struct lpcib_softc *sc = device_private(self); 714 715 if (sc->sc_has_rcba) { 716 uint32_t status; 717 718 status = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 719 LPCIB_GCS_OFFSET); 720 status &= ~LPCIB_GCS_NO_REBOOT; 721 bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, 722 LPCIB_GCS_OFFSET, status); 723 status = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 724 LPCIB_GCS_OFFSET); 725 if (status & LPCIB_GCS_NO_REBOOT) 726 goto error; 727 } else { 728 pcireg_t pcireg; 729 730 pcireg = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 731 LPCIB_PCI_GEN_STA); 732 if (pcireg & LPCIB_PCI_GEN_STA_NO_REBOOT) { 733 /* TCO timeout reset is disabled; try to enable it */ 734 pcireg &= ~LPCIB_PCI_GEN_STA_NO_REBOOT; 735 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 736 LPCIB_PCI_GEN_STA, pcireg); 737 if (pcireg & LPCIB_PCI_GEN_STA_NO_REBOOT) 738 goto error; 739 } 740 } 741 742 return 0; 743 error: 744 aprint_error_dev(self, "TCO timer reboot disabled by hardware; " 745 "hope SMBIOS properly handles it.\n"); 746 return EINVAL; 747 } 748 749 750 /* 751 * Intel ICH SpeedStep support. 752 */ 753 #define SS_READ(sc, reg) \ 754 bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (reg)) 755 #define SS_WRITE(sc, reg, val) \ 756 bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 757 758 /* 759 * Linux driver says that SpeedStep on older chipsets cause 760 * lockups on Dell Inspiron 8000 and 8100. 761 * It should also not be enabled on systems with the 82855GM 762 * Hub, which typically have an EST-enabled CPU. 763 */ 764 static int 765 speedstep_bad_hb_check(struct pci_attach_args *pa) 766 { 767 768 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82815_FULL_HUB && 769 PCI_REVISION(pa->pa_class) < 5) 770 return 1; 771 772 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82855GM_MCH) 773 return 1; 774 775 return 0; 776 } 777 778 static void 779 speedstep_configure(device_t self) 780 { 781 struct lpcib_softc *sc = device_private(self); 782 const struct sysctlnode *node, *ssnode; 783 int rv; 784 785 /* Supported on ICH2-M, ICH3-M and ICH4-M. */ 786 if (PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801DB_ISA || 787 PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801CAM_LPC || 788 (PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801BAM_LPC && 789 pci_find_device(&sc->sc_pa, speedstep_bad_hb_check) == 0)) { 790 pcireg_t pmcon; 791 792 /* Enable SpeedStep if it isn't already enabled. */ 793 pmcon = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 794 LPCIB_PCI_GEN_PMCON_1); 795 if ((pmcon & LPCIB_PCI_GEN_PMCON_1_SS_EN) == 0) 796 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 797 LPCIB_PCI_GEN_PMCON_1, 798 pmcon | LPCIB_PCI_GEN_PMCON_1_SS_EN); 799 800 /* Put in machdep.speedstep_state (0 for low, 1 for high). */ 801 if ((rv = sysctl_createv(&sc->sc_log, 0, NULL, &node, 802 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 803 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0) 804 goto err; 805 806 /* CTLFLAG_ANYWRITE? kernel option like EST? */ 807 if ((rv = sysctl_createv(&sc->sc_log, 0, &node, &ssnode, 808 CTLFLAG_READWRITE, CTLTYPE_INT, "speedstep_state", NULL, 809 speedstep_sysctl_helper, 0, NULL, 0, CTL_CREATE, 810 CTL_EOL)) != 0) 811 goto err; 812 813 /* XXX save the sc for IO tag/handle */ 814 speedstep_cookie = sc; 815 aprint_verbose_dev(self, "SpeedStep enabled\n"); 816 } 817 818 return; 819 820 err: 821 aprint_normal("%s: sysctl_createv failed (rv = %d)\n", __func__, rv); 822 } 823 824 static void 825 speedstep_unconfigure(device_t self) 826 { 827 struct lpcib_softc *sc = device_private(self); 828 829 sysctl_teardown(&sc->sc_log); 830 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 831 LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon_orig); 832 833 speedstep_cookie = NULL; 834 } 835 836 /* 837 * get/set the SpeedStep state: 0 == low power, 1 == high power. 838 */ 839 static int 840 speedstep_sysctl_helper(SYSCTLFN_ARGS) 841 { 842 struct sysctlnode node; 843 struct lpcib_softc *sc = speedstep_cookie; 844 uint8_t state, state2; 845 int ostate, nstate, s, error = 0; 846 847 /* 848 * We do the dance with spl's to avoid being at high ipl during 849 * sysctl_lookup() which can both copyin and copyout. 850 */ 851 s = splserial(); 852 state = SS_READ(sc, LPCIB_PM_SS_CNTL); 853 splx(s); 854 if ((state & LPCIB_PM_SS_STATE_LOW) == 0) 855 ostate = 1; 856 else 857 ostate = 0; 858 nstate = ostate; 859 860 node = *rnode; 861 node.sysctl_data = &nstate; 862 863 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 864 if (error || newp == NULL) 865 goto out; 866 867 /* Only two states are available */ 868 if (nstate != 0 && nstate != 1) { 869 error = EINVAL; 870 goto out; 871 } 872 873 s = splserial(); 874 state2 = SS_READ(sc, LPCIB_PM_SS_CNTL); 875 if ((state2 & LPCIB_PM_SS_STATE_LOW) == 0) 876 ostate = 1; 877 else 878 ostate = 0; 879 880 if (ostate != nstate) { 881 uint8_t cntl; 882 883 if (nstate == 0) 884 state2 |= LPCIB_PM_SS_STATE_LOW; 885 else 886 state2 &= ~LPCIB_PM_SS_STATE_LOW; 887 888 /* 889 * Must disable bus master arbitration during the change. 890 */ 891 cntl = SS_READ(sc, LPCIB_PM_CTRL); 892 SS_WRITE(sc, LPCIB_PM_CTRL, cntl | LPCIB_PM_SS_CNTL_ARB_DIS); 893 SS_WRITE(sc, LPCIB_PM_SS_CNTL, state2); 894 SS_WRITE(sc, LPCIB_PM_CTRL, cntl); 895 } 896 splx(s); 897 out: 898 return error; 899 } 900 901 #if NHPET > 0 902 struct lpcib_hpet_attach_arg { 903 bus_space_tag_t hpet_mem_t; 904 uint32_t hpet_reg; 905 }; 906 907 static int 908 lpcib_hpet_match(device_t parent, cfdata_t match, void *aux) 909 { 910 struct lpcib_hpet_attach_arg *arg = aux; 911 bus_space_tag_t tag; 912 bus_space_handle_t handle; 913 914 tag = arg->hpet_mem_t; 915 916 if (bus_space_map(tag, arg->hpet_reg, HPET_WINDOW_SIZE, 0, &handle)) { 917 aprint_verbose_dev(parent, "HPET window not mapped, skipping\n"); 918 return 0; 919 } 920 bus_space_unmap(tag, handle, HPET_WINDOW_SIZE); 921 922 return 1; 923 } 924 925 static int 926 lpcib_hpet_detach(device_t self, int flags) 927 { 928 struct hpet_softc *sc = device_private(self); 929 int rc; 930 931 if ((rc = hpet_detach(self, flags)) != 0) 932 return rc; 933 934 bus_space_unmap(sc->sc_memt, sc->sc_memh, HPET_WINDOW_SIZE); 935 936 return 0; 937 } 938 939 static void 940 lpcib_hpet_attach(device_t parent, device_t self, void *aux) 941 { 942 struct hpet_softc *sc = device_private(self); 943 struct lpcib_hpet_attach_arg *arg = aux; 944 945 aprint_naive("\n"); 946 aprint_normal("\n"); 947 948 sc->sc_memt = arg->hpet_mem_t; 949 950 if (bus_space_map(sc->sc_memt, arg->hpet_reg, HPET_WINDOW_SIZE, 0, 951 &sc->sc_memh)) { 952 aprint_error_dev(self, 953 "HPET memory window could not be mapped"); 954 return; 955 } 956 957 hpet_attach_subr(self); 958 } 959 960 CFATTACH_DECL_NEW(ichlpcib_hpet, sizeof(struct hpet_softc), lpcib_hpet_match, 961 lpcib_hpet_attach, lpcib_hpet_detach, NULL); 962 963 static void 964 lpcib_hpet_configure(device_t self) 965 { 966 struct lpcib_softc *sc = device_private(self); 967 struct lpcib_hpet_attach_arg arg; 968 uint32_t hpet_reg, val; 969 970 if (sc->sc_has_ich5_hpet) { 971 val = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 972 LPCIB_PCI_GEN_CNTL); 973 switch (val & LPCIB_ICH5_HPTC_WIN_MASK) { 974 case LPCIB_ICH5_HPTC_0000: 975 hpet_reg = LPCIB_ICH5_HPTC_0000_BASE; 976 break; 977 case LPCIB_ICH5_HPTC_1000: 978 hpet_reg = LPCIB_ICH5_HPTC_1000_BASE; 979 break; 980 case LPCIB_ICH5_HPTC_2000: 981 hpet_reg = LPCIB_ICH5_HPTC_2000_BASE; 982 break; 983 case LPCIB_ICH5_HPTC_3000: 984 hpet_reg = LPCIB_ICH5_HPTC_3000_BASE; 985 break; 986 default: 987 return; 988 } 989 val |= sc->sc_hpet_reg | LPCIB_ICH5_HPTC_EN; 990 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 991 LPCIB_PCI_GEN_CNTL, val); 992 } else if (sc->sc_has_rcba) { 993 val = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 994 LPCIB_RCBA_HPTC); 995 switch (val & LPCIB_RCBA_HPTC_WIN_MASK) { 996 case LPCIB_RCBA_HPTC_0000: 997 hpet_reg = LPCIB_RCBA_HPTC_0000_BASE; 998 break; 999 case LPCIB_RCBA_HPTC_1000: 1000 hpet_reg = LPCIB_RCBA_HPTC_1000_BASE; 1001 break; 1002 case LPCIB_RCBA_HPTC_2000: 1003 hpet_reg = LPCIB_RCBA_HPTC_2000_BASE; 1004 break; 1005 case LPCIB_RCBA_HPTC_3000: 1006 hpet_reg = LPCIB_RCBA_HPTC_3000_BASE; 1007 break; 1008 default: 1009 return; 1010 } 1011 val |= LPCIB_RCBA_HPTC_EN; 1012 bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC, 1013 val); 1014 } else { 1015 /* No HPET here */ 1016 return; 1017 } 1018 1019 arg.hpet_mem_t = sc->sc_pa.pa_memt; 1020 arg.hpet_reg = hpet_reg; 1021 1022 sc->sc_hpetbus = config_found_ia(self, "hpetichbus", &arg, NULL); 1023 } 1024 1025 static int 1026 lpcib_hpet_unconfigure(device_t self, int flags) 1027 { 1028 struct lpcib_softc *sc = device_private(self); 1029 int rc; 1030 1031 if (sc->sc_hpetbus != NULL && 1032 (rc = config_detach(sc->sc_hpetbus, flags)) != 0) 1033 return rc; 1034 1035 return 0; 1036 } 1037 #endif 1038 1039 #if NGPIO > 0 1040 static void 1041 lpcib_gpio_configure(device_t self) 1042 { 1043 struct lpcib_softc *sc = device_private(self); 1044 struct gpiobus_attach_args gba; 1045 pcireg_t gpio_cntl; 1046 uint32_t use, io, bit; 1047 int pin, shift, base_reg, cntl_reg, reg; 1048 1049 /* this implies ICH >= 6, and thus different mapreg */ 1050 if (sc->sc_has_rcba) { 1051 base_reg = LPCIB_PCI_GPIO_BASE_ICH6; 1052 cntl_reg = LPCIB_PCI_GPIO_CNTL_ICH6; 1053 } else { 1054 base_reg = LPCIB_PCI_GPIO_BASE; 1055 cntl_reg = LPCIB_PCI_GPIO_CNTL; 1056 } 1057 1058 gpio_cntl = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 1059 cntl_reg); 1060 1061 /* Is GPIO enabled? */ 1062 if ((gpio_cntl & LPCIB_PCI_GPIO_CNTL_EN) == 0) 1063 return; 1064 1065 if (pci_mapreg_map(&sc->sc_pa, base_reg, PCI_MAPREG_TYPE_IO, 0, 1066 &sc->sc_gpio_iot, &sc->sc_gpio_ioh, 1067 NULL, &sc->sc_gpio_ios)) { 1068 aprint_error_dev(self, "can't map general purpose i/o space\n"); 1069 return; 1070 } 1071 1072 mutex_init(&sc->sc_gpio_mtx, MUTEX_DEFAULT, IPL_NONE); 1073 1074 for (pin = 0; pin < LPCIB_GPIO_NPINS; pin++) { 1075 sc->sc_gpio_pins[pin].pin_num = pin; 1076 1077 /* Read initial state */ 1078 reg = (pin < 32) ? LPCIB_GPIO_GPIO_USE_SEL : LPCIB_GPIO_GPIO_USE_SEL2; 1079 use = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1080 reg = (pin < 32) ? LPCIB_GPIO_GP_IO_SEL : LPCIB_GPIO_GP_IO_SEL; 1081 io = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, 4); 1082 shift = pin % 32; 1083 bit = __BIT(shift); 1084 1085 if ((use & bit) != 0) { 1086 sc->sc_gpio_pins[pin].pin_caps = 1087 GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 1088 if (pin < 32) 1089 sc->sc_gpio_pins[pin].pin_caps |= 1090 GPIO_PIN_PULSATE; 1091 if ((io & bit) != 0) 1092 sc->sc_gpio_pins[pin].pin_flags = 1093 GPIO_PIN_INPUT; 1094 else 1095 sc->sc_gpio_pins[pin].pin_flags = 1096 GPIO_PIN_OUTPUT; 1097 } else 1098 sc->sc_gpio_pins[pin].pin_caps = 0; 1099 1100 if (lpcib_gpio_pin_read(sc, pin) == 0) 1101 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW; 1102 else 1103 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH; 1104 1105 } 1106 1107 /* Create controller tag */ 1108 sc->sc_gpio_gc.gp_cookie = sc; 1109 sc->sc_gpio_gc.gp_pin_read = lpcib_gpio_pin_read; 1110 sc->sc_gpio_gc.gp_pin_write = lpcib_gpio_pin_write; 1111 sc->sc_gpio_gc.gp_pin_ctl = lpcib_gpio_pin_ctl; 1112 1113 memset(&gba, 0, sizeof(gba)); 1114 1115 gba.gba_gc = &sc->sc_gpio_gc; 1116 gba.gba_pins = sc->sc_gpio_pins; 1117 gba.gba_npins = LPCIB_GPIO_NPINS; 1118 1119 sc->sc_gpiobus = config_found_ia(self, "gpiobus", &gba, gpiobus_print); 1120 } 1121 1122 static int 1123 lpcib_gpio_unconfigure(device_t self, int flags) 1124 { 1125 struct lpcib_softc *sc = device_private(self); 1126 int rc; 1127 1128 if (sc->sc_gpiobus != NULL && 1129 (rc = config_detach(sc->sc_gpiobus, flags)) != 0) 1130 return rc; 1131 1132 mutex_destroy(&sc->sc_gpio_mtx); 1133 1134 bus_space_unmap(sc->sc_gpio_iot, sc->sc_gpio_ioh, sc->sc_gpio_ios); 1135 1136 return 0; 1137 } 1138 1139 static int 1140 lpcib_gpio_pin_read(void *arg, int pin) 1141 { 1142 struct lpcib_softc *sc = arg; 1143 uint32_t data; 1144 int reg, shift; 1145 1146 reg = (pin < 32) ? LPCIB_GPIO_GP_LVL : LPCIB_GPIO_GP_LVL2; 1147 shift = pin % 32; 1148 1149 mutex_enter(&sc->sc_gpio_mtx); 1150 data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1151 mutex_exit(&sc->sc_gpio_mtx); 1152 1153 return (__SHIFTOUT(data, __BIT(shift)) ? GPIO_PIN_HIGH : GPIO_PIN_LOW); 1154 } 1155 1156 static void 1157 lpcib_gpio_pin_write(void *arg, int pin, int value) 1158 { 1159 struct lpcib_softc *sc = arg; 1160 uint32_t data; 1161 int reg, shift; 1162 1163 reg = (pin < 32) ? LPCIB_GPIO_GP_LVL : LPCIB_GPIO_GP_LVL2; 1164 shift = pin % 32; 1165 1166 mutex_enter(&sc->sc_gpio_mtx); 1167 1168 data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1169 1170 if(value) 1171 data |= __BIT(shift); 1172 else 1173 data &= ~__BIT(shift); 1174 1175 bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data); 1176 1177 mutex_exit(&sc->sc_gpio_mtx); 1178 } 1179 1180 static void 1181 lpcib_gpio_pin_ctl(void *arg, int pin, int flags) 1182 { 1183 struct lpcib_softc *sc = arg; 1184 uint32_t data; 1185 int reg, shift; 1186 1187 shift = pin % 32; 1188 reg = (pin < 32) ? LPCIB_GPIO_GP_IO_SEL : LPCIB_GPIO_GP_IO_SEL2; 1189 1190 mutex_enter(&sc->sc_gpio_mtx); 1191 1192 data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1193 1194 if (flags & GPIO_PIN_OUTPUT) 1195 data &= ~__BIT(shift); 1196 1197 if (flags & GPIO_PIN_INPUT) 1198 data |= __BIT(shift); 1199 1200 bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data); 1201 1202 1203 if (pin < 32) { 1204 reg = LPCIB_GPIO_GPO_BLINK; 1205 data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1206 1207 if (flags & GPIO_PIN_PULSATE) 1208 data |= __BIT(shift); 1209 else 1210 data &= ~__BIT(shift); 1211 1212 bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data); 1213 } 1214 1215 mutex_exit(&sc->sc_gpio_mtx); 1216 } 1217 #endif 1218