vr.c revision 1.35 1 /* $NetBSD: vr.c,v 1.35 2002/01/04 14:11:52 takemura Exp $ */
2
3 /*-
4 * Copyright (c) 1999-2002
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
37 #include "opt_vr41xx.h"
38 #include "opt_tx39xx.h"
39 #include "opt_kgdb.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/reboot.h>
44
45 #include <uvm/uvm_extern.h>
46
47 #include <machine/sysconf.h>
48 #include <machine/bootinfo.h>
49 #include <machine/bus.h>
50 #include <machine/bus_space_hpcmips.h>
51 #include <machine/platid.h>
52 #include <machine/platid_mask.h>
53
54 #include <dev/hpc/hpckbdvar.h>
55
56 #include <hpcmips/hpcmips/machdep.h> /* cpu_name, mem_cluster */
57
58 #include <hpcmips/vr/vr.h>
59 #include <hpcmips/vr/vr_asm.h>
60 #include <hpcmips/vr/vrcpudef.h>
61 #include <hpcmips/vr/vripreg.h>
62 #include <hpcmips/vr/rtcreg.h>
63
64 #include "vrip.h"
65 #if NVRIP > 0
66 #include <hpcmips/vr/vripvar.h>
67 #endif
68
69 #include "vrbcu.h"
70 #if NVRBCU > 0
71 #include <hpcmips/vr/bcuvar.h>
72 #endif
73
74 #include "vrdsu.h"
75 #if NVRDSU > 0
76 #include <hpcmips/vr/vrdsuvar.h>
77 #endif
78
79 #include "com.h"
80 #include "com_vrip.h"
81 #include "com_hpcio.h"
82 #if NCOM > 0
83 #include <sys/termios.h>
84 #include <sys/ttydefaults.h>
85 #include <dev/ic/comreg.h>
86 #include <dev/ic/comvar.h>
87 #if NCOM_VRIP > 0
88 #include <hpcmips/vr/siureg.h>
89 #include <hpcmips/vr/com_vripvar.h>
90 #endif
91 #if NCOM_HPCIO > 0
92 #include <hpcmips/dev/com_hpciovar.h>
93 #endif
94 #ifndef CONSPEED
95 #define CONSPEED TTYDEF_SPEED
96 #endif
97 #endif
98
99 #include "hpcfb.h"
100 #include "vrkiu.h"
101 #if (NVRKIU > 0) || (NHPCFB > 0)
102 #include <dev/wscons/wsdisplayvar.h>
103 #include <dev/rasops/rasops.h>
104 #endif
105
106 #if NHPCFB > 0
107 #include <dev/hpc/hpcfbvar.h>
108 #endif
109
110 #if NVRKIU > 0
111 #include <arch/hpcmips/vr/vrkiureg.h>
112 #include <arch/hpcmips/vr/vrkiuvar.h>
113 #endif
114
115 #ifdef DEBUG
116 #define STATIC
117 #else
118 #define STATIC static
119 #endif
120
121 /*
122 * This is a mask of bits to clear in the SR when we go to a
123 * given interrupt priority level.
124 */
125 const u_int32_t __ipl_sr_bits_vr[_IPL_N] = {
126 0, /* IPL_NONE */
127
128 MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
129
130 MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */
131
132 MIPS_SOFT_INT_MASK_0|
133 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */
134
135 MIPS_SOFT_INT_MASK_0|
136 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */
137
138 MIPS_SOFT_INT_MASK_0|
139 MIPS_SOFT_INT_MASK_1|
140 MIPS_INT_MASK_0, /* IPL_BIO */
141
142 MIPS_SOFT_INT_MASK_0|
143 MIPS_SOFT_INT_MASK_1|
144 MIPS_INT_MASK_0, /* IPL_NET */
145
146 MIPS_SOFT_INT_MASK_0|
147 MIPS_SOFT_INT_MASK_1|
148 MIPS_INT_MASK_0, /* IPL_{TTY,SERIAL} */
149
150 MIPS_SOFT_INT_MASK_0|
151 MIPS_SOFT_INT_MASK_1|
152 MIPS_INT_MASK_0|
153 MIPS_INT_MASK_1, /* IPL_{CLOCK,HIGH} */
154 };
155
156 #if defined(VR41XX) && defined(TX39XX)
157 #define VR_INTR vr_intr
158 #else
159 #define VR_INTR cpu_intr /* locore_mips3 directly call this */
160 #endif
161
162 void vr_init(void);
163 void VR_INTR(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
164 extern void vr_idle(void);
165 STATIC void vr_cons_init(void);
166 STATIC void vr_fb_init(caddr_t *);
167 STATIC void vr_mem_init(paddr_t);
168 STATIC void vr_find_dram(paddr_t, paddr_t);
169 STATIC void vr_reboot(int, char *);
170
171 /*
172 * CPU interrupt dispatch table (HwInt[0:3])
173 */
174 STATIC int vr_null_handler(void *, u_int32_t, u_int32_t);
175 STATIC int (*vr_intr_handler[4])(void *, u_int32_t, u_int32_t) =
176 {
177 vr_null_handler,
178 vr_null_handler,
179 vr_null_handler,
180 vr_null_handler
181 };
182 STATIC void *vr_intr_arg[4];
183
184 #if NCOM > 0
185 /*
186 * machine dependent serial console info
187 */
188 static struct vr_com_platdep {
189 platid_mask_t *platidmask;
190 int (*attach)(bus_space_tag_t, int, int, int, tcflag_t, int);
191 int addr;
192 int freq;
193 } platdep_com_table[] = {
194 #if NCOM_HPCIO > 0
195 {
196 &platid_mask_MACH_NEC_MCR_SIGMARION2,
197 com_hpcio_cndb_attach, /* attach proc */
198 0x0b600000, /* base address */
199 COM_FREQ, /* frequency */
200 },
201 #endif
202 #if NCOM_VRIP > 0
203 {
204 &platid_wild,
205 com_vrip_cndb_attach, /* attach proc */
206 VRIP_SIU_ADDR, /* base address */
207 VRCOM_FREQ, /* frequency */
208 },
209 #else
210 /* dummy */
211 {
212 &platid_wild,
213 NULL, /* attach proc */
214 0, /* base address */
215 0, /* frequency */
216 },
217 #endif
218 };
219 #endif /* NCOM > 0 */
220
221 void
222 vr_init()
223 {
224 /*
225 * Platform Specific Function Hooks
226 */
227 platform.cpu_idle = vr_idle;
228 platform.cpu_intr = VR_INTR;
229 platform.cons_init = vr_cons_init;
230 platform.fb_init = vr_fb_init;
231 platform.mem_init = vr_mem_init;
232 platform.reboot = vr_reboot;
233
234 #if NVRBCU > 0
235 sprintf(cpu_name, "NEC %s rev%d.%d %d.%03dMHz",
236 vrbcu_vrip_getcpuname(),
237 vrbcu_vrip_getcpumajor(),
238 vrbcu_vrip_getcpuminor(),
239 vrbcu_vrip_getcpuclock() / 1000000,
240 (vrbcu_vrip_getcpuclock() % 1000000) / 1000);
241 #else
242 sprintf(cpu_name, "NEC VR41xx");
243 #endif
244 }
245
246 void
247 vr_mem_init(paddr_t kernend)
248 {
249
250 mem_clusters[0].start = 0;
251 mem_clusters[0].size = kernend;
252 mem_cluster_cnt = 1;
253
254 vr_find_dram(kernend, 0x02000000);
255 vr_find_dram(0x02000000, 0x04000000);
256 vr_find_dram(0x04000000, 0x06000000);
257 vr_find_dram(0x06000000, 0x08000000);
258 }
259
260 void
261 vr_find_dram(paddr_t addr, paddr_t end)
262 {
263 int n;
264 caddr_t page;
265 #ifdef NARLY_MEMORY_PROBE
266 int x, i;
267 #endif
268
269 #ifdef VR_FIND_DRAMLIM
270 if (VR_FIND_DRAMLIM < end)
271 end = VR_FIND_DRAMLIM;
272 #endif /* VR_FIND_DRAMLIM */
273 n = mem_cluster_cnt;
274 for (; addr < end; addr += NBPG) {
275
276 page = (void *)MIPS_PHYS_TO_KSEG1(addr);
277 if (badaddr(page, 4))
278 goto bad;
279
280 /* stop memory probing at first memory image */
281 if (bcmp(page, (void *)MIPS_PHYS_TO_KSEG0(0), 128) == 0)
282 return;
283
284 *(volatile int *)(page+0) = 0xa5a5a5a5;
285 *(volatile int *)(page+4) = 0x5a5a5a5a;
286 wbflush();
287 if (*(volatile int *)(page+0) != 0xa5a5a5a5)
288 goto bad;
289
290 *(volatile int *)(page+0) = 0x5a5a5a5a;
291 *(volatile int *)(page+4) = 0xa5a5a5a5;
292 wbflush();
293 if (*(volatile int *)(page+0) != 0x5a5a5a5a)
294 goto bad;
295
296 #ifdef NARLY_MEMORY_PROBE
297 x = random();
298 for (i = 0; i < NBPG; i += 4)
299 *(volatile int *)(page+i) = (x ^ i);
300 wbflush();
301 for (i = 0; i < NBPG; i += 4)
302 if (*(volatile int *)(page+i) != (x ^ i))
303 goto bad;
304
305 x = random();
306 for (i = 0; i < NBPG; i += 4)
307 *(volatile int *)(page+i) = (x ^ i);
308 wbflush();
309 for (i = 0; i < NBPG; i += 4)
310 if (*(volatile int *)(page+i) != (x ^ i))
311 goto bad;
312 #endif /* NARLY_MEMORY_PROBE */
313
314 if (!mem_clusters[n].size)
315 mem_clusters[n].start = addr;
316 mem_clusters[n].size += NBPG;
317 continue;
318
319 bad:
320 if (mem_clusters[n].size)
321 ++n;
322 continue;
323 }
324 if (mem_clusters[n].size)
325 ++n;
326 mem_cluster_cnt = n;
327 }
328
329 void
330 vr_fb_init(caddr_t *kernend)
331 {
332 /* Nothing to do */
333 }
334
335 void
336 vr_cons_init()
337 {
338 #if NCOM > 0 || NHPCFB > 0 || NVRKIU > 0
339 bus_space_tag_t iot = hpcmips_system_bus_space();
340 #endif
341 #if NCOM > 0
342 static struct vr_com_platdep *com_info;
343 #endif
344
345 #if NCOM > 0
346 com_info = platid_search(&platid, platdep_com_table,
347 sizeof(platdep_com_table)/sizeof(*platdep_com_table),
348 sizeof(*platdep_com_table));
349 #ifdef KGDB
350 if (com_info->attach != NULL) {
351 /* if KGDB is defined, always use the serial port for KGDB */
352 if ((*com_info->attach)(iot, com_info->addr, 9600,
353 com_info->freq,
354 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 1)) {
355 printf("%s(%d): can't init kgdb's serial port",
356 __FILE__, __LINE__);
357 }
358 #else /* KGDB */
359 if (com_info->attach != NULL && (bootinfo->bi_cnuse&BI_CNUSE_SERIAL)) {
360 /* Serial console */
361 if ((*com_info->attach)(iot, com_info->addr, CONSPEED,
362 com_info->freq,
363 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 0)) {
364 printf("%s(%d): can't init serial console",
365 __FILE__, __LINE__);
366 } else {
367 return;
368 }
369 }
370 #endif /* KGDB */
371 #endif /* NCOM > 0 */
372
373 #if NHPCFB > 0
374 if (hpcfb_cnattach(NULL)) {
375 printf("%s(%d): can't init fb console", __FILE__, __LINE__);
376 } else {
377 goto find_keyboard;
378 }
379 find_keyboard:
380 #endif /* NHPCFB > 0 */
381
382 #if NVRKIU > 0 && VRIP_KIU_ADDR != VRIP_NO_ADDR
383 if (vrkiu_cnattach(iot, VRIP_KIU_ADDR)) {
384 printf("%s(%d): can't init vrkiu as console",
385 __FILE__, __LINE__);
386 } else {
387 return;
388 }
389 #endif /* NVRKIU > 0 && VRIP_KIU_ADDR != VRIP_NO_ADDR */
390 }
391
392 void
393 vr_reboot(int howto, char *bootstr)
394 {
395 /*
396 * power down
397 */
398 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
399 printf("fake powerdown\n");
400 __asm(__CONCAT(".word ",___STRING(VR_OPCODE_HIBERNATE)));
401 __asm("nop");
402 __asm("nop");
403 __asm("nop");
404 __asm("nop");
405 __asm("nop");
406 __asm(".set reorder");
407 /* not reach */
408 vr_reboot(howto&~RB_HALT, bootstr);
409 }
410 /*
411 * halt
412 */
413 if (howto & RB_HALT) {
414 #if NVRIP > 0
415 _spllower(~MIPS_INT_MASK_0);
416 vrip_intr_suspend();
417 #else
418 splhigh();
419 #endif
420 __asm(".set noreorder");
421 __asm(__CONCAT(".word ",___STRING(VR_OPCODE_SUSPEND)));
422 __asm("nop");
423 __asm("nop");
424 __asm("nop");
425 __asm("nop");
426 __asm("nop");
427 __asm(".set reorder");
428 #if NVRIP > 0
429 vrip_intr_resume();
430 #endif
431 }
432 /*
433 * reset
434 */
435 #if NVRDSU
436 vrdsu_reset();
437 #else
438 printf("%s(%d): There is no DSU.", __FILE__, __LINE__);
439 #endif
440 }
441
442 /*
443 * Handle interrupts.
444 */
445 void
446 VR_INTR(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
447 {
448 uvmexp.intrs++;
449
450 if (ipending & MIPS_INT_MASK_5) {
451 /*
452 * spl* uses MIPS_INT_MASK not MIPS3_INT_MASK. it causes
453 * INT5 interrupt.
454 */
455 mips3_cp0_compare_write(mips3_cp0_count_read());
456 }
457
458 /* for spllowersoftclock */
459 _splset(((status & ~cause) & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
460
461 if (ipending & MIPS_INT_MASK_1) {
462 (*vr_intr_handler[1])(vr_intr_arg[1], pc, status);
463
464 cause &= ~MIPS_INT_MASK_1;
465 _splset(((status & ~cause) & MIPS_HARD_INT_MASK)
466 | MIPS_SR_INT_IE);
467 }
468
469 if (ipending & MIPS_INT_MASK_0) {
470 (*vr_intr_handler[0])(vr_intr_arg[0], pc, status);
471
472 cause &= ~MIPS_INT_MASK_0;
473 }
474 _splset(((status & ~cause) & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
475
476 softintr(ipending);
477 }
478
479 void *
480 vr_intr_establish(int line, int (*ih_fun)(void *, u_int32_t, u_int32_t),
481 void *ih_arg)
482 {
483
484 KDASSERT(vr_intr_handler[line] == vr_null_handler);
485
486 vr_intr_handler[line] = ih_fun;
487 vr_intr_arg[line] = ih_arg;
488
489 return ((void *)line);
490 }
491
492 void
493 vr_intr_disestablish(void *ih)
494 {
495 int line = (int)ih;
496
497 vr_intr_handler[line] = vr_null_handler;
498 vr_intr_arg[line] = NULL;
499 }
500
501 int
502 vr_null_handler(void *arg, u_int32_t pc, u_int32_t status)
503 {
504
505 printf("vr_null_handler\n");
506
507 return (0);
508 }
509
510 /*
511 int x4181 = VR4181;
512 int x4101 = VR4101;
513 int x4102 = VR4102;
514 int x4111 = VR4111;
515 int x4121 = VR4121;
516 int x4122 = VR4122;
517 int xo4181 = ONLY_VR4181;
518 int xo4101 = ONLY_VR4101;
519 int xo4102 = ONLY_VR4102;
520 int xo4111_4121 = ONLY_VR4111_4121;
521 int g4101=VRGROUP_4101;
522 int g4102=VRGROUP_4102;
523 int g4181=VRGROUP_4181;
524 int g4102_4121=VRGROUP_4102_4121;
525 int g4111_4121=VRGROUP_4111_4121;
526 int g4102_4122=VRGROUP_4102_4122;
527 int g4111_4122=VRGROUP_4111_4122;
528 int single_vrip_base=SINGLE_VRIP_BASE;
529 int vrip_base_addr=VRIP_BASE_ADDR;
530 */
531