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