1 /* $NetBSD: vrip.c,v 1.16 2002/01/29 18:53:22 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2002 5 * Shin Takemura and PocketBSD Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 */ 32 #include "opt_vr41xx.h" 33 #include "opt_tx39xx.h" 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/device.h> 38 #include <sys/reboot.h> 39 40 #include <machine/cpu.h> 41 #include <machine/bus.h> 42 #include <machine/autoconf.h> 43 #include <machine/platid.h> 44 #include <machine/platid_mask.h> 45 46 #include <hpcmips/vr/vr.h> 47 #include <hpcmips/vr/vrcpudef.h> 48 #include <hpcmips/vr/vripunit.h> 49 #include <hpcmips/vr/vripif.h> 50 #include <hpcmips/vr/vripreg.h> 51 #include <hpcmips/vr/vripvar.h> 52 #include <hpcmips/vr/icureg.h> 53 #include <hpcmips/vr/cmureg.h> 54 #include "locators.h" 55 56 #ifdef VRIP_DEBUG 57 #define DPRINTF_ENABLE 58 #define DPRINTF_DEBUG vrip_debug 59 #endif 60 #define USE_HPC_DPRINTF 61 #include <machine/debug.h> 62 63 #ifdef VRIP_DEBUG 64 #define DBG_BIT_PRINT(reg) if (vrip_debug) dbg_bit_print(reg); 65 #define DUMP_LEVEL2MASK(sc,arg) if (vrip_debug) __vrip_dump_level2mask(sc,arg) 66 #else 67 #define DBG_BIT_PRINT(arg) 68 #define DUMP_LEVEL2MASK(sc,arg) 69 #endif 70 71 #define MAX_LEVEL1 32 72 #define VALID_UNIT(sc, unit) (0 <= (unit) && (unit) < (sc)->sc_nunits) 73 74 struct vrip_softc { 75 struct device sc_dv; 76 bus_space_tag_t sc_iot; 77 bus_space_handle_t sc_ioh; 78 hpcio_chip_t sc_gpio_chips[VRIP_NIOCHIPS]; 79 vrcmu_chipset_tag_t sc_cc; 80 int sc_pri; /* attaching device priority */ 81 u_int32_t sc_intrmask; 82 struct vrip_chipset_tag sc_chipset; 83 const struct vrip_unit *sc_units; 84 int sc_nunits; 85 struct intrhand { 86 int (*ih_fun)(void *); 87 void *ih_arg; 88 const struct vrip_unit *ih_unit; 89 } sc_intrhands[MAX_LEVEL1]; 90 }; 91 92 int vripmatch(struct device *, struct cfdata *, void *); 93 void vripattach(struct device *, struct device *, void *); 94 int vrip_print(void *, const char *); 95 int vrip_search(struct device *, struct cfdata *, void *); 96 int vrip_intr(void *, u_int32_t, u_int32_t); 97 98 int __vrip_power(vrip_chipset_tag_t, int, int); 99 vrip_intr_handle_t __vrip_intr_establish(vrip_chipset_tag_t, int, int, 100 int, int(*)(void*), void*); 101 void __vrip_intr_disestablish(vrip_chipset_tag_t, vrip_intr_handle_t); 102 void __vrip_intr_setmask1(vrip_chipset_tag_t, vrip_intr_handle_t, int); 103 void __vrip_intr_setmask2(vrip_chipset_tag_t, vrip_intr_handle_t, 104 u_int32_t, int); 105 void __vrip_intr_getstatus2(vrip_chipset_tag_t, vrip_intr_handle_t, 106 u_int32_t*); 107 void __vrip_register_cmu(vrip_chipset_tag_t, vrcmu_chipset_tag_t); 108 void __vrip_register_gpio(vrip_chipset_tag_t, hpcio_chip_t); 109 void __vrip_dump_level2mask(vrip_chipset_tag_t, void *); 110 111 struct cfattach vrip_ca = { 112 sizeof(struct vrip_softc), vripmatch, vripattach 113 }; 114 115 struct vrip_softc *the_vrip_sc = NULL; 116 117 static const struct vrip_chipset_tag vrip_chipset_methods = { 118 .vc_power = __vrip_power, 119 .vc_intr_establish = __vrip_intr_establish, 120 .vc_intr_disestablish = __vrip_intr_disestablish, 121 .vc_intr_setmask1 = __vrip_intr_setmask1, 122 .vc_intr_setmask2 = __vrip_intr_setmask2, 123 .vc_intr_getstatus2 = __vrip_intr_getstatus2, 124 .vc_register_cmu = __vrip_register_cmu, 125 .vc_register_gpio = __vrip_register_gpio, 126 }; 127 128 static const struct vrip_unit vrip_units[] = { 129 [VRIP_UNIT_PMU] = { "pmu", 130 { VRIP_INTR_POWER, VRIP_INTR_BAT, }, }, 131 [VRIP_UNIT_RTC] = { "rtc", 132 { VRIP_INTR_RTCL1, }, }, 133 [VRIP_UNIT_PIU] = { "piu", 134 { VRIP_INTR_PIU, }, 135 CMUMASK_PIU, 136 ICUPIUINT_REG_W, MPIUINT_REG_W }, 137 [VRIP_UNIT_KIU] = { "kiu", 138 { VRIP_INTR_KIU, }, 139 CMUMASK_KIU, 140 KIUINT_REG_W, MKIUINT_REG_W }, 141 [VRIP_UNIT_SIU] = { "siu", 142 { VRIP_INTR_SIU, }, }, 143 [VRIP_UNIT_GIU] = { "giu", 144 { VRIP_INTR_GIU, }, 145 0, 146 GIUINT_L_REG_W,MGIUINT_L_REG_W, 147 GIUINT_H_REG_W, MGIUINT_H_REG_W }, 148 [VRIP_UNIT_LED] = { "led", 149 { VRIP_INTR_LED, }, }, 150 [VRIP_UNIT_AIU] = { "aiu", 151 { VRIP_INTR_AIU, }, 152 CMUMASK_AIU, 153 AIUINT_REG_W, MAIUINT_REG_W }, 154 [VRIP_UNIT_FIR] = { "fir", 155 { VRIP_INTR_FIR, }, 156 CMUMASK_FIR, 157 FIRINT_REG_W, MFIRINT_REG_W }, 158 [VRIP_UNIT_DSIU]= { "dsiu", 159 { VRIP_INTR_DSIU, }, 160 CMUMASK_DSIU, 161 DSIUINT_REG_W, MDSIUINT_REG_W }, 162 [VRIP_UNIT_PCIU]= { "pciu", 163 { VRIP_INTR_PCI, }, 164 CMUMASK_PCIU, 165 PCIINT_REG_W, MPCIINT_REG_W }, 166 [VRIP_UNIT_SCU] = { "scu", 167 { VRIP_INTR_SCU, }, 168 0, 169 SCUINT_REG_W, MSCUINT_REG_W }, 170 [VRIP_UNIT_CSI] = { "csi", 171 { VRIP_INTR_CSI, }, 172 CMUMASK_CSI, 173 CSIINT_REG_W, MCSIINT_REG_W }, 174 [VRIP_UNIT_BCU] = { "bcu", 175 { VRIP_INTR_BCU, }, 176 0, 177 BCUINT_REG_W, MBCUINT_REG_W } 178 }; 179 180 int 181 vripmatch(struct device *parent, struct cfdata *match, void *aux) 182 { 183 struct mainbus_attach_args *ma = aux; 184 185 #ifdef TX39XX 186 if (!platid_match(&platid, &platid_mask_CPU_MIPS_VR_41XX)) 187 return (0); 188 #endif /* TX39XX */ 189 if (strcmp(ma->ma_name, match->cf_driver->cd_name)) 190 return (0); 191 192 return (1); 193 } 194 195 void 196 vripattach(struct device *parent, struct device *self, void *aux) 197 { 198 struct vrip_softc *sc = (struct vrip_softc*)self; 199 200 printf("\n"); 201 202 sc->sc_units = vrip_units; 203 sc->sc_nunits = sizeof(vrip_units)/sizeof(struct vrip_unit); 204 205 vripattach_common(parent, self, aux); 206 } 207 208 void 209 vripattach_common(struct device *parent, struct device *self, void *aux) 210 { 211 struct mainbus_attach_args *ma = aux; 212 struct vrip_softc *sc = (struct vrip_softc*)self; 213 214 sc->sc_chipset = vrip_chipset_methods; /* structure assignment */ 215 sc->sc_chipset.vc_sc = sc; 216 217 /* 218 * Map ICU (Interrupt Control Unit) register space. 219 */ 220 sc->sc_iot = ma->ma_iot; 221 if (bus_space_map(sc->sc_iot, VRIP_ICU_ADDR, 222 0x20 /*XXX lower area only*/, 223 0, /* no flags */ 224 &sc->sc_ioh)) { 225 printf("vripattach: can't map ICU register.\n"); 226 return; 227 } 228 229 /* 230 * Disable all Level 1 interrupts. 231 */ 232 sc->sc_intrmask = 0; 233 bus_space_write_2(sc->sc_iot, sc->sc_ioh, MSYSINT1_REG_W, 0x0000); 234 bus_space_write_2(sc->sc_iot, sc->sc_ioh, MSYSINT2_REG_W, 0x0000); 235 /* 236 * Level 1 interrupts are redirected to HwInt0 237 */ 238 vr_intr_establish(VR_INTR0, vrip_intr, self); 239 the_vrip_sc = sc; 240 /* 241 * Attach each devices 242 * GIU CMU interface interface is used by other system device. 243 * so attach first 244 */ 245 sc->sc_pri = 2; 246 config_search(vrip_search, self, vrip_print); 247 /* Other system devices. */ 248 sc->sc_pri = 1; 249 config_search(vrip_search, self, vrip_print); 250 } 251 252 int 253 vrip_print(void *aux, const char *hoge) 254 { 255 struct vrip_attach_args *va = (struct vrip_attach_args*)aux; 256 257 if (va->va_addr) 258 printf(" addr 0x%lx", va->va_addr); 259 if (va->va_size > 1) 260 printf("-0x%lx", va->va_addr + va->va_size - 1); 261 262 return (UNCONF); 263 } 264 265 int 266 vrip_search(struct device *parent, struct cfdata *cf, void *aux) 267 { 268 struct vrip_softc *sc = (struct vrip_softc *)parent; 269 struct vrip_attach_args va; 270 271 va.va_vc = &sc->sc_chipset; 272 va.va_iot = sc->sc_iot; 273 va.va_unit = cf->cf_loc[VRIPIFCF_UNIT]; 274 va.va_addr = cf->cf_loc[VRIPIFCF_ADDR]; 275 va.va_size = cf->cf_loc[VRIPIFCF_SIZE]; 276 va.va_addr2 = cf->cf_loc[VRIPIFCF_ADDR2]; 277 va.va_size2 = cf->cf_loc[VRIPIFCF_SIZE2]; 278 va.va_gpio_chips = sc->sc_gpio_chips; 279 if (((*cf->cf_attach->ca_match)(parent, cf, &va) == sc->sc_pri)) 280 config_attach(parent, cf, &va, vrip_print); 281 282 return (0); 283 } 284 285 int 286 __vrip_power(vrip_chipset_tag_t vc, int unit, int onoff) 287 { 288 struct vrip_softc *sc = vc->vc_sc; 289 const struct vrip_unit *vu; 290 291 if (sc->sc_chipset.vc_cc == NULL) 292 return (0); /* You have no clock mask unit yet. */ 293 if (!VALID_UNIT(sc, unit)) 294 return (0); 295 vu = &sc->sc_units[unit]; 296 297 return (*sc->sc_chipset.vc_cc->cc_clock)(sc->sc_chipset.vc_cc, 298 vu->vu_clkmask, onoff); 299 } 300 301 vrip_intr_handle_t 302 __vrip_intr_establish(vrip_chipset_tag_t vc, int unit, int line, int level, 303 int (*ih_fun)(void *), void *ih_arg) 304 { 305 struct vrip_softc *sc = vc->vc_sc; 306 const struct vrip_unit *vu; 307 struct intrhand *ih; 308 309 if (!VALID_UNIT(sc, unit)) 310 return (NULL); 311 vu = &sc->sc_units[unit]; 312 ih = &sc->sc_intrhands[vu->vu_intr[line]]; 313 if (ih->ih_fun) /* Can't share level 1 interrupt */ 314 return (NULL); 315 ih->ih_fun = ih_fun; 316 ih->ih_arg = ih_arg; 317 ih->ih_unit = vu; 318 319 /* Mask level 2 interrupt mask register. (disable interrupt) */ 320 vrip_intr_setmask2(vc, ih, ~0, 0); 321 /* Unmask Level 1 interrupt mask register (enable interrupt) */ 322 vrip_intr_setmask1(vc, ih, 1); 323 324 return ((void *)ih); 325 } 326 327 void 328 __vrip_intr_disestablish(vrip_chipset_tag_t vc, vrip_intr_handle_t handle) 329 { 330 struct intrhand *ih = handle; 331 332 ih->ih_fun = NULL; 333 ih->ih_arg = NULL; 334 /* Mask level 2 interrupt mask register(if any). (disable interrupt) */ 335 vrip_intr_setmask2(vc, ih, ~0, 0); 336 /* Mask Level 1 interrupt mask register (disable interrupt) */ 337 vrip_intr_setmask1(vc, ih, 0); 338 } 339 340 void 341 vrip_intr_suspend() 342 { 343 bus_space_tag_t iot = the_vrip_sc->sc_iot; 344 bus_space_handle_t ioh = the_vrip_sc->sc_ioh; 345 346 bus_space_write_2 (iot, ioh, MSYSINT1_REG_W, (1<<VRIP_INTR_POWER)); 347 bus_space_write_2 (iot, ioh, MSYSINT2_REG_W, 0); 348 } 349 350 void 351 vrip_intr_resume() 352 { 353 u_int32_t reg = the_vrip_sc->sc_intrmask; 354 bus_space_tag_t iot = the_vrip_sc->sc_iot; 355 bus_space_handle_t ioh = the_vrip_sc->sc_ioh; 356 357 bus_space_write_2 (iot, ioh, MSYSINT1_REG_W, reg & 0xffff); 358 bus_space_write_2 (iot, ioh, MSYSINT2_REG_W, (reg >> 16) & 0xffff); 359 } 360 361 /* Set level 1 interrupt mask. */ 362 void 363 __vrip_intr_setmask1(vrip_chipset_tag_t vc, vrip_intr_handle_t handle, 364 int enable) 365 { 366 struct vrip_softc *sc = vc->vc_sc; 367 struct intrhand *ih = handle; 368 int level1 = ih - sc->sc_intrhands; 369 bus_space_tag_t iot = sc->sc_iot; 370 bus_space_handle_t ioh = sc->sc_ioh; 371 u_int32_t reg = sc->sc_intrmask; 372 373 DPRINTF(("__vrip_intr_setmask1: SYSINT: %s %d\n", 374 enable ? "enable" : "disable", level1)); 375 reg = (bus_space_read_2 (iot, ioh, MSYSINT1_REG_W)&0xffff) | 376 ((bus_space_read_2 (iot, ioh, MSYSINT2_REG_W)<< 16)&0xffff0000); 377 if (enable) 378 reg |= (1 << level1); 379 else { 380 reg &= ~(1 << level1); 381 } 382 sc->sc_intrmask = reg; 383 bus_space_write_2 (iot, ioh, MSYSINT1_REG_W, reg & 0xffff); 384 bus_space_write_2 (iot, ioh, MSYSINT2_REG_W, (reg >> 16) & 0xffff); 385 DBG_BIT_PRINT(reg); 386 387 return; 388 } 389 390 void 391 __vrip_dump_level2mask(vrip_chipset_tag_t vc, vrip_intr_handle_t handle) 392 { 393 struct vrip_softc *sc = vc->vc_sc; 394 struct intrhand *ih = handle; 395 const struct vrip_unit *vu = ih->ih_unit; 396 u_int32_t reg; 397 398 if (vu->vu_mlreg) { 399 DPRINTF(("level1[%d] level2 mask:", vu->vu_intr[0])); 400 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, vu->vu_mlreg); 401 if (vu->vu_mhreg) { /* GIU [16:31] case only */ 402 reg |= (bus_space_read_2(sc->sc_iot, sc->sc_ioh, 403 vu->vu_mhreg) << 16); 404 dbg_bit_print(reg); 405 } else 406 dbg_bit_print(reg); 407 } 408 } 409 410 /* Get level 2 interrupt status */ 411 void 412 __vrip_intr_getstatus2(vrip_chipset_tag_t vc, vrip_intr_handle_t handle, 413 u_int32_t *mask /* Level 2 mask */) 414 { 415 struct vrip_softc *sc = vc->vc_sc; 416 struct intrhand *ih = handle; 417 const struct vrip_unit *vu = ih->ih_unit; 418 u_int32_t reg; 419 420 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 421 vu->vu_lreg); 422 reg |= ((bus_space_read_2(sc->sc_iot, sc->sc_ioh, 423 vu->vu_hreg) << 16)&0xffff0000); 424 /* dbg_bit_print(reg);*/ 425 *mask = reg; 426 } 427 428 /* Set level 2 interrupt mask. */ 429 void 430 __vrip_intr_setmask2(vrip_chipset_tag_t vc, vrip_intr_handle_t handle, 431 u_int32_t mask /* Level 2 mask */, int onoff) 432 { 433 struct vrip_softc *sc = vc->vc_sc; 434 struct intrhand *ih = handle; 435 const struct vrip_unit *vu = ih->ih_unit; 436 u_int16_t reg; 437 438 DPRINTF(("vrip_intr_setmask2:\n")); 439 DUMP_LEVEL2MASK(vc, handle); 440 #ifdef WINCE_DEFAULT_SETTING 441 #warning WINCE_DEFAULT_SETTING 442 #else 443 if (vu->vu_mlreg) { 444 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, vu->vu_mlreg); 445 if (onoff) 446 reg |= (mask&0xffff); 447 else 448 reg &= ~(mask&0xffff); 449 bus_space_write_2(sc->sc_iot, sc->sc_ioh, vu->vu_mlreg, reg); 450 if (vu->vu_mhreg != -1) { /* GIU [16:31] case only */ 451 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 452 vu->vu_mhreg); 453 if (onoff) 454 reg |= ((mask >> 16) & 0xffff); 455 else 456 reg &= ~((mask >> 16) & 0xffff); 457 bus_space_write_2(sc->sc_iot, sc->sc_ioh, 458 vu->vu_mhreg, reg); 459 } 460 } 461 #endif /* WINCE_DEFAULT_SETTING */ 462 DUMP_LEVEL2MASK(vc, handle); 463 464 return; 465 } 466 467 int 468 vrip_intr(void *arg, u_int32_t pc, u_int32_t statusReg) 469 { 470 struct vrip_softc *sc = (struct vrip_softc*)arg; 471 bus_space_tag_t iot = sc->sc_iot; 472 bus_space_handle_t ioh = sc->sc_ioh; 473 int i; 474 u_int32_t reg, mask; 475 /* 476 * Read level1 interrupt status. 477 */ 478 reg = (bus_space_read_2 (iot, ioh, SYSINT1_REG_W)&0xffff) | 479 ((bus_space_read_2 (iot, ioh, SYSINT2_REG_W)<< 16)&0xffff0000); 480 mask = (bus_space_read_2 (iot, ioh, MSYSINT1_REG_W)&0xffff) | 481 ((bus_space_read_2 (iot, ioh, MSYSINT2_REG_W)<< 16)&0xffff0000); 482 reg &= mask; 483 484 /* 485 * Dispatch each handler. 486 */ 487 for (i = 0; i < 32; i++) { 488 register struct intrhand *ih = &sc->sc_intrhands[i]; 489 if (ih->ih_fun && (reg & (1 << i))) { 490 ih->ih_fun(ih->ih_arg); 491 } 492 } 493 494 return (1); 495 } 496 497 void 498 __vrip_register_cmu(vrip_chipset_tag_t vc, vrcmu_chipset_tag_t cmu) 499 { 500 struct vrip_softc *sc = vc->vc_sc; 501 502 sc->sc_chipset.vc_cc = cmu; 503 } 504 505 void 506 __vrip_register_gpio(vrip_chipset_tag_t vc, hpcio_chip_t chip) 507 { 508 struct vrip_softc *sc = vc->vc_sc; 509 510 if (chip->hc_chipid < 0 || VRIP_NIOCHIPS <= chip->hc_chipid) 511 panic("%s: '%s' has unknown id, %d", __FUNCTION__, 512 chip->hc_name, chip->hc_chipid); 513 sc->sc_gpio_chips[chip->hc_chipid] = chip; 514 } 515