vrc4172gpio.c revision 1.1 1 /* $NetBSD: vrc4172gpio.c,v 1.1 2001/05/06 14:25:16 takemura Exp $ */
2 /*-
3 * Copyright (c) 2001 TAKEMRUA Shin. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/device.h>
34 #include <sys/malloc.h>
35 #include <sys/queue.h>
36 #include <sys/reboot.h>
37 #include <machine/bus.h>
38 #include <machine/platid.h>
39 #include <machine/platid_mask.h>
40
41 #include <dev/hpc/hpciovar.h>
42
43 #include <hpcmips/vr/vripvar.h>
44 #include <hpcmips/vr/vrc4172gpioreg.h>
45
46 #include "locators.h"
47
48 #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
49
50 #define VRC2GPIODEBUG
51 #ifdef VRC2GPIODEBUG
52 #define DBG_IO (1<<0)
53 #define DBG_INTR (1<<1)
54 #define DBG_INFO (1<<2)
55 #ifndef VRC2GPIODEBUG_CONF
56 #define VRC2GPIODEBUG_CONF 0
57 #endif /* VRC2GPIODEBUG_CONF */
58 int vrc4172gpio_debug = VRC2GPIODEBUG_CONF;
59 #define DBG(flag) (vrc4172gpio_debug & (flag))
60 #define DPRINTF(flag, arg...) do { \
61 if (DBG(flag)) \
62 printf(##arg); \
63 } while (0)
64 #else
65 #define DBG(flag) (0)
66 #define DPRINTF(flag, arg...) do {} while(0)
67 #endif
68 #define VPRINTF(arg...) do { \
69 if (bootverbose) \
70 printf(##arg); \
71 } while (0)
72
73 #define CHECK_PORT(x) (0 <= (x) && (x) < VRC2_EXGP_NPORTS)
74
75 struct vrc4172gpio_intr_entry {
76 int ih_port;
77 int (*ih_fun)(void*);
78 void *ih_arg;
79 TAILQ_ENTRY(vrc4172gpio_intr_entry) ih_link;
80 };
81
82 struct vrc4172gpio_softc {
83 struct device sc_dev;
84 bus_space_tag_t sc_iot;
85 bus_space_handle_t sc_ioh;
86 struct hpcio_attach_args sc_args;
87 struct hpcio_chip *sc_hc;
88
89 void *sc_intr_handle;
90 u_int32_t sc_intr_mask;
91 u_int32_t sc_data;
92 u_int32_t sc_intr_mode[VRC2_EXGP_NPORTS];
93 TAILQ_HEAD(, vrc4172gpio_intr_entry) sc_intr_head[VRC2_EXGP_NPORTS];
94 struct hpcio_chip sc_iochip;
95 struct hpcio_attach_args sc_haa;
96 };
97
98 int vrc4172gpio_match(struct device*, struct cfdata*, void*);
99 void vrc4172gpio_attach(struct device*, struct device*, void*);
100 void vrc4172gpio_callback(struct device *self);
101 int vrc4172gpio_intr(void*);
102 int vrc4172gpio_print(void*, const char*);
103
104 int vrc4172gpio_port_read(hpcio_chip_t, int);
105 void vrc4172gpio_port_write(hpcio_chip_t, int, int);
106 void *vrc4172gpio_intr_establish(hpcio_chip_t, int, int, int (*)(void *), void*);
107 void vrc4172gpio_intr_disestablish(hpcio_chip_t, void*);
108 void vrc4172gpio_intr_clear(hpcio_chip_t, void*);
109 void vrc4172gpio_register_iochip(hpcio_chip_t, hpcio_chip_t);
110 void vrc4172gpio_update(hpcio_chip_t);
111 void vrc4172gpio_dump(hpcio_chip_t);
112 void vrc4172gpio_intr_dump(struct vrc4172gpio_softc *, int);
113 hpcio_chip_t vrc4172gpio_getchip(void*, int);
114 static void vrc4172gpio_diffport(struct vrc4172gpio_softc *sc);
115
116 static u_int16_t read_2(struct vrc4172gpio_softc *, bus_addr_t);
117 static void write_2(struct vrc4172gpio_softc *, bus_addr_t, u_int16_t);
118 static u_int32_t read_4(struct vrc4172gpio_softc *, bus_addr_t);
119 static void write_4(struct vrc4172gpio_softc *, bus_addr_t, u_int32_t);
120 static void dumpbits(u_int32_t*, int, int, int, const char[2]);
121
122 static struct hpcio_chip vrc4172gpio_iochip = {
123 .hc_portread = vrc4172gpio_port_read,
124 .hc_portwrite = vrc4172gpio_port_write,
125 .hc_intr_establish = vrc4172gpio_intr_establish,
126 .hc_intr_disestablish = vrc4172gpio_intr_disestablish,
127 .hc_intr_clear = vrc4172gpio_intr_clear,
128 .hc_register_iochip = vrc4172gpio_register_iochip,
129 .hc_update = vrc4172gpio_update,
130 .hc_dump = vrc4172gpio_dump,
131 };
132
133 static int intlv_regs[] = {
134 VRC2_EXGPINTLV0L,
135 VRC2_EXGPINTLV0H,
136 VRC2_EXGPINTLV1L
137 };
138
139 struct cfattach vrc4172gpio_ca = {
140 sizeof(struct vrc4172gpio_softc), vrc4172gpio_match, vrc4172gpio_attach
141 };
142
143 /*
144 * regster access method
145 */
146 static inline u_int16_t
147 read_2(struct vrc4172gpio_softc *sc, bus_addr_t off)
148 {
149 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, off);
150 }
151
152 static inline void
153 write_2(struct vrc4172gpio_softc *sc, bus_addr_t off, u_int16_t data)
154 {
155 bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, data);
156 }
157
158 static u_int32_t
159 read_4(struct vrc4172gpio_softc *sc, bus_addr_t off)
160 {
161 u_int16_t reg0, reg1;
162
163 reg0 = read_2(sc, off);
164 reg1 = read_2(sc, off + VRC2_EXGP_OFFSET);
165
166 return (reg0|(reg1<<16));
167 }
168
169 static void
170 write_4(struct vrc4172gpio_softc *sc, bus_addr_t off, u_int32_t data)
171 {
172 write_2(sc, off, data & 0xffff);
173 write_2(sc, off + VRC2_EXGP_OFFSET, (data>>16)&0xffff);
174 }
175
176 int
177 vrc4172gpio_match(struct device *parent, struct cfdata *cf, void *aux)
178 {
179 struct hpcio_attach_args *haa = aux;
180 platid_mask_t mask;
181
182 if (strcmp(haa->haa_busname, HPCIO_BUSNAME))
183 return (0);
184 if (cf->cf_loc[HPCIOIFCF_PLATFORM] == 0)
185 return (0);
186 mask = PLATID_DEREF(cf->cf_loc[HPCIOIFCF_PLATFORM]);
187
188 return platid_match(&platid, &mask);
189 }
190
191 void
192 vrc4172gpio_attach(struct device *parent, struct device *self, void *aux)
193 {
194 struct hpcio_attach_args *args = aux;
195 struct vrc4172gpio_softc *sc = (void*)self;
196 int i, *loc, port, mode;
197 u_int32_t regs[6], t0, t1, t2;
198
199 printf("\n");
200 loc = sc->sc_dev.dv_cfdata->cf_loc;
201
202 /*
203 * map bus space
204 */
205 sc->sc_iot = args->haa_iot;
206 sc->sc_hc = (*args->haa_getchip)(args->haa_sc, loc[HPCIOIFCF_IOCHIP]);
207 sc->sc_args = *args; /* structure copy */
208 bus_space_map(sc->sc_iot, loc[HPCIOIFCF_ADDR], loc[HPCIOIFCF_SIZE],
209 0 /* no cache */, &sc->sc_ioh);
210 if (sc->sc_ioh == NULL) {
211 printf("%s: can't map bus space\n", sc->sc_dev.dv_xname);
212 return;
213 }
214
215 /*
216 * dump Windows CE register setting
217 */
218 regs[0] = read_4(sc, VRC2_EXGPDATA);
219 regs[1] = read_4(sc, VRC2_EXGPDIR);
220 regs[2] = read_4(sc, VRC2_EXGPINTEN);
221 regs[3] = read_4(sc, VRC2_EXGPINTTYP);
222 t0 = read_2(sc, VRC2_EXGPINTLV0L);
223 t1 = read_2(sc, VRC2_EXGPINTLV0H);
224 t2 = read_2(sc, VRC2_EXGPINTLV1L);
225 regs[4] = ((t2&0xff00)<<8) | (t1&0xff00) | ((t0&0xff00)>>8);
226 regs[5] = ((t2&0xff)<<16) | ((t1&0xff)<<8) | (t0&0xff);
227
228 if (bootverbose || DBG(DBG_INFO)) {
229 /*
230 * o: output
231 * i: input (no interrupt)
232 * H: level sense interrupt (active high)
233 * L: level sense interrupt (active low)
234 * B: both edge trigger interrupt
235 * P: positive edge trigger interrupt
236 * N: negative edge trigger interrupt
237 */
238 printf(" port#:321098765432109876543210\n");
239 printf(" EXGPDATA :");
240 dumpbits(®s[0], 1, 23, 0, "10\n");
241 printf("WIN setting:");
242 dumpbits(®s[1], 5, 23, 0,
243 "oooo" /* dir=1 en=1 typ=1 */
244 "oooo" /* dir=1 en=1 typ=0 */
245 "oooo" /* dir=1 en=0 typ=1 */
246 "oooo" /* dir=1 en=0 typ=0 */
247 "BBPN" /* dir=0 en=1 typ=1 */
248 "HLHL" /* dir=0 en=1 typ=0 */
249 "iiii" /* dir=0 en=0 typ=1 */
250 "iiii" /* dir=0 en=0 typ=0 */
251 );
252 printf("\n");
253 }
254 #ifdef VRC2GPIODEBUG
255 if (DBG(DBG_INFO)) {
256 printf(" EXGPDIR :");
257 dumpbits(®s[1], 1, 23, 0, "oi\n");
258
259 printf(" EXGPINTEN :");
260 dumpbits(®s[2], 1, 23, 0, "I-\n");
261
262 printf(" EXGPINTTYP:");
263 dumpbits(®s[3], 1, 23, 0, "EL\n");
264
265 printf(" EXPIB :");
266 dumpbits(®s[4], 1, 23, 0, "10\n");
267
268 printf(" EXPIL :");
269 dumpbits(®s[5], 1, 23, 0, "10\n");
270
271 printf(" EXGPINTLV :%04x %04x %04x\n", t2, t1, t0);
272 }
273 #endif /* VRC2GPIODEBUG */
274
275 /*
276 * initialize register and internal data
277 */
278 sc->sc_intr_mask = 0;
279 write_2(sc, VRC2_EXGPINTEN, sc->sc_intr_mask);
280 for (i = 0; i < VRC2_EXGP_NPORTS; i++)
281 TAILQ_INIT(&sc->sc_intr_head[i]);
282 sc->sc_data = read_4(sc, VRC2_EXGPDATA);
283 if (bootverbose || DBG(DBG_INFO)) {
284 u_int32_t data;
285
286 sc->sc_intr_mask = (~read_4(sc, VRC2_EXGPDIR) & 0xffffff);
287 write_4(sc, VRC2_EXGPINTTYP, 0); /* level sence interrupt */
288 data = ~read_4(sc, VRC2_EXGPDATA);
289 write_2(sc, VRC2_EXGPINTLV0L, (data >> 0) & 0xff);
290 write_2(sc, VRC2_EXGPINTLV0H, (data >> 8) & 0xff);
291 write_2(sc, VRC2_EXGPINTLV1L, (data >> 16) & 0xff);
292 }
293
294 /*
295 * install interrupt handler
296 */
297 port = loc[HPCIOIFCF_PORT];
298 mode = HPCIO_INTR_LEVEL | HPCIO_INTR_HIGH;
299 sc->sc_intr_handle =
300 hpcio_intr_establish(sc->sc_hc, port, mode, vrc4172gpio_intr, sc);
301 if (sc->sc_intr_handle == NULL) {
302 printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
303 return;
304 }
305
306 /*
307 * fill hpcio_chip structure
308 */
309 sc->sc_iochip = vrc4172gpio_iochip; /* structure copy */
310 sc->sc_iochip.hc_chipid = VRIP_IOCHIP_VRC4172GPIO;
311 sc->sc_iochip.hc_name = sc->sc_dev.dv_xname;
312 sc->sc_iochip.hc_sc = sc;
313 /* Register functions to upper interface */
314 hpcio_register_iochip(sc->sc_hc, &sc->sc_iochip);
315
316 /*
317 * hpcio I/F
318 */
319 sc->sc_haa.haa_busname = HPCIO_BUSNAME;
320 sc->sc_haa.haa_sc = sc;
321 sc->sc_haa.haa_getchip = vrc4172gpio_getchip;
322 sc->sc_haa.haa_iot = sc->sc_iot;
323 while (config_found(self, &sc->sc_haa, vrc4172gpio_print)) ;
324 /*
325 * GIU-ISA bridge
326 */
327 #if 1 /* XXX Sometimes mounting root device failed. Why? XXX*/
328 config_defer(self, vrc4172gpio_callback);
329 #else
330 vrc4172gpio_callback(self);
331 #endif
332 }
333
334 void
335 vrc4172gpio_callback(struct device *self)
336 {
337 struct vrc4172gpio_softc *sc = (void*)self;
338
339 sc->sc_haa.haa_busname = "vrisab";
340 config_found(self, &sc->sc_haa, vrc4172gpio_print);
341 }
342
343 int
344 vrc4172gpio_print(void *aux, const char *pnp)
345 {
346 if (pnp)
347 return (QUIET);
348 return (UNCONF);
349 }
350
351 /*
352 * PORT
353 */
354 int
355 vrc4172gpio_port_read(hpcio_chip_t hc, int port)
356 {
357 struct vrc4172gpio_softc *sc = hc->hc_sc;
358 int on;
359
360 if (!CHECK_PORT(port))
361 panic("%s: illegal gpio port", __FUNCTION__);
362
363 on = (read_4(sc, VRC2_EXGPDATA) & (1 << port));
364
365 return (on ? 1 : 0);
366 }
367
368 void
369 vrc4172gpio_port_write(hpcio_chip_t hc, int port, int onoff)
370 {
371 struct vrc4172gpio_softc *sc = hc->hc_sc;
372 u_int32_t data;
373
374 if (!CHECK_PORT(port))
375 panic("%s: illegal gpio port", __FUNCTION__);
376 data = read_4(sc, VRC2_EXGPDATA);
377 if (onoff)
378 data |= (1<<port);
379 else
380 data &= ~(1<<port);
381 write_4(sc, VRC2_EXGPDATA, data);
382 }
383
384 void
385 vrc4172gpio_update(hpcio_chip_t hc)
386 {
387 }
388
389 void
390 vrc4172gpio_intr_dump(struct vrc4172gpio_softc *sc, int port)
391 {
392 u_int32_t mask, mask2;
393 int intlv_reg;
394
395 mask = (1 << port);
396 mask2 = (1 << (port % 8));
397 intlv_reg = intlv_regs[port/8];
398
399 if (read_4(sc, VRC2_EXGPDIR) & mask) {
400 printf(" output");
401 return;
402 }
403 printf(" input");
404
405 if (read_4(sc, VRC2_EXGPINTTYP) & mask) {
406 if (read_4(sc, intlv_reg) & (mask2 << 8)) {
407 printf(", both edge");
408 } else {
409 if (read_4(sc, intlv_reg) & mask2)
410 printf(", positive edge");
411 else
412 printf(", negative edge");
413 }
414 } else {
415 if (read_4(sc, intlv_reg) & mask2)
416 printf(", high level");
417 else
418 printf(", low level");
419 }
420 }
421
422 static void
423 vrc4172gpio_diffport(struct vrc4172gpio_softc *sc)
424 {
425 u_int32_t data;
426 data = read_4(sc, VRC2_EXGPDATA);
427 if (sc->sc_data != data) {
428 printf(" port# 321098765432109876543210\n");
429 printf("vrc4172data:");
430 dumpbits(&data, 1, 23, 0, "10\n");
431 /* bits which changed */
432 data = (data & ~sc->sc_data)|(~data & sc->sc_data);
433 printf(" ");
434 dumpbits(&data, 1, 23, 0, "^ \n");
435 sc->sc_data = data;
436 }
437 }
438
439 static void
440 dumpbits(u_int32_t *data, int ndata, int start, int end, const char *sym)
441 {
442 int i, j;
443
444 if (start <= end)
445 panic("%s(%d): %s", __FILE__, __LINE__, __FUNCTION__);
446
447 for (i = start; end <= i; i--) {
448 int d = 0;
449 for (j = 0; j < ndata; j++)
450 d = (d << 1) | ((data[j] & (1 << i)) ? 1 : 0);
451 printf("%c", sym[(1 << ndata) - d - 1]);
452
453 }
454 if (sym[1<<ndata])
455 printf("%c", sym[1<<ndata]);
456 }
457
458 void
459 vrc4172gpio_dump(hpcio_chip_t hc)
460 {
461 }
462
463 hpcio_chip_t
464 vrc4172gpio_getchip(void* scx, int chipid)
465 {
466 struct vrc4172gpio_softc *sc = scx;
467
468 return (&sc->sc_iochip);
469 }
470
471 /*
472 * Interrupt staff
473 */
474 void *
475 vrc4172gpio_intr_establish(
476 hpcio_chip_t hc,
477 int port, /* GPIO pin # */
478 int mode, /* GIU trigger setting */
479 int (*ih_fun)(void*),
480 void *ih_arg)
481 {
482 struct vrc4172gpio_softc *sc = hc->hc_sc;
483 int s;
484 u_int32_t reg, mask, mask2;
485 struct vrc4172gpio_intr_entry *ih;
486 int intlv_reg;
487
488 s = splhigh();
489
490 if (!CHECK_PORT(port))
491 panic (__FUNCTION__": bogus interrupt line");
492 if (sc->sc_intr_mode[port] && mode != sc->sc_intr_mode[port])
493 panic (__FUNCTION__": bogus interrupt type");
494 else
495 sc->sc_intr_mode[port] = mode;
496
497 mask = (1 << port);
498 mask2 = (1 << (port % 8));
499 intlv_reg = intlv_regs[port/8];
500
501 ih = malloc(sizeof(struct vrc4172gpio_intr_entry), M_DEVBUF, M_NOWAIT);
502 if (ih == NULL)
503 panic(__FUNCTION__": no memory");
504
505 ih->ih_port = port;
506 ih->ih_fun = ih_fun;
507 ih->ih_arg = ih_arg;
508 TAILQ_INSERT_TAIL(&sc->sc_intr_head[port], ih, ih_link);
509
510 #ifdef VRC2GPIODEBUG
511 if (DBG(DBG_INFO)) {
512 printf("port %2d:", port);
513 vrc4172gpio_intr_dump(sc, port);
514 printf("->");
515 }
516 #endif
517
518 /*
519 * Setup registers
520 */
521 /* I/O direction */
522 reg = read_4(sc, VRC2_EXGPDIR);
523 reg &= ~mask;
524 write_4(sc, VRC2_EXGPDIR, reg);
525
526 /* interrupt triger (level/edge) */
527 reg = read_4(sc, VRC2_EXGPINTTYP);
528 if (mode & HPCIO_INTR_EDGE)
529 reg |= mask; /* edge */
530 else
531 reg &= ~mask; /* level */
532 write_4(sc, VRC2_EXGPINTTYP, reg);
533
534 /* interrupt trigger option */
535 reg = read_4(sc, intlv_reg);
536 if (mode & HPCIO_INTR_EDGE) {
537 switch (mode & (HPCIO_INTR_POSEDGE | HPCIO_INTR_NEGEDGE)) {
538 case HPCIO_INTR_POSEDGE:
539 reg &= ~(mask2 << 8);
540 reg |= mask2;
541 break;
542 case HPCIO_INTR_NEGEDGE:
543 reg &= ~(mask2 << 8);
544 reg &= ~mask2;
545 break;
546 case HPCIO_INTR_POSEDGE | HPCIO_INTR_NEGEDGE:
547 default:
548 reg |= (mask2 << 8);
549 break;
550 }
551 } else {
552 if (mode & HPCIO_INTR_HIGH)
553 reg |= mask2; /* high */
554 else
555 reg &= ~mask2; /* low */
556 }
557 write_4(sc, intlv_reg, reg);
558
559 #ifdef VRC2GPIODEBUG
560 if (DBG(DBG_INFO)) {
561 vrc4172gpio_intr_dump(sc, port);
562 printf("\n");
563 }
564 #endif
565
566 /* XXX, Vrc4172 doesn't have register to set hold or through */
567
568 /*
569 * clear interrupt status and enable interrupt
570 */
571 vrc4172gpio_intr_clear(&sc->sc_iochip, ih);
572 sc->sc_intr_mask |= mask;
573 write_4(sc, VRC2_EXGPINTEN, sc->sc_intr_mask);
574
575 splx(s);
576
577 DPRINTF(DBG_INFO, "\n");
578
579 return (ih);
580 }
581
582 void
583 vrc4172gpio_intr_disestablish(hpcio_chip_t hc, void *arg)
584 {
585 struct vrc4172gpio_intr_entry *ihe = arg;
586 struct vrc4172gpio_softc *sc = hc->hc_sc;
587 int port = ihe->ih_port;
588 struct vrc4172gpio_intr_entry *ih;
589 int s;
590
591 s = splhigh();
592 TAILQ_FOREACH(ih, &sc->sc_intr_head[port], ih_link) {
593 if (ih == ihe) {
594 TAILQ_REMOVE(&sc->sc_intr_head[port], ih, ih_link);
595 free(ih, M_DEVBUF);
596 if (TAILQ_EMPTY(&sc->sc_intr_head[port])) {
597 /* disable interrupt */
598 sc->sc_intr_mask &= ~(1<<port);
599 write_4(sc, VRC2_EXGPINTEN,
600 sc->sc_intr_mask);
601 }
602 splx(s);
603 return;
604 }
605 }
606 panic(__FUNCTION__": no such a handle.");
607 /* NOTREACHED */
608 }
609
610 /* Clear interrupt */
611 void
612 vrc4172gpio_intr_clear(hpcio_chip_t hc, void *arg)
613 {
614 struct vrc4172gpio_softc *sc = hc->hc_sc;
615 struct vrc4172gpio_intr_entry *ihe = arg;
616
617 write_4(sc, VRC2_EXGPINTST, 1 << ihe->ih_port);
618 write_4(sc, VRC2_EXGPINTST, 0);
619 }
620
621 void
622 vrc4172gpio_register_iochip(hpcio_chip_t hc, hpcio_chip_t iochip)
623 {
624 struct vrc4172gpio_softc *sc = hc->hc_sc;
625
626 hpcio_register_iochip(sc->sc_hc, iochip);
627 }
628
629 /* interrupt handler */
630 int
631 vrc4172gpio_intr(void *arg)
632 {
633 struct vrc4172gpio_softc *sc = arg;
634 int i;
635 u_int32_t reg;
636
637 /* dispatch handler */
638 reg = read_4(sc, VRC2_EXGPINTST);
639 DPRINTF(DBG_INTR, "%s: EXGPINTST=%06x\n", __FUNCTION__, reg);
640 for (i = 0; i < VRC2_EXGP_NPORTS; i++) {
641 if (reg & (1 << i)) {
642 register struct vrc4172gpio_intr_entry *ih;
643
644 /*
645 * call interrupt handler
646 */
647 TAILQ_FOREACH(ih, &sc->sc_intr_head[i], ih_link) {
648 ih->ih_fun(ih->ih_arg);
649 }
650
651 /*
652 * disable interrupt if no handler is installed
653 */
654 if (TAILQ_EMPTY(&sc->sc_intr_head[i])) {
655 sc->sc_intr_mask &= ~(1 << i);
656 write_2(sc, VRC2_EXGPINTEN, sc->sc_intr_mask);
657
658 /* dump EXGPDATA bits which changed */
659 if (bootverbose || DBG(DBG_INFO))
660 vrc4172gpio_diffport(sc);
661 }
662 }
663 }
664
665 return (0);
666 }
667