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