Home | History | Annotate | Line # | Download | only in vr
vr.c revision 1.13
      1 /*	$NetBSD: vr.c,v 1.13 2000/02/21 13:46:05 shin 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/types.h>
     38 #include <sys/systm.h>
     39 #include <sys/device.h>
     40 #include <sys/reboot.h>
     41 #include <sys/kcore.h>
     42 
     43 #include <machine/cpu.h>
     44 #include <machine/intr.h>
     45 #include <machine/reg.h>
     46 #include <machine/psl.h>
     47 #include <machine/locore.h>
     48 #include <machine/sysconf.h>
     49 #include <machine/bus.h>
     50 #include <machine/autoconf.h>
     51 
     52 #include <mips/mips_param.h>		/* hokey spl()s */
     53 #include <mips/mips/mips_mcclock.h>	/* mcclock CPUspeed estimation */
     54 
     55 #include <hpcmips/vr/vr.h>
     56 #include <hpcmips/vr/vr_asm.h>
     57 #include <hpcmips/vr/vripreg.h>
     58 #include <hpcmips/vr/rtcreg.h>
     59 #include <hpcmips/hpcmips/machdep.h>	/* cpu_name */
     60 #include <machine/bootinfo.h>
     61 
     62 #include "vrip.h"
     63 #if NVRIP > 0
     64 #include <hpcmips/vr/vripvar.h>
     65 #endif
     66 
     67 #include "vrbcu.h"
     68 #if NVRBCU > 0
     69 #include <hpcmips/vr/bcuvar.h>
     70 #endif
     71 
     72 #include "vrdsu.h"
     73 #if NVRDSU > 0
     74 #include <hpcmips/vr/vrdsuvar.h>
     75 #endif
     76 
     77 #include "com.h"
     78 #if NCOM > 0
     79 #include <sys/termios.h>
     80 #include <sys/ttydefaults.h>
     81 #include <dev/ic/comreg.h>
     82 #include <dev/ic/comvar.h>
     83 #include <hpcmips/vr/siureg.h>
     84 #include <hpcmips/vr/com_vripvar.h>
     85 #ifndef CONSPEED
     86 #define CONSPEED TTYDEF_SPEED
     87 #endif
     88 #endif
     89 
     90 #include "fb.h"
     91 #include "vrkiu.h"
     92 #if NFB > 0 || NVRKIU > 0
     93 #include <dev/rcons/raster.h>
     94 #include <dev/wscons/wsdisplayvar.h>
     95 #endif
     96 
     97 #if NFB > 0
     98 #include <arch/hpcmips/dev/fbvar.h>
     99 #endif
    100 
    101 #if NFB > 0
    102 #include <arch/hpcmips/vr/vrkiuvar.h>
    103 #endif
    104 
    105 void	vr_init __P((void));
    106 void	vr_os_init __P((void));
    107 void	vr_bus_reset __P((void));
    108 int	vr_intr __P((u_int32_t mask, u_int32_t pc, u_int32_t statusReg, u_int32_t causeReg));
    109 void	vr_cons_init __P((void));
    110 void	vr_device_register __P((struct device *, void *));
    111 void    vr_fb_init __P((caddr_t*));
    112 void    vr_mem_init __P((paddr_t));
    113 void	vr_find_dram __P((paddr_t, paddr_t));
    114 void	vr_reboot __P((int howto, char *bootstr));
    115 
    116 extern unsigned nullclkread __P((void));
    117 extern unsigned (*clkread) __P((void));
    118 
    119 /*
    120  * CPU interrupt dispatch table (HwInt[0:3])
    121  */
    122 int null_handler __P((void*, u_int32_t, u_int32_t));
    123 static int (*intr_handler[4]) __P((void*, u_int32_t, u_int32_t)) =
    124 {
    125 	null_handler,
    126 	null_handler,
    127 	null_handler,
    128 	null_handler
    129 };
    130 static void *intr_arg[4];
    131 
    132 extern phys_ram_seg_t mem_clusters[];
    133 extern int mem_cluster_cnt;
    134 
    135 void
    136 vr_init()
    137 {
    138 	/*
    139 	 * Platform Information.
    140 	 */
    141 
    142 	/*
    143 	 * Platform Specific Function Hooks
    144 	 */
    145 	platform.os_init = vr_os_init;
    146 	platform.bus_reset = vr_bus_reset;
    147 	platform.cons_init = vr_cons_init;
    148 	platform.device_register = vr_device_register;
    149 	platform.fb_init = vr_fb_init;
    150 	platform.mem_init = vr_mem_init;
    151 	platform.reboot = vr_reboot;
    152 
    153 #if NVRBCU > 0
    154 	sprintf(cpu_name, "NEC %s rev%d.%d %d.%03dMHz",
    155 		vrbcu_vrip_getcpuname(),
    156 		vrbcu_vrip_getcpumajor(),
    157 		vrbcu_vrip_getcpuminor(),
    158 		vrbcu_vrip_getcpuclock() / 1000000,
    159 		(vrbcu_vrip_getcpuclock() % 1000000) / 1000);
    160 #else
    161 	sprintf(cpu_name, "NEC VR41xx");
    162 #endif
    163 }
    164 
    165 void
    166 vr_mem_init(kernend)
    167 	paddr_t kernend;
    168 {
    169 	mem_clusters[0].start = 0;
    170 	mem_clusters[0].size = kernend;
    171 	mem_cluster_cnt = 1;
    172 	vr_find_dram(kernend, 0x02000000);
    173 	vr_find_dram(0x02000000, 0x04000000);
    174 	vr_find_dram(0x04000000, 0x06000000);
    175 	vr_find_dram(0x06000000, 0x08000000);
    176 
    177 	/* Clear currently unused D-RAM area (For reboot Windows CE clearly)*/
    178 	memset((void *)(KERNBASE + 0x400), 0, KERNTEXTOFF - (KERNBASE + 0x800));
    179 }
    180 
    181 void
    182 vr_find_dram(addr, end)
    183 	paddr_t addr, end;
    184 {
    185 	int n;
    186 	caddr_t page;
    187 #ifdef NARLY_MEMORY_PROBE
    188 	int x, i;
    189 #endif
    190 
    191 	n = mem_cluster_cnt;
    192 	for (; addr < end; addr += NBPG) {
    193 
    194 		page = (void *)MIPS_PHYS_TO_KSEG1(addr);
    195 		if (badaddr(page, 4))
    196 			goto bad;
    197 
    198 		*(volatile int *)(page+0) = 0xa5a5a5a5;
    199 		*(volatile int *)(page+4) = 0x5a5a5a5a;
    200 		wbflush();
    201 		if (*(volatile int *)(page+0) != 0xa5a5a5a5)
    202 			goto bad;
    203 
    204 		*(volatile int *)(page+0) = 0x5a5a5a5a;
    205 		*(volatile int *)(page+4) = 0xa5a5a5a5;
    206 		wbflush();
    207 		if (*(volatile int *)(page+0) != 0x5a5a5a5a)
    208 			goto bad;
    209 
    210 #ifdef NARLY_MEMORY_PROBE
    211 		x = random();
    212 		for (i = 0; i < NBPG; i += 4)
    213 			*(volatile int *)(page+i) = (x ^ i);
    214 		wbflush();
    215 		for (i = 0; i < NBPG; i += 4)
    216 			if (*(volatile int *)(page+i) != (x ^ i))
    217 				goto bad;
    218 
    219 		x = random();
    220 		for (i = 0; i < NBPG; i += 4)
    221 			*(volatile int *)(page+i) = (x ^ i);
    222 		wbflush();
    223 		for (i = 0; i < NBPG; i += 4)
    224 			if (*(volatile int *)(page+i) != (x ^ i))
    225 				goto bad;
    226 #endif
    227 
    228 		if (!mem_clusters[n].size)
    229 			mem_clusters[n].start = addr;
    230 		mem_clusters[n].size += NBPG;
    231 		continue;
    232 
    233 	bad:
    234 		if (mem_clusters[n].size)
    235 			++n;
    236 		continue;
    237 	}
    238 	if (mem_clusters[n].size)
    239 		++n;
    240 	mem_cluster_cnt = n;
    241 }
    242 
    243 void
    244 vr_fb_init(kernend)
    245 	caddr_t *kernend;
    246 {
    247 	/* Nothing to do */
    248 }
    249 
    250 void
    251 vr_os_init()
    252 {
    253 	/*
    254 	 * Set up interrupt handling and I/O addresses.
    255 	 */
    256 	mips_hardware_intr = vr_intr;
    257 
    258 	splvec.splbio = MIPS_SPL0;
    259 	splvec.splnet = MIPS_SPL0;
    260 	splvec.spltty = MIPS_SPL0;
    261 	splvec.splimp = MIPS_SPL0;
    262 	splvec.splclock = MIPS_SPL_0_1;
    263 	splvec.splstatclock = MIPS_SPL_0_1;
    264 
    265 	/* no high resolution timer circuit; possibly never called */
    266 	clkread = nullclkread;
    267 
    268 #ifdef NOT_YET
    269 	mcclock_addr = (volatile struct chiptime *)
    270 		MIPS_PHYS_TO_KSEG1(Vr_SYS_CLOCK);
    271 	mc_cpuspeed(mcclock_addr, MIPS_INT_MASK_1);
    272 #else
    273 	printf("%s(%d): cpuspeed estimation is notimplemented\n",
    274 	       __FILE__, __LINE__);
    275 #endif
    276 #ifdef HPCMIPS_L1CACHE_DISABLE
    277 	cpuspeed = 1;	/* XXX, CPU is very very slow because L1 cache is */
    278 	/* disabled. */
    279 #endif /*  HPCMIPS_L1CAHCE_DISABLE */
    280 }
    281 
    282 
    283 /*
    284  * Initalize the memory system and I/O buses.
    285  */
    286 void
    287 vr_bus_reset()
    288 {
    289 	printf("%s(%d): vr_bus_reset() not implemented.\n",
    290 	       __FILE__, __LINE__);
    291 }
    292 
    293 void
    294 vr_cons_init()
    295 {
    296 #if NCOM > 0 || NFB > 0 || NVRKIU > 0
    297 	extern bus_space_tag_t system_bus_iot;
    298 	extern bus_space_tag_t mb_bus_space_init __P((void));
    299 #endif
    300 
    301 #if NCOM > 0
    302 	if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) {
    303 		/* Serial console */
    304 		mb_bus_space_init(); /* At this time, not initialized yet */
    305 		if(com_vrip_cnattach(system_bus_iot, 0x0c000000, CONSPEED,
    306 				     VRCOM_FREQ,
    307 				     (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8)) {
    308 			printf("%s(%d): can't init serial console", __FILE__, __LINE__);
    309 		} else {
    310 			return;
    311 		}
    312 	}
    313 #endif
    314 
    315 #if NFB > 0
    316 	mb_bus_space_init(); /* At this time, not initialized yet */
    317 	if(fb_cnattach(system_bus_iot, 0x0c000000, 0, 0)) {
    318 		printf("%s(%d): can't init fb console", __FILE__, __LINE__);
    319 	} else {
    320 		goto find_keyboard;
    321 	}
    322 #endif
    323 
    324  find_keyboard:
    325 #if NVRKIU > 0
    326 	if (vrkiu_cnattach(system_bus_iot, VRIP_KIU_ADDR)) {
    327 		printf("%s(%d): can't init vrkiu as console",
    328 		       __FILE__, __LINE__);
    329 	} else {
    330 		return;
    331 	}
    332 #endif
    333 }
    334 
    335 void
    336 vr_device_register(dev, aux)
    337 	struct device *dev;
    338 	void *aux;
    339 {
    340 	printf("%s(%d): vr_device_register() not implemented.\n",
    341 	       __FILE__, __LINE__);
    342 	panic("abort");
    343 }
    344 
    345 void
    346 vr_reboot(howto, bootstr)
    347 	int howto;
    348 	char *bootstr;
    349 {
    350 	/*
    351 	 * power down
    352 	 */
    353 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
    354 		printf("fake powerdown\n");
    355 		__asm(__CONCAT(".word	",___STRING(VR_OPCODE_HIBERNATE)));
    356 		__asm("nop");
    357 		__asm("nop");
    358 		__asm("nop");
    359 		__asm("nop");
    360 		__asm("nop");
    361 		__asm(".set reorder");
    362 		/* not reach */
    363 		vr_reboot(howto&~RB_HALT, bootstr);
    364 	}
    365 	/*
    366 	 * halt
    367 	 */
    368 	if (howto & RB_HALT) {
    369 #if NVRIP > 0
    370 		_spllower(~MIPS_INT_MASK_0);
    371 		vrip_intr_suspend();
    372 #else
    373 		splhigh();
    374 #endif
    375 		__asm(".set noreorder");
    376 		__asm(__CONCAT(".word	",___STRING(VR_OPCODE_SUSPEND)));
    377 		__asm("nop");
    378 		__asm("nop");
    379 		__asm("nop");
    380 		__asm("nop");
    381 		__asm("nop");
    382 		__asm(".set reorder");
    383 #if NVRIP > 0
    384 		vrip_intr_resume();
    385 #endif
    386 	}
    387 	/*
    388 	 * reset
    389 	 */
    390 #if NVRDSU
    391 	vrdsu_reset();
    392 #else
    393 	printf("%s(%d): There is no DSU.", __FILE__, __LINE__);
    394 #endif
    395 }
    396 
    397 void *
    398 vr_intr_establish(line, ih_fun, ih_arg)
    399 	int line;
    400 	int (*ih_fun) __P((void*, u_int32_t, u_int32_t));
    401 	void *ih_arg;
    402 {
    403 	if (intr_handler[line] != null_handler) {
    404 		panic("vr_intr_establish: can't establish duplicated intr handler.");
    405 	}
    406 	intr_handler[line] = ih_fun;
    407 	intr_arg[line] = ih_arg;
    408 
    409 	return (void*)line;
    410 }
    411 
    412 
    413 void
    414 vr_intr_disestablish(ih)
    415 	void *ih;
    416 {
    417 	int line = (int)ih;
    418 	intr_handler[line] = null_handler;
    419 	intr_arg[line] = NULL;
    420 }
    421 
    422 int
    423 null_handler(arg, pc, statusReg)
    424 	void *arg;
    425 	u_int32_t pc;
    426 	u_int32_t statusReg;
    427 {
    428 	printf("null_handler\n");
    429 	return 0;
    430 }
    431 
    432 /*
    433  * Handle interrupts.
    434  */
    435 int
    436 vr_intr(mask, pc, status, cause)
    437 	u_int32_t mask;
    438 	u_int32_t pc;
    439 	u_int32_t status;
    440 	u_int32_t cause;
    441 {
    442 	int hwintr;
    443 
    444 	hwintr = (ffs(mask >> 10) -1) & 0x3;
    445 	(*intr_handler[hwintr])(intr_arg[hwintr], pc, status);
    446 	return (MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
    447 }
    448