elan520.c revision 1.24 1 /* $NetBSD: elan520.c,v 1.24 2008/02/29 06:25:08 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.24 2008/02/29 06:25:08 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 PG0_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_pg0par;
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_pg0 = 1;
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_pg0(device_t self, struct elansc_softc *sc)
588 {
589 int i;
590 uint32_t par;
591 const paddr_t pg0_paddr = 0;
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_pg0 == 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(self, "protect page 0\n");
607
608 /* clear PG_SZ, attribute, target, size, address. */
609 par = MMCR_PAR_TARGET_SDRAM | MMCR_PAR_ATTR_NOWRITE;
610 par |= __SHIFTIN(PG0_PROT_SIZE / PAGE_SIZE - 1, MMCR_PAR_4KB_SZ);
611 par |= __SHIFTIN(pg0_paddr / PAGE_SIZE, MMCR_PAR_4KB_ST_ADR);
612 bus_space_write_4(memt, memh, MMCR_PAR(i), par);
613 return i;
614 }
615
616 static void
617 elanpex_intr_ack(bus_space_tag_t memt, bus_space_handle_t memh)
618 {
619 bus_space_write_1(memt, memh, MMCR_PCIARBSTA,
620 MMCR_PCIARBSTA_GNT_TO_STA);
621 bus_space_write_2(memt, memh, MMCR_HBTGTIRQSTA, MMCR_TGTIRQ_ACT);
622 bus_space_write_2(memt, memh, MMCR_HBMSTIRQSTA, MMCR_MSTIRQ_ACT);
623 }
624
625 static bool
626 elansc_suspend(device_t dev PMF_FN_ARGS)
627 {
628 bool rc;
629 struct elansc_softc *sc = device_private(dev);
630
631 mutex_enter(&sc->sc_mtx);
632 rc = ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED);
633 mutex_exit(&sc->sc_mtx);
634 if (!rc)
635 aprint_debug_dev(dev, "watchdog enabled, suspend forbidden");
636 return rc;
637 }
638
639 static bool
640 elansc_resume(device_t dev PMF_FN_ARGS)
641 {
642 struct elansc_softc *sc = device_private(dev);
643
644 mutex_enter(&sc->sc_mtx);
645 /* Set up the watchdog registers with some defaults. */
646 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);
647
648 /* ...and clear it. */
649 elansc_wdogctl_reset(sc);
650 mutex_exit(&sc->sc_mtx);
651
652 return true;
653 }
654
655 static int
656 elansc_detach(device_t self, int flags)
657 {
658 int rc;
659 struct elansc_softc *sc = device_private(self);
660
661 if ((rc = config_detach_children(self, flags)) != 0)
662 return rc;
663
664 pmf_device_deregister(self);
665
666 if ((rc = sysmon_wdog_unregister(&sc->sc_smw)) != 0) {
667 if (rc == ERESTART)
668 rc = EINTR;
669 return rc;
670 }
671
672 mutex_enter(&sc->sc_mtx);
673
674 /* Set up the watchdog registers with some defaults. */
675 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);
676
677 /* ...and clear it. */
678 elansc_wdogctl_reset(sc);
679
680 bus_space_unmap(sc->sc_memt, sc->sc_memh, PAGE_SIZE);
681
682 mutex_exit(&sc->sc_mtx);
683 mutex_destroy(&sc->sc_mtx);
684 return 0;
685 }
686
687 static void *
688 elansc_intr_establish(device_t dev, int (*handler)(void *), void *arg)
689 {
690 struct pic *pic;
691 void *ih;
692
693 if ((pic = intr_findpic(ELAN_IRQ)) == NULL) {
694 aprint_error_dev(dev, "PIC for irq %d not found\n",
695 ELAN_IRQ);
696 return NULL;
697 } else if ((ih = intr_establish(ELAN_IRQ, pic, ELAN_IRQ,
698 IST_LEVEL, IPL_HIGH, handler, arg)) == NULL) {
699 aprint_error_dev(dev,
700 "could not establish interrupt\n");
701 return NULL;
702 }
703 aprint_verbose_dev(dev, "interrupting at irq %d\n", ELAN_IRQ);
704 return ih;
705 }
706
707 static bool
708 elanpex_resume(device_t self PMF_FN_ARGS)
709 {
710 struct elansc_softc *sc = device_private(device_parent(self));
711
712 elanpex_intr_establish(self, sc);
713 return sc->sc_eih != NULL;
714 }
715
716 static bool
717 elanpex_suspend(device_t self PMF_FN_ARGS)
718 {
719 struct elansc_softc *sc = device_private(device_parent(self));
720
721 elanpex_intr_disestablish(sc);
722
723 return true;
724 }
725
726 static bool
727 elanpar_resume(device_t self PMF_FN_ARGS)
728 {
729 struct elansc_softc *sc = device_private(device_parent(self));
730
731 elanpar_intr_establish(self, sc);
732 return sc->sc_pih != NULL;
733 }
734
735 static bool
736 elanpar_suspend(device_t self PMF_FN_ARGS)
737 {
738 struct elansc_softc *sc = device_private(device_parent(self));
739
740 elanpar_intr_disestablish(sc->sc_pih);
741
742 return true;
743 }
744
745 static void
746 elanpex_intr_establish(device_t self, struct elansc_softc *sc)
747 {
748 uint8_t sysarbctl;
749 uint16_t pcihostmap, mstirq, tgtirq;
750
751 pcihostmap = bus_space_read_2(sc->sc_memt, sc->sc_memh,
752 MMCR_PCIHOSTMAP);
753 /* Priority P2 (Master PIC IR1) */
754 pcihostmap &= ~MMCR_PCIHOSTMAP_PCI_IRQ_MAP;
755 pcihostmap |= __SHIFTIN(__BIT(ELAN_IRQ), MMCR_PCIHOSTMAP_PCI_IRQ_MAP);
756 if (elansc_pcinmi)
757 pcihostmap |= MMCR_PCIHOSTMAP_PCI_NMI_ENB;
758 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP,
759 pcihostmap);
760
761 elanpex_intr_ack(sc->sc_memt, sc->sc_memh);
762
763 sysarbctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL);
764 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL);
765 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL);
766
767 sysarbctl |= MMCR_SYSARBCTL_GNT_TO_INT_ENB;
768
769 mstirq |= MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_ENB;
770 mstirq |= MMCR_HBMSTIRQCTL_M_TABRT_IRQ_ENB;
771 mstirq |= MMCR_HBMSTIRQCTL_M_MABRT_IRQ_ENB;
772 mstirq |= MMCR_HBMSTIRQCTL_M_SERR_IRQ_ENB;
773 mstirq |= MMCR_HBMSTIRQCTL_M_RPER_IRQ_ENB;
774 mstirq |= MMCR_HBMSTIRQCTL_M_DPER_IRQ_ENB;
775
776 tgtirq |= MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_ENB;
777 tgtirq |= MMCR_HBTGTIRQCTL_T_APER_IRQ_ENB;
778 tgtirq |= MMCR_HBTGTIRQCTL_T_DPER_IRQ_ENB;
779
780 if (elansc_pcinmi) {
781 sc->sc_eih = nmi_establish(elanpex_intr, sc);
782
783 mstirq |= MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_SEL;
784 mstirq |= MMCR_HBMSTIRQCTL_M_TABRT_IRQ_SEL;
785 mstirq |= MMCR_HBMSTIRQCTL_M_MABRT_IRQ_SEL;
786 mstirq |= MMCR_HBMSTIRQCTL_M_SERR_IRQ_SEL;
787 mstirq |= MMCR_HBMSTIRQCTL_M_RPER_IRQ_SEL;
788 mstirq |= MMCR_HBMSTIRQCTL_M_DPER_IRQ_SEL;
789
790 tgtirq |= MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_SEL;
791 tgtirq |= MMCR_HBTGTIRQCTL_T_APER_IRQ_SEL;
792 tgtirq |= MMCR_HBTGTIRQCTL_T_DPER_IRQ_SEL;
793 } else
794 sc->sc_eih = elansc_intr_establish(self, elanpex_intr, sc);
795
796 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL, sysarbctl);
797 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL, mstirq);
798 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL, tgtirq);
799 }
800
801 static void
802 elanpex_attach(device_t parent, device_t self, void *aux)
803 {
804 struct elansc_softc *sc = device_private(parent);
805
806 aprint_naive(": PCI Exceptions\n");
807 aprint_normal(": AMD Elan SC520 PCI Exceptions\n");
808
809 elanpex_intr_establish(self, sc);
810
811 aprint_debug_dev(self, "HBMSTIRQCTL %04x\n",
812 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL));
813
814 aprint_debug_dev(self, "HBTGTIRQCTL %04x\n",
815 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL));
816
817 aprint_debug_dev(self, "PCIHOSTMAP %04x\n",
818 bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP));
819
820 pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG,
821 pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG) |
822 PCI_COMMAND_PARITY_ENABLE|PCI_COMMAND_SERR_ENABLE);
823
824 if (!pmf_device_register(self, elanpex_suspend, elanpex_resume))
825 aprint_error_dev(self, "could not establish power hooks\n");
826 }
827
828 static void
829 elanpex_intr_disestablish(struct elansc_softc *sc)
830 {
831 uint8_t sysarbctl;
832 uint16_t pcihostmap, mstirq, tgtirq;
833
834 sysarbctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL);
835 sysarbctl &= ~MMCR_SYSARBCTL_GNT_TO_INT_ENB;
836 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_SYSARBCTL, sysarbctl);
837
838 mstirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL);
839 mstirq &= ~MMCR_HBMSTIRQCTL_M_RTRTO_IRQ_ENB;
840 mstirq &= ~MMCR_HBMSTIRQCTL_M_TABRT_IRQ_ENB;
841 mstirq &= ~MMCR_HBMSTIRQCTL_M_MABRT_IRQ_ENB;
842 mstirq &= ~MMCR_HBMSTIRQCTL_M_SERR_IRQ_ENB;
843 mstirq &= ~MMCR_HBMSTIRQCTL_M_RPER_IRQ_ENB;
844 mstirq &= ~MMCR_HBMSTIRQCTL_M_DPER_IRQ_ENB;
845 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBMSTIRQCTL, mstirq);
846
847 tgtirq = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL);
848 tgtirq &= ~MMCR_HBTGTIRQCTL_T_DLYTO_IRQ_ENB;
849 tgtirq &= ~MMCR_HBTGTIRQCTL_T_APER_IRQ_ENB;
850 tgtirq &= ~MMCR_HBTGTIRQCTL_T_DPER_IRQ_ENB;
851 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_HBTGTIRQCTL, tgtirq);
852
853 pcihostmap = bus_space_read_2(sc->sc_memt, sc->sc_memh,
854 MMCR_PCIHOSTMAP);
855 /* Priority P2 (Master PIC IR1) */
856 pcihostmap &= ~MMCR_PCIHOSTMAP_PCI_IRQ_MAP;
857 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_PCIHOSTMAP,
858 pcihostmap);
859
860 if (elansc_pcinmi)
861 nmi_disestablish(sc->sc_eih);
862 else
863 intr_disestablish(sc->sc_eih);
864 sc->sc_eih = NULL;
865
866 }
867
868 static int
869 elanpex_detach(device_t self, int flags)
870 {
871 struct elansc_softc *sc = device_private(device_parent(self));
872
873 pmf_device_deregister(self);
874 elanpex_intr_disestablish(sc);
875
876 return 0;
877 }
878
879 static void
880 elanpar_intr_establish(device_t self, struct elansc_softc *sc)
881 {
882 uint8_t adddecctl, wpvmap;
883
884 wpvmap = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP);
885 wpvmap &= ~MMCR_WPVMAP_INT_MAP;
886 if (elansc_wpvnmi)
887 wpvmap |= MMCR_WPVMAP_INT_NMI;
888 else
889 wpvmap |= __SHIFTIN(__BIT(ELAN_IRQ), MMCR_WPVMAP_INT_MAP);
890 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP, wpvmap);
891
892 /* clear interrupt status */
893 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA,
894 MMCR_WPVSTA_WPV_STA);
895
896 /* establish interrupt */
897 if (elansc_wpvnmi)
898 sc->sc_pih = nmi_establish(elanpar_intr, sc);
899 else
900 sc->sc_pih = elansc_intr_establish(self, elanpar_intr, sc);
901
902 adddecctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL);
903 adddecctl |= MMCR_ADDDECCTL_WPV_INT_ENB;
904 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL, adddecctl);
905 }
906
907 static void
908 elanpar_attach(device_t parent, device_t self, void *aux)
909 {
910 struct elansc_softc *sc = device_private(parent);
911
912 aprint_naive(": Programmable Address Regions\n");
913 aprint_normal(": AMD Elan SC520 Programmable Address Regions\n");
914
915 elansc_print_1(self, sc, MMCR_WPVMAP);
916 elansc_print_all_par(self, sc->sc_memt, sc->sc_memh);
917
918 sc->sc_pg0par = elansc_protect_pg0(self, sc);
919 sc->sc_textpar = elansc_protect_text(self, sc);
920
921 elanpar_intr_establish(self, sc);
922
923 elansc_print_1(self, sc, MMCR_ADDDECCTL);
924
925 if (!pmf_device_register(self, elanpar_suspend, elanpar_resume))
926 aprint_error_dev(self, "could not establish power hooks\n");
927 }
928
929 static void
930 elanpar_intr_disestablish(struct elansc_softc *sc)
931 {
932 uint8_t adddecctl, wpvmap;
933
934 /* disable interrupt, acknowledge it, disestablish our
935 * handler, unmap it
936 */
937 adddecctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL);
938 adddecctl &= ~MMCR_ADDDECCTL_WPV_INT_ENB;
939 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_ADDDECCTL, adddecctl);
940
941 bus_space_write_2(sc->sc_memt, sc->sc_memh, MMCR_WPVSTA,
942 MMCR_WPVSTA_WPV_STA);
943
944 if (elansc_wpvnmi)
945 nmi_disestablish(sc->sc_pih);
946 else
947 intr_disestablish(sc->sc_pih);
948 sc->sc_pih = NULL;
949
950 wpvmap = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP);
951 wpvmap &= ~MMCR_WPVMAP_INT_MAP;
952 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_WPVMAP, wpvmap);
953 }
954
955 static int
956 elanpar_detach(device_t self, int flags)
957 {
958 struct elansc_softc *sc = device_private(device_parent(self));
959
960 pmf_device_deregister(self);
961
962 if (sc->sc_textpar != -1) {
963 elansc_disable_par(sc->sc_memt, sc->sc_memh, sc->sc_textpar);
964 sc->sc_textpar = -1;
965 }
966 if (sc->sc_pg0par != -1) {
967 elansc_disable_par(sc->sc_memt, sc->sc_memh, sc->sc_pg0par);
968 sc->sc_pg0par = -1;
969 }
970
971 elanpar_intr_disestablish(sc);
972
973 return 0;
974 }
975
976 static void
977 elansc_attach(device_t parent, device_t self, void *aux)
978 {
979 struct elansc_softc *sc = device_private(self);
980 struct pci_attach_args *pa = aux;
981 uint16_t rev;
982 uint8_t cpuctl, picicr, ressta;
983 #if NGPIO > 0
984 struct gpiobus_attach_args gba;
985 int pin, reg, shift;
986 uint16_t data;
987 #endif
988 sc->sc_pc = pa->pa_pc;
989 sc->sc_tag = pa->pa_tag;
990
991 aprint_naive(": System Controller\n");
992 aprint_normal(": AMD Elan SC520 System Controller\n");
993
994 sc->sc_memt = pa->pa_memt;
995 if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, PAGE_SIZE, 0,
996 &sc->sc_memh) != 0) {
997 aprint_error_dev(&sc->sc_dev, "unable to map registers\n");
998 return;
999 }
1000
1001 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_HIGH);
1002
1003 rev = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_REVID);
1004 cpuctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_CPUCTL);
1005
1006 aprint_normal_dev(&sc->sc_dev,
1007 "product %d stepping %d.%d, CPU clock %s\n",
1008 (rev & REVID_PRODID) >> REVID_PRODID_SHIFT,
1009 (rev & REVID_MAJSTEP) >> REVID_MAJSTEP_SHIFT,
1010 (rev & REVID_MINSTEP),
1011 elansc_speeds[cpuctl & CPUCTL_CPU_CLK_SPD_MASK]);
1012
1013 /*
1014 * SC520 rev A1 has a bug that affects the watchdog timer. If
1015 * the GP bus echo mode is enabled, writing to the watchdog control
1016 * register is blocked.
1017 *
1018 * The BIOS in some systems (e.g. the Soekris net4501) enables
1019 * GP bus echo for various reasons, so we need to switch it off
1020 * when we talk to the watchdog timer.
1021 *
1022 * XXX The step 1.1 (B1?) in my Soekris net4501 also has this
1023 * XXX problem, so we'll just enable it for all Elan SC520s
1024 * XXX for now. --thorpej (at) NetBSD.org
1025 */
1026 if (1 || rev == ((PRODID_ELAN_SC520 << REVID_PRODID_SHIFT) |
1027 (0 << REVID_MAJSTEP_SHIFT) | (1)))
1028 sc->sc_echobug = 1;
1029
1030 /*
1031 * Determine cause of the last reset, and issue a warning if it
1032 * was due to watchdog expiry.
1033 */
1034 ressta = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA);
1035 if (ressta & RESSTA_WDT_RST_DET)
1036 aprint_error_dev(&sc->sc_dev,
1037 "WARNING: LAST RESET DUE TO WATCHDOG EXPIRATION!\n");
1038 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA, ressta);
1039
1040 elansc_print_1(self, sc, MMCR_MPICMODE);
1041 elansc_print_1(self, sc, MMCR_SL1PICMODE);
1042 elansc_print_1(self, sc, MMCR_SL2PICMODE);
1043 elansc_print_1(self, sc, MMCR_PICICR);
1044
1045 sc->sc_mpicmode = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1046 MMCR_MPICMODE);
1047 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_MPICMODE,
1048 sc->sc_mpicmode | __BIT(ELAN_IRQ));
1049
1050 sc->sc_picicr = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_PICICR);
1051 picicr = sc->sc_picicr;
1052 if (elansc_pcinmi || elansc_wpvnmi)
1053 picicr |= MMCR_PICICR_NMI_ENB;
1054 #if 0
1055 /* PC/AT compatibility */
1056 picicr |= MMCR_PICICR_S1_GINT_MODE|MMCR_PICICR_M_GINT_MODE;
1057 #endif
1058 bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_PICICR, picicr);
1059
1060 elansc_print_1(self, sc, MMCR_PICICR);
1061 elansc_print_1(self, sc, MMCR_MPICMODE);
1062
1063 mutex_enter(&sc->sc_mtx);
1064 /* Set up the watchdog registers with some defaults. */
1065 elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);
1066
1067 /* ...and clear it. */
1068 elansc_wdogctl_reset(sc);
1069 mutex_exit(&sc->sc_mtx);
1070
1071 if (!pmf_device_register(self, elansc_suspend, elansc_resume))
1072 aprint_error_dev(self, "could not establish power hooks\n");
1073
1074 #if NGPIO > 0
1075 /* Initialize GPIO pins array */
1076 for (pin = 0; pin < ELANSC_PIO_NPINS; pin++) {
1077 sc->sc_gpio_pins[pin].pin_num = pin;
1078 sc->sc_gpio_pins[pin].pin_caps = GPIO_PIN_INPUT |
1079 GPIO_PIN_OUTPUT;
1080
1081 /* Read initial state */
1082 reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16);
1083 shift = pin % 16;
1084 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1085 if ((data & (1 << shift)) == 0)
1086 sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_INPUT;
1087 else
1088 sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_OUTPUT;
1089 if (elansc_gpio_pin_read(sc, pin) == 0)
1090 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW;
1091 else
1092 sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH;
1093 }
1094
1095 /* Create controller tag */
1096 sc->sc_gpio_gc.gp_cookie = sc;
1097 sc->sc_gpio_gc.gp_pin_read = elansc_gpio_pin_read;
1098 sc->sc_gpio_gc.gp_pin_write = elansc_gpio_pin_write;
1099 sc->sc_gpio_gc.gp_pin_ctl = elansc_gpio_pin_ctl;
1100
1101 gba.gba_gc = &sc->sc_gpio_gc;
1102 gba.gba_pins = sc->sc_gpio_pins;
1103 gba.gba_npins = ELANSC_PIO_NPINS;
1104
1105 sc->sc_par = config_found_ia(&sc->sc_dev, "elanparbus", NULL, NULL);
1106 sc->sc_pex = config_found_ia(&sc->sc_dev, "elanpexbus", NULL, NULL);
1107 /* Attach GPIO framework */
1108 config_found_ia(&sc->sc_dev, "gpiobus", &gba, gpiobus_print);
1109 #endif /* NGPIO */
1110
1111 /*
1112 * Hook up the watchdog timer.
1113 */
1114 sc->sc_smw.smw_name = device_xname(&sc->sc_dev);
1115 sc->sc_smw.smw_cookie = sc;
1116 sc->sc_smw.smw_setmode = elansc_wdog_setmode;
1117 sc->sc_smw.smw_tickle = elansc_wdog_tickle;
1118 sc->sc_smw.smw_period = 32; /* actually 32.54 */
1119 if (sysmon_wdog_register(&sc->sc_smw) != 0) {
1120 aprint_error_dev(&sc->sc_dev,
1121 "unable to register watchdog with sysmon\n");
1122 }
1123 }
1124
1125 static int
1126 elanpex_match(device_t parent, struct cfdata *match, void *aux)
1127 {
1128 struct elansc_softc *sc = device_private(parent);
1129
1130 return sc->sc_pex == NULL;
1131 }
1132
1133 static int
1134 elanpar_match(device_t parent, struct cfdata *match, void *aux)
1135 {
1136 struct elansc_softc *sc = device_private(parent);
1137
1138 return sc->sc_par == NULL;
1139 }
1140
1141 CFATTACH_DECL_NEW(elanpar, sizeof(struct device),
1142 elanpar_match, elanpar_attach, elanpar_detach, NULL);
1143
1144 CFATTACH_DECL_NEW(elanpex, sizeof(struct device),
1145 elanpex_match, elanpex_attach, elanpex_detach, NULL);
1146
1147 CFATTACH_DECL2(elansc, sizeof(struct elansc_softc),
1148 elansc_match, elansc_attach, elansc_detach, NULL, NULL,
1149 elansc_childdetached);
1150
1151 #if NGPIO > 0
1152 static int
1153 elansc_gpio_pin_read(void *arg, int pin)
1154 {
1155 struct elansc_softc *sc = arg;
1156 int reg, shift;
1157 uint16_t data;
1158
1159 reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16);
1160 shift = pin % 16;
1161
1162 mutex_enter(&sc->sc_mtx);
1163 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1164 mutex_exit(&sc->sc_mtx);
1165
1166 return ((data >> shift) & 0x1);
1167 }
1168
1169 static void
1170 elansc_gpio_pin_write(void *arg, int pin, int value)
1171 {
1172 struct elansc_softc *sc = arg;
1173 int reg, shift;
1174 uint16_t data;
1175
1176 reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16);
1177 shift = pin % 16;
1178
1179 mutex_enter(&sc->sc_mtx);
1180 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1181 if (value == 0)
1182 data &= ~(1 << shift);
1183 else if (value == 1)
1184 data |= (1 << shift);
1185
1186 bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data);
1187 mutex_exit(&sc->sc_mtx);
1188 }
1189
1190 static void
1191 elansc_gpio_pin_ctl(void *arg, int pin, int flags)
1192 {
1193 struct elansc_softc *sc = arg;
1194 int reg, shift;
1195 uint16_t data;
1196
1197 reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16);
1198 shift = pin % 16;
1199 mutex_enter(&sc->sc_mtx);
1200 data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
1201 if (flags & GPIO_PIN_INPUT)
1202 data &= ~(1 << shift);
1203 if (flags & GPIO_PIN_OUTPUT)
1204 data |= (1 << shift);
1205
1206 bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data);
1207 mutex_exit(&sc->sc_mtx);
1208 }
1209 #endif /* NGPIO */
1210