1/* $NetBSD: elan520.c,v 1.52 2021/08/07 16:18:55 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 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 * Device driver for the AMD Elan SC520 System Controller. This attaches 34 * where the "pchb" driver might normally attach, and provides support for 35 * extra features on the SC520, such as the watchdog timer and GPIO. 36 * 37 * Information about the GP bus echo bug work-around is from code posted 38 * to the "soekris-tech" mailing list by Jasper Wallace. 39 */ 40 41#include <sys/cdefs.h> 42 43__KERNEL_RCSID(0, "$NetBSD: elan520.c,v 1.52 2021/08/07 16:18:55 thorpej Exp $"); 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/time.h> 48#include <sys/device.h> 49#include <sys/gpio.h> 50#include <sys/mutex.h> 51#include <sys/wdog.h> 52#include <sys/reboot.h> 53 54#include <uvm/uvm_extern.h> 55 56#include <sys/bus.h> 57 58#include <x86/nmi.h> 59 60#include <dev/pci/pcivar.h> 61 62#include <dev/pci/pcidevs.h> 63 64#include "gpio.h" 65#if NGPIO > 0 66#include <dev/gpio/gpiovar.h> 67#endif 68 69#include <arch/i386/pci/elan520reg.h> 70 71#include <dev/sysmon/sysmonvar.h> 72 73#define ELAN_IRQ 1 74#define PG0_PROT_SIZE PAGE_SIZE 75 76struct elansc_softc { 77 device_t sc_dev; 78 device_t sc_gpio; 79 device_t sc_par; 80 device_t sc_pex; 81 device_t sc_pci; 82 83 pci_chipset_tag_t sc_pc; 84 pcitag_t sc_tag; 85 bus_dma_tag_t sc_dmat; 86 bus_dma_tag_t sc_dmat64; 87 bus_space_tag_t sc_iot; 88 bus_space_tag_t sc_memt; 89 bus_space_handle_t sc_memh; 90 int sc_pciflags; 91 92 int sc_echobug; 93 94 kmutex_t sc_mtx; 95 96 struct sysmon_wdog sc_smw; 97 void *sc_eih; 98 void *sc_pih; 99 void *sc_sh; 100 uint8_t sc_mpicmode; 101 uint8_t sc_picicr; 102 int sc_pg0par; 103 int sc_textpar[3]; 104#if NGPIO > 0 105 /* GPIO interface */ 106 struct gpio_chipset_tag sc_gpio_gc; 107 gpio_pin_t sc_gpio_pins[ELANSC_PIO_NPINS]; 108#endif 109}; 110 111struct pareg { 112 paddr_t start; 113 paddr_t end; 114}; 115 116static bool elansc_attached = false; 117int elansc_wpvnmi = 1; 118int elansc_pcinmi = 1; 119int elansc_do_protect_pg0 = 1; 120 121#if NGPIO > 0 122static int elansc_gpio_pin_read(void *, int); 123static void elansc_gpio_pin_write(void *, int, int); 124static void elansc_gpio_pin_ctl(void *, int, int); 125#endif 126 127static void elansc_print_par(device_t, int, uint32_t); 128 129static void elanpar_intr_establish(device_t, struct elansc_softc *); 130static void elanpar_intr_disestablish(struct elansc_softc *); 131static bool elanpar_shutdown(device_t, int); 132 133static void elanpex_intr_establish(device_t, struct elansc_softc *); 134static void elanpex_intr_disestablish(struct elansc_softc *); 135static bool elanpex_shutdown(device_t, int); 136static int elansc_rescan(device_t, const char *, const int *); 137 138static void elansc_protect(struct elansc_softc *, int, paddr_t, uint32_t); 139static bool elansc_shutdown(device_t, int); 140 141static const uint32_t sfkb = 64 * 1024, fkb = 4 * 1024; 142 143static void 144elansc_childdetached(device_t self, device_t child) 145{ 146 struct elansc_softc *sc = device_private(self); 147 148 if (child == sc->sc_par) 149 sc->sc_par = NULL; 150 if (child == sc->sc_pex) 151 sc->sc_pex = NULL; 152 if (child == sc->sc_pci) 153 sc->sc_pci = NULL; 154 if (child == sc->sc_gpio) 155 sc->sc_gpio = NULL; 156} 157 158static int 159elansc_match(device_t parent, cfdata_t match, void *aux) 160{ 161 struct pcibus_attach_args *pba = aux; 162 pcitag_t tag; 163 pcireg_t id; 164 165 if (elansc_attached) 166 return 0; 167 168 if (pcimatch(parent, match, aux) == 0) 169 return 0; 170 171 if (pba->pba_bus != 0) 172 return 0; 173 174 tag = pci_make_tag(pba->pba_pc, 0, 0, 0); 175 id = pci_conf_read(pba->pba_pc, tag, PCI_ID_REG); 176 177 if (PCI_VENDOR(id) == PCI_VENDOR_AMD && 178 PCI_PRODUCT(id) == PCI_PRODUCT_AMD_SC520_SC) 179 return 10; 180 181 return 0; 182} 183 184/* 185 * Performance tuning for Soekris net4501: 186 * - enable SDRAM write buffer and read prefetching 187 */ 188#if 0 189 uint8_t dbctl; 190 191 dbctl = bus_space_read_1(memt, memh, MMCR_DBCTL); 192 dbctl &= ~MMCR_DBCTL_WB_WM_MASK; 193 dbctl |= MMCR_DBCTL_WB_WM_16DW; 194 dbctl |= MMCR_DBCTL_WB_ENB | MMCR_DBCTL_RAB_ENB; 195 bus_space_write_1(memt, memh, MMCR_DBCTL, dbctl); 196#endif 197 198/* 199 * Performance tuning for PCI bus on the AMD Elan SC520: 200 * - enable concurrent arbitration of PCI and CPU busses 201 * (and PCI buffer) 202 * - enable PCI automatic delayed read transactions and 203 * write posting 204 * - enable PCI read buffer snooping (coherency) 205 */ 206static void 207elansc_perf_tune(device_t self, bus_space_tag_t memt, bus_space_handle_t memh) 208{ 209 uint8_t sysarbctl; 210 uint16_t hbctl; 211 const bool concurrency = true; /* concurrent bus arbitration */ 212 213 sysarbctl = bus_space_read_1(memt, memh, MMCR_SYSARBCTL); 214 if ((sysarbctl & MMCR_SYSARBCTL_CNCR_MODE_ENB) != 0) { 215 aprint_debug_dev(self, 216 "concurrent arbitration mode is active\n"); 217 } else if (concurrency) { 218 aprint_verbose_dev(self, "activating concurrent " 219 "arbitration mode\n"); 220 /* activate concurrent bus arbitration */ 221 sysarbctl |= MMCR_SYSARBCTL_CNCR_MODE_ENB; 222 bus_space_write_1(memt, memh, MMCR_SYSARBCTL, sysarbctl); 223 } 224 225 hbctl = bus_space_read_2(memt, memh, MMCR_HBCTL); 226 227 /* target read FIFO snoop */ 228 if ((hbctl & MMCR_HBCTL_T_PURGE_RD_ENB) != 0) 229 aprint_debug_dev(self, "read-FIFO snooping is active\n"); 230 else { 231 aprint_verbose_dev(self, "activating read-FIFO snooping\n"); 232 hbctl |= MMCR_HBCTL_T_PURGE_RD_ENB; 233 } 234 235 if ((hbctl & MMCR_HBCTL_M_WPOST_ENB) != 0) 236 aprint_debug_dev(self, "CPU->PCI write-posting is active\n"); 237 else if (concurrency) { 238 aprint_verbose_dev(self, "activating CPU->PCI write-posting\n"); 239 hbctl |= MMCR_HBCTL_M_WPOST_ENB; 240 } 241 242 /* auto delay read txn: looks safe, but seems to cause 243 * net4526 w/ minipci ath fits 244 */ 245#if 0 246 if ((hbctl & MMCR_HBCTL_T_DLYTR_ENB_AUTORETRY) != 0) 247 aprint_debug_dev(self, 248 "automatic read transaction delay is active\n"); 249 else { 250 aprint_verbose_dev(self, 251 "activating automatic read transaction delay\n"); 252 hbctl |= MMCR_HBCTL_T_DLYTR_ENB_AUTORETRY; 253 } 254#endif 255 bus_space_write_2(memt, memh, MMCR_HBCTL, hbctl); 256} 257 258static void 259elansc_wdogctl_write(struct elansc_softc *sc, uint16_t val) 260{ 261 uint8_t echo_mode = 0; /* XXX: gcc */ 262 263 KASSERT(mutex_owned(&sc->sc_mtx)); 264 265 /* Switch off GP bus echo mode if we need to. */ 266 if (sc->sc_echobug) { 267 echo_mode = bus_space_read_1(sc->sc_memt, sc->sc_memh, 268 MMCR_GPECHO); 269 bus_space_write_1(sc->sc_memt, sc->sc_memh, 270 MMCR_GPECHO, echo_mode & ~GPECHO_GP_ECHO_ENB); 271 } 272 273 /* Unlock the register. */ 274 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL, 275 WDTMRCTL_UNLOCK1); 276 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL, 277 WDTMRCTL_UNLOCK2); 278 279 /* Write the value. */ 280 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL, val); 281 282 /* Switch GP bus echo mode back. */ 283 if (sc->sc_echobug) 284 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_GPECHO, 285 echo_mode); 286} 287 288static void 289elansc_wdogctl_reset(struct elansc_softc *sc) 290{ 291 uint8_t echo_mode = 0/* XXX: gcc */; 292 293 KASSERT(mutex_owned(&sc->sc_mtx)); 294 295 /* Switch off GP bus echo mode if we need to. */ 296 if (sc->sc_echobug) { 297 echo_mode = bus_space_read_1(sc->sc_memt, sc->sc_memh, 298 MMCR_GPECHO); 299 bus_space_write_1(sc->sc_memt, sc->sc_memh, 300 MMCR_GPECHO, echo_mode & ~GPECHO_GP_ECHO_ENB); 301 } 302 303 /* Reset the watchdog. */ 304 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL, 305 WDTMRCTL_RESET1); 306 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL, 307 WDTMRCTL_RESET2); 308 309 /* Switch GP bus echo mode back. */ 310 if (sc->sc_echobug) 311 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_GPECHO, 312 echo_mode); 313} 314 315static const struct { 316 int period; /* whole seconds */ 317 uint16_t exp; /* exponent select */ 318} elansc_wdog_periods[] = { 319 { 1, WDTMRCTL_EXP_SEL25 }, 320 { 2, WDTMRCTL_EXP_SEL26 }, 321 { 4, WDTMRCTL_EXP_SEL27 }, 322 { 8, WDTMRCTL_EXP_SEL28 }, 323 { 16, WDTMRCTL_EXP_SEL29 }, 324 { 32, WDTMRCTL_EXP_SEL30 }, 325 { 0, 0 }, 326}; 327 328static int 329elansc_wdog_arm(struct elansc_softc *sc) 330{ 331 struct sysmon_wdog *smw = &sc->sc_smw; 332 int i; 333 uint16_t exp_sel = 0; /* XXX: gcc */ 334 335 KASSERT(mutex_owned(&sc->sc_mtx)); 336 337 if (smw->smw_period == WDOG_PERIOD_DEFAULT) { 338 smw->smw_period = 32; 339 exp_sel = WDTMRCTL_EXP_SEL30; 340 } else { 341 for (i = 0; elansc_wdog_periods[i].period != 0; i++) { 342 if (elansc_wdog_periods[i].period == 343 smw->smw_period) { 344 exp_sel = elansc_wdog_periods[i].exp; 345 break; 346 } 347 } 348 if (elansc_wdog_periods[i].period == 0) 349 return EINVAL; 350 } 351 elansc_wdogctl_write(sc, WDTMRCTL_ENB | 352 WDTMRCTL_WRST_ENB | exp_sel); 353 elansc_wdogctl_reset(sc); 354 return 0; 355} 356 357static int 358elansc_wdog_setmode(struct sysmon_wdog *smw) 359{ 360 struct elansc_softc *sc = smw->smw_cookie; 361 int rc = 0; 362 363 mutex_enter(&sc->sc_mtx); 364 365 if (!device_is_active(sc->sc_dev)) 366 rc = EBUSY; 367 else if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 368 elansc_wdogctl_write(sc, 369 WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30); 370 } else 371 rc = elansc_wdog_arm(sc); 372 373 mutex_exit(&sc->sc_mtx); 374 return rc; 375} 376 377static int 378elansc_wdog_tickle(struct sysmon_wdog *smw) 379{ 380 struct elansc_softc *sc = smw->smw_cookie; 381 382 mutex_enter(&sc->sc_mtx); 383 elansc_wdogctl_reset(sc); 384 mutex_exit(&sc->sc_mtx); 385 return 0; 386} 387 388static const char *elansc_speeds[] = { 389 "(reserved 00)", 390 "100MHz", 391 "133MHz", 392 "(reserved 11)", 393}; 394 395static int 396elanpar_intr(void *arg) 397{ 398 struct elansc_softc *sc = arg; 399 uint16_t wpvsta; 400 unsigned win; 401 uint32_t par; 402 const char *wpvstr; 403 404 wpvsta = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA); 405 406 if ((wpvsta & MMCR_WPVSTA_WPV_STA) == 0) 407 return 0; 408 409 win = __SHIFTOUT(wpvsta, MMCR_WPVSTA_WPV_WINDOW); 410 411 par = bus_space_read_4(sc->sc_memt, sc->sc_memh, MMCR_PAR(win)); 412 413 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA, 414 MMCR_WPVSTA_WPV_STA); 415 416 switch (wpvsta & MMCR_WPVSTA_WPV_MSTR) { 417 case MMCR_WPVSTA_WPV_MSTR_CPU: 418 wpvstr = "cpu"; 419 break; 420 case MMCR_WPVSTA_WPV_MSTR_PCI: 421 wpvstr = "pci"; 422 break; 423 case MMCR_WPVSTA_WPV_MSTR_GP: 424 wpvstr = "gp"; 425 break; 426 default: 427 wpvstr = "unknown"; 428 break; 429 } 430 printf_tolog("%s: %s violated write-protect window %u\n", 431 device_xname(sc->sc_par), wpvstr, win); 432 elansc_print_par(sc->sc_par, win, par); 433 return 0; 434} 435 436static int 437elanpar_nmi(const struct trapframe *tf, void *arg) 438{ 439 440 return elanpar_intr(arg); 441} 442 443static int 444elanpex_intr(void *arg) 445{ 446 static struct { 447 const char *string; 448 bool nonfatal; 449 } cmd[16] = { 450 [0] = {.string = "not latched"} 451 , [1] = {.string = "special cycle"} 452 , [2] = {.string = "i/o read"} 453 , [3] = {.string = "i/o write"} 454 , [4] = {.string = "4"} 455 , [5] = {.string = "5"} 456 , [6] = {.string = "memory rd"} 457 , [7] = {.string = "memory wr"} 458 , [8] = {.string = "8"} 459 , [9] = {.string = "9"} 460 , [10] = {.string = "cfg rd", .nonfatal = true} 461 , [11] = {.string = "cfg wr"} 462 , [12] = {.string = "memory rd mul"} 463 , [13] = {.string = "dual-address cycle"} 464 , [14] = {.string = "memory rd line"} 465 , [15] = {.string = "memory wr & inv"} 466 }; 467 468 static const struct { 469 uint16_t bit; 470 const char *msg; 471 } mmsg[] = { 472 {MMCR_HBMSTIRQSTA_M_RTRTO_IRQ_STA, "retry timeout"} 473 , {MMCR_HBMSTIRQSTA_M_TABRT_IRQ_STA, "target abort"} 474 , {MMCR_HBMSTIRQSTA_M_MABRT_IRQ_STA, "abort"} 475 , {MMCR_HBMSTIRQSTA_M_SERR_IRQ_STA, "system error"} 476 , {MMCR_HBMSTIRQSTA_M_RPER_IRQ_STA, "received parity error"} 477 , {MMCR_HBMSTIRQSTA_M_DPER_IRQ_STA, "detected parity error"} 478 }, tmsg[] = { 479 {MMCR_HBTGTIRQSTA_T_DLYTO_IRQ_STA, "delayed txn timeout"} 480 , {MMCR_HBTGTIRQSTA_T_APER_IRQ_STA, "address parity"} 481 , {MMCR_HBTGTIRQSTA_T_DPER_IRQ_STA, "data parity"} 482 }; 483 uint8_t pciarbsta; 484 uint16_t mstcmd, mstirq, tgtid, tgtirq; 485 uint32_t mstaddr; 486 uint16_t mstack = 0, tgtack = 0; 487 int fatal = 0, i, handled = 0; 488 struct elansc_softc *sc = arg; 489 490 pciarbsta = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_PCIARBSTA); 491 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQSTA); 492 mstaddr = bus_space_read_4(sc->sc_memt, sc->sc_memh, MMCR_MSTINTADD); 493 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQSTA); 494 495 if ((pciarbsta & MMCR_PCIARBSTA_GNT_TO_STA) != 0) { 496 printf_tolog( 497 "%s: grant time-out, GNT%" __PRIuBITS "# asserted\n", 498 device_xname(sc->sc_pex), 499 __SHIFTOUT(pciarbsta, MMCR_PCIARBSTA_GNT_TO_ID)); 500 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_PCIARBSTA, 501 MMCR_PCIARBSTA_GNT_TO_STA); 502 handled = true; 503 } 504 505 mstcmd = __SHIFTOUT(mstirq, MMCR_HBMSTIRQSTA_M_CMD_IRQ_ID); 506 507 for (i = 0; i < __arraycount(mmsg); i++) { 508 if ((mstirq & mmsg[i].bit) == 0) 509 continue; 510 printf_tolog("%s: %s %08" PRIx32 " master %s\n", 511 device_xname(sc->sc_pex), cmd[mstcmd].string, mstaddr, 512 mmsg[i].msg); 513 514 mstack |= mmsg[i].bit; 515 if (!cmd[mstcmd].nonfatal) 516 fatal = true; 517 } 518 519 tgtid = __SHIFTOUT(tgtirq, MMCR_HBTGTIRQSTA_T_IRQ_ID); 520 521 for (i = 0; i < __arraycount(tmsg); i++) { 522 if ((tgtirq & tmsg[i].bit) == 0) 523 continue; 524 printf_tolog("%s: %1x target %s\n", device_xname(sc->sc_pex), 525 tgtid, tmsg[i].msg); 526 tgtack |= tmsg[i].bit; 527 } 528 529 /* acknowledge interrupts */ 530 if (tgtack != 0) { 531 handled = true; 532 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQSTA, 533 tgtack); 534 } 535 if (mstack != 0) { 536 handled = true; 537 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQSTA, 538 mstack); 539 } 540 return fatal ? 0 : (handled ? 1 : 0); 541} 542 543static int 544elanpex_nmi(const struct trapframe *tf, void *arg) 545{ 546 547 return elanpex_intr(arg); 548} 549 550#define elansc_print_1(__dev, __sc, __reg) \ 551do { \ 552 aprint_debug_dev(__dev, \ 553 "%s: %s %02" PRIx8 "\n", __func__, #__reg, \ 554 bus_space_read_1((__sc)->sc_memt, (__sc)->sc_memh, __reg)); \ 555} while (/*CONSTCOND*/0) 556 557static void 558elansc_print_par(device_t dev, int i, uint32_t par) 559{ 560 uint32_t addr, sz, unit; 561 const char *tgtstr; 562 563 if ((boothowto & AB_DEBUG) == 0) 564 return; 565 566 switch (par & MMCR_PAR_TARGET) { 567 default: 568 case MMCR_PAR_TARGET_OFF: 569 tgtstr = "off"; 570 break; 571 case MMCR_PAR_TARGET_GPIO: 572 tgtstr = "gpio"; 573 break; 574 case MMCR_PAR_TARGET_GPMEM: 575 tgtstr = "gpmem"; 576 break; 577 case MMCR_PAR_TARGET_PCI: 578 tgtstr = "pci"; 579 break; 580 case MMCR_PAR_TARGET_BOOTCS: 581 tgtstr = "bootcs"; 582 break; 583 case MMCR_PAR_TARGET_ROMCS1: 584 tgtstr = "romcs1"; 585 break; 586 case MMCR_PAR_TARGET_ROMCS2: 587 tgtstr = "romcs2"; 588 break; 589 case MMCR_PAR_TARGET_SDRAM: 590 tgtstr = "sdram"; 591 break; 592 } 593 if ((par & MMCR_PAR_TARGET) == MMCR_PAR_TARGET_GPIO) { 594 unit = 1; 595 sz = __SHIFTOUT(par, MMCR_PAR_IO_SZ); 596 addr = __SHIFTOUT(par, MMCR_PAR_IO_ST_ADR); 597 } else if ((par & MMCR_PAR_PG_SZ) != 0) { 598 unit = 64 * 1024; 599 sz = __SHIFTOUT(par, MMCR_PAR_64KB_SZ); 600 addr = __SHIFTOUT(par, MMCR_PAR_64KB_ST_ADR); 601 } else { 602 unit = 4 * 1024; 603 sz = __SHIFTOUT(par, MMCR_PAR_4KB_SZ); 604 addr = __SHIFTOUT(par, MMCR_PAR_4KB_ST_ADR); 605 } 606 607 printf_tolog( 608 "%s: PAR[%d] %08" PRIx32 " tgt %s attr %1" __PRIxBITS 609 " start %08" PRIx32 " size %" PRIu32 "\n", device_xname(dev), 610 i, par, tgtstr, __SHIFTOUT(par, MMCR_PAR_ATTR), 611 addr * unit, (sz + 1) * unit); 612} 613 614static void 615elansc_print_all_par(device_t dev, 616 bus_space_tag_t memt, bus_space_handle_t memh) 617{ 618 int i; 619 uint32_t par; 620 621 for (i = 0; i < 16; i++) { 622 par = bus_space_read_4(memt, memh, MMCR_PAR(i)); 623 elansc_print_par(dev, i, par); 624 } 625} 626 627static int 628elansc_alloc_par(bus_space_tag_t memt, bus_space_handle_t memh) 629{ 630 int i; 631 uint32_t par; 632 633 for (i = 0; i < 16; i++) { 634 635 par = bus_space_read_4(memt, memh, MMCR_PAR(i)); 636 637 if ((par & MMCR_PAR_TARGET) == MMCR_PAR_TARGET_OFF) 638 break; 639 } 640 if (i == 16) 641 return -1; 642 return i; 643} 644 645static void 646elansc_disable_par(bus_space_tag_t memt, bus_space_handle_t memh, int idx) 647{ 648 uint32_t par; 649 par = bus_space_read_4(memt, memh, MMCR_PAR(idx)); 650 par &= ~MMCR_PAR_TARGET; 651 par |= MMCR_PAR_TARGET_OFF; 652 bus_space_write_4(memt, memh, MMCR_PAR(idx), par); 653} 654 655static int 656region_paddr_to_par(struct pareg *region0, struct pareg *regions, uint32_t unit) 657{ 658 struct pareg *residue = regions; 659 paddr_t start, end; 660 paddr_t start0, end0; 661 662 start0 = region0->start; 663 end0 = region0->end; 664 665 if (start0 % unit != 0) 666 start = start0 + unit - start0 % unit; 667 else 668 start = start0; 669 670 end = end0 - end0 % unit; 671 672 if (start >= end) 673 return 0; 674 675 residue->start = start; 676 residue->end = end; 677 residue++; 678 679 if (start0 < start) { 680 residue->start = start0; 681 residue->end = start; 682 residue++; 683 } 684 if (end < end0) { 685 residue->start = end; 686 residue->end = end0; 687 residue++; 688 } 689 return residue - regions; 690} 691 692static void 693elansc_protect_text(device_t self, struct elansc_softc *sc) 694{ 695 int i, j, nregion, pidx, tidx = 0, xnregion; 696 uint32_t protsize, unprotsize; 697 paddr_t start_pa, end_pa; 698 extern char kernel_text, etext; 699 bus_space_tag_t memt; 700 bus_space_handle_t memh; 701 struct pareg region0, regions[3], xregions[3]; 702 703 sc->sc_textpar[0] = sc->sc_textpar[1] = sc->sc_textpar[2] = -1; 704 705 memt = sc->sc_memt; 706 memh = sc->sc_memh; 707 708 if (!pmap_extract(pmap_kernel(), (vaddr_t)&kernel_text, 709 ®ion0.start) || 710 !pmap_extract(pmap_kernel(), (vaddr_t)&etext, 711 ®ion0.end)) 712 return; 713 714 if (&etext - &kernel_text != region0.end - region0.start) { 715 aprint_error_dev(self, "kernel text may not be contiguous\n"); 716 return; 717 } 718 719 if ((pidx = elansc_alloc_par(memt, memh)) == -1) { 720 aprint_error_dev(self, "cannot allocate PAR\n"); 721 return; 722 } 723 724 (void) bus_space_read_4(memt, memh, MMCR_PAR(pidx)); 725 726 aprint_debug_dev(self, 727 "protect kernel text at physical addresses " 728 "%#" PRIxPADDR " - %#" PRIxPADDR "\n", 729 region0.start, region0.end); 730 731 nregion = region_paddr_to_par(®ion0, regions, sfkb); 732 if (nregion == 0) { 733 aprint_error_dev(self, "kernel text is unprotected\n"); 734 return; 735 } 736 737 unprotsize = 0; 738 for (i = 1; i < nregion; i++) 739 unprotsize += regions[i].end - regions[i].start; 740 741 start_pa = regions[0].start; 742 end_pa = regions[0].end; 743 744 aprint_debug_dev(self, 745 "actually protect kernel text at physical addresses " 746 "%#" PRIxPADDR " - %#" PRIxPADDR "\n", 747 start_pa, end_pa); 748 749 aprint_verbose_dev(self, 750 "%" PRIu32 " bytes of kernel text are unprotected\n", unprotsize); 751 752 protsize = end_pa - start_pa; 753 754 elansc_protect(sc, pidx, start_pa, protsize); 755 756 sc->sc_textpar[tidx++] = pidx; 757 758 unprotsize = 0; 759 for (i = 1; i < nregion; i++) { 760 xnregion = region_paddr_to_par(®ions[i], xregions, fkb); 761 if (xnregion == 0) { 762 aprint_verbose_dev(self, "skip region " 763 "%#" PRIxPADDR " - %#" PRIxPADDR "\n", 764 regions[i].start, regions[i].end); 765 continue; 766 } 767 if ((pidx = elansc_alloc_par(memt, memh)) == -1) { 768 unprotsize += regions[i].end - regions[i].start; 769 continue; 770 } 771 elansc_protect(sc, pidx, xregions[0].start, 772 xregions[0].end - xregions[0].start); 773 sc->sc_textpar[tidx++] = pidx; 774 775 aprint_debug_dev(self, 776 "protect add'l kernel text at physical addresses " 777 "%#" PRIxPADDR " - %#" PRIxPADDR "\n", 778 xregions[0].start, xregions[0].end); 779 780 for (j = 1; j < xnregion; j++) 781 unprotsize += xregions[j].end - xregions[j].start; 782 } 783 aprint_verbose_dev(self, 784 "%" PRIu32 " bytes of kernel text still unprotected\n", unprotsize); 785 786} 787 788static void 789elansc_protect(struct elansc_softc *sc, int pidx, paddr_t addr, uint32_t sz) 790{ 791 uint32_t addr_field, blksz, par, size_field; 792 793 /* set attribute, target. */ 794 par = MMCR_PAR_TARGET_SDRAM | MMCR_PAR_ATTR_NOWRITE; 795 796 KASSERT(addr % fkb == 0 && sz % fkb == 0); 797 798 if (addr % sfkb == 0 && sz % sfkb == 0) { 799 par |= MMCR_PAR_PG_SZ; 800 801 size_field = MMCR_PAR_64KB_SZ; 802 addr_field = MMCR_PAR_64KB_ST_ADR; 803 blksz = 64 * 1024; 804 } else { 805 size_field = MMCR_PAR_4KB_SZ; 806 addr_field = MMCR_PAR_4KB_ST_ADR; 807 blksz = 4 * 1024; 808 } 809 810 KASSERT(sz / blksz - 1 <= __SHIFTOUT_MASK(size_field)); 811 KASSERT(addr / blksz <= __SHIFTOUT_MASK(addr_field)); 812 813 /* set size and address. */ 814 par |= __SHIFTIN(sz / blksz - 1, size_field); 815 par |= __SHIFTIN(addr / blksz, addr_field); 816 817 bus_space_write_4(sc->sc_memt, sc->sc_memh, MMCR_PAR(pidx), par); 818} 819 820static int 821elansc_protect_pg0(device_t self, struct elansc_softc *sc) 822{ 823 int pidx; 824 const paddr_t pg0_paddr = 0; 825 bus_space_tag_t memt; 826 bus_space_handle_t memh; 827 828 memt = sc->sc_memt; 829 memh = sc->sc_memh; 830 831 if (elansc_do_protect_pg0 == 0) 832 return -1; 833 834 if ((pidx = elansc_alloc_par(memt, memh)) == -1) 835 return -1; 836 837 aprint_debug_dev(self, "protect page 0\n"); 838 839 elansc_protect(sc, pidx, pg0_paddr, PG0_PROT_SIZE); 840 return pidx; 841} 842 843static void 844elanpex_intr_ack(bus_space_tag_t memt, bus_space_handle_t memh) 845{ 846 bus_space_write_1(memt, memh, MMCR_PCIARBSTA, 847 MMCR_PCIARBSTA_GNT_TO_STA); 848 bus_space_write_2(memt, memh, MMCR_HBTGTIRQSTA, MMCR_TGTIRQ_ACT); 849 bus_space_write_2(memt, memh, MMCR_HBMSTIRQSTA, MMCR_MSTIRQ_ACT); 850} 851 852static bool 853elansc_suspend(device_t dev, const pmf_qual_t *qual) 854{ 855 bool rc; 856 struct elansc_softc *sc = device_private(dev); 857 858 mutex_enter(&sc->sc_mtx); 859 rc = ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED); 860 mutex_exit(&sc->sc_mtx); 861 if (!rc) 862 aprint_debug_dev(dev, "watchdog enabled, suspend forbidden"); 863 return rc; 864} 865 866static bool 867elansc_resume(device_t dev, const pmf_qual_t *qual) 868{ 869 struct elansc_softc *sc = device_private(dev); 870 871 mutex_enter(&sc->sc_mtx); 872 /* Set up the watchdog registers with some defaults. */ 873 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30); 874 875 /* ...and clear it. */ 876 elansc_wdogctl_reset(sc); 877 mutex_exit(&sc->sc_mtx); 878 879 elansc_perf_tune(dev, sc->sc_memt, sc->sc_memh); 880 881 return true; 882} 883 884static bool 885elansc_shutdown(device_t self, int how) 886{ 887 struct elansc_softc *sc = device_private(self); 888 889 /* Set up the watchdog registers with some defaults. */ 890 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30); 891 892 /* ...and clear it. */ 893 elansc_wdogctl_reset(sc); 894 895 return true; 896} 897 898static int 899elansc_detach(device_t self, int flags) 900{ 901 int rc; 902 struct elansc_softc *sc = device_private(self); 903 904 if ((rc = config_detach_children(self, flags)) != 0) 905 return rc; 906 907 pmf_device_deregister(self); 908 909 if ((flags & DETACH_SHUTDOWN) == 0 && 910 (rc = sysmon_wdog_unregister(&sc->sc_smw)) != 0) { 911 if (rc == ERESTART) 912 rc = EINTR; 913 return rc; 914 } 915 916 mutex_enter(&sc->sc_mtx); 917 918 (void)elansc_shutdown(self, 0); 919 920 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_PICICR, sc->sc_picicr); 921 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_MPICMODE, 922 sc->sc_mpicmode); 923 924 mutex_exit(&sc->sc_mtx); 925 mutex_destroy(&sc->sc_mtx); 926 927 bus_space_unmap(sc->sc_memt, sc->sc_memh, PAGE_SIZE); 928 elansc_attached = false; 929 return 0; 930} 931 932static void * 933elansc_intr_establish(device_t dev, int (*handler)(void *), void *arg) 934{ 935 struct pic *pic; 936 void *ih; 937 938 if ((pic = intr_findpic(ELAN_IRQ)) == NULL) { 939 aprint_error_dev(dev, "PIC for irq %d not found\n", 940 ELAN_IRQ); 941 return NULL; 942 } else if ((ih = intr_establish(ELAN_IRQ, pic, ELAN_IRQ, 943 IST_LEVEL, IPL_HIGH, handler, arg, false)) == NULL) { 944 aprint_error_dev(dev, 945 "could not establish interrupt\n"); 946 return NULL; 947 } 948 aprint_verbose_dev(dev, "interrupting at irq %d\n", ELAN_IRQ); 949 return ih; 950} 951 952static bool 953elanpex_resume(device_t self, const pmf_qual_t *qual) 954{ 955 struct elansc_softc *sc = device_private(device_parent(self)); 956 957 elanpex_intr_establish(self, sc); 958 return sc->sc_eih != NULL; 959} 960 961static bool 962elanpex_suspend(device_t self, const pmf_qual_t *qual) 963{ 964 struct elansc_softc *sc = device_private(device_parent(self)); 965 966 elanpex_intr_disestablish(sc); 967 968 return true; 969} 970 971static bool 972elanpar_resume(device_t self, const pmf_qual_t *qual) 973{ 974 struct elansc_softc *sc = device_private(device_parent(self)); 975 976 elanpar_intr_establish(self, sc); 977 return sc->sc_pih != NULL; 978} 979 980static bool 981elanpar_suspend(device_t self, const pmf_qual_t *qual) 982{ 983 struct elansc_softc *sc = device_private(device_parent(self)); 984 985 elanpar_intr_disestablish(sc); 986 987 return true; 988} 989 990static void 991elanpex_intr_establish(device_t self, struct elansc_softc *sc) 992{ 993 uint8_t sysarbctl; 994 uint16_t pcihostmap, mstirq, tgtirq; 995 996 pcihostmap = bus_space_read_2(sc->sc_memt, sc->sc_memh, 997 MMCR_PCIHOSTMAP); 998 /* Priority P2 (Master PIC IR1) */ 999 pcihostmap &= ~MMCR_PCIHOSTMAP_PCI_IRQ_MAP; 1000 pcihostmap |= __SHIFTIN(__BIT(ELAN_IRQ), MMCR_PCIHOSTMAP_PCI_IRQ_MAP); 1001 if (elansc_pcinmi) 1002 pcihostmap |= MMCR_PCIHOSTMAP_PCI_NMI_ENB; 1003 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP, 1004 pcihostmap); 1005 1006 elanpex_intr_ack(sc->sc_memt, sc->sc_memh); 1007 1008 sysarbctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL); 1009 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL); 1010 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL); 1011 1012 sysarbctl |= MMCR_SYSARBCTL_GNT_TO_INT_ENB; 1013 1014 mstirq |= MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_ENB; 1015 mstirq |= MMCR_HBMSTIRQCTL_M_TABRT_IRQ_ENB; 1016 mstirq |= MMCR_HBMSTIRQCTL_M_MABRT_IRQ_ENB; 1017 mstirq |= MMCR_HBMSTIRQCTL_M_SERR_IRQ_ENB; 1018 mstirq |= MMCR_HBMSTIRQCTL_M_RPER_IRQ_ENB; 1019 mstirq |= MMCR_HBMSTIRQCTL_M_DPER_IRQ_ENB; 1020 1021 tgtirq |= MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_ENB; 1022 tgtirq |= MMCR_HBTGTIRQCTL_T_APER_IRQ_ENB; 1023 tgtirq |= MMCR_HBTGTIRQCTL_T_DPER_IRQ_ENB; 1024 1025 if (elansc_pcinmi) { 1026 sc->sc_eih = nmi_establish(elanpex_nmi, sc); 1027 1028 /* Activate NMI instead of maskable interrupts for 1029 * all PCI exceptions: 1030 */ 1031 mstirq |= MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_SEL; 1032 mstirq |= MMCR_HBMSTIRQCTL_M_TABRT_IRQ_SEL; 1033 mstirq |= MMCR_HBMSTIRQCTL_M_MABRT_IRQ_SEL; 1034 mstirq |= MMCR_HBMSTIRQCTL_M_SERR_IRQ_SEL; 1035 mstirq |= MMCR_HBMSTIRQCTL_M_RPER_IRQ_SEL; 1036 mstirq |= MMCR_HBMSTIRQCTL_M_DPER_IRQ_SEL; 1037 1038 tgtirq |= MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_SEL; 1039 tgtirq |= MMCR_HBTGTIRQCTL_T_APER_IRQ_SEL; 1040 tgtirq |= MMCR_HBTGTIRQCTL_T_DPER_IRQ_SEL; 1041 } else 1042 sc->sc_eih = elansc_intr_establish(self, elanpex_intr, sc); 1043 1044 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL, sysarbctl); 1045 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL, mstirq); 1046 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL, tgtirq); 1047} 1048 1049static void 1050elanpex_attach(device_t parent, device_t self, void *aux) 1051{ 1052 struct elansc_softc *sc = device_private(parent); 1053 1054 aprint_naive(": PCI Exceptions\n"); 1055 aprint_normal(": AMD Elan SC520 PCI Exceptions\n"); 1056 1057 elanpex_intr_establish(self, sc); 1058 1059 aprint_debug_dev(self, "HBMSTIRQCTL %04x\n", 1060 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL)); 1061 1062 aprint_debug_dev(self, "HBTGTIRQCTL %04x\n", 1063 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL)); 1064 1065 aprint_debug_dev(self, "PCIHOSTMAP %04x\n", 1066 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP)); 1067 1068 pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, 1069 pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG) | 1070 PCI_COMMAND_PARITY_ENABLE|PCI_COMMAND_SERR_ENABLE); 1071 1072 if (!pmf_device_register1(self, elanpex_suspend, elanpex_resume, 1073 elanpex_shutdown)) 1074 aprint_error_dev(self, "could not establish power hooks\n"); 1075} 1076 1077static bool 1078elanpex_shutdown(device_t self, int flags) 1079{ 1080 struct elansc_softc *sc = device_private(device_parent(self)); 1081 uint8_t sysarbctl; 1082 uint16_t pcihostmap, mstirq, tgtirq; 1083 1084 sysarbctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL); 1085 sysarbctl &= ~MMCR_SYSARBCTL_GNT_TO_INT_ENB; 1086 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL, sysarbctl); 1087 1088 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL); 1089 mstirq &= ~MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_ENB; 1090 mstirq &= ~MMCR_HBMSTIRQCTL_M_TABRT_IRQ_ENB; 1091 mstirq &= ~MMCR_HBMSTIRQCTL_M_MABRT_IRQ_ENB; 1092 mstirq &= ~MMCR_HBMSTIRQCTL_M_SERR_IRQ_ENB; 1093 mstirq &= ~MMCR_HBMSTIRQCTL_M_RPER_IRQ_ENB; 1094 mstirq &= ~MMCR_HBMSTIRQCTL_M_DPER_IRQ_ENB; 1095 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL, mstirq); 1096 1097 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL); 1098 tgtirq &= ~MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_ENB; 1099 tgtirq &= ~MMCR_HBTGTIRQCTL_T_APER_IRQ_ENB; 1100 tgtirq &= ~MMCR_HBTGTIRQCTL_T_DPER_IRQ_ENB; 1101 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL, tgtirq); 1102 1103 pcihostmap = bus_space_read_2(sc->sc_memt, sc->sc_memh, 1104 MMCR_PCIHOSTMAP); 1105 /* Priority P2 (Master PIC IR1) */ 1106 pcihostmap &= ~MMCR_PCIHOSTMAP_PCI_IRQ_MAP; 1107 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP, 1108 pcihostmap); 1109 1110 return true; 1111} 1112 1113static void 1114elanpex_intr_disestablish(struct elansc_softc *sc) 1115{ 1116 elanpex_shutdown(sc->sc_pex, 0); 1117 1118 if (elansc_pcinmi) 1119 nmi_disestablish(sc->sc_eih); 1120 else 1121 intr_disestablish(sc->sc_eih); 1122 sc->sc_eih = NULL; 1123 1124} 1125 1126static int 1127elanpex_detach(device_t self, int flags) 1128{ 1129 struct elansc_softc *sc = device_private(device_parent(self)); 1130 1131 pmf_device_deregister(self); 1132 elanpex_intr_disestablish(sc); 1133 1134 return 0; 1135} 1136 1137static void 1138elanpar_intr_establish(device_t self, struct elansc_softc *sc) 1139{ 1140 uint8_t adddecctl, wpvmap; 1141 1142 wpvmap = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP); 1143 wpvmap &= ~MMCR_WPVMAP_INT_MAP; 1144 if (elansc_wpvnmi) 1145 wpvmap |= MMCR_WPVMAP_INT_NMI; 1146 else 1147 wpvmap |= __SHIFTIN(__BIT(ELAN_IRQ), MMCR_WPVMAP_INT_MAP); 1148 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP, wpvmap); 1149 1150 /* clear interrupt status */ 1151 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA, 1152 MMCR_WPVSTA_WPV_STA); 1153 1154 /* establish interrupt */ 1155 if (elansc_wpvnmi) 1156 sc->sc_pih = nmi_establish(elanpar_nmi, sc); 1157 else 1158 sc->sc_pih = elansc_intr_establish(self, elanpar_intr, sc); 1159 1160 adddecctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL); 1161 adddecctl |= MMCR_ADDDECCTL_WPV_INT_ENB; 1162 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL, adddecctl); 1163} 1164 1165static bool 1166elanpar_shutdown(device_t self, int flags) 1167{ 1168 int i; 1169 struct elansc_softc *sc = device_private(device_parent(self)); 1170 1171 for (i = 0; i < __arraycount(sc->sc_textpar); i++) { 1172 if (sc->sc_textpar[i] == -1) 1173 continue; 1174 elansc_disable_par(sc->sc_memt, sc->sc_memh, sc->sc_textpar[i]); 1175 sc->sc_textpar[i] = -1; 1176 } 1177 if (sc->sc_pg0par != -1) { 1178 elansc_disable_par(sc->sc_memt, sc->sc_memh, sc->sc_pg0par); 1179 sc->sc_pg0par = -1; 1180 } 1181 return true; 1182} 1183 1184static void 1185elanpar_deferred_attach(device_t self) 1186{ 1187 struct elansc_softc *sc = device_private(device_parent(self)); 1188 1189 elansc_protect_text(self, sc); 1190} 1191 1192static void 1193elanpar_attach(device_t parent, device_t self, void *aux) 1194{ 1195 struct elansc_softc *sc = device_private(parent); 1196 1197 aprint_naive(": Programmable Address Regions\n"); 1198 aprint_normal(": AMD Elan SC520 Programmable Address Regions\n"); 1199 1200 elansc_print_1(self, sc, MMCR_WPVMAP); 1201 elansc_print_all_par(self, sc->sc_memt, sc->sc_memh); 1202 1203 sc->sc_pg0par = elansc_protect_pg0(self, sc); 1204 /* XXX grotty hack to avoid trapping writes by x86_patch() 1205 * to the kernel text on a MULTIPROCESSOR kernel. 1206 */ 1207 config_interrupts(self, elanpar_deferred_attach); 1208 1209 elansc_print_all_par(self, sc->sc_memt, sc->sc_memh); 1210 1211 elanpar_intr_establish(self, sc); 1212 1213 elansc_print_1(self, sc, MMCR_ADDDECCTL); 1214 1215 if (!pmf_device_register1(self, elanpar_suspend, elanpar_resume, 1216 elanpar_shutdown)) 1217 aprint_error_dev(self, "could not establish power hooks\n"); 1218} 1219 1220static void 1221elanpar_intr_disestablish(struct elansc_softc *sc) 1222{ 1223 uint8_t adddecctl, wpvmap; 1224 1225 /* disable interrupt, acknowledge it, disestablish our 1226 * handler, unmap it 1227 */ 1228 adddecctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL); 1229 adddecctl &= ~MMCR_ADDDECCTL_WPV_INT_ENB; 1230 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL, adddecctl); 1231 1232 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA, 1233 MMCR_WPVSTA_WPV_STA); 1234 1235 if (elansc_wpvnmi) 1236 nmi_disestablish(sc->sc_pih); 1237 else 1238 intr_disestablish(sc->sc_pih); 1239 sc->sc_pih = NULL; 1240 1241 wpvmap = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP); 1242 wpvmap &= ~MMCR_WPVMAP_INT_MAP; 1243 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP, wpvmap); 1244} 1245 1246static int 1247elanpar_detach(device_t self, int flags) 1248{ 1249 struct elansc_softc *sc = device_private(device_parent(self)); 1250 1251 pmf_device_deregister(self); 1252 1253 elanpar_shutdown(self, 0); 1254 1255 elanpar_intr_disestablish(sc); 1256 1257 return 0; 1258} 1259 1260static void 1261elansc_attach(device_t parent, device_t self, void *aux) 1262{ 1263 struct elansc_softc *sc = device_private(self); 1264 struct pcibus_attach_args *pba = aux; 1265 uint16_t rev; 1266 uint8_t cpuctl, picicr, ressta; 1267#if NGPIO > 0 1268 int pin, reg, shift; 1269 uint16_t data; 1270#endif 1271 1272 sc->sc_dev = self; 1273 1274 sc->sc_pc = pba->pba_pc; 1275 sc->sc_pciflags = pba->pba_flags; 1276 sc->sc_dmat = pba->pba_dmat; 1277 sc->sc_dmat64 = pba->pba_dmat64; 1278 sc->sc_tag = pci_make_tag(sc->sc_pc, 0, 0, 0); 1279 1280 aprint_naive(": System Controller\n"); 1281 aprint_normal(": AMD Elan SC520 System Controller\n"); 1282 1283 sc->sc_iot = pba->pba_iot; 1284 sc->sc_memt = pba->pba_memt; 1285 if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, PAGE_SIZE, 0, 1286 &sc->sc_memh) != 0) { 1287 aprint_error_dev(sc->sc_dev, "unable to map registers\n"); 1288 return; 1289 } 1290 1291 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_HIGH); 1292 1293 rev = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_REVID); 1294 cpuctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_CPUCTL); 1295 1296 aprint_normal_dev(sc->sc_dev, 1297 "product %d stepping %d.%d, CPU clock %s\n", 1298 (rev & REVID_PRODID) >> REVID_PRODID_SHIFT, 1299 (rev & REVID_MAJSTEP) >> REVID_MAJSTEP_SHIFT, 1300 (rev & REVID_MINSTEP), 1301 elansc_speeds[cpuctl & CPUCTL_CPU_CLK_SPD_MASK]); 1302 1303 /* 1304 * SC520 rev A1 has a bug that affects the watchdog timer. If 1305 * the GP bus echo mode is enabled, writing to the watchdog control 1306 * register is blocked. 1307 * 1308 * The BIOS in some systems (e.g. the Soekris net4501) enables 1309 * GP bus echo for various reasons, so we need to switch it off 1310 * when we talk to the watchdog timer. 1311 * 1312 * XXX The step 1.1 (B1?) in my Soekris net4501 also has this 1313 * XXX problem, so we'll just enable it for all Elan SC520s 1314 * XXX for now. --thorpej@NetBSD.org 1315 */ 1316 if (1 || rev == ((PRODID_ELAN_SC520 << REVID_PRODID_SHIFT) | 1317 (0 << REVID_MAJSTEP_SHIFT) | (1))) 1318 sc->sc_echobug = 1; 1319 1320 /* 1321 * Determine cause of the last reset, and issue a warning if it 1322 * was due to watchdog expiry. 1323 */ 1324 ressta = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA); 1325 if (ressta & RESSTA_WDT_RST_DET) 1326 aprint_error_dev(sc->sc_dev, 1327 "WARNING: LAST RESET DUE TO WATCHDOG EXPIRATION!\n"); 1328 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA, ressta); 1329 1330 elansc_print_1(self, sc, MMCR_MPICMODE); 1331 elansc_print_1(self, sc, MMCR_SL1PICMODE); 1332 elansc_print_1(self, sc, MMCR_SL2PICMODE); 1333 elansc_print_1(self, sc, MMCR_PICICR); 1334 1335 sc->sc_mpicmode = bus_space_read_1(sc->sc_memt, sc->sc_memh, 1336 MMCR_MPICMODE); 1337 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_MPICMODE, 1338 sc->sc_mpicmode | __BIT(ELAN_IRQ)); 1339 1340 sc->sc_picicr = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_PICICR); 1341 picicr = sc->sc_picicr; 1342 if (elansc_pcinmi || elansc_wpvnmi) 1343 picicr |= MMCR_PICICR_NMI_ENB; 1344#if 0 1345 /* PC/AT compatibility */ 1346 picicr |= MMCR_PICICR_S1_GINT_MODE|MMCR_PICICR_M_GINT_MODE; 1347#endif 1348 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_PICICR, picicr); 1349 1350 elansc_print_1(self, sc, MMCR_PICICR); 1351 elansc_print_1(self, sc, MMCR_MPICMODE); 1352 1353 mutex_enter(&sc->sc_mtx); 1354 /* Set up the watchdog registers with some defaults. */ 1355 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30); 1356 1357 /* ...and clear it. */ 1358 elansc_wdogctl_reset(sc); 1359 mutex_exit(&sc->sc_mtx); 1360 1361 if (!pmf_device_register1(self, elansc_suspend, elansc_resume, 1362 elansc_shutdown)) 1363 aprint_error_dev(self, "could not establish power hooks\n"); 1364 1365#if NGPIO > 0 1366 /* Initialize GPIO pins array */ 1367 for (pin = 0; pin < ELANSC_PIO_NPINS; pin++) { 1368 sc->sc_gpio_pins[pin].pin_num = pin; 1369 sc->sc_gpio_pins[pin].pin_caps = GPIO_PIN_INPUT | 1370 GPIO_PIN_OUTPUT; 1371 1372 /* Read initial state */ 1373 reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16); 1374 shift = pin % 16; 1375 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg); 1376 if ((data & (1 << shift)) == 0) 1377 sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_INPUT; 1378 else 1379 sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_OUTPUT; 1380 if (elansc_gpio_pin_read(sc, pin) == 0) 1381 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW; 1382 else 1383 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH; 1384 } 1385 1386 /* Create controller tag */ 1387 sc->sc_gpio_gc.gp_cookie = sc; 1388 sc->sc_gpio_gc.gp_pin_read = elansc_gpio_pin_read; 1389 sc->sc_gpio_gc.gp_pin_write = elansc_gpio_pin_write; 1390 sc->sc_gpio_gc.gp_pin_ctl = elansc_gpio_pin_ctl; 1391 1392#endif /* NGPIO */ 1393 1394 elansc_rescan(sc->sc_dev, "elanparbus", NULL); 1395 elansc_rescan(sc->sc_dev, "elanpexbus", NULL); 1396 elansc_rescan(sc->sc_dev, "gpiobus", NULL); 1397 1398 /* 1399 * Hook up the watchdog timer. 1400 */ 1401 sc->sc_smw.smw_name = device_xname(sc->sc_dev); 1402 sc->sc_smw.smw_cookie = sc; 1403 sc->sc_smw.smw_setmode = elansc_wdog_setmode; 1404 sc->sc_smw.smw_tickle = elansc_wdog_tickle; 1405 sc->sc_smw.smw_period = 32; /* actually 32.54 */ 1406 if (sysmon_wdog_register(&sc->sc_smw) != 0) { 1407 aprint_error_dev(sc->sc_dev, 1408 "unable to register watchdog with sysmon\n"); 1409 } 1410 elansc_attached = true; 1411 elansc_rescan(sc->sc_dev, "pcibus", NULL); 1412} 1413 1414static int 1415elanpex_match(device_t parent, cfdata_t match, void *aux) 1416{ 1417 struct elansc_softc *sc = device_private(parent); 1418 1419 return sc->sc_pex == NULL; 1420} 1421 1422static int 1423elanpar_match(device_t parent, cfdata_t match, void *aux) 1424{ 1425 struct elansc_softc *sc = device_private(parent); 1426 1427 return sc->sc_par == NULL; 1428} 1429 1430/* scan for new children */ 1431static int 1432elansc_rescan(device_t self, const char *ifattr, const int *locators) 1433{ 1434 struct elansc_softc *sc = device_private(self); 1435 1436 if (ifattr_match(ifattr, "elanparbus") && sc->sc_par == NULL) { 1437 sc->sc_par = config_found(sc->sc_dev, NULL, NULL, 1438 CFARGS(.iattr = "elanparbus")); 1439 } 1440 1441 if (ifattr_match(ifattr, "elanpexbus") && sc->sc_pex == NULL) { 1442 sc->sc_pex = config_found(sc->sc_dev, NULL, NULL, 1443 CFARGS(.iattr = "elanpexbus")); 1444 } 1445 1446 if (ifattr_match(ifattr, "gpiobus") && sc->sc_gpio == NULL) { 1447#if NGPIO > 0 1448 struct gpiobus_attach_args gba; 1449 1450 memset(&gba, 0, sizeof(gba)); 1451 1452 gba.gba_gc = &sc->sc_gpio_gc; 1453 gba.gba_pins = sc->sc_gpio_pins; 1454 gba.gba_npins = ELANSC_PIO_NPINS; 1455 sc->sc_gpio = config_found(sc->sc_dev, &gba, gpiobus_print, 1456 CFARGS(.iattr = "gpiobus")); 1457#endif 1458 } 1459 1460 if (ifattr_match(ifattr, "pcibus") && sc->sc_pci == NULL) { 1461 struct pcibus_attach_args pba; 1462 1463 memset(&pba, 0, sizeof(pba)); 1464 pba.pba_iot = sc->sc_iot; 1465 pba.pba_memt = sc->sc_memt; 1466 pba.pba_dmat = sc->sc_dmat; 1467 pba.pba_dmat64 = sc->sc_dmat64; 1468 pba.pba_pc = sc->sc_pc; 1469 pba.pba_flags = sc->sc_pciflags; 1470 pba.pba_bus = 0; 1471 pba.pba_bridgetag = NULL; 1472 sc->sc_pci = config_found(self, &pba, pcibusprint, 1473 CFARGS(.iattr = "pcibus")); 1474 } 1475 1476 return 0; 1477} 1478 1479CFATTACH_DECL3_NEW(elanpar, 0, 1480 elanpar_match, elanpar_attach, elanpar_detach, NULL, NULL, NULL, 1481 DVF_DETACH_SHUTDOWN); 1482 1483CFATTACH_DECL3_NEW(elanpex, 0, 1484 elanpex_match, elanpex_attach, elanpex_detach, NULL, NULL, NULL, 1485 DVF_DETACH_SHUTDOWN); 1486 1487CFATTACH_DECL3_NEW(elansc, sizeof(struct elansc_softc), 1488 elansc_match, elansc_attach, elansc_detach, NULL, elansc_rescan, 1489 elansc_childdetached, DVF_DETACH_SHUTDOWN); 1490 1491#if NGPIO > 0 1492static int 1493elansc_gpio_pin_read(void *arg, int pin) 1494{ 1495 struct elansc_softc *sc = arg; 1496 int reg, shift; 1497 uint16_t data; 1498 1499 reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16); 1500 shift = pin % 16; 1501 1502 mutex_enter(&sc->sc_mtx); 1503 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg); 1504 mutex_exit(&sc->sc_mtx); 1505 1506 return ((data >> shift) & 0x1); 1507} 1508 1509static void 1510elansc_gpio_pin_write(void *arg, int pin, int value) 1511{ 1512 struct elansc_softc *sc = arg; 1513 int reg, shift; 1514 uint16_t data; 1515 1516 reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16); 1517 shift = pin % 16; 1518 1519 mutex_enter(&sc->sc_mtx); 1520 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg); 1521 if (value == 0) 1522 data &= ~(1 << shift); 1523 else if (value == 1) 1524 data |= (1 << shift); 1525 1526 bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data); 1527 mutex_exit(&sc->sc_mtx); 1528} 1529 1530static void 1531elansc_gpio_pin_ctl(void *arg, int pin, int flags) 1532{ 1533 struct elansc_softc *sc = arg; 1534 int reg, shift; 1535 uint16_t data; 1536 1537 reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16); 1538 shift = pin % 16; 1539 mutex_enter(&sc->sc_mtx); 1540 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg); 1541 if (flags & GPIO_PIN_INPUT) 1542 data &= ~(1 << shift); 1543 if (flags & GPIO_PIN_OUTPUT) 1544 data |= (1 << shift); 1545 1546 bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data); 1547 mutex_exit(&sc->sc_mtx); 1548} 1549#endif /* NGPIO */ 1550