1 /* $NetBSD: machdep.c,v 1.47 2010/02/08 19:02:27 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Itronix Inc. 5 * All rights reserved. 6 * 7 * Portions written by Garrett D'Amore for Itronix Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of Itronix Inc. may not be used to endorse 18 * or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /* 34 * Copyright (c) 1992, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department, The Mach Operating System project at 40 * Carnegie-Mellon University and Ralph Campbell. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 * 66 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 67 * from: Utah Hdr: machdep.c 1.63 91/04/24 68 */ 69 /* 70 * Copyright (c) 1988 University of Utah. 71 * 72 * This code is derived from software contributed to Berkeley by 73 * the Systems Programming Group of the University of Utah Computer 74 * Science Department, The Mach Operating System project at 75 * Carnegie-Mellon University and Ralph Campbell. 76 * 77 * Redistribution and use in source and binary forms, with or without 78 * modification, are permitted provided that the following conditions 79 * are met: 80 * 1. Redistributions of source code must retain the above copyright 81 * notice, this list of conditions and the following disclaimer. 82 * 2. Redistributions in binary form must reproduce the above copyright 83 * notice, this list of conditions and the following disclaimer in the 84 * documentation and/or other materials provided with the distribution. 85 * 3. All advertising materials mentioning features or use of this software 86 * must display the following acknowledgement: 87 * This product includes software developed by the University of 88 * California, Berkeley and its contributors. 89 * 4. Neither the name of the University nor the names of its contributors 90 * may be used to endorse or promote products derived from this software 91 * without specific prior written permission. 92 * 93 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 94 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 95 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 96 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 97 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 98 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 99 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 101 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 102 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 103 * SUCH DAMAGE. 104 * 105 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 106 * from: Utah Hdr: machdep.c 1.63 91/04/24 107 */ 108 109 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 110 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.47 2010/02/08 19:02:27 joerg Exp $"); 111 112 #include "opt_ddb.h" 113 #include "opt_kgdb.h" 114 115 #include "opt_memsize.h" 116 #include "opt_modular.h" 117 #include "opt_ethaddr.h" 118 119 #include <sys/param.h> 120 #include <sys/systm.h> 121 #include <sys/kernel.h> 122 #include <sys/buf.h> 123 #include <sys/reboot.h> 124 #include <sys/mount.h> 125 #include <sys/kcore.h> 126 #include <sys/boot_flag.h> 127 #include <sys/termios.h> 128 #include <sys/ksyms.h> 129 #include <sys/device.h> 130 131 #include <net/if.h> 132 #include <net/if_ether.h> 133 134 #include <uvm/uvm_extern.h> 135 136 #include <dev/cons.h> 137 138 #include "ksyms.h" 139 140 #if NKSYMS || defined(DDB) || defined(MODULAR) 141 #include <machine/db_machdep.h> 142 #include <ddb/db_extern.h> 143 #endif 144 145 #include <mips/cache.h> 146 #include <mips/locore.h> 147 #include <machine/yamon.h> 148 149 #include <evbmips/alchemy/board.h> 150 #include <mips/alchemy/dev/aupcivar.h> 151 #include <mips/alchemy/dev/aupcmciavar.h> 152 #include <mips/alchemy/dev/auspivar.h> 153 #include <mips/alchemy/include/aureg.h> 154 #include <mips/alchemy/include/auvar.h> 155 #include <mips/alchemy/include/aubusvar.h> 156 157 #include "com.h" 158 #if NCOM > 0 159 160 int aucomcnrate = 0; 161 #endif /* NAUCOM > 0 */ 162 163 #include "ohci.h" 164 165 /* Our exported CPU info; we can have only one. */ 166 struct cpu_info cpu_info_store; 167 168 /* Maps for VM objects. */ 169 struct vm_map *phys_map = NULL; 170 171 int maxmem; /* max memory per process */ 172 173 int mem_cluster_cnt; 174 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 175 176 yamon_env_var *yamon_envp; 177 struct mips_bus_space alchemy_cpuregt; 178 179 void mach_init(int, char **, yamon_env_var *, u_long); /* XXX */ 180 181 void 182 mach_init(int argc, char **argv, yamon_env_var *envp, u_long memsize) 183 { 184 bus_space_handle_t sh; 185 void *kernend; 186 const char *cp; 187 u_long first, last; 188 int freqok, howto, i; 189 const struct alchemy_board *board; 190 191 extern char edata[], end[]; /* XXX */ 192 193 board = board_info(); 194 KASSERT(board != NULL); 195 196 /* clear the BSS segment */ 197 kernend = (void *)mips_round_page(end); 198 memset(edata, 0, (char *)kernend - edata); 199 200 /* set CPU model info for sysctl_hw */ 201 strcpy(cpu_model, board->ab_name); 202 203 /* save the yamon environment pointer */ 204 yamon_envp = envp; 205 206 /* Use YAMON callbacks for early console I/O */ 207 cn_tab = &yamon_promcd; 208 209 /* 210 * Set up the exception vectors and CPU-specific function 211 * vectors early on. We need the wbflush() vector set up 212 * before comcnattach() is called (or at least before the 213 * first printf() after that is called). 214 * Sets up mips_cpu_flags that may be queried by other 215 * functions called during startup. 216 * Also clears the I+D caches. 217 */ 218 mips_vector_init(); 219 220 /* 221 * Set the VM page size. 222 */ 223 uvm_setpagesize(); 224 225 /* 226 * Use YAMON's CPU frequency if available. 227 */ 228 freqok = yamon_setcpufreq(1); 229 230 /* 231 * Initialize bus space tags. 232 */ 233 au_cpureg_bus_mem_init(&alchemy_cpuregt, &alchemy_cpuregt); 234 aubus_st = &alchemy_cpuregt; 235 236 /* 237 * Calibrate the timer if YAMON failed to tell us. 238 */ 239 if (!freqok) { 240 bus_space_map(aubus_st, PC_BASE, PC_SIZE, 0, &sh); 241 au_cal_timers(aubus_st, sh); 242 bus_space_unmap(aubus_st, sh, PC_SIZE); 243 } 244 245 /* 246 * Perform board-specific initialization. 247 */ 248 board->ab_init(); 249 250 /* 251 * Bring up the console. 252 */ 253 #if NCOM > 0 254 #ifdef CONSPEED 255 if (aucomcnrate == 0) 256 aucomcnrate = CONSPEED; 257 #else /* !CONSPEED */ 258 /* 259 * Learn default console speed. We use the YAMON environment, 260 * though we could probably also figure it out by checking the 261 * aucom registers directly. 262 */ 263 if ((aucomcnrate == 0) && ((cp = yamon_getenv("modetty0")) != NULL)) 264 aucomcnrate = strtoul(cp, NULL, 0); 265 266 if (aucomcnrate == 0) { 267 printf("FATAL: `modetty0' YAMON variable not set. Set it\n"); 268 printf(" to the speed of the console and try again.\n"); 269 printf(" Or, build a kernel with the `CONSPEED' " 270 "option.\n"); 271 panic("mach_init"); 272 } 273 #endif /* CONSPEED */ 274 275 /* 276 * Delay to allow firmware putchars to complete. 277 * FIFO depth * character time. 278 * character time = (1000000 / (defaultrate / 10)) 279 */ 280 delay(160000000 / aucomcnrate); 281 if (com_aubus_cnattach(UART0_BASE, aucomcnrate) != 0) 282 panic("mach_init: unable to initialize serial console"); 283 284 #else /* NCOM > 0 */ 285 panic("mach_init: not configured to use serial console"); 286 #endif /* NAUCOM > 0 */ 287 288 /* 289 * Look at arguments passed to us and compute boothowto. 290 */ 291 boothowto = RB_AUTOBOOT; 292 #ifdef KADB 293 boothowto |= RB_KDB; 294 #endif 295 for (i = 1; i < argc; i++) { 296 for (cp = argv[i]; *cp; cp++) { 297 /* Ignore superfluous '-', if there is one */ 298 if (*cp == '-') 299 continue; 300 301 howto = 0; 302 BOOT_FLAG(*cp, howto); 303 if (! howto) 304 printf("bootflag '%c' not recognised\n", *cp); 305 else 306 boothowto |= howto; 307 } 308 } 309 310 /* 311 * Determine the memory size. Use the `memsize' PMON 312 * variable. If that's not available, panic. 313 * 314 * Note: Reserve the first page! That's where the trap 315 * vectors are located. 316 */ 317 318 #if defined(MEMSIZE) 319 memsize = MEMSIZE; 320 #else 321 if (memsize == 0) { 322 if ((cp = yamon_getenv("memsize")) != NULL) 323 memsize = strtoul(cp, NULL, 0); 324 else { 325 printf("FATAL: `memsize' YAMON variable not set. Set it to\n"); 326 printf(" the amount of memory (in MB) and try again.\n"); 327 printf(" Or, build a kernel with the `MEMSIZE' " 328 "option.\n"); 329 panic("mach_init"); 330 } 331 } 332 #endif /* MEMSIZE */ 333 printf("Memory size: 0x%08lx\n", memsize); 334 physmem = btoc(memsize); 335 336 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 337 mem_clusters[mem_cluster_cnt].size = 338 memsize - mem_clusters[mem_cluster_cnt].start; 339 mem_cluster_cnt++; 340 341 /* 342 * Load the rest of the available pages into the VM system. 343 */ 344 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 345 last = mem_clusters[0].start + mem_clusters[0].size; 346 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 347 VM_FREELIST_DEFAULT); 348 349 /* 350 * Initialize message buffer (at end of core). 351 */ 352 mips_init_msgbuf(); 353 354 /* 355 * Initialize the virtual memory system. 356 */ 357 pmap_bootstrap(); 358 359 /* 360 * Allocate uarea page for lwp0 and set it. 361 */ 362 mips_init_lwp0_uarea(); 363 364 /* 365 * Initialize debuggers, and break into them, if appropriate. 366 */ 367 #ifdef DDB 368 if (boothowto & RB_KDB) 369 Debugger(); 370 #endif 371 } 372 373 void 374 consinit(void) 375 { 376 377 /* 378 * Everything related to console initialization is done 379 * in mach_init(). 380 */ 381 } 382 383 void 384 cpu_startup(void) 385 { 386 char pbuf[9]; 387 vaddr_t minaddr, maxaddr; 388 #ifdef DEBUG 389 extern int pmapdebug; /* XXX */ 390 int opmapdebug = pmapdebug; 391 392 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 393 #endif 394 395 /* 396 * Good {morning,afternoon,evening,night}. 397 */ 398 printf("%s%s", copyright, version); 399 printf("%s\n", cpu_model); 400 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 401 printf("total memory = %s\n", pbuf); 402 403 minaddr = 0; 404 405 /* 406 * Allocate a submap for physio 407 */ 408 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 409 VM_PHYS_SIZE, 0, false, NULL); 410 411 /* 412 * No need to allocate an mbuf cluster submap. Mbuf clusters 413 * are allocated via the pool allocator, and we use KSEG to 414 * map those pages. 415 */ 416 417 #ifdef DEBUG 418 pmapdebug = opmapdebug; 419 #endif 420 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 421 printf("avail memory = %s\n", pbuf); 422 } 423 424 void 425 cpu_reboot(int howto, char *bootstr) 426 { 427 static int waittime = -1; 428 const struct alchemy_board *board; 429 430 /* Take a snapshot before clobbering any registers. */ 431 if (curproc) 432 savectx(curpcb); 433 434 board = board_info(); 435 KASSERT(board != NULL); 436 437 /* If "always halt" was specified as a boot flag, obey. */ 438 if (boothowto & RB_HALT) 439 howto |= RB_HALT; 440 441 boothowto = howto; 442 443 /* If system is cold, just halt. */ 444 if (cold) { 445 boothowto |= RB_HALT; 446 goto haltsys; 447 } 448 449 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 450 waittime = 0; 451 452 /* 453 * Synchronize the disks.... 454 */ 455 vfs_shutdown(); 456 457 /* 458 * If we've been adjusting the clock, the todr 459 * will be out of synch; adjust it now. 460 */ 461 resettodr(); 462 } 463 464 /* Disable interrupts. */ 465 splhigh(); 466 467 if (boothowto & RB_DUMP) 468 dumpsys(); 469 470 haltsys: 471 /* Run any shutdown hooks. */ 472 doshutdownhooks(); 473 474 pmf_system_shutdown(boothowto); 475 476 if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN) 477 if (board && board->ab_poweroff) 478 board->ab_poweroff(); 479 480 /* 481 * YAMON may autoboot (depending on settings), and we cannot pass 482 * flags to it (at least I haven't figured out how to yet), so 483 * we "pseudo-halt" now. 484 */ 485 if (boothowto & RB_HALT) { 486 printf("\n"); 487 printf("The operating system has halted.\n"); 488 printf("Please press any key to reboot.\n\n"); 489 cnpollc(1); /* For proper keyboard command handling */ 490 cngetc(); 491 cnpollc(0); 492 } 493 494 printf("reseting board...\n\n"); 495 496 /* 497 * Try to use board-specific reset logic, which might involve a better 498 * hardware reset. 499 */ 500 if (board->ab_reboot) 501 board->ab_reboot(); 502 503 #if 1 504 /* XXX 505 * For some reason we are leaving the ethernet MAC in a state where 506 * YAMON isn't happy with it. So just call the reset vector (grr, 507 * Alchemy YAMON doesn't have a "reset" command). 508 */ 509 mips_icache_sync_all(); 510 mips_dcache_wbinv_all(); 511 __asm volatile("jr %0" :: "r"(MIPS_RESET_EXC_VEC)); 512 #else 513 printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting..."); 514 yamon_exit(boothowto); 515 printf("Oops, back from yamon_exit()\n\nSpinning..."); 516 #endif 517 for (;;) 518 /* spin forever */ ; /* XXX */ 519 /*NOTREACHED*/ 520 } 521 522 /* 523 * Export our interrupt map function so aupci can find it. 524 */ 525 int 526 aupci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 527 { 528 const struct alchemy_board *board; 529 530 board = board_info(); 531 if (board->ab_pci_intr_map != NULL) 532 return (board->ab_pci_intr_map(pa, ihp)); 533 return 1; 534 } 535 536 struct aupcmcia_machdep * 537 aupcmcia_machdep(void) 538 { 539 const struct alchemy_board *board; 540 541 board = board_info(); 542 return (board->ab_pcmcia); 543 } 544 545 const struct auspi_machdep * 546 auspi_machdep(bus_addr_t ba) 547 { 548 const struct alchemy_board *board; 549 550 board = board_info(); 551 if (board->ab_spi != NULL) 552 return (board->ab_spi(ba)); 553 return NULL; 554 } 555