1 /* $NetBSD: vrpmu.c,v 1.16 2002/10/02 05:26:57 thorpej 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 CFATTACH_DECL(vrpmu, sizeof(struct vrpmu_softc), 78 vrpmumatch, vrpmuattach, NULL, NULL); 79 80 struct vrpmu_softc *this_pmu; 81 82 static inline void 83 vrpmu_write(struct vrpmu_softc *sc, int port, unsigned short val) 84 { 85 86 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 87 } 88 89 static inline unsigned short 90 vrpmu_read(struct vrpmu_softc *sc, int port) 91 { 92 93 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 94 } 95 96 static int 97 vrpmumatch(struct device *parent, struct cfdata *cf, void *aux) 98 { 99 100 return (1); 101 } 102 103 static void 104 vrpmuattach(struct device *parent, struct device *self, void *aux) 105 { 106 struct vrpmu_softc *sc = (struct vrpmu_softc *)self; 107 struct vrip_attach_args *va = aux; 108 #if NVRBCU > 0 109 int cpuid; 110 #endif /* NVRBCU > 0 */ 111 112 bus_space_tag_t iot = va->va_iot; 113 bus_space_handle_t ioh; 114 115 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 116 printf(": can't map bus space\n"); 117 return; 118 } 119 120 sc->sc_iot = iot; 121 sc->sc_ioh = ioh; 122 123 if (!(sc->sc_handler = 124 vrip_intr_establish(va->va_vc, va->va_unit, 0, IPL_TTY, 125 vrpmu_intr, sc))) { 126 printf (": can't map interrupt line.\n"); 127 return; 128 } 129 if (!vrip_intr_establish(va->va_vc, va->va_unit, 1, IPL_TTY, 130 vrpmu_intr, sc)) { 131 printf (": can't map interrupt line.\n"); 132 return; 133 } 134 135 printf("\n"); 136 /* dump current intrrupt states */ 137 vrpmu_dump_intr(sc); 138 DDUMP_REGS(DEBUG_BOOT, sc); 139 /* clear interrupt status */ 140 vrpmu_write(sc, PMUINT_REG_W, PMUINT_ALL); 141 vrpmu_write(sc, PMUINT2_REG_W, PMUINT2_ALL); 142 #if NVRBCU > 0 143 cpuid = vrbcu_vrip_getcpuid(); 144 if (cpuid >= BCUREVID_RID_4111){ 145 vrpmu_write(sc, PMUWAIT_REG_W, PMUWAIT_DEFAULT); 146 } 147 #endif /* NVRBCU */ 148 149 this_pmu = sc; 150 } 151 152 /* 153 * dump PMU intr status regs 154 * 155 */ 156 void 157 vrpmu_dump_intr(void *arg) 158 { 159 struct vrpmu_softc *sc = arg; 160 unsigned int intstat1; 161 unsigned int intstat2; 162 163 intstat1 = vrpmu_read(sc, PMUINT_REG_W); 164 intstat2 = vrpmu_read(sc, PMUINT2_REG_W); 165 vrpmu_dump_intr2(intstat1, intstat2); 166 } 167 168 /* 169 * dump PMU intr status regs 170 */ 171 void 172 vrpmu_dump_intr2(unsigned int intstat1, unsigned int intstat2) 173 { 174 if (intstat1 & PMUINT_GPIO3) 175 printf("vrpmu: GPIO[3] activation\n"); 176 if (intstat1 & PMUINT_GPIO2) 177 printf("vrpmu: GPIO[2] activation\n"); 178 if (intstat1 & PMUINT_GPIO1) 179 printf("vrpmu: GPIO[1] activation\n"); 180 if (intstat1 & PMUINT_GPIO0) 181 printf("vrpmu: GPIO[0] activation\n"); 182 183 if (intstat1 & PMUINT_RTC) 184 printf("vrpmu: RTC alarm detected\n"); 185 if (intstat1 & PMUINT_BATT) 186 printf("vrpmu: Battery low during activation\n"); 187 188 if (intstat1 & PMUINT_TIMOUTRST) 189 printf("vrpmu: HAL timer reset\n"); 190 if (intstat1 & PMUINT_RTCRST) 191 printf("vrpmu: RTC reset detected\n"); 192 if (intstat1 & PMUINT_RSTSWRST) 193 printf("vrpmu: RESET switch detected\n"); 194 if (intstat1 & PMUINT_DMSWRST) 195 printf("vrpmu: Deadman's switch detected\n"); 196 if (intstat1 & PMUINT_BATTINTR) 197 printf("vrpmu: Battery low during normal ops\n"); 198 if (intstat1 & PMUINT_POWERSW) 199 printf("vrpmu: POWER switch detected\n"); 200 201 if (intstat2 & PMUINT_GPIO12) 202 printf("vrpmu: GPIO[12] activation\n"); 203 if (intstat2 & PMUINT_GPIO11) 204 printf("vrpmu: GPIO[11] activation\n"); 205 if (intstat2 & PMUINT_GPIO10) 206 printf("vrpmu: GPIO[10] activation\n"); 207 if (intstat2 & PMUINT_GPIO9) 208 printf("vrpmu: GPIO[9] activation\n"); 209 } 210 211 /* 212 * dump PMU registers 213 * 214 */ 215 void 216 vrpmu_dump_regs(void *arg) 217 { 218 struct vrpmu_softc *sc = arg; 219 unsigned int intstat1; 220 unsigned int intstat2; 221 unsigned int reg; 222 #if NVRBCU > 0 223 int cpuid; 224 #endif 225 intstat1 = vrpmu_read(sc, PMUINT_REG_W); 226 intstat2 = vrpmu_read(sc, PMUINT2_REG_W); 227 228 /* others? XXXX */ 229 reg = vrpmu_read(sc, PMUCNT_REG_W); 230 printf("vrpmu: cnt 0x%x: ", reg); 231 dbg_bit_print(reg); 232 reg = vrpmu_read(sc, PMUCNT2_REG_W); 233 printf("vrpmu: cnt2 0x%x: ", reg); 234 dbg_bit_print(reg); 235 #if NVRBCU > 0 236 cpuid = vrbcu_vrip_getcpuid(); 237 if (cpuid >= BCUREVID_RID_4111){ 238 reg = vrpmu_read(sc, PMUWAIT_REG_W); 239 printf("vrpmu: wait 0x%x", reg); 240 } 241 if (cpuid >= BCUREVID_RID_4121){ 242 reg = vrpmu_read(sc, PMUDIV_REG_W); 243 printf(" div 0x%x", reg); 244 } 245 printf("\n"); 246 #endif /* NVRBCU > 0 */ 247 } 248 249 /* 250 * PMU interrupt handler. 251 * XXX 252 * 253 * In the following interrupt routine we should actually DO something 254 * with the knowledge that we've gained. For now we just report it. 255 */ 256 int 257 vrpmu_intr(void *arg) 258 { 259 struct vrpmu_softc *sc = arg; 260 unsigned int intstat1; 261 unsigned int intstat2; 262 263 intstat1 = vrpmu_read(sc, PMUINT_REG_W); 264 /* clear interrupt status */ 265 vrpmu_write(sc, PMUINT_REG_W, intstat1); 266 267 268 intstat2 = vrpmu_read(sc, PMUINT2_REG_W); 269 /* clear interrupt status */ 270 vrpmu_write(sc, PMUINT2_REG_W, intstat2); 271 272 DDUMP_INTR2(DEBUG_INTR, intstat1, intstat2); 273 274 if (intstat1 & PMUINT_GPIO3) 275 ; 276 if (intstat1 & PMUINT_GPIO2) 277 ; 278 if (intstat1 & PMUINT_GPIO1) 279 ; 280 if (intstat1 & PMUINT_GPIO0) 281 ; 282 283 if (intstat1 & PMUINT_RTC) 284 ; 285 if (intstat1 & PMUINT_BATT) 286 config_hook_call(CONFIG_HOOK_PMEVENT, 287 CONFIG_HOOK_PMEVENT_SUSPENDREQ, NULL); 288 if (intstat1 & PMUINT_TIMOUTRST) 289 ; 290 if (intstat1 & PMUINT_RTCRST) 291 ; 292 if (intstat1 & PMUINT_RSTSWRST) 293 ; 294 if (intstat1 & PMUINT_DMSWRST) 295 ; 296 if (intstat1 & PMUINT_BATTINTR) 297 config_hook_call(CONFIG_HOOK_PMEVENT, 298 CONFIG_HOOK_PMEVENT_SUSPENDREQ, NULL); 299 if (intstat1 & PMUINT_POWERSW) { 300 /* 301 * you can't detect when the button is released 302 */ 303 config_hook_call(CONFIG_HOOK_BUTTONEVENT, 304 CONFIG_HOOK_BUTTONEVENT_POWER, 305 (void*)1 /* on */); 306 config_hook_call(CONFIG_HOOK_BUTTONEVENT, 307 CONFIG_HOOK_BUTTONEVENT_POWER, 308 (void*)0 /* off */); 309 } 310 311 if (intstat2 & PMUINT_GPIO12) 312 ; 313 if (intstat2 & PMUINT_GPIO11) 314 ; 315 if (intstat2 & PMUINT_GPIO10) 316 ; 317 if (intstat2 & PMUINT_GPIO9) 318 ; 319 320 return (0); 321 } 322