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