elan520.c revision 1.22 1 /* $NetBSD: elan520.c,v 1.22 2008/01/21 08:04:51 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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Device driver for the AMD Elan SC520 System Controller. This attaches
41 * where the "pchb" driver might normally attach, and provides support for
42 * extra features on the SC520, such as the watchdog timer and GPIO.
43 *
44 * Information about the GP bus echo bug work-around is from code posted
45 * to the "soekris-tech" mailing list by Jasper Wallace.
46 */
47
48 #include <sys/cdefs.h>
49
50 __KERNEL_RCSID(0, "$NetBSD: elan520.c,v 1.22 2008/01/21 08:04:51 dyoung Exp $");
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/time.h>
55 #include <sys/device.h>
56 #include <sys/gpio.h>
57 #include <sys/mutex.h>
58 #include <sys/wdog.h>
59
60 #include <uvm/uvm_extern.h>
61
62 #include <machine/bus.h>
63
64 #include <dev/pci/pcivar.h>
65
66 #include <dev/pci/pcidevs.h>
67
68 #include "gpio.h"
69 #if NGPIO > 0
70 #include <dev/gpio/gpiovar.h>
71 #endif
72
73 #include <arch/i386/pci/elan520reg.h>
74
75 #include <dev/sysmon/sysmonvar.h>
76
77 #define ELAN_IRQ 1
78 #define IDT_PROT_SIZE PAGE_SIZE
79
80 struct elansc_softc {
81 struct device sc_dev;
82 device_t sc_par;
83 device_t sc_pex;
84
85 pci_chipset_tag_t sc_pc;
86 pcitag_t sc_tag;
87 bus_space_tag_t sc_memt;
88 bus_space_handle_t sc_memh;
89 int sc_echobug;
90
91 kmutex_t sc_mtx;
92
93 struct sysmon_wdog sc_smw;
94 void *sc_eih;
95 void *sc_pih;
96 void *sc_sh;
97 uint8_t sc_mpicmode;
98 uint8_t sc_picicr;
99 int sc_idtpar;
100 int sc_textpar;
101 #if NGPIO > 0
102 /* GPIO interface */
103 struct gpio_chipset_tag sc_gpio_gc;
104 gpio_pin_t sc_gpio_pins[ELANSC_PIO_NPINS];
105 #endif
106 };
107
108 int elansc_wpvnmi = 1;
109 int elansc_pcinmi = 1;
110 int elansc_do_protect_idt = 0;
111
112 #if NGPIO > 0
113 static int elansc_gpio_pin_read(void *, int);
114 static void elansc_gpio_pin_write(void *, int, int);
115 static void elansc_gpio_pin_ctl(void *, int, int);
116 #endif
117
118 static void elansc_print_par(device_t, int, uint32_t);
119 static void elanpex_intr_establish(device_t, struct elansc_softc *);
120 static void elanpar_intr_establish(device_t, struct elansc_softc *);
121 static void elanpex_intr_disestablish(struct elansc_softc *);
122 static void elanpar_intr_disestablish(struct elansc_softc *);
123
124 static void
125 elansc_childdetached(device_t self, device_t child)
126 {
127 struct elansc_softc *sc = device_private(self);
128
129 if (child == sc->sc_par)
130 sc->sc_par = NULL;
131 if (child == sc->sc_pex)
132 sc->sc_pex = NULL;
133 /* elansc does not presently keep a pointer to
134 * the gpio, so there is nothing to do if it is detached.
135 */
136 }
137
138 static void
139 elansc_wdogctl_write(struct elansc_softc *sc, uint16_t val)
140 {
141 uint8_t echo_mode = 0; /* XXX: gcc */
142
143 KASSERT(mutex_owned(&sc->sc_mtx));
144
145 /* Switch off GP bus echo mode if we need to. */
146 if (sc->sc_echobug) {
147 echo_mode = bus_space_read_1(sc->sc_memt, sc->sc_memh,
148 MMCR_GPECHO);
149 bus_space_write_1(sc->sc_memt, sc->sc_memh,
150 MMCR_GPECHO, echo_mode & ~GPECHO_GP_ECHO_ENB);
151 }
152
153 /* Unlock the register. */
154 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL,
155 WDTMRCTL_UNLOCK1);
156 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL,
157 WDTMRCTL_UNLOCK2);
158
159 /* Write the value. */
160 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL, val);
161
162 /* Switch GP bus echo mode back. */
163 if (sc->sc_echobug)
164 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_GPECHO,
165 echo_mode);
166 }
167
168 static void
169 elansc_wdogctl_reset(struct elansc_softc *sc)
170 {
171 uint8_t echo_mode = 0/* XXX: gcc */;
172
173 KASSERT(mutex_owned(&sc->sc_mtx));
174
175 /* Switch off GP bus echo mode if we need to. */
176 if (sc->sc_echobug) {
177 echo_mode = bus_space_read_1(sc->sc_memt, sc->sc_memh,
178 MMCR_GPECHO);
179 bus_space_write_1(sc->sc_memt, sc->sc_memh,
180 MMCR_GPECHO, echo_mode & ~GPECHO_GP_ECHO_ENB);
181 }
182
183 /* Reset the watchdog. */
184 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL,
185 WDTMRCTL_RESET1);
186 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WDTMRCTL,
187 WDTMRCTL_RESET2);
188
189 /* Switch GP bus echo mode back. */
190 if (sc->sc_echobug)
191 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_GPECHO,
192 echo_mode);
193 }
194
195 static const struct {
196 int period; /* whole seconds */
197 uint16_t exp; /* exponent select */
198 } elansc_wdog_periods[] = {
199 { 1, WDTMRCTL_EXP_SEL25 },
200 { 2, WDTMRCTL_EXP_SEL26 },
201 { 4, WDTMRCTL_EXP_SEL27 },
202 { 8, WDTMRCTL_EXP_SEL28 },
203 { 16, WDTMRCTL_EXP_SEL29 },
204 { 32, WDTMRCTL_EXP_SEL30 },
205 { 0, 0 },
206 };
207
208 static int
209 elansc_wdog_arm(struct elansc_softc *sc)
210 {
211 struct sysmon_wdog *smw = &sc->sc_smw;
212 int i;
213 uint16_t exp_sel = 0; /* XXX: gcc */
214
215 KASSERT(mutex_owned(&sc->sc_mtx));
216
217 if (smw->smw_period == WDOG_PERIOD_DEFAULT) {
218 smw->smw_period = 32;
219 exp_sel = WDTMRCTL_EXP_SEL30;
220 } else {
221 for (i = 0; elansc_wdog_periods[i].period != 0; i++) {
222 if (elansc_wdog_periods[i].period ==
223 smw->smw_period) {
224 exp_sel = elansc_wdog_periods[i].exp;
225 break;
226 }
227 }
228 if (elansc_wdog_periods[i].period == 0)
229 return EINVAL;
230 }
231 elansc_wdogctl_write(sc, WDTMRCTL_ENB |
232 WDTMRCTL_WRST_ENB | exp_sel);
233 elansc_wdogctl_reset(sc);
234 return 0;
235 }
236
237 static int
238 elansc_wdog_setmode(struct sysmon_wdog *smw)
239 {
240 struct elansc_softc *sc = smw->smw_cookie;
241 int rc = 0;
242
243 mutex_enter(&sc->sc_mtx);
244
245 if (!device_is_active(&sc->sc_dev))
246 rc = EBUSY;
247 else if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
248 elansc_wdogctl_write(sc,
249 WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);
250 } else
251 rc = elansc_wdog_arm(sc);
252
253 mutex_exit(&sc->sc_mtx);
254 return rc;
255 }
256
257 static int
258 elansc_wdog_tickle(struct sysmon_wdog *smw)
259 {
260 struct elansc_softc *sc = smw->smw_cookie;
261
262 mutex_enter(&sc->sc_mtx);
263 elansc_wdogctl_reset(sc);
264 mutex_exit(&sc->sc_mtx);
265 return 0;
266 }
267
268 static int
269 elansc_match(device_t parent, struct cfdata *match, void *aux)
270 {
271 struct pci_attach_args *pa = aux;
272
273 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD &&
274 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_SC520_SC)
275 return (10); /* beat pchb */
276
277 return (0);
278 }
279
280 static const char *elansc_speeds[] = {
281 "(reserved 00)",
282 "100MHz",
283 "133MHz",
284 "(reserved 11)",
285 };
286
287 static int
288 elanpar_intr(void *arg)
289 {
290 struct elansc_softc *sc = arg;
291 uint16_t wpvsta;
292 unsigned win;
293 uint32_t par;
294 const char *wpvstr;
295
296 wpvsta = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA);
297
298 if ((wpvsta & MMCR_WPVSTA_WPV_STA) == 0)
299 return 0;
300
301 win = __SHIFTOUT(wpvsta, MMCR_WPVSTA_WPV_WINDOW);
302
303 par = bus_space_read_4(sc->sc_memt, sc->sc_memh, MMCR_PAR(win));
304
305 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA,
306 MMCR_WPVSTA_WPV_STA);
307
308 switch (wpvsta & MMCR_WPVSTA_WPV_MSTR) {
309 case MMCR_WPVSTA_WPV_MSTR_CPU:
310 wpvstr = "cpu";
311 break;
312 case MMCR_WPVSTA_WPV_MSTR_PCI:
313 wpvstr = "pci";
314 break;
315 case MMCR_WPVSTA_WPV_MSTR_GP:
316 wpvstr = "gp";
317 break;
318 default:
319 wpvstr = "unknown";
320 break;
321 }
322 aprint_error_dev(sc->sc_par,
323 "%s violated write-protect window %u\n", wpvstr, win);
324 elansc_print_par(sc->sc_par, win, par);
325 return 0;
326 }
327
328 static int
329 elanpex_intr(void *arg)
330 {
331 static struct {
332 const char *string;
333 bool nonfatal;
334 } cmd[16] = {
335 [0] = {.string = "not latched"}
336 , [1] = {.string = "special cycle"}
337 , [2] = {.string = "i/o read"}
338 , [3] = {.string = "i/o write"}
339 , [4] = {.string = "4"}
340 , [5] = {.string = "5"}
341 , [6] = {.string = "memory rd"}
342 , [7] = {.string = "memory wr"}
343 , [8] = {.string = "8"}
344 , [9] = {.string = "9"}
345 , [10] = {.string = "cfg rd", .nonfatal = true}
346 , [11] = {.string = "cfg wr"}
347 , [12] = {.string = "memory rd mul"}
348 , [13] = {.string = "dual-address cycle"}
349 , [14] = {.string = "memory rd line"}
350 , [15] = {.string = "memory wr & inv"}
351 };
352
353 static const struct {
354 uint16_t bit;
355 const char *msg;
356 } mmsg[] = {
357 {MMCR_HBMSTIRQSTA_M_RTRTO_IRQ_STA, "retry timeout"}
358 , {MMCR_HBMSTIRQSTA_M_TABRT_IRQ_STA, "target abort"}
359 , {MMCR_HBMSTIRQSTA_M_MABRT_IRQ_STA, "abort"}
360 , {MMCR_HBMSTIRQSTA_M_SERR_IRQ_STA, "system error"}
361 , {MMCR_HBMSTIRQSTA_M_RPER_IRQ_STA, "received parity error"}
362 , {MMCR_HBMSTIRQSTA_M_DPER_IRQ_STA, "detected parity error"}
363 }, tmsg[] = {
364 {MMCR_HBTGTIRQSTA_T_DLYTO_IRQ_STA, "delayed txn timeout"}
365 , {MMCR_HBTGTIRQSTA_T_APER_IRQ_STA, "address parity"}
366 , {MMCR_HBTGTIRQSTA_T_DPER_IRQ_STA, "data parity"}
367 };
368 uint8_t pciarbsta;
369 uint16_t mstcmd, mstirq, tgtid, tgtirq;
370 uint32_t mstaddr;
371 uint16_t mstack = 0, tgtack = 0;
372 int fatal = 0, i, handled = 0;
373 struct elansc_softc *sc = arg;
374
375 pciarbsta = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_PCIARBSTA);
376 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQSTA);
377 mstaddr = bus_space_read_4(sc->sc_memt, sc->sc_memh, MMCR_MSTINTADD);
378 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQSTA);
379
380 if ((pciarbsta & MMCR_PCIARBSTA_GNT_TO_STA) != 0) {
381 aprint_error_dev(sc->sc_pex,
382 "grant time-out, GNT%" __PRIuBITS "# asserted\n",
383 __SHIFTOUT(pciarbsta, MMCR_PCIARBSTA_GNT_TO_ID));
384 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_PCIARBSTA,
385 MMCR_PCIARBSTA_GNT_TO_STA);
386 handled = true;
387 }
388
389 mstcmd = __SHIFTOUT(mstirq, MMCR_HBMSTIRQSTA_M_CMD_IRQ_ID);
390
391 for (i = 0; i < __arraycount(mmsg); i++) {
392 if ((mstirq & mmsg[i].bit) == 0)
393 continue;
394 aprint_error_dev(sc->sc_pex,
395 "%s %08" PRIx32 " master %s\n",
396 cmd[mstcmd].string, mstaddr, mmsg[i].msg);
397
398 mstack |= mmsg[i].bit;
399 if (!cmd[mstcmd].nonfatal)
400 fatal = true;
401 }
402
403 tgtid = __SHIFTOUT(tgtirq, MMCR_HBTGTIRQSTA_T_IRQ_ID);
404
405 for (i = 0; i < __arraycount(tmsg); i++) {
406 if ((tgtirq & tmsg[i].bit) == 0)
407 continue;
408 aprint_error_dev(sc->sc_pex, "%1x target %s\n", tgtid,
409 tmsg[i].msg);
410 tgtack |= tmsg[i].bit;
411 }
412
413 /* acknowledge interrupts */
414 if (tgtack != 0) {
415 handled = true;
416 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQSTA,
417 tgtack);
418 }
419 if (mstack != 0) {
420 handled = true;
421 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQSTA,
422 mstack);
423 }
424 return fatal ? 0 : (handled ? 1 : 0);
425 }
426
427 #define elansc_print_1(__dev, __sc, __reg) \
428 do { \
429 aprint_debug_dev(__dev, \
430 "%s: %s %02" PRIx8 "\n", __func__, #__reg, \
431 bus_space_read_1((__sc)->sc_memt, (__sc)->sc_memh, __reg)); \
432 } while (/*CONSTCOND*/0)
433
434 static void
435 elansc_print_par(device_t dev, int i, uint32_t par)
436 {
437 uint32_t addr, sz, unit;
438 const char *tgtstr;
439
440 switch (par & MMCR_PAR_TARGET) {
441 default:
442 case MMCR_PAR_TARGET_OFF:
443 tgtstr = "off";
444 break;
445 case MMCR_PAR_TARGET_GPIO:
446 tgtstr = "gpio";
447 break;
448 case MMCR_PAR_TARGET_GPMEM:
449 tgtstr = "gpmem";
450 break;
451 case MMCR_PAR_TARGET_PCI:
452 tgtstr = "pci";
453 break;
454 case MMCR_PAR_TARGET_BOOTCS:
455 tgtstr = "bootcs";
456 break;
457 case MMCR_PAR_TARGET_ROMCS1:
458 tgtstr = "romcs1";
459 break;
460 case MMCR_PAR_TARGET_ROMCS2:
461 tgtstr = "romcs2";
462 break;
463 case MMCR_PAR_TARGET_SDRAM:
464 tgtstr = "sdram";
465 break;
466 }
467 if ((par & MMCR_PAR_TARGET) == MMCR_PAR_TARGET_GPIO) {
468 unit = 1;
469 sz = __SHIFTOUT(par, MMCR_PAR_IO_SZ);
470 addr = __SHIFTOUT(par, MMCR_PAR_IO_ST_ADR);
471 } else if ((par & MMCR_PAR_PG_SZ) != 0) {
472 unit = 64 * 1024;
473 sz = __SHIFTOUT(par, MMCR_PAR_64KB_SZ);
474 addr = __SHIFTOUT(par, MMCR_PAR_64KB_ST_ADR);
475 } else {
476 unit = 4 * 1024;
477 sz = __SHIFTOUT(par, MMCR_PAR_4KB_SZ);
478 addr = __SHIFTOUT(par, MMCR_PAR_4KB_ST_ADR);
479 }
480
481 aprint_debug_dev(dev,
482 "PAR[%d] %08" PRIx32 " tgt %s attr %1" __PRIxBITS
483 " start %08" PRIx32 " size %" PRIu32 "\n",
484 i, par, tgtstr, __SHIFTOUT(par, MMCR_PAR_ATTR),
485 addr * unit, (sz + 1) * unit);
486 }
487
488 static void
489 elansc_print_all_par(device_t dev,
490 bus_space_tag_t memt, bus_space_handle_t memh)
491 {
492 int i;
493 uint32_t par;
494
495 for (i = 0; i < 16; i++) {
496 par = bus_space_read_4(memt, memh, MMCR_PAR(i));
497 elansc_print_par(dev, i, par);
498 }
499 }
500
501 static int
502 elansc_alloc_par(bus_space_tag_t memt, bus_space_handle_t memh)
503 {
504 int i;
505 uint32_t par;
506
507 for (i = 0; i < 16; i++) {
508
509 par = bus_space_read_4(memt, memh, MMCR_PAR(i));
510
511 if ((par & MMCR_PAR_TARGET) == MMCR_PAR_TARGET_OFF)
512 break;
513 }
514 if (i == 16)
515 return -1;
516 return i;
517 }
518
519 static void
520 elansc_disable_par(bus_space_tag_t memt, bus_space_handle_t memh, int idx)
521 {
522 uint32_t par;
523 par = bus_space_read_4(memt, memh, MMCR_PAR(idx));
524 par &= ~MMCR_PAR_TARGET;
525 par |= MMCR_PAR_TARGET_OFF;
526 bus_space_write_4(memt, memh, MMCR_PAR(idx), par);
527 }
528
529 static int
530 elansc_protect_text(device_t self, struct elansc_softc *sc)
531 {
532 int i;
533 uint32_t par;
534 uint32_t protsize, unprotsize;
535 const uint32_t sfkb = 64 * 1024;
536 paddr_t start_pa, end_pa;
537 extern char kernel_text, etext;
538 bus_space_tag_t memt;
539 bus_space_handle_t memh;
540
541 memt = sc->sc_memt;
542 memh = sc->sc_memh;
543
544 if (!pmap_extract(pmap_kernel(), (vaddr_t)&kernel_text, &start_pa) ||
545 !pmap_extract(pmap_kernel(), (vaddr_t)&etext, &end_pa))
546 return -1;
547
548 if (&etext - &kernel_text != end_pa - start_pa) {
549 aprint_error_dev(self, "kernel text may not be contiguous\n");
550 return -1;
551 }
552
553 if ((i = elansc_alloc_par(memt, memh)) == -1) {
554 aprint_error_dev(self, "cannot allocate PAR\n");
555 return -1;
556 }
557
558 par = bus_space_read_4(memt, memh, MMCR_PAR(i));
559
560 aprint_debug_dev(self,
561 "protect kernel text at physical addresses %p - %p\n",
562 (void *)start_pa, (void *)end_pa);
563
564 unprotsize = sfkb - start_pa % sfkb;
565 start_pa += unprotsize;
566 unprotsize += end_pa % sfkb;
567 end_pa -= end_pa % sfkb;
568
569 aprint_debug_dev(self,
570 "actually protect kernel text at physical addresses %p - %p\n",
571 (void *)start_pa, (void *)end_pa);
572
573 aprint_verbose_dev(self,
574 "%" PRIu32 " bytes of kernel text are unprotected\n", unprotsize);
575
576 protsize = end_pa - start_pa;
577
578 /* clear PG_SZ, attribute, target, size, address. */
579 par = MMCR_PAR_TARGET_SDRAM | MMCR_PAR_ATTR_NOWRITE | MMCR_PAR_PG_SZ;
580 par |= __SHIFTIN(protsize / sfkb - 1, MMCR_PAR_64KB_SZ);
581 par |= __SHIFTIN(start_pa / sfkb, MMCR_PAR_64KB_ST_ADR);
582 bus_space_write_4(memt, memh, MMCR_PAR(i), par);
583 return i;
584 }
585
586 static int
587 elansc_protect_idt(struct elansc_softc *sc)
588 {
589 int i;
590 uint32_t par;
591 extern paddr_t idt_paddr;
592 bus_space_tag_t memt;
593 bus_space_handle_t memh;
594
595 memt = sc->sc_memt;
596 memh = sc->sc_memh;
597
598 if (elansc_do_protect_idt == 0)
599 return -1;
600
601 if ((i = elansc_alloc_par(memt, memh)) == -1)
602 return -1;
603
604 par = bus_space_read_4(memt, memh, MMCR_PAR(i));
605
606 aprint_debug_dev(sc->sc_par, "protect IDT at paddr %p\n",
607 (const void *)idt_paddr);
608
609 /* clear PG_SZ, attribute, target, size, address. */
610 par = MMCR_PAR_TARGET_SDRAM | MMCR_PAR_ATTR_NOWRITE;
611 par |= __SHIFTIN(IDT_PROT_SIZE / PAGE_SIZE - 1, MMCR_PAR_4KB_SZ);
612 par |= __SHIFTIN(idt_paddr / PAGE_SIZE, MMCR_PAR_4KB_ST_ADR);
613 bus_space_write_4(memt, memh, MMCR_PAR(i), par);
614 return i;
615 }
616
617 static void
618 elanpex_intr_ack(bus_space_tag_t memt, bus_space_handle_t memh)
619 {
620 bus_space_write_1(memt, memh, MMCR_PCIARBSTA,
621 MMCR_PCIARBSTA_GNT_TO_STA);
622 bus_space_write_2(memt, memh, MMCR_HBTGTIRQSTA, MMCR_TGTIRQ_ACT);
623 bus_space_write_2(memt, memh, MMCR_HBMSTIRQSTA, MMCR_MSTIRQ_ACT);
624 }
625
626 static bool
627 elansc_suspend(device_t dev)
628 {
629 bool rc;
630 struct elansc_softc *sc = device_private(dev);
631
632 mutex_enter(&sc->sc_mtx);
633 rc = ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED);
634 mutex_exit(&sc->sc_mtx);
635 if (!rc)
636 aprint_debug_dev(dev, "watchdog enabled, suspend forbidden");
637 return rc;
638 }
639
640 static bool
641 elansc_resume(device_t dev)
642 {
643 struct elansc_softc *sc = device_private(dev);
644
645 mutex_enter(&sc->sc_mtx);
646 /* Set up the watchdog registers with some defaults. */
647 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);
648
649 /* ...and clear it. */
650 elansc_wdogctl_reset(sc);
651 mutex_exit(&sc->sc_mtx);
652
653 return true;
654 }
655
656 static int
657 elansc_detach(device_t self, int flags)
658 {
659 int rc;
660 struct elansc_softc *sc = device_private(self);
661
662 if ((rc = config_detach_children(self, flags)) != 0)
663 return rc;
664
665 pmf_device_deregister(self);
666
667 if ((rc = sysmon_wdog_unregister(&sc->sc_smw)) != 0) {
668 if (rc == ERESTART)
669 rc = EINTR;
670 return rc;
671 }
672
673 mutex_enter(&sc->sc_mtx);
674
675 /* Set up the watchdog registers with some defaults. */
676 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);
677
678 /* ...and clear it. */
679 elansc_wdogctl_reset(sc);
680
681 bus_space_unmap(sc->sc_memt, sc->sc_memh, PAGE_SIZE);
682
683 mutex_exit(&sc->sc_mtx);
684 mutex_destroy(&sc->sc_mtx);
685 return 0;
686 }
687
688 static void *
689 elansc_intr_establish(device_t dev, int (*handler)(void *), void *arg)
690 {
691 struct pic *pic;
692 void *ih;
693
694 if ((pic = intr_findpic(ELAN_IRQ)) == NULL) {
695 aprint_error_dev(dev, "PIC for irq %d not found\n",
696 ELAN_IRQ);
697 return NULL;
698 } else if ((ih = intr_establish(ELAN_IRQ, pic, ELAN_IRQ,
699 IST_LEVEL, IPL_HIGH, handler, arg)) == NULL) {
700 aprint_error_dev(dev,
701 "could not establish interrupt\n");
702 return NULL;
703 }
704 aprint_verbose_dev(dev, "interrupting at irq %d\n", ELAN_IRQ);
705 return ih;
706 }
707
708 static bool
709 elanpex_resume(device_t self)
710 {
711 struct elansc_softc *sc = device_private(device_parent(self));
712
713 elanpex_intr_establish(self, sc);
714 return sc->sc_eih != NULL;
715 }
716
717 static bool
718 elanpex_suspend(device_t self)
719 {
720 struct elansc_softc *sc = device_private(device_parent(self));
721
722 elanpex_intr_disestablish(sc);
723
724 return true;
725 }
726
727 static bool
728 elanpar_resume(device_t self)
729 {
730 struct elansc_softc *sc = device_private(device_parent(self));
731
732 elanpar_intr_establish(self, sc);
733 return sc->sc_pih != NULL;
734 }
735
736 static bool
737 elanpar_suspend(device_t self)
738 {
739 struct elansc_softc *sc = device_private(device_parent(self));
740
741 elanpar_intr_disestablish(sc->sc_pih);
742
743 return true;
744 }
745
746 static void
747 elanpex_intr_establish(device_t self, struct elansc_softc *sc)
748 {
749 uint8_t sysarbctl;
750 uint16_t pcihostmap, mstirq, tgtirq;
751
752 pcihostmap = bus_space_read_2(sc->sc_memt, sc->sc_memh,
753 MMCR_PCIHOSTMAP);
754 /* Priority P2 (Master PIC IR1) */
755 pcihostmap &= ~MMCR_PCIHOSTMAP_PCI_IRQ_MAP;
756 pcihostmap |= __SHIFTIN(__BIT(ELAN_IRQ), MMCR_PCIHOSTMAP_PCI_IRQ_MAP);
757 if (elansc_pcinmi)
758 pcihostmap |= MMCR_PCIHOSTMAP_PCI_NMI_ENB;
759 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP,
760 pcihostmap);
761
762 elanpex_intr_ack(sc->sc_memt, sc->sc_memh);
763
764 sysarbctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL);
765 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL);
766 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL);
767
768 sysarbctl |= MMCR_SYSARBCTL_GNT_TO_INT_ENB;
769
770 mstirq |= MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_ENB;
771 mstirq |= MMCR_HBMSTIRQCTL_M_TABRT_IRQ_ENB;
772 mstirq |= MMCR_HBMSTIRQCTL_M_MABRT_IRQ_ENB;
773 mstirq |= MMCR_HBMSTIRQCTL_M_SERR_IRQ_ENB;
774 mstirq |= MMCR_HBMSTIRQCTL_M_RPER_IRQ_ENB;
775 mstirq |= MMCR_HBMSTIRQCTL_M_DPER_IRQ_ENB;
776
777 tgtirq |= MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_ENB;
778 tgtirq |= MMCR_HBTGTIRQCTL_T_APER_IRQ_ENB;
779 tgtirq |= MMCR_HBTGTIRQCTL_T_DPER_IRQ_ENB;
780
781 if (elansc_pcinmi) {
782 sc->sc_eih = nmi_establish(elanpex_intr, sc);
783
784 mstirq |= MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_SEL;
785 mstirq |= MMCR_HBMSTIRQCTL_M_TABRT_IRQ_SEL;
786 mstirq |= MMCR_HBMSTIRQCTL_M_MABRT_IRQ_SEL;
787 mstirq |= MMCR_HBMSTIRQCTL_M_SERR_IRQ_SEL;
788 mstirq |= MMCR_HBMSTIRQCTL_M_RPER_IRQ_SEL;
789 mstirq |= MMCR_HBMSTIRQCTL_M_DPER_IRQ_SEL;
790
791 tgtirq |= MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_SEL;
792 tgtirq |= MMCR_HBTGTIRQCTL_T_APER_IRQ_SEL;
793 tgtirq |= MMCR_HBTGTIRQCTL_T_DPER_IRQ_SEL;
794 } else
795 sc->sc_eih = elansc_intr_establish(self, elanpex_intr, sc);
796
797 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL, sysarbctl);
798 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL, mstirq);
799 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL, tgtirq);
800 }
801
802 static void
803 elanpex_attach(device_t parent, device_t self, void *aux)
804 {
805 struct elansc_softc *sc = device_private(parent);
806
807 aprint_naive(": PCI Exceptions\n");
808 aprint_normal(": AMD Elan SC520 PCI Exceptions\n");
809
810 elanpex_intr_establish(self, sc);
811
812 aprint_debug_dev(self, "HBMSTIRQCTL %04x\n",
813 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL));
814
815 aprint_debug_dev(self, "HBTGTIRQCTL %04x\n",
816 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL));
817
818 aprint_debug_dev(self, "PCIHOSTMAP %04x\n",
819 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP));
820
821 pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG,
822 pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG) |
823 PCI_COMMAND_PARITY_ENABLE|PCI_COMMAND_SERR_ENABLE);
824
825 if (!pmf_device_register(self, elanpex_suspend, elanpex_resume))
826 aprint_error_dev(self, "could not establish power hooks\n");
827 }
828
829 static void
830 elanpex_intr_disestablish(struct elansc_softc *sc)
831 {
832 uint8_t sysarbctl;
833 uint16_t pcihostmap, mstirq, tgtirq;
834
835 sysarbctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL);
836 sysarbctl &= ~MMCR_SYSARBCTL_GNT_TO_INT_ENB;
837 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL, sysarbctl);
838
839 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL);
840 mstirq &= ~MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_ENB;
841 mstirq &= ~MMCR_HBMSTIRQCTL_M_TABRT_IRQ_ENB;
842 mstirq &= ~MMCR_HBMSTIRQCTL_M_MABRT_IRQ_ENB;
843 mstirq &= ~MMCR_HBMSTIRQCTL_M_SERR_IRQ_ENB;
844 mstirq &= ~MMCR_HBMSTIRQCTL_M_RPER_IRQ_ENB;
845 mstirq &= ~MMCR_HBMSTIRQCTL_M_DPER_IRQ_ENB;
846 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL, mstirq);
847
848 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL);
849 tgtirq &= ~MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_ENB;
850 tgtirq &= ~MMCR_HBTGTIRQCTL_T_APER_IRQ_ENB;
851 tgtirq &= ~MMCR_HBTGTIRQCTL_T_DPER_IRQ_ENB;
852 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL, tgtirq);
853
854 pcihostmap = bus_space_read_2(sc->sc_memt, sc->sc_memh,
855 MMCR_PCIHOSTMAP);
856 /* Priority P2 (Master PIC IR1) */
857 pcihostmap &= ~MMCR_PCIHOSTMAP_PCI_IRQ_MAP;
858 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP,
859 pcihostmap);
860
861 if (elansc_pcinmi)
862 nmi_disestablish(sc->sc_eih);
863 else
864 intr_disestablish(sc->sc_eih);
865 sc->sc_eih = NULL;
866
867 }
868
869 static int
870 elanpex_detach(device_t self, int flags)
871 {
872 struct elansc_softc *sc = device_private(device_parent(self));
873
874 pmf_device_deregister(self);
875 elanpex_intr_disestablish(sc);
876
877 return 0;
878 }
879
880 static void
881 elanpar_intr_establish(device_t self, struct elansc_softc *sc)
882 {
883 uint8_t adddecctl, wpvmap;
884
885 wpvmap = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP);
886 wpvmap &= ~MMCR_WPVMAP_INT_MAP;
887 if (elansc_wpvnmi)
888 wpvmap |= MMCR_WPVMAP_INT_NMI;
889 else
890 wpvmap |= __SHIFTIN(__BIT(ELAN_IRQ), MMCR_WPVMAP_INT_MAP);
891 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP, wpvmap);
892
893 /* clear interrupt status */
894 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA,
895 MMCR_WPVSTA_WPV_STA);
896
897 /* establish interrupt */
898 if (elansc_wpvnmi)
899 sc->sc_pih = nmi_establish(elanpar_intr, sc);
900 else
901 sc->sc_pih = elansc_intr_establish(self, elanpar_intr, sc);
902
903 adddecctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL);
904 adddecctl |= MMCR_ADDDECCTL_WPV_INT_ENB;
905 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL, adddecctl);
906 }
907
908 static void
909 elanpar_attach(device_t parent, device_t self, void *aux)
910 {
911 struct elansc_softc *sc = device_private(parent);
912
913 aprint_naive(": Programmable Address Regions\n");
914 aprint_normal(": AMD Elan SC520 Programmable Address Regions\n");
915
916 elansc_print_1(self, sc, MMCR_WPVMAP);
917 elansc_print_all_par(self, sc->sc_memt, sc->sc_memh);
918
919 sc->sc_idtpar = elansc_protect_idt(sc);
920 sc->sc_textpar = elansc_protect_text(self, sc);
921
922 elanpar_intr_establish(self, sc);
923
924 elansc_print_1(self, sc, MMCR_ADDDECCTL);
925
926 if (!pmf_device_register(self, elanpar_suspend, elanpar_resume))
927 aprint_error_dev(self, "could not establish power hooks\n");
928 }
929
930 static void
931 elanpar_intr_disestablish(struct elansc_softc *sc)
932 {
933 uint8_t adddecctl, wpvmap;
934
935 /* disable interrupt, acknowledge it, disestablish our
936 * handler, unmap it
937 */
938 adddecctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL);
939 adddecctl &= ~MMCR_ADDDECCTL_WPV_INT_ENB;
940 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL, adddecctl);
941
942 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA,
943 MMCR_WPVSTA_WPV_STA);
944
945 if (elansc_wpvnmi)
946 nmi_disestablish(sc->sc_pih);
947 else
948 intr_disestablish(sc->sc_pih);
949 sc->sc_pih = NULL;
950
951 wpvmap = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP);
952 wpvmap &= ~MMCR_WPVMAP_INT_MAP;
953 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP, wpvmap);
954 }
955
956 static int
957 elanpar_detach(device_t self, int flags)
958 {
959 struct elansc_softc *sc = device_private(device_parent(self));
960
961 pmf_device_deregister(self);
962
963 if (sc->sc_textpar != -1) {
964 elansc_disable_par(sc->sc_memt, sc->sc_memh, sc->sc_textpar);
965 sc->sc_textpar = -1;
966 }
967 if (sc->sc_idtpar != -1) {
968 elansc_disable_par(sc->sc_memt, sc->sc_memh, sc->sc_idtpar);
969 sc->sc_idtpar = -1;
970 }
971
972 elanpar_intr_disestablish(sc);
973
974 return 0;
975 }
976
977 static void
978 elansc_attach(device_t parent, device_t self, void *aux)
979 {
980 struct elansc_softc *sc = device_private(self);
981 struct pci_attach_args *pa = aux;
982 uint16_t rev;
983 uint8_t cpuctl, picicr, ressta;
984 #if 0
985 struct pci_conf_state pcf;
986 #endif
987 #if NGPIO > 0
988 struct gpiobus_attach_args gba;
989 int pin, reg, shift;
990 uint16_t data;
991 #endif
992 sc->sc_pc = pa->pa_pc;
993 sc->sc_tag = pa->pa_tag;
994
995 aprint_naive(": System Controller\n");
996 aprint_normal(": AMD Elan SC520 System Controller\n");
997
998 sc->sc_memt = pa->pa_memt;
999 if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, PAGE_SIZE, 0,
1000 &sc->sc_memh) != 0) {
1001 aprint_error_dev(&sc->sc_dev, "unable to map registers\n");
1002 return;
1003 }
1004
1005 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_HIGH);
1006
1007 rev = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_REVID);
1008 cpuctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_CPUCTL);
1009
1010 aprint_normal_dev(&sc->sc_dev,
1011 "product %d stepping %d.%d, CPU clock %s\n",
1012 (rev & REVID_PRODID) >> REVID_PRODID_SHIFT,
1013 (rev & REVID_MAJSTEP) >> REVID_MAJSTEP_SHIFT,
1014 (rev & REVID_MINSTEP),
1015 elansc_speeds[cpuctl & CPUCTL_CPU_CLK_SPD_MASK]);
1016
1017 /*
1018 * SC520 rev A1 has a bug that affects the watchdog timer. If
1019 * the GP bus echo mode is enabled, writing to the watchdog control
1020 * register is blocked.
1021 *
1022 * The BIOS in some systems (e.g. the Soekris net4501) enables
1023 * GP bus echo for various reasons, so we need to switch it off
1024 * when we talk to the watchdog timer.
1025 *
1026 * XXX The step 1.1 (B1?) in my Soekris net4501 also has this
1027 * XXX problem, so we'll just enable it for all Elan SC520s
1028 * XXX for now. --thorpej (at) NetBSD.org
1029 */
1030 if (1 || rev == ((PRODID_ELAN_SC520 << REVID_PRODID_SHIFT) |
1031 (0 << REVID_MAJSTEP_SHIFT) | (1)))
1032 sc->sc_echobug = 1;
1033
1034 /*
1035 * Determine cause of the last reset, and issue a warning if it
1036 * was due to watchdog expiry.
1037 */
1038 ressta = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA);
1039 if (ressta & RESSTA_WDT_RST_DET)
1040 aprint_error_dev(&sc->sc_dev,
1041 "WARNING: LAST RESET DUE TO WATCHDOG EXPIRATION!\n");
1042 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA, ressta);
1043
1044 elansc_print_1(self, sc, MMCR_MPICMODE);
1045 elansc_print_1(self, sc, MMCR_SL1PICMODE);
1046 elansc_print_1(self, sc, MMCR_SL2PICMODE);
1047 elansc_print_1(self, sc, MMCR_PICICR);
1048
1049 sc->sc_mpicmode = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1050 MMCR_MPICMODE);
1051 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_MPICMODE,
1052 sc->sc_mpicmode | __BIT(ELAN_IRQ));
1053
1054 sc->sc_picicr = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_PICICR);
1055 picicr = sc->sc_picicr;
1056 if (elansc_pcinmi || elansc_wpvnmi)
1057 picicr |= MMCR_PICICR_NMI_ENB;
1058 #if 0
1059 /* PC/AT compatibility */
1060 picicr |= MMCR_PICICR_S1_GINT_MODE|MMCR_PICICR_M_GINT_MODE;
1061 #endif
1062 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_PICICR, picicr);
1063
1064 elansc_print_1(self, sc, MMCR_PICICR);
1065 elansc_print_1(self, sc, MMCR_MPICMODE);
1066
1067 mutex_enter(&sc->sc_mtx);
1068 /* Set up the watchdog registers with some defaults. */
1069 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);
1070
1071 /* ...and clear it. */
1072 elansc_wdogctl_reset(sc);
1073 mutex_exit(&sc->sc_mtx);
1074
1075 if (!pmf_device_register(self, elansc_suspend, elansc_resume))
1076 aprint_error_dev(self, "could not establish power hooks\n");
1077
1078 #if NGPIO > 0
1079 /* Initialize GPIO pins array */
1080 for (pin = 0; pin < ELANSC_PIO_NPINS; pin++) {
1081 sc->sc_gpio_pins[pin].pin_num = pin;
1082 sc->sc_gpio_pins[pin].pin_caps = GPIO_PIN_INPUT |
1083 GPIO_PIN_OUTPUT;
1084
1085 /* Read initial state */
1086 reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16);
1087 shift = pin % 16;
1088 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1089 if ((data & (1 << shift)) == 0)
1090 sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_INPUT;
1091 else
1092 sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_OUTPUT;
1093 if (elansc_gpio_pin_read(sc, pin) == 0)
1094 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW;
1095 else
1096 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH;
1097 }
1098
1099 /* Create controller tag */
1100 sc->sc_gpio_gc.gp_cookie = sc;
1101 sc->sc_gpio_gc.gp_pin_read = elansc_gpio_pin_read;
1102 sc->sc_gpio_gc.gp_pin_write = elansc_gpio_pin_write;
1103 sc->sc_gpio_gc.gp_pin_ctl = elansc_gpio_pin_ctl;
1104
1105 gba.gba_gc = &sc->sc_gpio_gc;
1106 gba.gba_pins = sc->sc_gpio_pins;
1107 gba.gba_npins = ELANSC_PIO_NPINS;
1108
1109 sc->sc_par = config_found_ia(&sc->sc_dev, "elanparbus", NULL, NULL);
1110 sc->sc_pex = config_found_ia(&sc->sc_dev, "elanpexbus", NULL, NULL);
1111 /* Attach GPIO framework */
1112 config_found_ia(&sc->sc_dev, "gpiobus", &gba, gpiobus_print);
1113 #endif /* NGPIO */
1114
1115 /*
1116 * Hook up the watchdog timer.
1117 */
1118 sc->sc_smw.smw_name = device_xname(&sc->sc_dev);
1119 sc->sc_smw.smw_cookie = sc;
1120 sc->sc_smw.smw_setmode = elansc_wdog_setmode;
1121 sc->sc_smw.smw_tickle = elansc_wdog_tickle;
1122 sc->sc_smw.smw_period = 32; /* actually 32.54 */
1123 if (sysmon_wdog_register(&sc->sc_smw) != 0) {
1124 aprint_error_dev(&sc->sc_dev,
1125 "unable to register watchdog with sysmon\n");
1126 }
1127 }
1128
1129 static int
1130 elanpex_match(device_t parent, struct cfdata *match, void *aux)
1131 {
1132 struct elansc_softc *sc = device_private(parent);
1133
1134 return sc->sc_pex == NULL;
1135 }
1136
1137 static int
1138 elanpar_match(device_t parent, struct cfdata *match, void *aux)
1139 {
1140 struct elansc_softc *sc = device_private(parent);
1141
1142 return sc->sc_par == NULL;
1143 }
1144
1145 CFATTACH_DECL_NEW(elanpar, sizeof(struct device),
1146 elanpar_match, elanpar_attach, elanpar_detach, NULL);
1147
1148 CFATTACH_DECL_NEW(elanpex, sizeof(struct device),
1149 elanpex_match, elanpex_attach, elanpex_detach, NULL);
1150
1151 CFATTACH_DECL2(elansc, sizeof(struct elansc_softc),
1152 elansc_match, elansc_attach, elansc_detach, NULL, NULL,
1153 elansc_childdetached);
1154
1155 #if NGPIO > 0
1156 static int
1157 elansc_gpio_pin_read(void *arg, int pin)
1158 {
1159 struct elansc_softc *sc = arg;
1160 int reg, shift;
1161 uint16_t data;
1162
1163 reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16);
1164 shift = pin % 16;
1165
1166 mutex_enter(&sc->sc_mtx);
1167 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1168 mutex_exit(&sc->sc_mtx);
1169
1170 return ((data >> shift) & 0x1);
1171 }
1172
1173 static void
1174 elansc_gpio_pin_write(void *arg, int pin, int value)
1175 {
1176 struct elansc_softc *sc = arg;
1177 int reg, shift;
1178 uint16_t data;
1179
1180 reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16);
1181 shift = pin % 16;
1182
1183 mutex_enter(&sc->sc_mtx);
1184 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1185 if (value == 0)
1186 data &= ~(1 << shift);
1187 else if (value == 1)
1188 data |= (1 << shift);
1189
1190 bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data);
1191 mutex_exit(&sc->sc_mtx);
1192 }
1193
1194 static void
1195 elansc_gpio_pin_ctl(void *arg, int pin, int flags)
1196 {
1197 struct elansc_softc *sc = arg;
1198 int reg, shift;
1199 uint16_t data;
1200
1201 reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16);
1202 shift = pin % 16;
1203 mutex_enter(&sc->sc_mtx);
1204 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1205 if (flags & GPIO_PIN_INPUT)
1206 data &= ~(1 << shift);
1207 if (flags & GPIO_PIN_OUTPUT)
1208 data |= (1 << shift);
1209
1210 bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data);
1211 mutex_exit(&sc->sc_mtx);
1212 }
1213 #endif /* NGPIO */
1214