xref: /netbsd/sys/arch/hpcmips/vr/vrpmu.c (revision bf9ec67e)
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