1/* $NetBSD: vr.c,v 1.63 2011/03/16 13:38:34 tsutsui 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.63 2011/03/16 13:38:34 tsutsui 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 */ 133const 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 154void vr_init(void); 155void VR_INTR(int, vaddr_t, uint32_t); 156extern void vr_idle(void); 157STATIC void vr_cons_init(void); 158STATIC void vr_fb_init(void **); 159STATIC void vr_mem_init(paddr_t); 160STATIC void vr_find_dram(paddr_t, paddr_t); 161STATIC void vr_reboot(int, char *); 162 163/* 164 * CPU interrupt dispatch table (HwInt[0:3]) 165 */ 166STATIC int vr_null_handler(void *, uint32_t, uint32_t); 167STATIC 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}; 174STATIC void *vr_intr_arg[4]; 175 176#if NCOM > 0 177/* 178 * machine dependent serial console info 179 */ 180static 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 */ 259static 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 292void 293vr_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 sprintf(hpcmips_cpuname, "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 sprintf(hpcmips_cpuname, "NEC VR41xx"); 314#endif 315} 316 317void 318vr_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 331void 332vr_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 403void 404vr_fb_init(void **kernend) 405{ 406 /* Nothing to do */ 407} 408 409void 410vr_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 475extern char vr_hibernate[]; 476extern char evr_hibernate[]; 477 478void 479vr_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 */ 537void 538VR_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 560void * 561vr_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 573void 574vr_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 582int 583vr_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/* 592int x4181 = VR4181; 593int x4101 = VR4101; 594int x4102 = VR4102; 595int x4111 = VR4111; 596int x4121 = VR4121; 597int x4122 = VR4122; 598int xo4181 = ONLY_VR4181; 599int xo4101 = ONLY_VR4101; 600int xo4102 = ONLY_VR4102; 601int xo4111_4121 = ONLY_VR4111_4121; 602int g4101=VRGROUP_4101; 603int g4102=VRGROUP_4102; 604int g4181=VRGROUP_4181; 605int g4102_4121=VRGROUP_4102_4121; 606int g4111_4121=VRGROUP_4111_4121; 607int g4102_4122=VRGROUP_4102_4122; 608int g4111_4122=VRGROUP_4111_4122; 609int single_vrip_base=SINGLE_VRIP_BASE; 610int vrip_base_addr=VRIP_BASE_ADDR; 611*/ 612