1 /* $NetBSD: vrgiu.c,v 1.26 2001/09/16 05:32:21 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 47 #include <dev/hpc/hpciovar.h> 48 49 #include "opt_vr41xx.h" 50 #include <hpcmips/vr/vrcpudef.h> 51 #include <hpcmips/vr/vripreg.h> 52 #include <hpcmips/vr/vripvar.h> 53 #include <hpcmips/vr/vrgiureg.h> 54 #include <hpcmips/vr/vrgiuvar.h> 55 56 #include "locators.h" 57 58 #define VRGIUDEBUG 59 #ifdef VRGIUDEBUG 60 #define DEBUG_IO 1 61 #define DEBUG_INTR 2 62 #ifndef VRGIUDEBUG_CONF 63 #define VRGIUDEBUG_CONF 0 64 #endif /* VRGIUDEBUG_CONF */ 65 int vrgiu_debug = VRGIUDEBUG_CONF; 66 #define DPRINTF(flag, arg) if (vrgiu_debug & flag) printf arg; 67 #define DDUMP_IO(flag, sc) if (vrgiu_debug & flag) vrgiu_dump_io(sc); 68 #define DDUMP_IOSETTING(flag, sc) \ 69 if (vrgiu_debug & flag) vrgiu_dump_iosetting(sc); 70 #define VPRINTF(flag, arg) \ 71 if (bootverbose || vrgiu_debug & flag) printf arg; 72 #define VDUMP_IO(flag, sc) \ 73 if (bootverbose || vrgiu_debug & flag) vrgiu_dump_io(sc); 74 #define VDUMP_IOSETTING(flag, sc) \ 75 if (bootverbose || vrgiu_debug & flag) vrgiu_dump_iosetting(sc); 76 #else 77 #define DPRINTF(flag, arg) 78 #define DDUMP_IO(flag, sc) 79 #define DDUMP_IOSETTING(flag, sc) 80 #define VPRINTF(flag, arg) if (bootverbose) printf arg; 81 #define VDUMP_IO(flag, sc) if (bootverbose) vrgiu_dump_io(sc); 82 #define VDUMP_IOSETTING(flag, sc) \ 83 if (bootverbose) vrgiu_dump_iosetting(sc); 84 #endif 85 86 #ifdef VRGIU_INTR_NOLED 87 int vrgiu_intr_led = 0; 88 #else /* VRGIU_INTR_NOLED */ 89 int vrgiu_intr_led = 1; 90 #endif /* VRGIU_INTR_NOLED */ 91 92 #define LEGAL_INTR_PORT(x) ((x) >= 0 && (x) < MAX_GPIO_INOUT) 93 #define LEGAL_OUT_PORT(x) ((x) >= 0 && (x) < MAX_GPIO_OUT) 94 95 int vrgiu_match(struct device*, struct cfdata*, void*); 96 void vrgiu_attach(struct device*, struct device*, void*); 97 int vrgiu_intr(void*); 98 int vrgiu_print(void*, const char*); 99 void vrgiu_callback(struct device*); 100 101 void vrgiu_dump_regs(struct vrgiu_softc *); 102 void vrgiu_dump_io(struct vrgiu_softc *); 103 void vrgiu_diff_io(void); 104 void vrgiu_dump_iosetting(struct vrgiu_softc *); 105 void vrgiu_diff_iosetting(void); 106 u_int32_t vrgiu_regread_4(struct vrgiu_softc *, bus_addr_t); 107 u_int16_t vrgiu_regread(struct vrgiu_softc *, bus_addr_t); 108 void vrgiu_regwrite_4(struct vrgiu_softc *, bus_addr_t, u_int32_t); 109 void vrgiu_regwrite(struct vrgiu_softc *, bus_addr_t, u_int16_t); 110 111 static int vrgiu_port_read(hpcio_chip_t, int); 112 static void vrgiu_port_write(hpcio_chip_t, int, int); 113 static void *vrgiu_intr_establish(hpcio_chip_t, int, int, int (*)(void *), void*); 114 static void vrgiu_intr_disestablish(hpcio_chip_t, void*); 115 static void vrgiu_intr_clear(hpcio_chip_t, void*); 116 static void vrgiu_register_iochip(hpcio_chip_t, hpcio_chip_t); 117 static void vrgiu_update(hpcio_chip_t); 118 static void vrgiu_dump(hpcio_chip_t); 119 static hpcio_chip_t vrgiu_getchip(void*, int); 120 121 static struct hpcio_chip vrgiu_iochip = { 122 .hc_portread = vrgiu_port_read, 123 .hc_portwrite = vrgiu_port_write, 124 .hc_intr_establish = vrgiu_intr_establish, 125 .hc_intr_disestablish = vrgiu_intr_disestablish, 126 .hc_intr_clear = vrgiu_intr_clear, 127 .hc_register_iochip = vrgiu_register_iochip, 128 .hc_update = vrgiu_update, 129 .hc_dump = vrgiu_dump, 130 }; 131 132 struct cfattach vrgiu_ca = { 133 sizeof(struct vrgiu_softc), vrgiu_match, vrgiu_attach 134 }; 135 136 struct vrgiu_softc *this_giu; 137 138 int 139 vrgiu_match(struct device *parent, struct cfdata *cf, void *aux) 140 { 141 142 return (2); /* 1st attach group of vrip */ 143 } 144 145 void 146 vrgiu_attach(struct device *parent, struct device *self, void *aux) 147 { 148 struct vrip_attach_args *va = aux; 149 struct vrgiu_softc *sc = (void*)self; 150 struct hpcio_attach_args haa; 151 int i; 152 153 this_giu = sc; 154 sc->sc_vc = va->va_vc; 155 sc->sc_iot = va->va_iot; 156 bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 157 0 /* no cache */, &sc->sc_ioh); 158 /* 159 * Disable all interrupts. 160 */ 161 sc->sc_intr_mask = 0; 162 printf("\n"); 163 #ifdef WINCE_DEFAULT_SETTING 164 #warning WINCE_DEFAULT_SETTING 165 #else 166 VPRINTF(DEBUG_IO, ("WIN setting: ")); 167 VDUMP_IOSETTING(DEBUG_IO, sc); 168 VPRINTF(DEBUG_IO, ("\n")); 169 vrgiu_regwrite_4(sc, GIUINTEN_REG, sc->sc_intr_mask); 170 #endif 171 172 for (i = 0; i < MAX_GPIO_INOUT; i++) 173 TAILQ_INIT(&sc->sc_intr_head[i]); 174 if (!(sc->sc_ih = vrip_intr_establish(va->va_vc, va->va_intr, IPL_BIO, 175 vrgiu_intr, sc))) { 176 printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname); 177 return; 178 } 179 /* 180 * fill hpcio_chip structure 181 */ 182 sc->sc_iochip = vrgiu_iochip; /* structure copy */ 183 sc->sc_iochip.hc_chipid = VRIP_IOCHIP_VRGIU; 184 sc->sc_iochip.hc_name = sc->sc_dev.dv_xname; 185 sc->sc_iochip.hc_sc = sc; 186 /* Register functions to upper interface */ 187 vrip_gpio_register(va->va_vc, &sc->sc_iochip); 188 189 /* Display port status (Input/Output) for debugging */ 190 VPRINTF(DEBUG_IO, ("I/O setting: ")); 191 VDUMP_IOSETTING(DEBUG_IO, sc); 192 VPRINTF(DEBUG_IO, ("\n")); 193 VPRINTF(DEBUG_IO, (" data:")); 194 VDUMP_IO(DEBUG_IO, sc); 195 196 /* 197 * hpcio I/F 198 */ 199 haa.haa_busname = HPCIO_BUSNAME; 200 haa.haa_sc = sc; 201 haa.haa_getchip = vrgiu_getchip; 202 haa.haa_iot = sc->sc_iot; 203 while (config_found(self, &haa, vrgiu_print)) ; 204 /* 205 * GIU-ISA bridge 206 */ 207 #if 1 /* XXX Sometimes mounting root device failed. Why? XXX*/ 208 config_defer(self, vrgiu_callback); 209 #else 210 vrgiu_callback(self); 211 #endif 212 } 213 214 void 215 vrgiu_callback(struct device *self) 216 { 217 struct vrgiu_softc *sc = (void*)self; 218 struct hpcio_attach_args haa; 219 220 haa.haa_busname = "vrisab"; 221 haa.haa_sc = sc; 222 haa.haa_getchip = vrgiu_getchip; 223 haa.haa_iot = sc->sc_iot; 224 config_found(self, &haa, vrgiu_print); 225 } 226 227 int 228 vrgiu_print(void *aux, const char *pnp) 229 { 230 if (pnp) 231 return (QUIET); 232 return (UNCONF); 233 } 234 235 void 236 vrgiu_dump_iosetting(struct vrgiu_softc *sc) 237 { 238 long iosel, inten, useupdn, termupdn; 239 u_int32_t m; 240 241 iosel= vrgiu_regread_4(sc, GIUIOSEL_REG); 242 inten= vrgiu_regread_4(sc, GIUINTEN_REG); 243 #ifdef ONLY_VR4122_4131 244 useupdn = termupdn = 0; 245 #else 246 useupdn = vrgiu_regread(sc, GIUUSEUPDN_REG_W); 247 termupdn = vrgiu_regread(sc, GIUTERMUPDN_REG_W); 248 #endif 249 for (m = 0x80000000; m; m >>=1) 250 printf ("%c" , (useupdn&m) ? 251 ((termupdn&m) ? 'U' : 'D') : 252 ((iosel&m) ? 'o' : ((inten&m)?'I':'i'))); 253 } 254 255 void 256 vrgiu_diff_iosetting() 257 { 258 struct vrgiu_softc *sc = this_giu; 259 static long oiosel = 0, ointen = 0, ouseupdn = 0, otermupdn = 0; 260 long iosel, inten, useupdn, termupdn; 261 u_int32_t m; 262 263 iosel= vrgiu_regread_4(sc, GIUIOSEL_REG); 264 inten= vrgiu_regread_4(sc, GIUINTEN_REG); 265 #ifdef ONLY_VR4122_4131 266 useupdn = termupdn = 0; 267 #else 268 useupdn = vrgiu_regread(sc, GIUUSEUPDN_REG_W); 269 termupdn = vrgiu_regread(sc, GIUTERMUPDN_REG_W); 270 #endif 271 if (oiosel != iosel || ointen != inten || 272 ouseupdn != useupdn || otermupdn != termupdn) { 273 for (m = 0x80000000; m; m >>=1) 274 printf ("%c" , (useupdn&m) ? 275 ((termupdn&m) ? 'U' : 'D') : 276 ((iosel&m) ? 'o' : ((inten&m)?'I':'i'))); 277 } 278 oiosel = iosel; 279 ointen = inten; 280 ouseupdn = useupdn; 281 otermupdn = termupdn; 282 } 283 284 void 285 vrgiu_dump_io(struct vrgiu_softc *sc) 286 { 287 u_int32_t preg[2]; 288 289 preg[0] = vrgiu_regread_4(sc, GIUPIOD_REG); 290 preg[1] = vrgiu_regread_4(sc, GIUPODAT_REG); 291 292 bitdisp64(preg); 293 } 294 295 void 296 vrgiu_diff_io() 297 { 298 struct vrgiu_softc *sc = this_giu; 299 static u_int32_t opreg[2] = {0, 0}; 300 u_int32_t preg[2]; 301 302 preg[0] = vrgiu_regread_4(sc, GIUPIOD_REG); 303 preg[1] = vrgiu_regread_4(sc, GIUPODAT_REG); 304 305 if (opreg[0] != preg[0] || opreg[1] != preg[1]) { 306 printf("giu data: "); 307 bitdisp64(preg); 308 } 309 opreg[0] = preg[0]; 310 opreg[1] = preg[1]; 311 } 312 313 void 314 vrgiu_dump_regs(struct vrgiu_softc *sc) 315 { 316 317 if (sc == NULL) { 318 panic("%s(%d): VRGIU device not initialized\n", 319 __FILE__, __LINE__); 320 } 321 printf(" IOSEL: %08x\n", vrgiu_regread_4(sc, GIUIOSEL_REG)); 322 printf(" PIOD: %08x\n", vrgiu_regread_4(sc, GIUPIOD_REG)); 323 printf(" PODAT: %08x\n", vrgiu_regread_4(sc, GIUPODAT_REG)); 324 printf(" INTSTAT: %08x\n", vrgiu_regread_4(sc, GIUINTSTAT_REG)); 325 printf(" INTEN: %08x\n", vrgiu_regread_4(sc, GIUINTEN_REG)); 326 printf(" INTTYP: %08x\n", vrgiu_regread_4(sc, GIUINTTYP_REG)); 327 printf(" INTALSEL: %08x\n", vrgiu_regread_4(sc, GIUINTALSEL_REG)); 328 printf(" INTHTSEL: %08x\n", vrgiu_regread_4(sc, GIUINTHTSEL_REG)); 329 } 330 /* 331 * GIU regster access method. 332 */ 333 u_int32_t 334 vrgiu_regread_4(struct vrgiu_softc *sc, bus_addr_t offs) 335 { 336 u_int16_t reg[2]; 337 338 bus_space_read_region_2 (sc->sc_iot, sc->sc_ioh, offs, reg, 2); 339 340 return (reg[0] | (reg[1] << 16)); 341 } 342 343 u_int16_t 344 vrgiu_regread(struct vrgiu_softc *sc, bus_addr_t off) 345 { 346 347 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, off)); 348 } 349 350 void 351 vrgiu_regwrite_4(struct vrgiu_softc *sc, bus_addr_t offs, u_int32_t data) 352 { 353 u_int16_t reg[2]; 354 355 reg[0] = data & 0xffff; 356 reg[1] = (data>>16)&0xffff; 357 bus_space_write_region_2 (sc->sc_iot, sc->sc_ioh, offs, reg, 2); 358 } 359 360 void 361 vrgiu_regwrite(struct vrgiu_softc *sc, bus_addr_t off, u_int16_t data) 362 { 363 364 bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, data); 365 } 366 367 /* 368 * PORT 369 */ 370 int 371 vrgiu_port_read(hpcio_chip_t hc, int port) 372 { 373 struct vrgiu_softc *sc = hc->hc_sc; 374 int on; 375 376 if (!LEGAL_OUT_PORT(port)) 377 panic("vrgiu_port_read: illegal gpio port"); 378 379 if (port < 32) 380 on = (vrgiu_regread_4(sc, GIUPIOD_REG) & (1 << port)); 381 else 382 on = (vrgiu_regread_4(sc, GIUPODAT_REG) & (1 << (port - 32))); 383 384 return (on ? 1 : 0); 385 } 386 387 void 388 vrgiu_port_write(hpcio_chip_t hc, int port, int onoff) 389 { 390 struct vrgiu_softc *sc = hc->hc_sc; 391 u_int32_t reg[2]; 392 int bank; 393 394 if (!LEGAL_OUT_PORT(port)) 395 panic("vrgiu_port_write: illegal gpio port"); 396 397 reg[0] = vrgiu_regread_4(sc, GIUPIOD_REG); 398 reg[1] = vrgiu_regread_4(sc, GIUPODAT_REG); 399 bank = port < 32 ? 0 : 1; 400 if (bank == 1) 401 port -= 32; 402 403 if (onoff) 404 reg[bank] |= (1<<port); 405 else 406 reg[bank] &= ~(1<<port); 407 vrgiu_regwrite_4(sc, GIUPIOD_REG, reg[0]); 408 vrgiu_regwrite_4(sc, GIUPODAT_REG, reg[1]); 409 } 410 411 static void 412 vrgiu_update(hpcio_chip_t hc) 413 { 414 } 415 416 static void 417 vrgiu_dump(hpcio_chip_t hc) 418 { 419 } 420 421 static hpcio_chip_t 422 vrgiu_getchip(void* scx, int chipid) 423 { 424 struct vrgiu_softc *sc = scx; 425 426 return (&sc->sc_iochip); 427 } 428 429 /* 430 * For before autoconfiguration. 431 */ 432 void 433 __vrgiu_out(int port, int data) 434 { 435 u_int16_t reg; 436 u_int32_t addr; 437 int offs; 438 439 if (!LEGAL_OUT_PORT(port)) 440 panic("__vrgiu_out: illegal gpio port"); 441 if (port < 16) { 442 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPIOD_L_REG_W)); 443 offs = port; 444 } else if (port < 32) { 445 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPIOD_H_REG_W)); 446 offs = port - 16; 447 } else if (port < 48) { 448 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPODAT_L_REG_W)); 449 offs = port - 32; 450 } else { 451 addr = MIPS_PHYS_TO_KSEG1((VRIP_GIU_ADDR + GIUPODAT_H_REG_W)); 452 offs = port - 48; 453 panic ("__vrgiu_out: not coded yet."); 454 } 455 DPRINTF(DEBUG_IO, ("__vrgiu_out: addr %08x bit %d\n", addr, offs)); 456 457 wbflush(); 458 reg = *((volatile u_int16_t*)addr); 459 if (data) { 460 reg |= (1 << offs); 461 } else { 462 reg &= ~(1 << offs); 463 } 464 *((volatile u_int16_t*)addr) = reg; 465 wbflush(); 466 } 467 /* 468 * Interrupt staff 469 */ 470 void * 471 vrgiu_intr_establish( 472 hpcio_chip_t hc, 473 int port, /* GPIO pin # */ 474 int mode, /* GIU trigger setting */ 475 int (*ih_fun)(void *), 476 void *ih_arg) 477 { 478 struct vrgiu_softc *sc = hc->hc_sc; 479 int s; 480 u_int32_t reg, mask; 481 struct vrgiu_intr_entry *ih; 482 483 if (!LEGAL_INTR_PORT(port)) 484 panic ("vrgiu_intr_establish: bogus interrupt line."); 485 if (sc->sc_intr_mode[port] && mode != sc->sc_intr_mode[port]) 486 panic ("vrgiu_intr_establish: bogus interrupt type."); 487 else 488 sc->sc_intr_mode[port] = mode; 489 mask = (1 << port); 490 491 s = splhigh(); 492 493 if (!(ih = malloc(sizeof(struct vrgiu_intr_entry), M_DEVBUF, M_NOWAIT))) 494 panic ("vrgiu_intr_establish: no memory."); 495 496 ih->ih_port = port; 497 ih->ih_fun = ih_fun; 498 ih->ih_arg = ih_arg; 499 TAILQ_INSERT_TAIL(&sc->sc_intr_head[port], ih, ih_link); 500 #ifdef WINCE_DEFAULT_SETTING 501 #warning WINCE_DEFAULT_SETTING 502 #else 503 /* 504 * Setup registers 505 */ 506 /* Input mode */ 507 reg = vrgiu_regread_4(sc, GIUIOSEL_REG); 508 reg &= ~mask; 509 vrgiu_regwrite_4(sc, GIUIOSEL_REG, reg); 510 511 /* interrupt type */ 512 reg = vrgiu_regread_4(sc, GIUINTTYP_REG); 513 DPRINTF(DEBUG_INTR, ("[%s->",reg & mask ? "edge" : "level")); 514 if (mode & HPCIO_INTR_EDGE) { 515 DPRINTF(DEBUG_INTR, ("edge]")); 516 reg |= mask; /* edge */ 517 } else { 518 DPRINTF(DEBUG_INTR, ("level]")); 519 reg &= ~mask; /* level */ 520 } 521 vrgiu_regwrite_4(sc, GIUINTTYP_REG, reg); 522 523 /* interrupt level */ 524 if (!(mode & HPCIO_INTR_EDGE)) { 525 reg = vrgiu_regread_4(sc, GIUINTALSEL_REG); 526 DPRINTF(DEBUG_INTR, ("[%s->",reg & mask ? "high" : "low")); 527 if (mode & HPCIO_INTR_HIGH) { 528 DPRINTF(DEBUG_INTR, ("high]")); 529 reg |= mask; /* high */ 530 } else { 531 DPRINTF(DEBUG_INTR, ("low]")); 532 reg &= ~mask; /* low */ 533 } 534 vrgiu_regwrite_4(sc, GIUINTALSEL_REG, reg); 535 } 536 /* hold or through */ 537 reg = vrgiu_regread_4(sc, GIUINTHTSEL_REG); 538 DPRINTF(DEBUG_INTR, ("[%s->",reg & mask ? "hold" : "through")); 539 if (mode & HPCIO_INTR_HOLD) { 540 DPRINTF(DEBUG_INTR, ("hold]")); 541 reg |= mask; /* hold */ 542 } else { 543 DPRINTF(DEBUG_INTR, ("through]")); 544 reg &= ~mask; /* through */ 545 } 546 vrgiu_regwrite_4(sc, GIUINTHTSEL_REG, reg); 547 #endif 548 /* 549 * clear interrupt status 550 */ 551 reg = vrgiu_regread_4(sc, GIUINTSTAT_REG); 552 reg &= ~mask; 553 vrgiu_regwrite_4(sc, GIUINTSTAT_REG, reg); 554 /* 555 * enable interrupt 556 */ 557 #ifdef WINCE_DEFAULT_SETTING 558 #warning WINCE_DEFAULT_SETTING 559 #else 560 sc->sc_intr_mask |= mask; 561 vrgiu_regwrite_4(sc, GIUINTEN_REG, sc->sc_intr_mask); 562 /* Unmask GIU level 2 mask register */ 563 vrip_intr_setmask2(sc->sc_vc, sc->sc_ih, (1<<port), 1); 564 #endif 565 splx(s); 566 567 DPRINTF(DEBUG_INTR, ("\n")); 568 569 return (ih); 570 } 571 572 void 573 vrgiu_intr_disestablish(hpcio_chip_t hc, void *arg) 574 { 575 struct vrgiu_intr_entry *ihe = arg; 576 struct vrgiu_softc *sc = hc->hc_sc; 577 int port = ihe->ih_port; 578 struct vrgiu_intr_entry *ih; 579 int s; 580 581 s = splhigh(); 582 TAILQ_FOREACH(ih, &sc->sc_intr_head[port], ih_link) { 583 if (ih == ihe) { 584 TAILQ_REMOVE(&sc->sc_intr_head[port], ih, ih_link); 585 free(ih, M_DEVBUF); 586 if (TAILQ_EMPTY(&sc->sc_intr_head[port])) { 587 /* Disable interrupt */ 588 #ifdef WINCE_DEFAULT_SETTING 589 #warning WINCE_DEFAULT_SETTING 590 #else 591 sc->sc_intr_mask &= ~(1<<port); 592 vrgiu_regwrite_4(sc, GIUINTEN_REG, sc->sc_intr_mask); 593 #endif 594 } 595 splx(s); 596 return; 597 } 598 } 599 panic("vrgiu_intr_disetablish: no such a handle."); 600 /* NOTREACHED */ 601 } 602 603 /* Clear interrupt */ 604 void 605 vrgiu_intr_clear(hpcio_chip_t hc, void *arg) 606 { 607 struct vrgiu_softc *sc = hc->hc_sc; 608 struct vrgiu_intr_entry *ihe = arg; 609 u_int32_t reg; 610 611 reg = vrgiu_regread_4(sc, GIUINTSTAT_REG); 612 vrgiu_regwrite_4(sc, GIUINTSTAT_REG, reg & ~(1 << ihe->ih_port)); 613 } 614 615 static void 616 vrgiu_register_iochip(hpcio_chip_t hc, hpcio_chip_t iochip) 617 { 618 struct vrgiu_softc *sc = hc->hc_sc; 619 620 vrip_gpio_register(sc->sc_vc, iochip); 621 } 622 623 /* interrupt handler */ 624 int 625 vrgiu_intr(void *arg) 626 { 627 #ifdef DUMP_GIU_LEVEL2_INTR 628 #warning DUMP_GIU_LEVEL2_INTR 629 static u_int32_t oreg; 630 #endif 631 struct vrgiu_softc *sc = arg; 632 int i; 633 u_int32_t reg; 634 int ledvalue = CONFIG_HOOK_LED_FLASH; 635 636 /* Get Level 2 interrupt status */ 637 vrip_intr_get_status2 (sc->sc_vc, sc->sc_ih, ®); 638 #ifdef DUMP_GIU_LEVEL2_INTR 639 #warning DUMP_GIU_LEVEL2_INTR 640 { 641 u_int32_t uedge, dedge, j; 642 for (j = 0x80000000; j > 0; j >>=1) 643 printf ("%c" , reg&j ? '|' : '.'); 644 uedge = (reg ^ oreg) & reg; 645 dedge = (reg ^ oreg) & ~reg; 646 if (uedge || dedge) { 647 for (j = 0; j < 32; j++) { 648 if (uedge & (1 << j)) 649 printf ("+%d", j); 650 else if (dedge & (1 << j)) 651 printf ("-%d", j); 652 } 653 } 654 oreg = reg; 655 printf ("\n"); 656 } 657 #endif 658 /* Clear interrupt */ 659 vrgiu_regwrite_4(sc, GIUINTSTAT_REG, vrgiu_regread_4(sc, GIUINTSTAT_REG)); 660 661 /* Dispatch handler */ 662 for (i = 0; i < MAX_GPIO_INOUT; i++) { 663 if (reg & (1 << i)) { 664 register struct vrgiu_intr_entry *ih; 665 TAILQ_FOREACH(ih, &sc->sc_intr_head[i], ih_link) { 666 ih->ih_fun(ih->ih_arg); 667 } 668 } 669 } 670 671 if (vrgiu_intr_led) 672 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_LED, 673 (void *)&ledvalue); 674 return (0); 675 } 676