1/* $NetBSD: vrpmu.c,v 1.21 2022/07/21 10:09:21 andvar 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/cdefs.h> 31__KERNEL_RCSID(0, "$NetBSD: vrpmu.c,v 1.21 2022/07/21 10:09:21 andvar Exp $"); 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/device.h> 36 37#include <machine/bus.h> 38#include <machine/config_hook.h> 39#include <machine/debug.h> 40 41#include <hpcmips/vr/vripif.h> 42#include <hpcmips/vr/vrpmuvar.h> 43#include <hpcmips/vr/vrpmureg.h> 44 45#include "vrbcu.h" 46#if NVRBCU > 0 47#include <hpcmips/vr/bcuvar.h> 48#include <hpcmips/vr/bcureg.h> 49#endif 50 51#ifdef VRPMUDEBUG 52#define DEBUG_BOOT 0x1 /* boot time */ 53#define DEBUG_INTR 0x2 /* intr */ 54#define DEBUG_IO 0x4 /* I/O */ 55#ifndef VRPMUDEBUG_CONF 56#define VRPMUDEBUG_CONF 0 57#endif /* VRPMUDEBUG_CONF */ 58int vrpmudebug = VRPMUDEBUG_CONF; 59#define DPRINTF(flag, arg) if (vrpmudebug&flag) printf arg; 60#define DDUMP_INTR2(flag, arg1, arg2) \ 61 if (vrpmudebug&flag) vrpmu_dump_intr2(arg1,arg2); 62#define DDUMP_REGS(flag, arg) if (vrpmudebug&flag) vrpmu_dump_regs(arg); 63#else /* VRPMUDEBUG */ 64#define DPRINTF(flag, arg) 65#define DDUMP_INTR2(flag, arg1, arg2) 66#define DDUMP_REGS(flag, arg) 67#endif /* VRPMUDEBUG */ 68 69static int vrpmumatch(device_t, cfdata_t, void *); 70static void vrpmuattach(device_t, device_t, void *); 71 72static void vrpmu_write(struct vrpmu_softc *, int, unsigned short); 73static unsigned short vrpmu_read(struct vrpmu_softc *, int); 74 75int vrpmu_intr(void *); 76void vrpmu_dump_intr(void *); 77void vrpmu_dump_intr2(unsigned int, unsigned int); 78void vrpmu_dump_regs(void *); 79 80CFATTACH_DECL_NEW(vrpmu, sizeof(struct vrpmu_softc), 81 vrpmumatch, vrpmuattach, NULL, NULL); 82 83struct vrpmu_softc *this_pmu; 84 85static inline void 86vrpmu_write(struct vrpmu_softc *sc, int port, unsigned short val) 87{ 88 89 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 90} 91 92static inline unsigned short 93vrpmu_read(struct vrpmu_softc *sc, int port) 94{ 95 96 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 97} 98 99static int 100vrpmumatch(device_t parent, cfdata_t cf, void *aux) 101{ 102 103 return (1); 104} 105 106static void 107vrpmuattach(device_t parent, device_t self, void *aux) 108{ 109 struct vrpmu_softc *sc = device_private(self); 110 struct vrip_attach_args *va = aux; 111#if NVRBCU > 0 112 int cpuid; 113#endif /* NVRBCU > 0 */ 114 115 bus_space_tag_t iot = va->va_iot; 116 bus_space_handle_t ioh; 117 118 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 119 printf(": can't map bus space\n"); 120 return; 121 } 122 123 sc->sc_iot = iot; 124 sc->sc_ioh = ioh; 125 126 if (!(sc->sc_handler = 127 vrip_intr_establish(va->va_vc, va->va_unit, 0, IPL_TTY, 128 vrpmu_intr, sc))) { 129 printf (": can't map interrupt line.\n"); 130 return; 131 } 132 if (!vrip_intr_establish(va->va_vc, va->va_unit, 1, IPL_TTY, 133 vrpmu_intr, sc)) { 134 printf (": can't map interrupt line.\n"); 135 return; 136 } 137 138 printf("\n"); 139 /* dump current interrupt states */ 140 vrpmu_dump_intr(sc); 141 DDUMP_REGS(DEBUG_BOOT, sc); 142 /* clear interrupt status */ 143 vrpmu_write(sc, PMUINT_REG_W, PMUINT_ALL); 144 vrpmu_write(sc, PMUINT2_REG_W, PMUINT2_ALL); 145#if NVRBCU > 0 146 cpuid = vrbcu_vrip_getcpuid(); 147 if (cpuid >= BCUREVID_RID_4111){ 148 vrpmu_write(sc, PMUWAIT_REG_W, PMUWAIT_DEFAULT); 149 } 150#endif /* NVRBCU */ 151 152 this_pmu = sc; 153} 154 155/* 156 * dump PMU intr status regs 157 * 158 */ 159void 160vrpmu_dump_intr(void *arg) 161{ 162 struct vrpmu_softc *sc = arg; 163 unsigned int intstat1; 164 unsigned int intstat2; 165 166 intstat1 = vrpmu_read(sc, PMUINT_REG_W); 167 intstat2 = vrpmu_read(sc, PMUINT2_REG_W); 168 vrpmu_dump_intr2(intstat1, intstat2); 169} 170 171/* 172 * dump PMU intr status regs 173 */ 174void 175vrpmu_dump_intr2(unsigned int intstat1, unsigned int intstat2) 176{ 177 if (intstat1 & PMUINT_GPIO3) 178 printf("vrpmu: GPIO[3] activation\n"); 179 if (intstat1 & PMUINT_GPIO2) 180 printf("vrpmu: GPIO[2] activation\n"); 181 if (intstat1 & PMUINT_GPIO1) 182 printf("vrpmu: GPIO[1] activation\n"); 183 if (intstat1 & PMUINT_GPIO0) 184 printf("vrpmu: GPIO[0] activation\n"); 185 186 if (intstat1 & PMUINT_RTC) 187 printf("vrpmu: RTC alarm detected\n"); 188 if (intstat1 & PMUINT_BATT) 189 printf("vrpmu: Battery low during activation\n"); 190 191 if (intstat1 & PMUINT_TIMOUTRST) 192 printf("vrpmu: HAL timer reset\n"); 193 if (intstat1 & PMUINT_RTCRST) 194 printf("vrpmu: RTC reset detected\n"); 195 if (intstat1 & PMUINT_RSTSWRST) 196 printf("vrpmu: RESET switch detected\n"); 197 if (intstat1 & PMUINT_DMSWRST) 198 printf("vrpmu: Deadman's switch detected\n"); 199 if (intstat1 & PMUINT_BATTINTR) 200 printf("vrpmu: Battery low during normal ops\n"); 201 if (intstat1 & PMUINT_POWERSW) 202 printf("vrpmu: POWER switch detected\n"); 203 204 if (intstat2 & PMUINT_GPIO12) 205 printf("vrpmu: GPIO[12] activation\n"); 206 if (intstat2 & PMUINT_GPIO11) 207 printf("vrpmu: GPIO[11] activation\n"); 208 if (intstat2 & PMUINT_GPIO10) 209 printf("vrpmu: GPIO[10] activation\n"); 210 if (intstat2 & PMUINT_GPIO9) 211 printf("vrpmu: GPIO[9] activation\n"); 212} 213 214/* 215 * dump PMU registers 216 * 217 */ 218void 219vrpmu_dump_regs(void *arg) 220{ 221 struct vrpmu_softc *sc = arg; 222 unsigned int reg; 223#if NVRBCU > 0 224 int cpuid; 225#endif 226 reg = vrpmu_read(sc, PMUINT_REG_W); 227 reg = 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 */ 257int 258vrpmu_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