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