vrip.c revision 1.5 1 /* $NetBSD: vrip.c,v 1.5 2000/03/05 05:22:13 takemura Exp $ */
2
3 /*-
4 * Copyright (c) 1999
5 * Shin Takemura and PocketBSD Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the PocketBSD project
18 * and its contributors.
19 * 4. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/reboot.h>
40
41 #include <machine/cpu.h>
42 #include <machine/bus.h>
43 #include <machine/autoconf.h>
44
45 #include <hpcmips/vr/vr.h>
46 #include <hpcmips/vr/vripreg.h>
47 #include <hpcmips/vr/vripvar.h>
48 #include <hpcmips/vr/icureg.h>
49 #include "locators.h"
50
51 #define VRIPDEBUG
52 #ifdef VRIPDEBUG
53 int vrip_debug = 0;
54 #define DPRINTF(arg) if (vrip_debug) printf arg;
55 #else
56 #define DPRINTF(arg)
57 #endif
58
59 int vripmatch __P((struct device*, struct cfdata*, void*));
60 void vripattach __P((struct device*, struct device*, void*));
61 int vrip_print __P((void*, const char*));
62 int vrip_search __P((struct device*, struct cfdata*, void*));
63 int vrip_intr __P((void*, u_int32_t, u_int32_t));
64
65 static void vrip_dump_level2mask __P((vrip_chipset_tag_t, void*));
66
67 struct cfattach vrip_ca = {
68 sizeof(struct vrip_softc), vripmatch, vripattach
69 };
70
71 #define MAX_LEVEL1 32
72
73 struct vrip_softc *the_vrip_sc = NULL;
74
75 static struct intrhand {
76 int (*ih_fun) __P((void *));
77 void *ih_arg;
78 int ih_l1line;
79 int ih_ipl;
80 bus_addr_t ih_lreg;
81 bus_addr_t ih_mlreg;
82 bus_addr_t ih_hreg;
83 bus_addr_t ih_mhreg;
84 } intrhand[MAX_LEVEL1] = {
85 [5] = { 0, 0, 0, 0, ICUPIUINT_REG_W, MPIUINT_REG_W },
86 [6] = { 0, 0, 0, 0, AIUINT_REG_W, MAIUINT_REG_W },
87 [7] = { 0, 0, 0, 0, KIUINT_REG_W, MKIUINT_REG_W },
88 [8] = { 0, 0, 0, 0, GIUINT_L_REG_W, MGIUINT_L_REG_W, GIUINT_H_REG_W, MGIUINT_H_REG_W },
89 [20] = { 0, 0, 0, 0, FIRINT_REG_W, MFIRINT_REG_W },
90 [21] = { 0, 0, 0, 0, DSIUINT_REG_W, MDSIUINT_REG_W }
91 };
92 #define LEGAL_LEVEL1(x) ((x) >= 0 && (x) < MAX_LEVEL1)
93
94 void
95 bitdisp16 (u_int16_t a)
96 {
97 u_int16_t j;
98 for (j = 0x8000; j > 0; j >>=1)
99 printf ("%c", a&j ?'|':'.');
100 printf ("\n");
101 }
102
103 void
104 bitdisp32 (u_int32_t a)
105 {
106 u_int32_t j;
107 for (j = 0x80000000; j > 0; j >>=1)
108 printf ("%c" , a&j ? '|' : '.');
109 printf ("\n");
110 }
111
112 void
113 bitdisp64(u_int32_t a[2])
114 {
115 u_int32_t j;
116 for( j = 0x80000000 ; j > 0 ; j >>=1 )
117 printf("%c" , a[1]&j ?';':',' );
118 for( j = 0x80000000 ; j > 0 ; j >>=1 )
119 printf("%c" , a[0]&j ?'|':'.' );
120 printf("\n");
121 }
122
123 int
124 vripmatch(parent, match, aux)
125 struct device *parent;
126 struct cfdata *match;
127 void *aux;
128 {
129 struct mainbus_attach_args *ma = aux;
130
131 if (strcmp(ma->ma_name, match->cf_driver->cd_name))
132 return 0;
133 return 1;
134 }
135
136 void
137 vripattach(parent, self, aux)
138 struct device *parent;
139 struct device *self;
140 void *aux;
141 {
142 struct mainbus_attach_args *ma = aux;
143 struct vrip_softc *sc = (struct vrip_softc*)self;
144
145 printf("\n");
146 /*
147 * Map ICU (Interrupt Control Unit) register space.
148 */
149 sc->sc_iot = ma->ma_iot;
150 if (bus_space_map(sc->sc_iot, VRIP_ICU_ADDR, 0x20/*XXX lower area only*/,
151 0, /* no flags */
152 &sc->sc_ioh)) {
153 printf("vripattach: can't map ICU register.\n");
154 return;
155 }
156
157 /*
158 * Disable all Level 1 interrupts.
159 */
160 sc->sc_intrmask = 0;
161 bus_space_write_2(sc->sc_iot, sc->sc_ioh, MSYSINT1_REG_W, 0x0000);
162 bus_space_write_2(sc->sc_iot, sc->sc_ioh, MSYSINT2_REG_W, 0x0000);
163 /*
164 * Level 1 interrupts are redirected to HwInt0
165 */
166 vr_intr_establish(VR_INTR0, vrip_intr, self);
167 the_vrip_sc = sc;
168 /*
169 * Attach each devices
170 */
171 /* GIU CMU interface interface is used by other system device. so attach first */
172 sc->sc_pri = 2;
173 config_search(vrip_search, self, vrip_print);
174 /* Other system devices. */
175 sc->sc_pri = 1;
176 config_search(vrip_search, self, vrip_print);
177 }
178
179 int
180 vrip_print(aux, hoge)
181 void *aux;
182 const char *hoge;
183 {
184 struct vrip_attach_args *va = (struct vrip_attach_args*)aux;
185
186 if (va->va_addr)
187 printf(" addr 0x%lx", va->va_addr);
188 if (va->va_size > 1)
189 printf("-0x%lx", va->va_addr + va->va_size - 1);
190 if (va->va_intr != VRIPCF_INTR_DEFAULT)
191 printf(" intr %d", va->va_intr);
192 return (UNCONF);
193 }
194
195 int
196 vrip_search(parent, cf, aux)
197 struct device *parent;
198 struct cfdata *cf;
199 void *aux;
200 {
201 struct vrip_softc *sc = (struct vrip_softc *)parent;
202 struct vrip_attach_args va;
203
204 va.va_vc = sc;
205 va.va_iot = sc->sc_iot;
206 va.va_addr = cf->cf_loc[VRIPCF_ADDR];
207 va.va_size = cf->cf_loc[VRIPCF_SIZE];
208 va.va_intr = cf->cf_loc[VRIPCF_INTR];
209 va.va_addr2 = cf->cf_loc[VRIPCF_ADDR2];
210 va.va_size2 = cf->cf_loc[VRIPCF_SIZE2];
211 va.va_gc = sc->sc_gc;
212 va.va_gf = sc->sc_gf;
213 va.va_cc = sc->sc_cc;
214 va.va_cf = sc->sc_cf;
215 if (((*cf->cf_attach->ca_match)(parent, cf, &va) == sc->sc_pri))
216 config_attach(parent, cf, &va, vrip_print);
217
218 return 0;
219 }
220
221 void *
222 vrip_intr_establish(vc, intr, level, ih_fun, ih_arg)
223 vrip_chipset_tag_t vc;
224 int intr;
225 int level; /* XXX not yet */
226 int (*ih_fun) __P((void *));
227 void *ih_arg;
228 {
229 struct intrhand *ih;
230
231 if (!LEGAL_LEVEL1(intr))
232 return 0;
233 ih = &intrhand[intr];
234 if (ih->ih_fun) /* Can't share level 1 interrupt */
235 return 0;
236 ih->ih_l1line = intr;
237 ih->ih_fun = ih_fun;
238 ih->ih_arg = ih_arg;
239
240 /* Mask level 2 interrupt mask register. (disable interrupt) */
241 vrip_intr_setmask2(vc, ih, ~0, 0);
242 /* Unmask Level 1 interrupt mask register (enable interrupt) */
243 vrip_intr_setmask1(vc, ih, 1);
244
245 return (void *)ih;
246 }
247
248 void
249 vrip_intr_disestablish(vc, arg)
250 vrip_chipset_tag_t vc;
251 void *arg;
252 {
253 struct intrhand *ih = arg;
254 ih->ih_fun = NULL;
255 ih->ih_arg = NULL;
256 /* Mask level 2 interrupt mask register(if any). (disable interrupt) */
257 vrip_intr_setmask2(vc, ih, ~0, 0);
258 /* Mask Level 1 interrupt mask register (disable interrupt) */
259 vrip_intr_setmask1(vc, ih, 0);
260 }
261
262 void
263 vrip_intr_suspend()
264 {
265 bus_space_tag_t iot = the_vrip_sc->sc_iot;
266 bus_space_handle_t ioh = the_vrip_sc->sc_ioh;
267
268 bus_space_write_2 (iot, ioh, MSYSINT1_REG_W, (1<<VRIP_INTR_POWER));
269 bus_space_write_2 (iot, ioh, MSYSINT2_REG_W, 0);
270 }
271
272 void
273 vrip_intr_resume()
274 {
275 u_int32_t reg = the_vrip_sc->sc_intrmask;
276 bus_space_tag_t iot = the_vrip_sc->sc_iot;
277 bus_space_handle_t ioh = the_vrip_sc->sc_ioh;
278
279 bus_space_write_2 (iot, ioh, MSYSINT1_REG_W, reg & 0xffff);
280 bus_space_write_2 (iot, ioh, MSYSINT2_REG_W, (reg >> 16) & 0xffff);
281 }
282
283 /* Set level 1 interrupt mask. */
284 void
285 vrip_intr_setmask1(vc, arg, enable)
286 vrip_chipset_tag_t vc;
287 void *arg;
288 int enable;
289 {
290 struct vrip_softc *sc = (void*)vc;
291 struct intrhand *ih = arg;
292 int level1 = ih->ih_l1line;
293 bus_space_tag_t iot = sc->sc_iot;
294 bus_space_handle_t ioh = sc->sc_ioh;
295 u_int32_t reg = sc->sc_intrmask;
296
297 reg = (bus_space_read_2 (iot, ioh, MSYSINT1_REG_W)&0xffff) |
298 ((bus_space_read_2 (iot, ioh, MSYSINT2_REG_W)<< 16)&0xffff0000);
299 if (enable)
300 reg |= (1 << level1);
301 else {
302 reg &= ~(1 << level1);
303 }
304 sc->sc_intrmask = reg;
305 bus_space_write_2 (iot, ioh, MSYSINT1_REG_W, reg & 0xffff);
306 bus_space_write_2 (iot, ioh, MSYSINT2_REG_W, (reg >> 16) & 0xffff);
307 #ifdef VRIPDEBUG
308 if (vrip_debug)
309 bitdisp32(reg);
310 #endif /* VRIPDEBUG */
311
312 return;
313 }
314
315 static void
316 vrip_dump_level2mask (vc, arg)
317 vrip_chipset_tag_t vc;
318 void *arg;
319 {
320 struct vrip_softc *sc = (void*)vc;
321 struct intrhand *ih = arg;
322 u_int32_t reg;
323
324 if (ih->ih_mlreg) {
325 printf ("level1[%d] level2 mask:", ih->ih_l1line);
326 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ih->ih_mlreg);
327 if (ih->ih_mhreg) { /* GIU [16:31] case only */
328 reg |= (bus_space_read_2(sc->sc_iot, sc->sc_ioh, ih->ih_mhreg) << 16);
329 bitdisp32(reg);
330 } else
331 bitdisp16(reg);
332 }
333 }
334
335 /* Get level 2 interrupt status */
336 void
337 vrip_intr_get_status2(vc, arg, mask)
338 vrip_chipset_tag_t vc;
339 void *arg;
340 u_int32_t *mask; /* Level 2 mask */
341 {
342 struct vrip_softc *sc = (void*)vc;
343 struct intrhand *ih = arg;
344 u_int32_t reg;
345 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
346 ih->ih_lreg);
347 reg |= ((bus_space_read_2(sc->sc_iot, sc->sc_ioh,
348 ih->ih_hreg) << 16)&0xffff0000);
349 /* bitdisp32(reg);*/
350 *mask = reg;
351 }
352
353 /* Set level 2 interrupt mask. */
354 void
355 vrip_intr_setmask2(vc, arg, mask, onoff)
356 vrip_chipset_tag_t vc;
357 void *arg;
358 u_int32_t mask; /* Level 2 mask */
359 {
360 struct vrip_softc *sc = (void*)vc;
361 struct intrhand *ih = arg;
362 u_int16_t reg;
363
364 #ifdef VRIPDEBUG
365 if (vrip_debug) {
366 printf("vrip_intr_setmask2:\n");
367 vrip_dump_level2mask (vc, arg);
368 }
369 #endif /* VRIPDEBUG */
370 #ifdef WINCE_DEFAULT_SETTING
371 #warning WINCE_DEFAULT_SETTING
372 #else
373 if (ih->ih_mlreg) {
374 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ih->ih_mlreg);
375 if (onoff)
376 reg |= (mask&0xffff);
377 else
378 reg &= ~(mask&0xffff);
379 bus_space_write_2(sc->sc_iot, sc->sc_ioh, ih->ih_mlreg, reg);
380 if (ih->ih_mhreg != -1) { /* GIU [16:31] case only */
381 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ih->ih_mhreg);
382 if (onoff)
383 reg |= ((mask >> 16) & 0xffff);
384 else
385 reg &= ~((mask >> 16) & 0xffff);
386 bus_space_write_2(sc->sc_iot, sc->sc_ioh,
387 ih->ih_mhreg, reg);
388 }
389 }
390 #endif /* WINCE_DEFAULT_SETTING */
391 #ifdef VRIPDEBUG
392 if (vrip_debug)
393 vrip_dump_level2mask (vc, arg);
394 #endif /* VRIPDEBUG */
395
396 return;
397 }
398
399 int
400 vrip_intr(arg, pc, statusReg)
401 void *arg;
402 u_int32_t pc;
403 u_int32_t statusReg;
404 {
405 struct vrip_softc *sc = (struct vrip_softc*)arg;
406 bus_space_tag_t iot = sc->sc_iot;
407 bus_space_handle_t ioh = sc->sc_ioh;
408 int i;
409 u_int32_t reg, mask;
410 /*
411 * Read level1 interrupt status.
412 */
413 reg = (bus_space_read_2 (iot, ioh, SYSINT1_REG_W)&0xffff) |
414 ((bus_space_read_2 (iot, ioh, SYSINT2_REG_W)<< 16)&0xffff0000);
415 mask = (bus_space_read_2 (iot, ioh, MSYSINT1_REG_W)&0xffff) |
416 ((bus_space_read_2 (iot, ioh, MSYSINT2_REG_W)<< 16)&0xffff0000);
417 reg &= mask;
418
419 /*
420 * Dispatch each handler.
421 */
422 for (i = 0; i < 32; i++) {
423 register struct intrhand *ih = &intrhand[i];
424 if (ih->ih_fun && (reg & (1 << i))) {
425 ih->ih_fun(ih->ih_arg);
426 }
427 }
428 return 1;
429 }
430
431 void
432 vrip_cmu_function_register(vc, func, arg)
433 vrip_chipset_tag_t vc;
434 vrcmu_function_tag_t func;
435 vrcmu_chipset_tag_t arg;
436 {
437 struct vrip_softc *sc = (void*)vc;
438 sc->sc_cf = func;
439 sc->sc_cc = arg;
440 }
441
442 void
443 vrip_giu_function_register(vc, func, arg)
444 vrip_chipset_tag_t vc;
445 vrgiu_function_tag_t func;
446 vrgiu_chipset_tag_t arg;
447 {
448 struct vrip_softc *sc = (void*)vc;
449 sc->sc_gf = func;
450 sc->sc_gc = arg;
451 }
452
453