vrpmu.c revision 1.10.2.3 1 /* $NetBSD: vrpmu.c,v 1.10.2.3 2002/10/10 18:33:03 jdolecek 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