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