1 /* $NetBSD: vr.c,v 1.40 2002/11/24 06:02:24 shin 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 <mips/cache.h> 63 64 #include "vrip_common.h" 65 #if NVRIP_COMMON > 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 #ifdef VR4102 204 { 205 &platid_mask_CPU_MIPS_VR_4102, 206 com_vrip_cndb_attach, /* attach proc */ 207 VR4102_SIU_ADDR, /* base address */ 208 VRCOM_FREQ, /* frequency */ 209 }, 210 #endif /* VR4102 */ 211 #ifdef VR4111 212 { 213 &platid_mask_CPU_MIPS_VR_4111, 214 com_vrip_cndb_attach, /* attach proc */ 215 VR4102_SIU_ADDR, /* base address */ 216 VRCOM_FREQ, /* frequency */ 217 }, 218 #endif /* VR4111 */ 219 #ifdef VR4121 220 { 221 &platid_mask_CPU_MIPS_VR_4121, 222 com_vrip_cndb_attach, /* attach proc */ 223 VR4102_SIU_ADDR, /* base address */ 224 VRCOM_FREQ, /* frequency */ 225 }, 226 #endif /* VR4121 */ 227 #ifdef VR4122 228 { 229 &platid_mask_CPU_MIPS_VR_4122, 230 com_vrip_cndb_attach, /* attach proc */ 231 VR4122_SIU_ADDR, /* base address */ 232 VRCOM_FREQ, /* frequency */ 233 }, 234 #endif /* VR4122 */ 235 #ifdef VR4131 236 { 237 &platid_mask_CPU_MIPS_VR_4122, 238 com_vrip_cndb_attach, /* attach proc */ 239 VR4122_SIU_ADDR, /* base address */ 240 VRCOM_FREQ, /* frequency */ 241 }, 242 #endif /* VR4131 */ 243 #ifdef SINGLE_VRIP_BASE 244 { 245 &platid_wild, 246 com_vrip_cndb_attach, /* attach proc */ 247 VRIP_SIU_ADDR, /* base address */ 248 VRCOM_FREQ, /* frequency */ 249 }, 250 #endif /* SINGLE_VRIP_BASE */ 251 #else /* NCOM_VRIP > 0 */ 252 /* dummy */ 253 { 254 &platid_wild, 255 NULL, /* attach proc */ 256 0, /* base address */ 257 0, /* frequency */ 258 }, 259 #endif /* NCOM_VRIP > 0 */ 260 }; 261 #endif /* NCOM > 0 */ 262 263 #if NVRKIU > 0 264 /* 265 * machine dependent keyboard info 266 */ 267 static struct vr_kiu_platdep { 268 platid_mask_t *platidmask; 269 int addr; 270 } platdep_kiu_table[] = { 271 #ifdef VR4102 272 { 273 &platid_mask_CPU_MIPS_VR_4102, 274 VR4102_KIU_ADDR, /* base address */ 275 }, 276 #endif /* VR4102 */ 277 #ifdef VR4111 278 { 279 &platid_mask_CPU_MIPS_VR_4111, 280 VR4102_KIU_ADDR, /* base address */ 281 }, 282 #endif /* VR4111 */ 283 #ifdef VR4121 284 { 285 &platid_mask_CPU_MIPS_VR_4121, 286 VR4102_KIU_ADDR, /* base address */ 287 }, 288 #endif /* VR4121 */ 289 { 290 &platid_wild, 291 #ifdef SINGLE_VRIP_BASE 292 VRIP_KIU_ADDR, /* base address */ 293 #else 294 VRIP_NO_ADDR, /* base address */ 295 #endif /* SINGLE_VRIP_BASE */ 296 }, 297 }; 298 #endif /* NVRKIU > 0 */ 299 300 void 301 vr_init() 302 { 303 /* 304 * Platform Specific Function Hooks 305 */ 306 platform.cpu_idle = vr_idle; 307 platform.cpu_intr = VR_INTR; 308 platform.cons_init = vr_cons_init; 309 platform.fb_init = vr_fb_init; 310 platform.mem_init = vr_mem_init; 311 platform.reboot = vr_reboot; 312 313 #if NVRBCU > 0 314 sprintf(cpu_name, "NEC %s rev%d.%d %d.%03dMHz", 315 vrbcu_vrip_getcpuname(), 316 vrbcu_vrip_getcpumajor(), 317 vrbcu_vrip_getcpuminor(), 318 vrbcu_vrip_getcpuclock() / 1000000, 319 (vrbcu_vrip_getcpuclock() % 1000000) / 1000); 320 #else 321 sprintf(cpu_name, "NEC VR41xx"); 322 #endif 323 } 324 325 void 326 vr_mem_init(paddr_t kernend) 327 { 328 329 mem_clusters[0].start = 0; 330 mem_clusters[0].size = kernend; 331 mem_cluster_cnt = 1; 332 333 vr_find_dram(kernend, 0x02000000); 334 vr_find_dram(0x02000000, 0x04000000); 335 vr_find_dram(0x04000000, 0x06000000); 336 vr_find_dram(0x06000000, 0x08000000); 337 } 338 339 void 340 vr_find_dram(paddr_t addr, paddr_t end) 341 { 342 int n; 343 caddr_t page; 344 #ifdef NARLY_MEMORY_PROBE 345 int x, i; 346 #endif 347 348 #ifdef VR_FIND_DRAMLIM 349 if (VR_FIND_DRAMLIM < end) 350 end = VR_FIND_DRAMLIM; 351 #endif /* VR_FIND_DRAMLIM */ 352 n = mem_cluster_cnt; 353 for (; addr < end; addr += NBPG) { 354 355 page = (void *)MIPS_PHYS_TO_KSEG1(addr); 356 if (badaddr(page, 4)) 357 goto bad; 358 359 /* stop memory probing at first memory image */ 360 if (bcmp(page, (void *)MIPS_PHYS_TO_KSEG0(0), 128) == 0) 361 return; 362 363 *(volatile int *)(page+0) = 0xa5a5a5a5; 364 *(volatile int *)(page+4) = 0x5a5a5a5a; 365 wbflush(); 366 if (*(volatile int *)(page+0) != 0xa5a5a5a5) 367 goto bad; 368 369 *(volatile int *)(page+0) = 0x5a5a5a5a; 370 *(volatile int *)(page+4) = 0xa5a5a5a5; 371 wbflush(); 372 if (*(volatile int *)(page+0) != 0x5a5a5a5a) 373 goto bad; 374 375 #ifdef NARLY_MEMORY_PROBE 376 x = random(); 377 for (i = 0; i < NBPG; i += 4) 378 *(volatile int *)(page+i) = (x ^ i); 379 wbflush(); 380 for (i = 0; i < NBPG; i += 4) 381 if (*(volatile int *)(page+i) != (x ^ i)) 382 goto bad; 383 384 x = random(); 385 for (i = 0; i < NBPG; i += 4) 386 *(volatile int *)(page+i) = (x ^ i); 387 wbflush(); 388 for (i = 0; i < NBPG; i += 4) 389 if (*(volatile int *)(page+i) != (x ^ i)) 390 goto bad; 391 #endif /* NARLY_MEMORY_PROBE */ 392 393 if (!mem_clusters[n].size) 394 mem_clusters[n].start = addr; 395 mem_clusters[n].size += NBPG; 396 continue; 397 398 bad: 399 if (mem_clusters[n].size) 400 ++n; 401 continue; 402 } 403 if (mem_clusters[n].size) 404 ++n; 405 mem_cluster_cnt = n; 406 } 407 408 void 409 vr_fb_init(caddr_t *kernend) 410 { 411 /* Nothing to do */ 412 } 413 414 void 415 vr_cons_init() 416 { 417 #if NCOM > 0 || NHPCFB > 0 || NVRKIU > 0 418 bus_space_tag_t iot = hpcmips_system_bus_space(); 419 #endif 420 #if NCOM > 0 421 static struct vr_com_platdep *com_info; 422 #endif 423 #if NVRKIU > 0 424 static struct vr_kiu_platdep *kiu_info; 425 #endif 426 427 #if NCOM > 0 428 com_info = platid_search(&platid, platdep_com_table, 429 sizeof(platdep_com_table)/sizeof(*platdep_com_table), 430 sizeof(*platdep_com_table)); 431 #ifdef KGDB 432 if (com_info->attach != NULL) { 433 /* if KGDB is defined, always use the serial port for KGDB */ 434 if ((*com_info->attach)(iot, com_info->addr, 9600, 435 com_info->freq, 436 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 1)) { 437 printf("%s(%d): can't init kgdb's serial port", 438 __FILE__, __LINE__); 439 } 440 #else /* KGDB */ 441 if (com_info->attach != NULL && (bootinfo->bi_cnuse&BI_CNUSE_SERIAL)) { 442 /* Serial console */ 443 if ((*com_info->attach)(iot, com_info->addr, CONSPEED, 444 com_info->freq, 445 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 0)) { 446 printf("%s(%d): can't init serial console", 447 __FILE__, __LINE__); 448 } else { 449 return; 450 } 451 } 452 #endif /* KGDB */ 453 #endif /* NCOM > 0 */ 454 455 #if NHPCFB > 0 456 if (hpcfb_cnattach(NULL)) { 457 printf("%s(%d): can't init fb console", __FILE__, __LINE__); 458 } else { 459 goto find_keyboard; 460 } 461 find_keyboard: 462 #endif /* NHPCFB > 0 */ 463 464 #if NVRKIU > 0 465 kiu_info = platid_search(&platid, platdep_kiu_table, 466 sizeof(platdep_kiu_table)/sizeof(*platdep_kiu_table), 467 sizeof(*platdep_kiu_table)); 468 if (kiu_info->addr != VRIP_NO_ADDR) { 469 if (vrkiu_cnattach(iot, kiu_info->addr)) { 470 printf("%s(%d): can't init vrkiu as console", 471 __FILE__, __LINE__); 472 } else { 473 return; 474 } 475 } 476 #endif /* NVRKIU > 0 */ 477 } 478 479 extern char vr_hibernate[]; 480 extern char evr_hibernate[]; 481 482 void 483 vr_reboot(int howto, char *bootstr) 484 { 485 /* 486 * power down 487 */ 488 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 489 printf("fake powerdown\n"); 490 /* 491 * copy vr_hibernate() to top of physical memory. 492 */ 493 memcpy((void *)MIPS_KSEG0_START, vr_hibernate, 494 evr_hibernate - (char *)vr_hibernate); 495 /* sync I&D cache */ 496 mips_dcache_wbinv_all(); 497 mips_icache_sync_all(); 498 /* 499 * call vr_hibernate() at MIPS_KSEG0_START. 500 */ 501 ((void (*)(void *,int))MIPS_KSEG0_START)( 502 (void *)MIPS_KSEG0_START, ptoa(physmem)); 503 /* not reach */ 504 vr_reboot(howto&~RB_HALT, bootstr); 505 } 506 /* 507 * halt 508 */ 509 if (howto & RB_HALT) { 510 #if NVRIP_COMMON > 0 511 _spllower(~MIPS_INT_MASK_0); 512 vrip_intr_suspend(); 513 #else 514 splhigh(); 515 #endif 516 __asm(".set noreorder"); 517 __asm(__CONCAT(".word ",___STRING(VR_OPCODE_SUSPEND))); 518 __asm("nop"); 519 __asm("nop"); 520 __asm("nop"); 521 __asm("nop"); 522 __asm("nop"); 523 __asm(".set reorder"); 524 #if NVRIP_COMMON > 0 525 vrip_intr_resume(); 526 #endif 527 } 528 /* 529 * reset 530 */ 531 #if NVRDSU 532 vrdsu_reset(); 533 #else 534 printf("%s(%d): There is no DSU.", __FILE__, __LINE__); 535 #endif 536 } 537 538 /* 539 * Handle interrupts. 540 */ 541 void 542 VR_INTR(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending) 543 { 544 uvmexp.intrs++; 545 546 if (ipending & MIPS_INT_MASK_5) { 547 /* 548 * spl* uses MIPS_INT_MASK not MIPS3_INT_MASK. it causes 549 * INT5 interrupt. 550 */ 551 mips3_cp0_compare_write(mips3_cp0_count_read()); 552 } 553 554 /* for spllowersoftclock */ 555 _splset(((status & ~cause) & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); 556 557 if (ipending & MIPS_INT_MASK_1) { 558 (*vr_intr_handler[1])(vr_intr_arg[1], pc, status); 559 560 cause &= ~MIPS_INT_MASK_1; 561 _splset(((status & ~cause) & MIPS_HARD_INT_MASK) 562 | MIPS_SR_INT_IE); 563 } 564 565 if (ipending & MIPS_INT_MASK_0) { 566 (*vr_intr_handler[0])(vr_intr_arg[0], pc, status); 567 568 cause &= ~MIPS_INT_MASK_0; 569 } 570 _splset(((status & ~cause) & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); 571 572 softintr(ipending); 573 } 574 575 void * 576 vr_intr_establish(int line, int (*ih_fun)(void *, u_int32_t, u_int32_t), 577 void *ih_arg) 578 { 579 580 KDASSERT(vr_intr_handler[line] == vr_null_handler); 581 582 vr_intr_handler[line] = ih_fun; 583 vr_intr_arg[line] = ih_arg; 584 585 return ((void *)line); 586 } 587 588 void 589 vr_intr_disestablish(void *ih) 590 { 591 int line = (int)ih; 592 593 vr_intr_handler[line] = vr_null_handler; 594 vr_intr_arg[line] = NULL; 595 } 596 597 int 598 vr_null_handler(void *arg, u_int32_t pc, u_int32_t status) 599 { 600 601 printf("vr_null_handler\n"); 602 603 return (0); 604 } 605 606 /* 607 int x4181 = VR4181; 608 int x4101 = VR4101; 609 int x4102 = VR4102; 610 int x4111 = VR4111; 611 int x4121 = VR4121; 612 int x4122 = VR4122; 613 int xo4181 = ONLY_VR4181; 614 int xo4101 = ONLY_VR4101; 615 int xo4102 = ONLY_VR4102; 616 int xo4111_4121 = ONLY_VR4111_4121; 617 int g4101=VRGROUP_4101; 618 int g4102=VRGROUP_4102; 619 int g4181=VRGROUP_4181; 620 int g4102_4121=VRGROUP_4102_4121; 621 int g4111_4121=VRGROUP_4111_4121; 622 int g4102_4122=VRGROUP_4102_4122; 623 int g4111_4122=VRGROUP_4111_4122; 624 int single_vrip_base=SINGLE_VRIP_BASE; 625 int vrip_base_addr=VRIP_BASE_ADDR; 626 */ 627