1 /* $NetBSD: vrpmu.c,v 1.14 2002/01/29 18:53:22 uch Exp $ */ 2 3 /* 4 * Copyright (c) 1999 M. Warner Losh. All rights reserved. 5 * Copyright (c) 2000 SATO Kazumi. All rights reserved. 6 * Copyright (c) 1999,2000 PocketBSD Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/device.h> 33 34 #include <machine/bus.h> 35 #include <machine/config_hook.h> 36 #include <machine/debug.h> 37 38 #include <hpcmips/vr/vripif.h> 39 #include <hpcmips/vr/vrpmuvar.h> 40 #include <hpcmips/vr/vrpmureg.h> 41 42 #include "vrbcu.h" 43 #if NVRBCU > 0 44 #include <hpcmips/vr/bcuvar.h> 45 #include <hpcmips/vr/bcureg.h> 46 #endif 47 48 #ifdef VRPMUDEBUG 49 #define DEBUG_BOOT 0x1 /* boot time */ 50 #define DEBUG_INTR 0x2 /* intr */ 51 #define DEBUG_IO 0x4 /* I/O */ 52 #ifndef VRPMUDEBUG_CONF 53 #define VRPMUDEBUG_CONF 0 54 #endif /* VRPMUDEBUG_CONF */ 55 int vrpmudebug = VRPMUDEBUG_CONF; 56 #define DPRINTF(flag, arg) if (vrpmudebug&flag) printf arg; 57 #define DDUMP_INTR2(flag, arg1, arg2) \ 58 if (vrpmudebug&flag) vrpmu_dump_intr2(arg1,arg2); 59 #define DDUMP_REGS(flag, arg) if (vrpmudebug&flag) vrpmu_dump_regs(arg); 60 #else /* VRPMUDEBUG */ 61 #define DPRINTF(flag, arg) 62 #define DDUMP_INTR2(flag, arg1, arg2) 63 #define DDUMP_REGS(flag, arg) 64 #endif /* VRPMUDEBUG */ 65 66 static int vrpmumatch(struct device *, struct cfdata *, void *); 67 static void vrpmuattach(struct device *, struct device *, void *); 68 69 static void vrpmu_write(struct vrpmu_softc *, int, unsigned short); 70 static unsigned short vrpmu_read(struct vrpmu_softc *, int); 71 72 int vrpmu_intr(void *); 73 void vrpmu_dump_intr(void *); 74 void vrpmu_dump_intr2(unsigned int, unsigned int); 75 void vrpmu_dump_regs(void *); 76 77 struct cfattach vrpmu_ca = { 78 sizeof(struct vrpmu_softc), vrpmumatch, vrpmuattach 79 }; 80 81 struct vrpmu_softc *this_pmu; 82 83 static inline void 84 vrpmu_write(struct vrpmu_softc *sc, int port, unsigned short val) 85 { 86 87 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 88 } 89 90 static inline unsigned short 91 vrpmu_read(struct vrpmu_softc *sc, int port) 92 { 93 94 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 95 } 96 97 static int 98 vrpmumatch(struct device *parent, struct cfdata *cf, void *aux) 99 { 100 101 return (1); 102 } 103 104 static void 105 vrpmuattach(struct device *parent, struct device *self, void *aux) 106 { 107 struct vrpmu_softc *sc = (struct vrpmu_softc *)self; 108 struct vrip_attach_args *va = aux; 109 #if NVRBCU > 0 110 int cpuid; 111 #endif /* NVRBCU > 0 */ 112 113 bus_space_tag_t iot = va->va_iot; 114 bus_space_handle_t ioh; 115 116 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 117 printf(": can't map bus space\n"); 118 return; 119 } 120 121 sc->sc_iot = iot; 122 sc->sc_ioh = ioh; 123 124 if (!(sc->sc_handler = 125 vrip_intr_establish(va->va_vc, va->va_unit, 0, IPL_TTY, 126 vrpmu_intr, sc))) { 127 printf (": can't map interrupt line.\n"); 128 return; 129 } 130 if (!vrip_intr_establish(va->va_vc, va->va_unit, 1, IPL_TTY, 131 vrpmu_intr, sc)) { 132 printf (": can't map interrupt line.\n"); 133 return; 134 } 135 136 printf("\n"); 137 /* dump current intrrupt states */ 138 vrpmu_dump_intr(sc); 139 DDUMP_REGS(DEBUG_BOOT, sc); 140 /* clear interrupt status */ 141 vrpmu_write(sc, PMUINT_REG_W, PMUINT_ALL); 142 vrpmu_write(sc, PMUINT2_REG_W, PMUINT2_ALL); 143 #if NVRBCU > 0 144 cpuid = vrbcu_vrip_getcpuid(); 145 if (cpuid >= BCUREVID_RID_4111){ 146 vrpmu_write(sc, PMUWAIT_REG_W, PMUWAIT_DEFAULT); 147 } 148 #endif /* NVRBCU */ 149 150 this_pmu = sc; 151 } 152 153 /* 154 * dump PMU intr status regs 155 * 156 */ 157 void 158 vrpmu_dump_intr(void *arg) 159 { 160 struct vrpmu_softc *sc = arg; 161 unsigned int intstat1; 162 unsigned int intstat2; 163 164 intstat1 = vrpmu_read(sc, PMUINT_REG_W); 165 intstat2 = vrpmu_read(sc, PMUINT2_REG_W); 166 vrpmu_dump_intr2(intstat1, intstat2); 167 } 168 169 /* 170 * dump PMU intr status regs 171 */ 172 void 173 vrpmu_dump_intr2(unsigned int intstat1, unsigned int intstat2) 174 { 175 if (intstat1 & PMUINT_GPIO3) 176 printf("vrpmu: GPIO[3] activation\n"); 177 if (intstat1 & PMUINT_GPIO2) 178 printf("vrpmu: GPIO[2] activation\n"); 179 if (intstat1 & PMUINT_GPIO1) 180 printf("vrpmu: GPIO[1] activation\n"); 181 if (intstat1 & PMUINT_GPIO0) 182 printf("vrpmu: GPIO[0] activation\n"); 183 184 if (intstat1 & PMUINT_RTC) 185 printf("vrpmu: RTC alarm detected\n"); 186 if (intstat1 & PMUINT_BATT) 187 printf("vrpmu: Battery low during activation\n"); 188 189 if (intstat1 & PMUINT_TIMOUTRST) 190 printf("vrpmu: HAL timer reset\n"); 191 if (intstat1 & PMUINT_RTCRST) 192 printf("vrpmu: RTC reset detected\n"); 193 if (intstat1 & PMUINT_RSTSWRST) 194 printf("vrpmu: RESET switch detected\n"); 195 if (intstat1 & PMUINT_DMSWRST) 196 printf("vrpmu: Deadman's switch detected\n"); 197 if (intstat1 & PMUINT_BATTINTR) 198 printf("vrpmu: Battery low during normal ops\n"); 199 if (intstat1 & PMUINT_POWERSW) 200 printf("vrpmu: POWER switch detected\n"); 201 202 if (intstat2 & PMUINT_GPIO12) 203 printf("vrpmu: GPIO[12] activation\n"); 204 if (intstat2 & PMUINT_GPIO11) 205 printf("vrpmu: GPIO[11] activation\n"); 206 if (intstat2 & PMUINT_GPIO10) 207 printf("vrpmu: GPIO[10] activation\n"); 208 if (intstat2 & PMUINT_GPIO9) 209 printf("vrpmu: GPIO[9] activation\n"); 210 } 211 212 /* 213 * dump PMU registers 214 * 215 */ 216 void 217 vrpmu_dump_regs(void *arg) 218 { 219 struct vrpmu_softc *sc = arg; 220 unsigned int intstat1; 221 unsigned int intstat2; 222 unsigned int reg; 223 #if NVRBCU > 0 224 int cpuid; 225 #endif 226 intstat1 = vrpmu_read(sc, PMUINT_REG_W); 227 intstat2 = vrpmu_read(sc, PMUINT2_REG_W); 228 229 /* others? XXXX */ 230 reg = vrpmu_read(sc, PMUCNT_REG_W); 231 printf("vrpmu: cnt 0x%x: ", reg); 232 dbg_bit_print(reg); 233 reg = vrpmu_read(sc, PMUCNT2_REG_W); 234 printf("vrpmu: cnt2 0x%x: ", reg); 235 dbg_bit_print(reg); 236 #if NVRBCU > 0 237 cpuid = vrbcu_vrip_getcpuid(); 238 if (cpuid >= BCUREVID_RID_4111){ 239 reg = vrpmu_read(sc, PMUWAIT_REG_W); 240 printf("vrpmu: wait 0x%x", reg); 241 } 242 if (cpuid >= BCUREVID_RID_4121){ 243 reg = vrpmu_read(sc, PMUDIV_REG_W); 244 printf(" div 0x%x", reg); 245 } 246 printf("\n"); 247 #endif /* NVRBCU > 0 */ 248 } 249 250 /* 251 * PMU interrupt handler. 252 * XXX 253 * 254 * In the following interrupt routine we should actually DO something 255 * with the knowledge that we've gained. For now we just report it. 256 */ 257 int 258 vrpmu_intr(void *arg) 259 { 260 struct vrpmu_softc *sc = arg; 261 unsigned int intstat1; 262 unsigned int intstat2; 263 264 intstat1 = vrpmu_read(sc, PMUINT_REG_W); 265 /* clear interrupt status */ 266 vrpmu_write(sc, PMUINT_REG_W, intstat1); 267 268 269 intstat2 = vrpmu_read(sc, PMUINT2_REG_W); 270 /* clear interrupt status */ 271 vrpmu_write(sc, PMUINT2_REG_W, intstat2); 272 273 DDUMP_INTR2(DEBUG_INTR, intstat1, intstat2); 274 275 if (intstat1 & PMUINT_GPIO3) 276 ; 277 if (intstat1 & PMUINT_GPIO2) 278 ; 279 if (intstat1 & PMUINT_GPIO1) 280 ; 281 if (intstat1 & PMUINT_GPIO0) 282 ; 283 284 if (intstat1 & PMUINT_RTC) 285 ; 286 if (intstat1 & PMUINT_BATT) 287 config_hook_call(CONFIG_HOOK_PMEVENT, 288 CONFIG_HOOK_PMEVENT_SUSPENDREQ, NULL); 289 if (intstat1 & PMUINT_TIMOUTRST) 290 ; 291 if (intstat1 & PMUINT_RTCRST) 292 ; 293 if (intstat1 & PMUINT_RSTSWRST) 294 ; 295 if (intstat1 & PMUINT_DMSWRST) 296 ; 297 if (intstat1 & PMUINT_BATTINTR) 298 config_hook_call(CONFIG_HOOK_PMEVENT, 299 CONFIG_HOOK_PMEVENT_SUSPENDREQ, NULL); 300 if (intstat1 & PMUINT_POWERSW) { 301 /* 302 * you can't detect when the button is released 303 */ 304 config_hook_call(CONFIG_HOOK_BUTTONEVENT, 305 CONFIG_HOOK_BUTTONEVENT_POWER, 306 (void*)1 /* on */); 307 config_hook_call(CONFIG_HOOK_BUTTONEVENT, 308 CONFIG_HOOK_BUTTONEVENT_POWER, 309 (void*)0 /* off */); 310 } 311 312 if (intstat2 & PMUINT_GPIO12) 313 ; 314 if (intstat2 & PMUINT_GPIO11) 315 ; 316 if (intstat2 & PMUINT_GPIO10) 317 ; 318 if (intstat2 & PMUINT_GPIO9) 319 ; 320 321 return (0); 322 } 323