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