1 /* $NetBSD: vr.c,v 1.53 2009/03/18 15:14:29 cegger Exp $ */
4 * Copyright (c) 1999-2002
5 * Shin Takemura and PocketBSD Project. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: vr.c,v 1.53 2009/03/18 15:14:29 cegger Exp $");
40 #include "opt_vr41xx.h"
41 #include "opt_tx39xx.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/reboot.h>
47 #include <sys/device.h>
50 #include <uvm/uvm_extern.h>
52 #include <machine/sysconf.h>
53 #include <machine/bootinfo.h>
54 #include <machine/bus_space_hpcmips.h>
55 #include <machine/platid.h>
56 #include <machine/platid_mask.h>
58 #include <dev/hpc/hpckbdvar.h>
60 #include <hpcmips/vr/vr.h>
61 #include <hpcmips/vr/vr_asm.h>
62 #include <hpcmips/vr/vrcpudef.h>
63 #include <hpcmips/vr/vripreg.h>
64 #include <hpcmips/vr/rtcreg.h>
66 #include <mips/cache.h>
68 #include "vrip_common.h"
70 #include <hpcmips/vr/vripvar.h>
75 #include <hpcmips/vr/bcuvar.h>
80 #include <hpcmips/vr/vrdsuvar.h>
85 #include "com_hpcio.h"
87 #include <sys/termios.h>
88 #include <sys/ttydefaults.h>
89 #include <dev/ic/comreg.h>
90 #include <dev/ic/comvar.h>
92 #include <hpcmips/vr/siureg.h>
93 #include <hpcmips/vr/com_vripvar.h>
96 #include <hpcmips/dev/com_hpciovar.h>
99 #define CONSPEED TTYDEF_SPEED
105 #if (NVRKIU > 0) || (NHPCFB > 0)
106 #include <dev/wscons/wsdisplayvar.h>
107 #include <dev/rasops/rasops.h>
111 #include <dev/hpc/hpcfbvar.h>
115 #include <arch/hpcmips/vr/vrkiureg.h>
116 #include <arch/hpcmips/vr/vrkiuvar.h>
122 #define STATIC static
126 * This is a mask of bits to clear in the SR when we go to a
127 * given interrupt priority level.
129 const u_int32_t __ipl_sr_bits_vr
[_IPL_N
] = {
132 MIPS_SOFT_INT_MASK_0
, /* IPL_SOFTCLOCK */
134 MIPS_SOFT_INT_MASK_0
|
135 MIPS_SOFT_INT_MASK_1
, /* IPL_SOFTNET */
137 MIPS_SOFT_INT_MASK_0
|
138 MIPS_SOFT_INT_MASK_1
|
139 MIPS_INT_MASK_0
, /* IPL_VM */
141 MIPS_SOFT_INT_MASK_0
|
142 MIPS_SOFT_INT_MASK_1
|
144 MIPS_INT_MASK_1
, /* IPL_SCHED */
147 #if defined(VR41XX) && defined(TX39XX)
148 #define VR_INTR vr_intr
150 #define VR_INTR cpu_intr /* locore_mips3 directly call this */
154 void VR_INTR(u_int32_t
, u_int32_t
, u_int32_t
, u_int32_t
);
155 extern void vr_idle(void);
156 STATIC
void vr_cons_init(void);
157 STATIC
void vr_fb_init(void **);
158 STATIC
void vr_mem_init(paddr_t
);
159 STATIC
void vr_find_dram(paddr_t
, paddr_t
);
160 STATIC
void vr_reboot(int, char *);
163 * CPU interrupt dispatch table (HwInt[0:3])
165 STATIC
int vr_null_handler(void *, u_int32_t
, u_int32_t
);
166 STATIC
int (*vr_intr_handler
[4])(void *, u_int32_t
, u_int32_t
) =
173 STATIC
void *vr_intr_arg
[4];
177 * machine dependent serial console info
179 static struct vr_com_platdep
{
180 platid_mask_t
*platidmask
;
181 int (*attach
)(bus_space_tag_t
, int, int, int, tcflag_t
, int);
184 } platdep_com_table
[] = {
187 &platid_mask_MACH_NEC_MCR_SIGMARION2
,
188 com_hpcio_cndb_attach
, /* attach proc */
189 0x0b600000, /* base address */
190 COM_FREQ
, /* frequency */
196 &platid_mask_CPU_MIPS_VR_4102
,
197 com_vrip_cndb_attach
, /* attach proc */
198 VR4102_SIU_ADDR
, /* base address */
199 VRCOM_FREQ
, /* frequency */
204 &platid_mask_CPU_MIPS_VR_4111
,
205 com_vrip_cndb_attach
, /* attach proc */
206 VR4102_SIU_ADDR
, /* base address */
207 VRCOM_FREQ
, /* frequency */
212 &platid_mask_CPU_MIPS_VR_4121
,
213 com_vrip_cndb_attach
, /* attach proc */
214 VR4102_SIU_ADDR
, /* base address */
215 VRCOM_FREQ
, /* frequency */
220 &platid_mask_CPU_MIPS_VR_4122
,
221 com_vrip_cndb_attach
, /* attach proc */
222 VR4122_SIU_ADDR
, /* base address */
223 VRCOM_FREQ
, /* frequency */
228 &platid_mask_CPU_MIPS_VR_4122
,
229 com_vrip_cndb_attach
, /* attach proc */
230 VR4122_SIU_ADDR
, /* base address */
231 VRCOM_FREQ
, /* frequency */
234 #ifdef SINGLE_VRIP_BASE
237 com_vrip_cndb_attach
, /* attach proc */
238 VRIP_SIU_ADDR
, /* base address */
239 VRCOM_FREQ
, /* frequency */
241 #endif /* SINGLE_VRIP_BASE */
242 #else /* NCOM_VRIP > 0 */
246 NULL
, /* attach proc */
247 0, /* base address */
250 #endif /* NCOM_VRIP > 0 */
252 #endif /* NCOM > 0 */
256 * machine dependent keyboard info
258 static struct vr_kiu_platdep
{
259 platid_mask_t
*platidmask
;
261 } platdep_kiu_table
[] = {
264 &platid_mask_CPU_MIPS_VR_4102
,
265 VR4102_KIU_ADDR
, /* base address */
270 &platid_mask_CPU_MIPS_VR_4111
,
271 VR4102_KIU_ADDR
, /* base address */
276 &platid_mask_CPU_MIPS_VR_4121
,
277 VR4102_KIU_ADDR
, /* base address */
282 #ifdef SINGLE_VRIP_BASE
283 VRIP_KIU_ADDR
, /* base address */
285 VRIP_NO_ADDR
, /* base address */
286 #endif /* SINGLE_VRIP_BASE */
289 #endif /* NVRKIU > 0 */
295 * Platform Specific Function Hooks
297 platform
.cpu_idle
= vr_idle
;
298 platform
.cpu_intr
= VR_INTR
;
299 platform
.cons_init
= vr_cons_init
;
300 platform
.fb_init
= vr_fb_init
;
301 platform
.mem_init
= vr_mem_init
;
302 platform
.reboot
= vr_reboot
;
305 sprintf(cpu_name
, "NEC %s rev%d.%d %d.%03dMHz",
306 vrbcu_vrip_getcpuname(),
307 vrbcu_vrip_getcpumajor(),
308 vrbcu_vrip_getcpuminor(),
309 vrbcu_vrip_getcpuclock() / 1000000,
310 (vrbcu_vrip_getcpuclock() % 1000000) / 1000);
312 sprintf(cpu_name
, "NEC VR41xx");
317 vr_mem_init(paddr_t kernend
)
320 mem_clusters
[0].start
= 0;
321 mem_clusters
[0].size
= kernend
;
324 vr_find_dram(kernend
, 0x02000000);
325 vr_find_dram(0x02000000, 0x04000000);
326 vr_find_dram(0x04000000, 0x06000000);
327 vr_find_dram(0x06000000, 0x08000000);
331 vr_find_dram(paddr_t addr
, paddr_t end
)
335 #ifdef NARLY_MEMORY_PROBE
339 #ifdef VR_FIND_DRAMLIM
340 if (VR_FIND_DRAMLIM
< end
)
341 end
= VR_FIND_DRAMLIM
;
342 #endif /* VR_FIND_DRAMLIM */
344 for (; addr
< end
; addr
+= PAGE_SIZE
) {
346 page
= (char *)MIPS_PHYS_TO_KSEG1(addr
);
347 if (badaddr(page
, 4))
350 /* stop memory probing at first memory image */
351 if (memcmp(page
, (void *)MIPS_PHYS_TO_KSEG0(0), 128) == 0)
354 *(volatile int *)(page
+0) = 0xa5a5a5a5;
355 *(volatile int *)(page
+4) = 0x5a5a5a5a;
357 if (*(volatile int *)(page
+0) != 0xa5a5a5a5)
360 *(volatile int *)(page
+0) = 0x5a5a5a5a;
361 *(volatile int *)(page
+4) = 0xa5a5a5a5;
363 if (*(volatile int *)(page
+0) != 0x5a5a5a5a)
366 #ifdef NARLY_MEMORY_PROBE
368 for (i
= 0; i
< PAGE_SIZE
; i
+= 4)
369 *(volatile int *)(page
+i
) = (x
^ i
);
371 for (i
= 0; i
< PAGE_SIZE
; i
+= 4)
372 if (*(volatile int *)(page
+i
) != (x
^ i
))
376 for (i
= 0; i
< PAGE_SIZE
; i
+= 4)
377 *(volatile int *)(page
+i
) = (x
^ i
);
379 for (i
= 0; i
< PAGE_SIZE
; i
+= 4)
380 if (*(volatile int *)(page
+i
) != (x
^ i
))
382 #endif /* NARLY_MEMORY_PROBE */
384 if (!mem_clusters
[n
].size
)
385 mem_clusters
[n
].start
= addr
;
386 mem_clusters
[n
].size
+= PAGE_SIZE
;
390 if (mem_clusters
[n
].size
)
394 if (mem_clusters
[n
].size
)
400 vr_fb_init(void **kernend
)
408 #if NCOM > 0 || NHPCFB > 0 || NVRKIU > 0
409 bus_space_tag_t iot
= hpcmips_system_bus_space();
412 static struct vr_com_platdep
*com_info
;
415 static struct vr_kiu_platdep
*kiu_info
;
419 com_info
= platid_search(&platid
, platdep_com_table
,
420 sizeof(platdep_com_table
)/sizeof(*platdep_com_table
),
421 sizeof(*platdep_com_table
));
423 if (com_info
->attach
!= NULL
) {
424 /* if KGDB is defined, always use the serial port for KGDB */
425 if ((*com_info
->attach
)(iot
, com_info
->addr
, 9600,
427 (TTYDEF_CFLAG
& ~(CSIZE
| PARENB
)) | CS8
, 1)) {
428 printf("%s(%d): can't init kgdb's serial port",
433 if (com_info
->attach
!= NULL
&& (bootinfo
->bi_cnuse
&BI_CNUSE_SERIAL
)) {
435 if ((*com_info
->attach
)(iot
, com_info
->addr
, CONSPEED
,
437 (TTYDEF_CFLAG
& ~(CSIZE
| PARENB
)) | CS8
, 0)) {
438 printf("%s(%d): can't init serial console",
445 #endif /* NCOM > 0 */
448 if (hpcfb_cnattach(NULL
)) {
449 printf("%s(%d): can't init fb console", __FILE__
, __LINE__
);
454 #endif /* NHPCFB > 0 */
457 kiu_info
= platid_search(&platid
, platdep_kiu_table
,
458 sizeof(platdep_kiu_table
)/sizeof(*platdep_kiu_table
),
459 sizeof(*platdep_kiu_table
));
460 if (kiu_info
->addr
!= VRIP_NO_ADDR
) {
461 if (vrkiu_cnattach(iot
, kiu_info
->addr
)) {
462 printf("%s(%d): can't init vrkiu as console",
468 #endif /* NVRKIU > 0 */
471 extern char vr_hibernate
[];
472 extern char evr_hibernate
[];
475 vr_reboot(int howto
, char *bootstr
)
480 if ((howto
& RB_POWERDOWN
) == RB_POWERDOWN
) {
481 printf("fake powerdown\n");
483 * copy vr_hibernate() to top of physical memory.
485 memcpy((void *)MIPS_KSEG0_START
, vr_hibernate
,
486 evr_hibernate
- (char *)vr_hibernate
);
488 mips_dcache_wbinv_all();
489 mips_icache_sync_all();
491 * call vr_hibernate() at MIPS_KSEG0_START.
493 ((void (*)(void *,int))MIPS_KSEG0_START
)(
494 (void *)MIPS_KSEG0_START
, ptoa(physmem
));
496 vr_reboot(howto
&~RB_HALT
, bootstr
);
501 if (howto
& RB_HALT
) {
503 _spllower(~MIPS_INT_MASK_0
);
508 __asm(".set noreorder");
509 __asm(".word " ___STRING(VR_OPCODE_SUSPEND
));
515 __asm(".set reorder");
526 printf("%s(%d): There is no DSU.", __FILE__
, __LINE__
);
534 VR_INTR(u_int32_t status
, u_int32_t cause
, u_int32_t pc
, u_int32_t ipending
)
542 /* Deal with unneded compare interrupts occasionally so that we can
543 * keep spllowersoftclock. */
544 if (ipending
& MIPS_INT_MASK_5
) {
545 mips3_cp0_compare_write(0);
548 if (ipending
& MIPS_INT_MASK_1
) {
549 _splset(MIPS_SR_INT_IE
); /* for spllowersoftclock */
550 /* Remove the lower priority pending bits from status so that
551 * spllowersoftclock will not happen if other interrupts are
553 (*vr_intr_handler
[1])(vr_intr_arg
[1], pc
, status
& ~(ipending
554 & (MIPS_INT_MASK_0
|MIPS_SOFT_INT_MASK_0
|MIPS_SOFT_INT_MASK_1
)));
557 if (ipending
& MIPS_INT_MASK_0
) {
558 _splset(MIPS_INT_MASK_1
|MIPS_SR_INT_IE
);
559 (*vr_intr_handler
[0])(vr_intr_arg
[0], pc
, status
);
563 #ifdef __HAVE_FAST_SOFTINTS
564 if (ipending
& MIPS_SOFT_INT_MASK_1
) {
565 _splset(MIPS_INT_MASK_1
|MIPS_INT_MASK_0
|MIPS_SR_INT_IE
);
566 softintr(MIPS_SOFT_INT_MASK_1
);
569 if (ipending
& MIPS_SOFT_INT_MASK_0
) {
570 _splset(MIPS_SOFT_INT_MASK_1
|MIPS_INT_MASK_1
|MIPS_INT_MASK_0
|
572 softintr(MIPS_SOFT_INT_MASK_0
);
578 vr_intr_establish(int line
, int (*ih_fun
)(void *, u_int32_t
, u_int32_t
),
582 KDASSERT(vr_intr_handler
[line
] == vr_null_handler
);
584 vr_intr_handler
[line
] = ih_fun
;
585 vr_intr_arg
[line
] = ih_arg
;
587 return ((void *)line
);
591 vr_intr_disestablish(void *ih
)
595 vr_intr_handler
[line
] = vr_null_handler
;
596 vr_intr_arg
[line
] = NULL
;
600 vr_null_handler(void *arg
, u_int32_t pc
, u_int32_t status
)
603 printf("vr_null_handler\n");
615 int xo4181 = ONLY_VR4181;
616 int xo4101 = ONLY_VR4101;
617 int xo4102 = ONLY_VR4102;
618 int xo4111_4121 = ONLY_VR4111_4121;
619 int g4101=VRGROUP_4101;
620 int g4102=VRGROUP_4102;
621 int g4181=VRGROUP_4181;
622 int g4102_4121=VRGROUP_4102_4121;
623 int g4111_4121=VRGROUP_4111_4121;
624 int g4102_4122=VRGROUP_4102_4122;
625 int g4111_4122=VRGROUP_4111_4122;
626 int single_vrip_base=SINGLE_VRIP_BASE;
627 int vrip_base_addr=VRIP_BASE_ADDR;