1 /* $NetBSD: machdep.c,v 1.54 2014/03/25 10:44:12 martin 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.54 2014/03/25 10:44:12 martin 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 #include <sys/cpu.h> 94 95 #include <net/if.h> 96 #include <net/if_ether.h> 97 98 #include <uvm/uvm_extern.h> 99 100 #include <dev/cons.h> 101 102 #include "ksyms.h" 103 104 #if NKSYMS || defined(DDB) || defined(MODULAR) 105 #include <mips/db_machdep.h> 106 #include <ddb/db_extern.h> 107 #endif 108 109 #include <mips/cache.h> 110 #include <mips/locore.h> 111 112 #include <machine/yamon.h> 113 114 #include <evbmips/alchemy/board.h> 115 116 #include <mips/alchemy/dev/aupcivar.h> 117 #include <mips/alchemy/dev/aupcmciavar.h> 118 #include <mips/alchemy/dev/auspivar.h> 119 #include <mips/alchemy/include/aureg.h> 120 #include <mips/alchemy/include/auvar.h> 121 #include <mips/alchemy/include/aubusvar.h> 122 123 #include "com.h" 124 #if NCOM > 0 125 126 int aucomcnrate = 0; 127 #endif /* NAUCOM > 0 */ 128 129 #include "ohci.h" 130 131 /* Maps for VM objects. */ 132 struct vm_map *phys_map = NULL; 133 134 int maxmem; /* max memory per process */ 135 136 int mem_cluster_cnt; 137 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 138 139 yamon_env_var *yamon_envp; 140 struct mips_bus_space alchemy_cpuregt; 141 142 void mach_init(int, char **, yamon_env_var *, u_long); /* XXX */ 143 144 void 145 mach_init(int argc, char **argv, yamon_env_var *envp, u_long memsize) 146 { 147 bus_space_handle_t sh; 148 void *kernend; 149 const char *cp; 150 int freqok, howto, i; 151 const struct alchemy_board *board; 152 153 extern char edata[], end[]; /* XXX */ 154 155 board = board_info(); 156 KASSERT(board != NULL); 157 158 /* clear the BSS segment */ 159 kernend = (void *)mips_round_page(end); 160 memset(edata, 0, (char *)kernend - edata); 161 162 /* set CPU model info for sysctl_hw */ 163 cpu_setmodel("%s", board->ab_name); 164 165 /* save the yamon environment pointer */ 166 yamon_envp = envp; 167 168 /* Use YAMON callbacks for early console I/O */ 169 cn_tab = &yamon_promcd; 170 171 /* 172 * Set up the exception vectors and CPU-specific function 173 * vectors early on. We need the wbflush() vector set up 174 * before comcnattach() is called (or at least before the 175 * first printf() after that is called). 176 * Sets up mips_cpu_flags that may be queried by other 177 * functions called during startup. 178 * Also clears the I+D caches. 179 */ 180 mips_vector_init(NULL, false); 181 182 /* 183 * Set the VM page size. 184 */ 185 uvm_setpagesize(); 186 187 /* 188 * Use YAMON's CPU frequency if available. 189 */ 190 freqok = yamon_setcpufreq(1); 191 192 /* 193 * Initialize bus space tags. 194 */ 195 au_cpureg_bus_mem_init(&alchemy_cpuregt, &alchemy_cpuregt); 196 aubus_st = &alchemy_cpuregt; 197 198 /* 199 * Calibrate the timer if YAMON failed to tell us. 200 */ 201 if (!freqok) { 202 bus_space_map(aubus_st, PC_BASE, PC_SIZE, 0, &sh); 203 au_cal_timers(aubus_st, sh); 204 bus_space_unmap(aubus_st, sh, PC_SIZE); 205 } 206 207 /* 208 * Perform board-specific initialization. 209 */ 210 board->ab_init(); 211 212 /* 213 * Bring up the console. 214 */ 215 #if NCOM > 0 216 #ifdef CONSPEED 217 if (aucomcnrate == 0) 218 aucomcnrate = CONSPEED; 219 #else /* !CONSPEED */ 220 /* 221 * Learn default console speed. We use the YAMON environment, 222 * though we could probably also figure it out by checking the 223 * aucom registers directly. 224 */ 225 if ((aucomcnrate == 0) && ((cp = yamon_getenv("modetty0")) != NULL)) 226 aucomcnrate = strtoul(cp, NULL, 0); 227 228 if (aucomcnrate == 0) { 229 printf("FATAL: `modetty0' YAMON variable not set. Set it\n"); 230 printf(" to the speed of the console and try again.\n"); 231 printf(" Or, build a kernel with the `CONSPEED' " 232 "option.\n"); 233 panic("mach_init"); 234 } 235 #endif /* CONSPEED */ 236 237 /* 238 * Delay to allow firmware putchars to complete. 239 * FIFO depth * character time. 240 * character time = (1000000 / (defaultrate / 10)) 241 */ 242 delay(160000000 / aucomcnrate); 243 if (com_aubus_cnattach(UART0_BASE, aucomcnrate) != 0) 244 panic("mach_init: unable to initialize serial console"); 245 246 #else /* NCOM > 0 */ 247 panic("mach_init: not configured to use serial console"); 248 #endif /* NAUCOM > 0 */ 249 250 /* 251 * Look at arguments passed to us and compute boothowto. 252 */ 253 boothowto = RB_AUTOBOOT; 254 #ifdef KADB 255 boothowto |= RB_KDB; 256 #endif 257 for (i = 1; i < argc; i++) { 258 for (cp = argv[i]; *cp; cp++) { 259 /* Ignore superfluous '-', if there is one */ 260 if (*cp == '-') 261 continue; 262 263 howto = 0; 264 BOOT_FLAG(*cp, howto); 265 if (! howto) 266 printf("bootflag '%c' not recognised\n", *cp); 267 else 268 boothowto |= howto; 269 } 270 } 271 272 /* 273 * Determine the memory size. Use the `memsize' PMON 274 * variable. If that's not available, panic. 275 * 276 * Note: Reserve the first page! That's where the trap 277 * vectors are located. 278 */ 279 280 #if defined(MEMSIZE) 281 memsize = MEMSIZE; 282 #else 283 if (memsize == 0) { 284 if ((cp = yamon_getenv("memsize")) != NULL) 285 memsize = strtoul(cp, NULL, 0); 286 else { 287 printf("FATAL: `memsize' YAMON variable not set. Set it to\n"); 288 printf(" the amount of memory (in MB) and try again.\n"); 289 printf(" Or, build a kernel with the `MEMSIZE' " 290 "option.\n"); 291 panic("mach_init"); 292 } 293 } 294 #endif /* MEMSIZE */ 295 printf("Memory size: 0x%08lx\n", memsize); 296 physmem = btoc(memsize); 297 298 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 299 mem_clusters[mem_cluster_cnt].size = 300 memsize - mem_clusters[mem_cluster_cnt].start; 301 mem_cluster_cnt++; 302 303 /* 304 * Load the rest of the available pages into the VM system. 305 */ 306 mips_page_physload(MIPS_KSEG0_START, (vaddr_t)kernend, 307 mem_clusters, mem_cluster_cnt, NULL, 0); 308 309 /* 310 * Initialize message buffer (at end of core). 311 */ 312 mips_init_msgbuf(); 313 314 /* 315 * Initialize the virtual memory system. 316 */ 317 pmap_bootstrap(); 318 319 /* 320 * Allocate uarea page for lwp0 and set it. 321 */ 322 mips_init_lwp0_uarea(); 323 324 /* 325 * Initialize debuggers, and break into them, if appropriate. 326 */ 327 #ifdef DDB 328 if (boothowto & RB_KDB) 329 Debugger(); 330 #endif 331 } 332 333 void 334 consinit(void) 335 { 336 337 /* 338 * Everything related to console initialization is done 339 * in mach_init(). 340 */ 341 } 342 343 void 344 cpu_startup(void) 345 { 346 char pbuf[9]; 347 vaddr_t minaddr, maxaddr; 348 #ifdef DEBUG 349 extern int pmapdebug; /* XXX */ 350 int opmapdebug = pmapdebug; 351 352 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 353 #endif 354 355 /* 356 * Good {morning,afternoon,evening,night}. 357 */ 358 printf("%s%s", copyright, version); 359 printf("%s\n", cpu_getmodel()); 360 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 361 printf("total memory = %s\n", pbuf); 362 363 minaddr = 0; 364 365 /* 366 * Allocate a submap for physio 367 */ 368 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 369 VM_PHYS_SIZE, 0, false, NULL); 370 371 /* 372 * No need to allocate an mbuf cluster submap. Mbuf clusters 373 * are allocated via the pool allocator, and we use KSEG to 374 * map those pages. 375 */ 376 377 #ifdef DEBUG 378 pmapdebug = opmapdebug; 379 #endif 380 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 381 printf("avail memory = %s\n", pbuf); 382 } 383 384 void 385 cpu_reboot(int howto, char *bootstr) 386 { 387 static int waittime = -1; 388 const struct alchemy_board *board; 389 390 /* Take a snapshot before clobbering any registers. */ 391 savectx(curpcb); 392 393 board = board_info(); 394 KASSERT(board != NULL); 395 396 /* If "always halt" was specified as a boot flag, obey. */ 397 if (boothowto & RB_HALT) 398 howto |= RB_HALT; 399 400 boothowto = howto; 401 402 /* If system is cold, just halt. */ 403 if (cold) { 404 boothowto |= RB_HALT; 405 goto haltsys; 406 } 407 408 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 409 waittime = 0; 410 411 /* 412 * Synchronize the disks.... 413 */ 414 vfs_shutdown(); 415 416 /* 417 * If we've been adjusting the clock, the todr 418 * will be out of synch; adjust it now. 419 */ 420 resettodr(); 421 } 422 423 /* Disable interrupts. */ 424 splhigh(); 425 426 if (boothowto & RB_DUMP) 427 dumpsys(); 428 429 haltsys: 430 /* Run any shutdown hooks. */ 431 doshutdownhooks(); 432 433 pmf_system_shutdown(boothowto); 434 435 if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN) 436 if (board && board->ab_poweroff) 437 board->ab_poweroff(); 438 439 /* 440 * YAMON may autoboot (depending on settings), and we cannot pass 441 * flags to it (at least I haven't figured out how to yet), so 442 * we "pseudo-halt" now. 443 */ 444 if (boothowto & RB_HALT) { 445 printf("\n"); 446 printf("The operating system has halted.\n"); 447 printf("Please press any key to reboot.\n\n"); 448 cnpollc(1); /* For proper keyboard command handling */ 449 cngetc(); 450 cnpollc(0); 451 } 452 453 printf("reseting board...\n\n"); 454 455 /* 456 * Try to use board-specific reset logic, which might involve a better 457 * hardware reset. 458 */ 459 if (board->ab_reboot) 460 board->ab_reboot(); 461 462 #if 1 463 /* XXX 464 * For some reason we are leaving the ethernet MAC in a state where 465 * YAMON isn't happy with it. So just call the reset vector (grr, 466 * Alchemy YAMON doesn't have a "reset" command). 467 */ 468 mips_icache_sync_all(); 469 mips_dcache_wbinv_all(); 470 __asm volatile("jr %0" :: "r"(MIPS_RESET_EXC_VEC)); 471 #else 472 printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting..."); 473 yamon_exit(boothowto); 474 printf("Oops, back from yamon_exit()\n\nSpinning..."); 475 #endif 476 for (;;) 477 /* spin forever */ ; /* XXX */ 478 /*NOTREACHED*/ 479 } 480 481 /* 482 * Export our interrupt map function so aupci can find it. 483 */ 484 int 485 aupci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 486 { 487 const struct alchemy_board *board; 488 489 board = board_info(); 490 if (board->ab_pci_intr_map != NULL) 491 return (board->ab_pci_intr_map(pa, ihp)); 492 return 1; 493 } 494 495 struct aupcmcia_machdep * 496 aupcmcia_machdep(void) 497 { 498 const struct alchemy_board *board; 499 500 board = board_info(); 501 return (board->ab_pcmcia); 502 } 503 504 const struct auspi_machdep * 505 auspi_machdep(bus_addr_t ba) 506 { 507 const struct alchemy_board *board; 508 509 board = board_info(); 510 if (board->ab_spi != NULL) 511 return (board->ab_spi(ba)); 512 return NULL; 513 } 514