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