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