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