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