1 /* $NetBSD: vrgiu.c,v 1.31 2002/01/29 18:53:22 uch Exp $ */ 2 /*- 3 * Copyright (c) 1999-2001 4 * Shin Takemura and PocketBSD Project. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the PocketBSD project 17 * and its contributors. 18 * 4. Neither the name of the project nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/device.h> 39 #include <sys/malloc.h> 40 #include <sys/queue.h> 41 #include <sys/reboot.h> 42 43 #include <mips/cpuregs.h> 44 #include <machine/bus.h> 45 #include <machine/config_hook.h> 46 #include <machine/debug.h> 47 48 #include <dev/hpc/hpciovar.h> 49 50 #include "opt_vr41xx.h" 51 #include <hpcmips/vr/vrcpudef.h> 52 #include <hpcmips/vr/vripif.h> 53 #include <hpcmips/vr/vripreg.h> 54 #include <hpcmips/vr/vrgiureg.h> 55 #include <hpcmips/vr/vrgiuvar.h> 56 57 #include "locators.h" 58 59 /* 60 * constant and macro definitions 61 */ 62 #define VRGIUDEBUG 63 #ifdef VRGIUDEBUG 64 #define DEBUG_IO 1 65 #define DEBUG_INTR 2 66 #ifndef VRGIUDEBUG_CONF 67 #define VRGIUDEBUG_CONF 0 68 #endif /* VRGIUDEBUG_CONF */ 69 int vrgiu_debug = VRGIUDEBUG_CONF; 70 #define DPRINTF(flag, arg) if (vrgiu_debug & flag) printf arg; 71 #define DDUMP_IO(flag, sc) if (vrgiu_debug & flag) vrgiu_dump_io(sc); 72 #define DDUMP_IOSETTING(flag, sc) \ 73 if (vrgiu_debug & flag) vrgiu_dump_iosetting(sc); 74 #define VPRINTF(flag, arg) \ 75 if (bootverbose || vrgiu_debug & flag) printf arg; 76 #define VDUMP_IO(flag, sc) \ 77 if (bootverbose || vrgiu_debug & flag) vrgiu_dump_io(sc); 78 #define VDUMP_IOSETTING(flag, sc) \ 79 if (bootverbose || vrgiu_debug & flag) vrgiu_dump_iosetting(sc); 80 #else 81 #define DPRINTF(flag, arg) 82 #define DDUMP_IO(flag, sc) 83 #define DDUMP_IOSETTING(flag, sc) 84 #define VPRINTF(flag, arg) if (bootverbose) printf arg; 85 #define VDUMP_IO(flag, sc) if (bootverbose) vrgiu_dump_io(sc); 86 #define VDUMP_IOSETTING(flag, sc) \ 87 if (bootverbose) vrgiu_dump_iosetting(sc); 88 #endif 89 90 #ifdef VRGIU_INTR_NOLED 91 int vrgiu_intr_led = 0; 92 #else /* VRGIU_INTR_NOLED */ 93 int vrgiu_intr_led = 1; 94 #endif /* VRGIU_INTR_NOLED */ 95 96 #define MAX_GPIO_OUT 50 /* port 32:49 are output only port */ 97 #define MAX_GPIO_INOUT 32 /* input/output port(0:31) */ 98 99 #define LEGAL_INTR_PORT(x) ((x) >= 0 && (x) < MAX_GPIO_INOUT) 100 #define LEGAL_OUT_PORT(x) ((x) >= 0 && (x) < MAX_GPIO_OUT) 101 102 /* flags for variant chips */ 103 #if !defined(VR4122) && !defined(VR4131) 104 #define VRGIU_HAVE_PULLUPDNREGS 105 #endif 106 107 /* 108 * type declarations 109 */ 110 struct vrgiu_intr_entry { 111 int ih_port; 112 int (*ih_fun)(void *); 113 void *ih_arg; 114 TAILQ_ENTRY(vrgiu_intr_entry) ih_link; 115 }; 116 117 struct vrgiu_softc { 118 struct device sc_dev; 119 bus_space_tag_t sc_iot; 120 bus_space_handle_t sc_ioh; 121 /* Interrupt */ 122 vrip_chipset_tag_t sc_vc; 123 void *sc_ih; 124 u_int32_t sc_intr_mask; 125 u_int32_t sc_intr_mode[MAX_GPIO_INOUT]; 126 TAILQ_HEAD(, vrgiu_intr_entry) sc_intr_head[MAX_GPIO_INOUT]; 127 struct hpcio_chip sc_iochip; 128 }; 129 130 /* 131 * prototypes 132 */ 133 int vrgiu_match(struct device*, struct cfdata*, void*); 134 void vrgiu_attach(struct device*, struct device*, void*); 135 int vrgiu_intr(void*); 136 int vrgiu_print(void*, const char*); 137 void vrgiu_callback(struct device*); 138 139 void vrgiu_dump_regs(struct vrgiu_softc *); 140 void vrgiu_dump_io(struct vrgiu_softc *); 141 void vrgiu_diff_io(void); 142 void vrgiu_dump_iosetting(struct vrgiu_softc *); 143 void vrgiu_diff_iosetting(void); 144 u_int32_t vrgiu_regread_4(struct vrgiu_softc *, bus_addr_t); 145 u_int16_t vrgiu_regread(struct vrgiu_softc *, bus_addr_t); 146 void vrgiu_regwrite_4(struct vrgiu_softc *, bus_addr_t, u_int32_t); 147 void vrgiu_regwrite(struct vrgiu_softc *, bus_addr_t, u_int16_t); 148 149 static int vrgiu_port_read(hpcio_chip_t, int); 150 static void vrgiu_port_write(hpcio_chip_t, int, int); 151 static void *vrgiu_intr_establish(hpcio_chip_t, int, int, int (*)(void *), void*); 152 static void vrgiu_intr_disestablish(hpcio_chip_t, void*); 153 static void vrgiu_intr_clear(hpcio_chip_t, void*); 154 static void vrgiu_register_iochip(hpcio_chip_t, hpcio_chip_t); 155 static void vrgiu_update(hpcio_chip_t); 156 static void vrgiu_dump(hpcio_chip_t); 157 static hpcio_chip_t vrgiu_getchip(void*, int); 158 159 /* 160 * variables 161 */ 162 static struct hpcio_chip vrgiu_iochip = { 163 .hc_portread = vrgiu_port_read, 164 .hc_portwrite = vrgiu_port_write, 165 .hc_intr_establish = vrgiu_intr_establish, 166 .hc_intr_disestablish = vrgiu_intr_disestablish, 167 .hc_intr_clear = vrgiu_intr_clear, 168 .hc_register_iochip = vrgiu_register_iochip, 169 .hc_update = vrgiu_update, 170 .hc_dump = vrgiu_dump, 171 }; 172 173 struct cfattach vrgiu_ca = { 174 sizeof(struct vrgiu_softc), vrgiu_match, vrgiu_attach 175 }; 176 177 struct vrgiu_softc *this_giu; 178 179 /* 180 * function bodies 181 */ 182 int 183 vrgiu_match(struct device *parent, struct cfdata *cf, void *aux) 184 { 185 186 return (2); /* 1st attach group of vrip */ 187 } 188 189 void 190 vrgiu_attach(struct device *parent, struct device *self, void *aux) 191 { 192 struct vrip_attach_args *va = aux; 193 struct vrgiu_softc *sc = (void*)self; 194 struct hpcio_attach_args haa; 195 int i; 196 197 this_giu = sc; 198 sc->sc_vc = va->va_vc; 199 sc->sc_iot = va->va_iot; 200 bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 201 0 /* no cache */, &sc->sc_ioh); 202 /* 203 * Disable all interrupts. 204 */ 205 sc->sc_intr_mask = 0; 206 printf("\n"); 207 #ifdef WINCE_DEFAULT_SETTING 208 #warning WINCE_DEFAULT_SETTING 209 #else 210 VPRINTF(DEBUG_IO, (" " 211 " 3 2 1\n")); 212 VPRINTF(DEBUG_IO, (" " 213 "10987654321098765432109876543210\n")); 214 VPRINTF(DEBUG_IO, ("WIN setting: ")); 215 VDUMP_IOSETTING(DEBUG_IO, sc); 216 VPRINTF(DEBUG_IO, ("\n")); 217 vrgiu_regwrite_4(sc, GIUINTEN_REG, sc->sc_intr_mask); 218 #endif 219 220 for (i = 0; i < MAX_GPIO_INOUT; i++) 221 TAILQ_INIT(&sc->sc_intr_head[i]); 222 if (!(sc->sc_ih = vrip_intr_establish(va->va_vc, va->va_unit, 0, 223 IPL_BIO, vrgiu_intr, sc))) { 224 printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname); 225 return; 226 } 227 /* 228 * fill hpcio_chip structure 229 */ 230 sc->sc_iochip = vrgiu_iochip; /* structure copy */ 231 sc->sc_iochip.hc_chipid = VRIP_IOCHIP_VRGIU; 232 sc->sc_iochip.hc_name = sc->sc_dev.dv_xname; 233 sc->sc_iochip.hc_sc = sc; 234 /* Register functions to upper interface */ 235 vrip_register_gpio(va->va_vc, &sc->sc_iochip); 236 237 /* Display port status (Input/Output) for debugging */ 238 VPRINTF(DEBUG_IO, ("I/O setting: ")); 239 VDUMP_IOSETTING(DEBUG_IO, sc); 240 VPRINTF(DEBUG_IO, ("\n")); 241 VPRINTF(DEBUG_IO, (" data:")); 242 VDUMP_IO(DEBUG_IO, sc); 243 244 /* 245 * hpcio I/F 246 */ 247 haa.haa_busname = HPCIO_BUSNAME; 248 haa.haa_sc = sc; 249 haa.haa_getchip = vrgiu_getchip; 250 haa.haa_iot = sc->sc_iot; 251 while (config_found(self, &haa, vrgiu_print)) ; 252 /* 253 * GIU-ISA bridge 254 */ 255 #if 1 /* XXX Sometimes mounting root device failed. Why? XXX*/ 256 config_defer(self, vrgiu_callback); 257 #else 258 vrgiu_callback(self); 259 #endif 260 } 261 262 void 263 vrgiu_callback(struct device *self) 264 { 265 struct vrgiu_softc *sc = (void*)self; 266 struct hpcio_attach_args haa; 267 268 haa.haa_busname = "vrisab"; 269 haa.haa_sc = sc; 270 haa.haa_getchip = vrgiu_getchip; 271 haa.haa_iot = sc->sc_iot; 272 config_found(self, &haa, vrgiu_print); 273 } 274 275 int 276 vrgiu_print(void *aux, const char *pnp) 277 { 278 if (pnp) 279 return (QUIET); 280 return (UNCONF); 281 } 282 283 void 284 vrgiu_dump_iosetting(struct vrgiu_softc *sc) 285 { 286 long iosel, inten, useupdn, termupdn, edge, hold, level; 287 u_int32_t m; 288 char syms[] = "iiiiiiiilhLHeeEEoooooooooooooooo" 289 "DDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUU"; 290 291 iosel= vrgiu_regread_4(sc, GIUIOSEL_REG); 292 inten= vrgiu_regread_4(sc, GIUINTEN_REG); 293 edge = vrgiu_regread_4(sc, GIUINTTYP_REG); 294 hold = vrgiu_regread_4(sc, GIUINTHTSEL_REG); 295 level = vrgiu_regread_4(sc, GIUINTALSEL_REG); 296 #ifndef VRGIU_HAVE_PULLUPDNREGS 297 useupdn = termupdn = 0; 298 #else 299 useupdn = vrgiu_regread(sc, GIUUSEUPDN_REG_W); 300 termupdn = vrgiu_regread(sc, GIUTERMUPDN_REG_W); 301 #endif 302 for (m = 0x80000000; m; m >>=1) 303 printf ("%c", syms[ 304 ((useupdn&m) ? 32 : 0) + 305 ((iosel&m) ? 16 : 0) + ((termupdn&m) ? 16 : 0) + 306 ((inten&m) ? 8 : 0) + 307 ((edge&m) ? 4 : 0) + 308 ((hold&m) ? 2 : 0) + 309 ((level&m) ? 1 : 0)]); 310 } 311 312 void 313 vrgiu_diff_iosetting() 314 { 315 struct vrgiu_softc *sc = this_giu; 316 static long oiosel = 0, ointen = 0, ouseupdn = 0, otermupdn = 0; 317 long iosel, inten, useupdn, termupdn; 318 u_int32_t m; 319 320 iosel= vrgiu_regread_4(sc, GIUIOSEL_REG); 321 inten= vrgiu_regread_4(sc, GIUINTEN_REG); 322 #ifndef VRGIU_HAVE_PULLUPDNREGS 323 useupdn = termupdn = 0; 324 #else 325 useupdn = vrgiu_regread(sc, GIUUSEUPDN_REG_W); 326 termupdn = vrgiu_regread(sc, GIUTERMUPDN_REG_W); 327 #endif 328 if (oiosel != iosel || ointen != inten || 329 ouseupdn != useupdn || otermupdn != termupdn) { 330 for (m = 0x80000000; m; m >>=1) 331 printf ("%c" , (useupdn&m) ? 332 ((termupdn&m) ? 'U' : 'D') : 333 ((iosel&m) ? 'o' : ((inten&m)?'I':'i'))); 334 } 335 oiosel = iosel; 336 ointen = inten; 337 ouseupdn = useupdn; 338 otermupdn = termupdn; 339 } 340 341 void 342 vrgiu_dump_io(struct vrgiu_softc *sc) 343 { 344 345 dbg_bit_print(vrgiu_regread_4(sc, GIUPIOD_REG)); 346 dbg_bit_print(vrgiu_regread_4(sc, GIUPODAT_REG)); 347 } 348 349 void 350 vrgiu_diff_io() 351 { 352 struct vrgiu_softc *sc = this_giu; 353 static u_int32_t opreg[2] = {0, 0}; 354 u_int32_t preg[2]; 355 356 preg[0] = vrgiu_regread_4(sc, GIUPIOD_REG); 357 preg[1] = vrgiu_regread_4(sc, GIUPODAT_REG); 358 359 if (opreg[0] != preg[0] || opreg[1] != preg[1]) { 360 printf("giu data: "); 361 dbg_bit_print(preg[0]); 362 dbg_bit_print(preg[1]); 363 } 364 opreg[0] = preg[0]; 365 opreg[1] = preg[1]; 366 } 367 368 void 369 vrgiu_dump_regs(struct vrgiu_softc *sc) 370 { 371 372 if (sc == NULL) { 373 panic("%s(%d): VRGIU device not initialized\n", 374 __FILE__, __LINE__); 375 } 376 printf(" IOSEL: %08x\n", vrgiu_regread_4(sc, GIUIOSEL_REG)); 377 printf(" PIOD: %08x\n", vrgiu_regread_4(sc, GIUPIOD_REG)); 378 printf(" PODAT: %08x\n", vrgiu_regread_4(sc, GIUPODAT_REG)); 379 printf(" INTSTAT: %08x\n", vrgiu_regread_4(sc, GIUINTSTAT_REG)); 380 printf(" INTEN: %08x\n", vrgiu_regread_4(sc, GIUINTEN_REG)); 381 printf(" INTTYP: %08x\n", vrgiu_regread_4(sc, GIUINTTYP_REG)); 382 printf(" INTALSEL: %08x\n", vrgiu_regread_4(sc, GIUINTALSEL_REG)); 383 printf(" INTHTSEL: %08x\n", vrgiu_regread_4(sc, GIUINTHTSEL_REG)); 384 } 385 /* 386 * GIU regster access method. 387 */ 388 u_int32_t 389 vrgiu_regread_4(struct vrgiu_softc *sc, bus_addr_t offs) 390 { 391 u_int16_t reg[2]; 392 393 bus_space_read_region_2 (sc->sc_iot, sc->sc_ioh, offs, reg, 2); 394 395 return (reg[0] | (reg[1] << 16)); 396 } 397 398 u_int16_t 399 vrgiu_regread(struct vrgiu_softc *sc, bus_addr_t off) 400 { 401 402 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, off)); 403 } 404 405 void 406 vrgiu_regwrite_4(struct vrgiu_softc *sc, bus_addr_t offs, u_int32_t data) 407 { 408 u_int16_t reg[2]; 409 410 reg[0] = data & 0xffff; 411 reg[1] = (data>>16)&0xffff; 412 bus_space_write_region_2 (sc->sc_iot, sc->sc_ioh, offs, reg, 2); 413 } 414 415 void 416 vrgiu_regwrite(struct vrgiu_softc *sc, bus_addr_t off, u_int16_t data) 417 { 418 419 bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, data); 420 } 421 422 /* 423 * PORT 424 */ 425 int 426 vrgiu_port_read(hpcio_chip_t hc, int port) 427 { 428 struct vrgiu_softc *sc = hc->hc_sc; 429 int on; 430 431 if (!LEGAL_OUT_PORT(port)) 432 panic("vrgiu_port_read: illegal gpio port"); 433 434 if (port < 32) 435 on = (vrgiu_regread_4(sc, GIUPIOD_REG) & (1 << port)); 436 else 437 on = (vrgiu_regread_4(sc, GIUPODAT_REG) & (1 << (port - 32))); 438 439 return (on ? 1 : 0); 440 } 441 442 void 443 vrgiu_port_write(hpcio_chip_t hc, int port, int onoff) 444 { 445 struct vrgiu_softc *sc = hc->hc_sc; 446 u_int32_t reg[2]; 447 int bank; 448 449 if (!LEGAL_OUT_PORT(port)) 450 panic("vrgiu_port_write: illegal gpio port"); 451 452 reg[0] = vrgiu_regread_4(sc, GIUPIOD_REG); 453 reg[1] = vrgiu_regread_4(sc, GIUPODAT_REG); 454 bank = port < 32 ? 0 : 1; 455 if (bank == 1) 456 port -= 32; 457 458 if (onoff) 459 reg[bank] |= (1<<port); 460 else 461 reg[bank] &= ~(1<<port); 462 vrgiu_regwrite_4(sc, GIUPIOD_REG, reg[0]); 463 vrgiu_regwrite_4(sc, GIUPODAT_REG, reg[1]); 464 } 465 466 static void 467 vrgiu_update(hpcio_chip_t hc) 468 { 469 } 470 471 static void 472 vrgiu_dump(hpcio_chip_t hc) 473 { 474 } 475 476 static hpcio_chip_t 477 vrgiu_getchip(void* scx, int chipid) 478 { 479 struct vrgiu_softc *sc = scx; 480 481 return (&sc->sc_iochip); 482 } 483 484 /* 485 * For before autoconfiguration. 486 */ 487 void 488 __vrgiu_out(int port, int data) 489 { 490 u_int16_t reg; 491 u_int32_t addr; 492 int offs; 493 494 if (!LEGAL_OUT_PORT(port)) 495 panic("__vrgiu_out: illegal gpio port"); 496 if (port < 16) { 497 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPIOD_L_REG_W)); 498 offs = port; 499 } else if (port < 32) { 500 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPIOD_H_REG_W)); 501 offs = port - 16; 502 } else if (port < 48) { 503 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPODAT_L_REG_W)); 504 offs = port - 32; 505 } else { 506 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPODAT_H_REG_W)); 507 offs = port - 48; 508 panic ("__vrgiu_out: not coded yet."); 509 } 510 DPRINTF(DEBUG_IO, ("__vrgiu_out: addr %08x bit %d\n", addr, offs)); 511 512 wbflush(); 513 reg = *((volatile u_int16_t*)addr); 514 if (data) { 515 reg |= (1 << offs); 516 } else { 517 reg &= ~(1 << offs); 518 } 519 *((volatile u_int16_t*)addr) = reg; 520 wbflush(); 521 } 522 /* 523 * Interrupt staff 524 */ 525 void * 526 vrgiu_intr_establish( 527 hpcio_chip_t hc, 528 int port, /* GPIO pin # */ 529 int mode, /* GIU trigger setting */ 530 int (*ih_fun)(void *), 531 void *ih_arg) 532 { 533 struct vrgiu_softc *sc = hc->hc_sc; 534 int s; 535 u_int32_t reg, mask; 536 struct vrgiu_intr_entry *ih; 537 538 if (!LEGAL_INTR_PORT(port)) 539 panic ("vrgiu_intr_establish: bogus interrupt line."); 540 if (sc->sc_intr_mode[port] && mode != sc->sc_intr_mode[port]) 541 panic ("vrgiu_intr_establish: bogus interrupt type."); 542 else 543 sc->sc_intr_mode[port] = mode; 544 mask = (1 << port); 545 546 s = splhigh(); 547 548 if (!(ih = malloc(sizeof(struct vrgiu_intr_entry), M_DEVBUF, M_NOWAIT))) 549 panic ("vrgiu_intr_establish: no memory."); 550 551 DPRINTF(DEBUG_INTR, ("%s: port %d ", sc->sc_dev.dv_xname, port)); 552 ih->ih_port = port; 553 ih->ih_fun = ih_fun; 554 ih->ih_arg = ih_arg; 555 TAILQ_INSERT_TAIL(&sc->sc_intr_head[port], ih, ih_link); 556 #ifdef WINCE_DEFAULT_SETTING 557 #warning WINCE_DEFAULT_SETTING 558 #else 559 /* 560 * Setup registers 561 */ 562 /* Input mode */ 563 reg = vrgiu_regread_4(sc, GIUIOSEL_REG); 564 reg &= ~mask; 565 vrgiu_regwrite_4(sc, GIUIOSEL_REG, reg); 566 567 /* interrupt type */ 568 reg = vrgiu_regread_4(sc, GIUINTTYP_REG); 569 DPRINTF(DEBUG_INTR, ("[%s->",reg & mask ? "edge" : "level")); 570 if (mode & HPCIO_INTR_EDGE) { 571 DPRINTF(DEBUG_INTR, ("edge]")); 572 reg |= mask; /* edge */ 573 } else { 574 DPRINTF(DEBUG_INTR, ("level]")); 575 reg &= ~mask; /* level */ 576 } 577 vrgiu_regwrite_4(sc, GIUINTTYP_REG, reg); 578 579 /* interrupt level */ 580 if (!(mode & HPCIO_INTR_EDGE)) { 581 reg = vrgiu_regread_4(sc, GIUINTALSEL_REG); 582 DPRINTF(DEBUG_INTR, ("[%s->",reg & mask ? "high" : "low")); 583 if (mode & HPCIO_INTR_HIGH) { 584 DPRINTF(DEBUG_INTR, ("high]")); 585 reg |= mask; /* high */ 586 } else { 587 DPRINTF(DEBUG_INTR, ("low]")); 588 reg &= ~mask; /* low */ 589 } 590 vrgiu_regwrite_4(sc, GIUINTALSEL_REG, reg); 591 } 592 /* hold or through */ 593 reg = vrgiu_regread_4(sc, GIUINTHTSEL_REG); 594 DPRINTF(DEBUG_INTR, ("[%s->",reg & mask ? "hold" : "through")); 595 if (mode & HPCIO_INTR_HOLD) { 596 DPRINTF(DEBUG_INTR, ("hold]")); 597 reg |= mask; /* hold */ 598 } else { 599 DPRINTF(DEBUG_INTR, ("through]")); 600 reg &= ~mask; /* through */ 601 } 602 vrgiu_regwrite_4(sc, GIUINTHTSEL_REG, reg); 603 #endif 604 /* 605 * clear interrupt status 606 */ 607 reg = vrgiu_regread_4(sc, GIUINTSTAT_REG); 608 reg &= ~mask; 609 vrgiu_regwrite_4(sc, GIUINTSTAT_REG, reg); 610 /* 611 * enable interrupt 612 */ 613 #ifdef WINCE_DEFAULT_SETTING 614 #warning WINCE_DEFAULT_SETTING 615 #else 616 sc->sc_intr_mask |= mask; 617 vrgiu_regwrite_4(sc, GIUINTEN_REG, sc->sc_intr_mask); 618 /* Unmask GIU level 2 mask register */ 619 vrip_intr_setmask2(sc->sc_vc, sc->sc_ih, (1<<port), 1); 620 #endif 621 splx(s); 622 623 DPRINTF(DEBUG_INTR, ("\n")); 624 625 return (ih); 626 } 627 628 void 629 vrgiu_intr_disestablish(hpcio_chip_t hc, void *arg) 630 { 631 struct vrgiu_intr_entry *ihe = arg; 632 struct vrgiu_softc *sc = hc->hc_sc; 633 int port = ihe->ih_port; 634 struct vrgiu_intr_entry *ih; 635 int s; 636 637 s = splhigh(); 638 TAILQ_FOREACH(ih, &sc->sc_intr_head[port], ih_link) { 639 if (ih == ihe) { 640 TAILQ_REMOVE(&sc->sc_intr_head[port], ih, ih_link); 641 free(ih, M_DEVBUF); 642 if (TAILQ_EMPTY(&sc->sc_intr_head[port])) { 643 /* Disable interrupt */ 644 #ifdef WINCE_DEFAULT_SETTING 645 #warning WINCE_DEFAULT_SETTING 646 #else 647 sc->sc_intr_mask &= ~(1<<port); 648 vrgiu_regwrite_4(sc, GIUINTEN_REG, sc->sc_intr_mask); 649 #endif 650 } 651 splx(s); 652 return; 653 } 654 } 655 panic("vrgiu_intr_disetablish: no such a handle."); 656 /* NOTREACHED */ 657 } 658 659 /* Clear interrupt */ 660 void 661 vrgiu_intr_clear(hpcio_chip_t hc, void *arg) 662 { 663 struct vrgiu_softc *sc = hc->hc_sc; 664 struct vrgiu_intr_entry *ihe = arg; 665 u_int32_t reg; 666 667 reg = vrgiu_regread_4(sc, GIUINTSTAT_REG); 668 vrgiu_regwrite_4(sc, GIUINTSTAT_REG, reg & ~(1 << ihe->ih_port)); 669 } 670 671 static void 672 vrgiu_register_iochip(hpcio_chip_t hc, hpcio_chip_t iochip) 673 { 674 struct vrgiu_softc *sc = hc->hc_sc; 675 676 vrip_register_gpio(sc->sc_vc, iochip); 677 } 678 679 /* interrupt handler */ 680 int 681 vrgiu_intr(void *arg) 682 { 683 #ifdef DUMP_GIU_LEVEL2_INTR 684 #warning DUMP_GIU_LEVEL2_INTR 685 static u_int32_t oreg; 686 #endif 687 struct vrgiu_softc *sc = arg; 688 int i; 689 u_int32_t reg; 690 int ledvalue = CONFIG_HOOK_LED_FLASH; 691 692 /* Get Level 2 interrupt status */ 693 vrip_intr_getstatus2 (sc->sc_vc, sc->sc_ih, ®); 694 #ifdef DUMP_GIU_LEVEL2_INTR 695 #warning DUMP_GIU_LEVEL2_INTR 696 { 697 u_int32_t uedge, dedge, j; 698 for (j = 0x80000000; j > 0; j >>=1) 699 printf ("%c" , reg&j ? '|' : '.'); 700 uedge = (reg ^ oreg) & reg; 701 dedge = (reg ^ oreg) & ~reg; 702 if (uedge || dedge) { 703 for (j = 0; j < 32; j++) { 704 if (uedge & (1 << j)) 705 printf ("+%d", j); 706 else if (dedge & (1 << j)) 707 printf ("-%d", j); 708 } 709 } 710 oreg = reg; 711 printf ("\n"); 712 } 713 #endif 714 /* Clear interrupt */ 715 vrgiu_regwrite_4(sc, GIUINTSTAT_REG, vrgiu_regread_4(sc, GIUINTSTAT_REG)); 716 717 /* Dispatch handler */ 718 for (i = 0; i < MAX_GPIO_INOUT; i++) { 719 if (reg & (1 << i)) { 720 register struct vrgiu_intr_entry *ih; 721 TAILQ_FOREACH(ih, &sc->sc_intr_head[i], ih_link) { 722 ih->ih_fun(ih->ih_arg); 723 } 724 } 725 } 726 727 if (vrgiu_intr_led) 728 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_LED, 729 (void *)&ledvalue); 730 return (0); 731 } 732