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