1 /* $NetBSD: vr.c,v 1.65 2014/03/26 17:53:36 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.65 2014/03/26 17:53:36 christos Exp $"); 39 40 #include "opt_vr41xx.h" 41 #include "opt_tx39xx.h" 42 #include "opt_kgdb.h" 43 44 #define __INTR_PRIVATE 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/reboot.h> 49 #include <sys/device.h> 50 #include <sys/bus.h> 51 #include <sys/cpu.h> 52 53 #include <uvm/uvm_extern.h> 54 55 #include <mips/cache.h> 56 #include <mips/locore.h> 57 58 #include <machine/sysconf.h> 59 #include <machine/bootinfo.h> 60 #include <machine/bus_space_hpcmips.h> 61 #include <machine/platid.h> 62 #include <machine/platid_mask.h> 63 64 #include <dev/hpc/hpckbdvar.h> 65 66 #include <hpcmips/vr/vr.h> 67 #include <hpcmips/vr/vr_asm.h> 68 #include <hpcmips/vr/vrcpudef.h> 69 #include <hpcmips/vr/vripreg.h> 70 #include <hpcmips/vr/rtcreg.h> 71 72 #include "vrip_common.h" 73 #if NVRIP_COMMON > 0 74 #include <hpcmips/vr/vripvar.h> 75 #endif 76 77 #include "vrbcu.h" 78 #if NVRBCU > 0 79 #include <hpcmips/vr/bcuvar.h> 80 #endif 81 82 #include "vrdsu.h" 83 #if NVRDSU > 0 84 #include <hpcmips/vr/vrdsuvar.h> 85 #endif 86 87 #include "com.h" 88 #include "com_vrip.h" 89 #include "com_hpcio.h" 90 #if NCOM > 0 91 #include <sys/termios.h> 92 #include <sys/ttydefaults.h> 93 #include <dev/ic/comreg.h> 94 #include <dev/ic/comvar.h> 95 #if NCOM_VRIP > 0 96 #include <hpcmips/vr/siureg.h> 97 #include <hpcmips/vr/com_vripvar.h> 98 #endif 99 #if NCOM_HPCIO > 0 100 #include <hpcmips/dev/com_hpciovar.h> 101 #endif 102 #ifndef CONSPEED 103 #define CONSPEED TTYDEF_SPEED 104 #endif 105 #endif 106 107 #include "hpcfb.h" 108 #include "vrkiu.h" 109 #if (NVRKIU > 0) || (NHPCFB > 0) 110 #include <dev/wscons/wsdisplayvar.h> 111 #include <dev/rasops/rasops.h> 112 #endif 113 114 #if NHPCFB > 0 115 #include <dev/hpc/hpcfbvar.h> 116 #endif 117 118 #if NVRKIU > 0 119 #include <arch/hpcmips/vr/vrkiureg.h> 120 #include <arch/hpcmips/vr/vrkiuvar.h> 121 #endif 122 123 #ifdef DEBUG 124 #define STATIC 125 #else 126 #define STATIC static 127 #endif 128 129 /* 130 * This is a mask of bits to clear in the SR when we go to a 131 * given interrupt priority level. 132 */ 133 const struct ipl_sr_map __ipl_sr_map_vr = { 134 .sr_bits = { 135 [IPL_NONE] = 0, 136 [IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0, 137 [IPL_SOFTNET] = MIPS_SOFT_INT_MASK, 138 [IPL_VM] = MIPS_SOFT_INT_MASK 139 | MIPS_INT_MASK_0, 140 [IPL_SCHED] = MIPS_SOFT_INT_MASK 141 | MIPS_INT_MASK_0 142 | MIPS_INT_MASK_1, 143 [IPL_DDB] = MIPS_INT_MASK, 144 [IPL_HIGH] = MIPS_INT_MASK, 145 }, 146 }; 147 148 #if defined(VR41XX) && defined(TX39XX) 149 #define VR_INTR vr_intr 150 #else 151 #define VR_INTR cpu_intr /* locore_mips3 directly call this */ 152 #endif 153 154 void vr_init(void); 155 void VR_INTR(int, vaddr_t, uint32_t); 156 extern void vr_idle(void); 157 STATIC void vr_cons_init(void); 158 STATIC void vr_fb_init(void **); 159 STATIC void vr_mem_init(paddr_t); 160 STATIC void vr_find_dram(paddr_t, paddr_t); 161 STATIC void vr_reboot(int, char *); 162 163 /* 164 * CPU interrupt dispatch table (HwInt[0:3]) 165 */ 166 STATIC int vr_null_handler(void *, uint32_t, uint32_t); 167 STATIC int (*vr_intr_handler[4])(void *, vaddr_t, uint32_t) = 168 { 169 vr_null_handler, 170 vr_null_handler, 171 vr_null_handler, 172 vr_null_handler 173 }; 174 STATIC void *vr_intr_arg[4]; 175 176 #if NCOM > 0 177 /* 178 * machine dependent serial console info 179 */ 180 static struct vr_com_platdep { 181 platid_mask_t *platidmask; 182 int (*attach)(bus_space_tag_t, int, int, int, tcflag_t, int); 183 int addr; 184 int freq; 185 } platdep_com_table[] = { 186 #if NCOM_HPCIO > 0 187 { 188 &platid_mask_MACH_NEC_MCR_SIGMARION2, 189 com_hpcio_cndb_attach, /* attach proc */ 190 0x0b600000, /* base address */ 191 COM_FREQ, /* frequency */ 192 }, 193 #endif 194 #if NCOM_VRIP > 0 195 #ifdef VR4102 196 { 197 &platid_mask_CPU_MIPS_VR_4102, 198 com_vrip_cndb_attach, /* attach proc */ 199 VR4102_SIU_ADDR, /* base address */ 200 VRCOM_FREQ, /* frequency */ 201 }, 202 #endif /* VR4102 */ 203 #ifdef VR4111 204 { 205 &platid_mask_CPU_MIPS_VR_4111, 206 com_vrip_cndb_attach, /* attach proc */ 207 VR4102_SIU_ADDR, /* base address */ 208 VRCOM_FREQ, /* frequency */ 209 }, 210 #endif /* VR4111 */ 211 #ifdef VR4121 212 { 213 &platid_mask_CPU_MIPS_VR_4121, 214 com_vrip_cndb_attach, /* attach proc */ 215 VR4102_SIU_ADDR, /* base address */ 216 VRCOM_FREQ, /* frequency */ 217 }, 218 #endif /* VR4121 */ 219 #ifdef VR4122 220 { 221 &platid_mask_CPU_MIPS_VR_4122, 222 com_vrip_cndb_attach, /* attach proc */ 223 VR4122_SIU_ADDR, /* base address */ 224 VRCOM_FREQ, /* frequency */ 225 }, 226 #endif /* VR4122 */ 227 #ifdef VR4131 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 /* VR4131 */ 235 #ifdef SINGLE_VRIP_BASE 236 { 237 &platid_wild, 238 com_vrip_cndb_attach, /* attach proc */ 239 VRIP_SIU_ADDR, /* base address */ 240 VRCOM_FREQ, /* frequency */ 241 }, 242 #endif /* SINGLE_VRIP_BASE */ 243 #else /* NCOM_VRIP > 0 */ 244 /* dummy */ 245 { 246 &platid_wild, 247 NULL, /* attach proc */ 248 0, /* base address */ 249 0, /* frequency */ 250 }, 251 #endif /* NCOM_VRIP > 0 */ 252 }; 253 #endif /* NCOM > 0 */ 254 255 #if NVRKIU > 0 256 /* 257 * machine dependent keyboard info 258 */ 259 static struct vr_kiu_platdep { 260 platid_mask_t *platidmask; 261 int addr; 262 } platdep_kiu_table[] = { 263 #ifdef VR4102 264 { 265 &platid_mask_CPU_MIPS_VR_4102, 266 VR4102_KIU_ADDR, /* base address */ 267 }, 268 #endif /* VR4102 */ 269 #ifdef VR4111 270 { 271 &platid_mask_CPU_MIPS_VR_4111, 272 VR4102_KIU_ADDR, /* base address */ 273 }, 274 #endif /* VR4111 */ 275 #ifdef VR4121 276 { 277 &platid_mask_CPU_MIPS_VR_4121, 278 VR4102_KIU_ADDR, /* base address */ 279 }, 280 #endif /* VR4121 */ 281 { 282 &platid_wild, 283 #ifdef SINGLE_VRIP_BASE 284 VRIP_KIU_ADDR, /* base address */ 285 #else 286 VRIP_NO_ADDR, /* base address */ 287 #endif /* SINGLE_VRIP_BASE */ 288 }, 289 }; 290 #endif /* NVRKIU > 0 */ 291 292 void 293 vr_init(void) 294 { 295 /* 296 * Platform Specific Function Hooks 297 */ 298 platform.cpu_idle = vr_idle; 299 platform.cpu_intr = VR_INTR; 300 platform.cons_init = vr_cons_init; 301 platform.fb_init = vr_fb_init; 302 platform.mem_init = vr_mem_init; 303 platform.reboot = vr_reboot; 304 305 #if NVRBCU > 0 306 cpuname_printf("NEC %s rev%d.%d %d.%03dMHz", 307 vrbcu_vrip_getcpuname(), 308 vrbcu_vrip_getcpumajor(), 309 vrbcu_vrip_getcpuminor(), 310 vrbcu_vrip_getcpuclock() / 1000000, 311 (vrbcu_vrip_getcpuclock() % 1000000) / 1000); 312 #else 313 cpuname_printf("NEC VR41xx"); 314 #endif 315 } 316 317 void 318 vr_mem_init(paddr_t kernend) 319 { 320 321 mem_clusters[0].start = 0; 322 mem_clusters[0].size = kernend; 323 mem_cluster_cnt = 1; 324 325 vr_find_dram(kernend, 0x02000000); 326 vr_find_dram(0x02000000, 0x04000000); 327 vr_find_dram(0x04000000, 0x06000000); 328 vr_find_dram(0x06000000, 0x08000000); 329 } 330 331 void 332 vr_find_dram(paddr_t addr, paddr_t end) 333 { 334 int n; 335 char *page; 336 #ifdef NARLY_MEMORY_PROBE 337 int x, i; 338 #endif 339 340 #ifdef VR_FIND_DRAMLIM 341 if (VR_FIND_DRAMLIM < end) 342 end = VR_FIND_DRAMLIM; 343 #endif /* VR_FIND_DRAMLIM */ 344 n = mem_cluster_cnt; 345 for (; addr < end; addr += PAGE_SIZE) { 346 347 page = (char *)MIPS_PHYS_TO_KSEG1(addr); 348 /* 349 XXX see port-hpcmips/42934 350 if (badaddr(page, 4)) 351 goto bad; 352 */ 353 354 /* stop memory probing at first memory image */ 355 if (memcmp(page, (void *)MIPS_PHYS_TO_KSEG0(0), 128) == 0) 356 return; 357 358 *(volatile int *)(page+0) = 0xa5a5a5a5; 359 *(volatile int *)(page+4) = 0x5a5a5a5a; 360 wbflush(); 361 if (*(volatile int *)(page+0) != 0xa5a5a5a5) 362 goto bad; 363 364 *(volatile int *)(page+0) = 0x5a5a5a5a; 365 *(volatile int *)(page+4) = 0xa5a5a5a5; 366 wbflush(); 367 if (*(volatile int *)(page+0) != 0x5a5a5a5a) 368 goto bad; 369 370 #ifdef NARLY_MEMORY_PROBE 371 x = random(); 372 for (i = 0; i < PAGE_SIZE; i += 4) 373 *(volatile int *)(page+i) = (x ^ i); 374 wbflush(); 375 for (i = 0; i < PAGE_SIZE; i += 4) 376 if (*(volatile int *)(page+i) != (x ^ i)) 377 goto bad; 378 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 #endif /* NARLY_MEMORY_PROBE */ 387 388 if (!mem_clusters[n].size) 389 mem_clusters[n].start = addr; 390 mem_clusters[n].size += PAGE_SIZE; 391 continue; 392 393 bad: 394 if (mem_clusters[n].size) 395 ++n; 396 continue; 397 } 398 if (mem_clusters[n].size) 399 ++n; 400 mem_cluster_cnt = n; 401 } 402 403 void 404 vr_fb_init(void **kernend) 405 { 406 /* Nothing to do */ 407 } 408 409 void 410 vr_cons_init(void) 411 { 412 #if NCOM > 0 || NHPCFB > 0 || NVRKIU > 0 413 bus_space_tag_t iot = hpcmips_system_bus_space(); 414 #endif 415 #if NCOM > 0 416 static struct vr_com_platdep *com_info; 417 #endif 418 #if NVRKIU > 0 419 static struct vr_kiu_platdep *kiu_info; 420 #endif 421 422 #if NCOM > 0 423 com_info = platid_search(&platid, platdep_com_table, 424 sizeof(platdep_com_table)/sizeof(*platdep_com_table), 425 sizeof(*platdep_com_table)); 426 #ifdef KGDB 427 if (com_info->attach != NULL) { 428 /* if KGDB is defined, always use the serial port for KGDB */ 429 if ((*com_info->attach)(iot, com_info->addr, 9600, 430 com_info->freq, 431 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 1)) { 432 printf("%s(%d): can't init kgdb's serial port", 433 __FILE__, __LINE__); 434 } 435 } 436 #else /* KGDB */ 437 if (com_info->attach != NULL && (bootinfo->bi_cnuse&BI_CNUSE_SERIAL)) { 438 /* Serial console */ 439 if ((*com_info->attach)(iot, com_info->addr, CONSPEED, 440 com_info->freq, 441 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 0)) { 442 printf("%s(%d): can't init serial console", 443 __FILE__, __LINE__); 444 } else { 445 return; 446 } 447 } 448 #endif /* KGDB */ 449 #endif /* NCOM > 0 */ 450 451 #if NHPCFB > 0 452 if (hpcfb_cnattach(NULL)) { 453 printf("%s(%d): can't init fb console", __FILE__, __LINE__); 454 } else { 455 goto find_keyboard; 456 } 457 find_keyboard: 458 #endif /* NHPCFB > 0 */ 459 460 #if NVRKIU > 0 461 kiu_info = platid_search(&platid, platdep_kiu_table, 462 sizeof(platdep_kiu_table)/sizeof(*platdep_kiu_table), 463 sizeof(*platdep_kiu_table)); 464 if (kiu_info->addr != VRIP_NO_ADDR) { 465 if (vrkiu_cnattach(iot, kiu_info->addr)) { 466 printf("%s(%d): can't init vrkiu as console", 467 __FILE__, __LINE__); 468 } else { 469 return; 470 } 471 } 472 #endif /* NVRKIU > 0 */ 473 } 474 475 extern char vr_hibernate[]; 476 extern char evr_hibernate[]; 477 478 void 479 vr_reboot(int howto, char *bootstr) 480 { 481 /* 482 * power down 483 */ 484 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 485 printf("fake powerdown\n"); 486 /* 487 * copy vr_hibernate() to top of physical memory. 488 */ 489 memcpy((void *)MIPS_KSEG0_START, vr_hibernate, 490 evr_hibernate - (char *)vr_hibernate); 491 /* sync I&D cache */ 492 mips_dcache_wbinv_all(); 493 mips_icache_sync_all(); 494 /* 495 * call vr_hibernate() at MIPS_KSEG0_START. 496 */ 497 ((void (*)(void *,int))MIPS_KSEG0_START)( 498 (void *)MIPS_KSEG0_START, ptoa(physmem)); 499 /* not reach */ 500 vr_reboot(howto&~RB_HALT, bootstr); 501 } 502 /* 503 * halt 504 */ 505 if (howto & RB_HALT) { 506 #if NVRIP_COMMON > 0 507 vrip_splpiu(); 508 vrip_intr_suspend(); 509 #else 510 splhigh(); 511 #endif 512 __asm(".set noreorder"); 513 __asm(".word " ___STRING(VR_OPCODE_SUSPEND)); 514 __asm("nop"); 515 __asm("nop"); 516 __asm("nop"); 517 __asm("nop"); 518 __asm("nop"); 519 __asm(".set reorder"); 520 #if NVRIP_COMMON > 0 521 vrip_intr_resume(); 522 #endif 523 } 524 /* 525 * reset 526 */ 527 #if NVRDSU 528 vrdsu_reset(); 529 #else 530 printf("%s(%d): There is no DSU.", __FILE__, __LINE__); 531 #endif 532 } 533 534 /* 535 * Handle interrupts. 536 */ 537 void 538 VR_INTR(int ppl, vaddr_t pc, uint32_t status) 539 { 540 uint32_t ipending; 541 int ipl; 542 543 while (ppl < (ipl = splintr(&ipending))) { 544 /* Deal with unneded compare interrupts occasionally so that 545 * we can keep spllowersoftclock. */ 546 if (ipending & MIPS_INT_MASK_5) { 547 mips3_cp0_compare_write(0); 548 } 549 550 if (ipending & MIPS_INT_MASK_1) { 551 (*vr_intr_handler[1])(vr_intr_arg[1], pc, status); 552 } 553 554 if (ipending & MIPS_INT_MASK_0) { 555 (*vr_intr_handler[0])(vr_intr_arg[0], pc, status); 556 } 557 } 558 } 559 560 void * 561 vr_intr_establish(int line, int (*ih_fun)(void *, vaddr_t, uint32_t), 562 void *ih_arg) 563 { 564 565 KDASSERT(vr_intr_handler[line] == vr_null_handler); 566 567 vr_intr_handler[line] = ih_fun; 568 vr_intr_arg[line] = ih_arg; 569 570 return ((void *)line); 571 } 572 573 void 574 vr_intr_disestablish(void *ih) 575 { 576 int line = (int)ih; 577 578 vr_intr_handler[line] = vr_null_handler; 579 vr_intr_arg[line] = NULL; 580 } 581 582 int 583 vr_null_handler(void *arg, vaddr_t pc, uint32_t status) 584 { 585 586 printf("vr_null_handler\n"); 587 588 return (0); 589 } 590 591 /* 592 int x4181 = VR4181; 593 int x4101 = VR4101; 594 int x4102 = VR4102; 595 int x4111 = VR4111; 596 int x4121 = VR4121; 597 int x4122 = VR4122; 598 int xo4181 = ONLY_VR4181; 599 int xo4101 = ONLY_VR4101; 600 int xo4102 = ONLY_VR4102; 601 int xo4111_4121 = ONLY_VR4111_4121; 602 int g4101=VRGROUP_4101; 603 int g4102=VRGROUP_4102; 604 int g4181=VRGROUP_4181; 605 int g4102_4121=VRGROUP_4102_4121; 606 int g4111_4121=VRGROUP_4111_4121; 607 int g4102_4122=VRGROUP_4102_4122; 608 int g4111_4122=VRGROUP_4111_4122; 609 int single_vrip_base=SINGLE_VRIP_BASE; 610 int vrip_base_addr=VRIP_BASE_ADDR; 611 */ 612