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