1/* $NetBSD: machdep.c,v 1.58 2024/03/05 14:15:30 thorpej 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.58 2024/03/05 14:15:30 thorpej 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 126int aucomcnrate = 0; 127#endif /* NAUCOM > 0 */ 128 129#include "ohci.h" 130 131/* Maps for VM objects. */ 132struct vm_map *phys_map = NULL; 133 134int maxmem; /* max memory per process */ 135 136int mem_cluster_cnt; 137phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 138 139yamon_env_var *yamon_envp; 140struct mips_bus_space alchemy_cpuregt; 141 142void mach_init(int, char **, yamon_env_var *, u_long); /* XXX */ 143 144void 145mach_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 uvm_md_init(); 183 184 /* 185 * Use YAMON's CPU frequency if available. 186 */ 187 freqok = yamon_setcpufreq(1); 188 189 /* 190 * Initialize bus space tags. 191 */ 192 au_cpureg_bus_mem_init(&alchemy_cpuregt, &alchemy_cpuregt); 193 aubus_st = &alchemy_cpuregt; 194 195 /* 196 * Calibrate the timer if YAMON failed to tell us. 197 */ 198 if (!freqok) { 199 bus_space_map(aubus_st, PC_BASE, PC_SIZE, 0, &sh); 200 au_cal_timers(aubus_st, sh); 201 bus_space_unmap(aubus_st, sh, PC_SIZE); 202 } 203 204 /* 205 * Perform board-specific initialization. 206 */ 207 board->ab_init(); 208 209 /* 210 * Bring up the console. 211 */ 212#if NCOM > 0 213#ifdef CONSPEED 214 if (aucomcnrate == 0) 215 aucomcnrate = CONSPEED; 216#else /* !CONSPEED */ 217 /* 218 * Learn default console speed. We use the YAMON environment, 219 * though we could probably also figure it out by checking the 220 * aucom registers directly. 221 */ 222 if ((aucomcnrate == 0) && ((cp = yamon_getenv("modetty0")) != NULL)) 223 aucomcnrate = strtoul(cp, NULL, 0); 224 225 if (aucomcnrate == 0) { 226 printf("FATAL: `modetty0' YAMON variable not set. Set it\n"); 227 printf(" to the speed of the console and try again.\n"); 228 printf(" Or, build a kernel with the `CONSPEED' " 229 "option.\n"); 230 panic("mach_init"); 231 } 232#endif /* CONSPEED */ 233 234 /* 235 * Delay to allow firmware putchars to complete. 236 * FIFO depth * character time. 237 * character time = (1000000 / (defaultrate / 10)) 238 */ 239 delay(160000000 / aucomcnrate); 240 if (com_aubus_cnattach(UART0_BASE, aucomcnrate) != 0) 241 panic("mach_init: unable to initialize serial console"); 242 243#else /* NCOM > 0 */ 244 panic("mach_init: not configured to use serial console"); 245#endif /* NAUCOM > 0 */ 246 247 /* 248 * Look at arguments passed to us and compute boothowto. 249 */ 250 boothowto = RB_AUTOBOOT; 251#ifdef KADB 252 boothowto |= RB_KDB; 253#endif 254 for (i = 1; i < argc; i++) { 255 for (cp = argv[i]; *cp; cp++) { 256 /* Ignore superfluous '-', if there is one */ 257 if (*cp == '-') 258 continue; 259 260 howto = 0; 261 BOOT_FLAG(*cp, howto); 262 if (! howto) 263 printf("bootflag '%c' not recognised\n", *cp); 264 else 265 boothowto |= howto; 266 } 267 } 268 269 /* 270 * Determine the memory size. Use the `memsize' PMON 271 * variable. If that's not available, panic. 272 * 273 * Note: Reserve the first page! That's where the trap 274 * vectors are located. 275 */ 276 277#if defined(MEMSIZE) 278 memsize = MEMSIZE; 279#else 280 if (memsize == 0) { 281 if ((cp = yamon_getenv("memsize")) != NULL) 282 memsize = strtoul(cp, NULL, 0); 283 else { 284 printf("FATAL: `memsize' YAMON variable not set. Set it to\n"); 285 printf(" the amount of memory (in MB) and try again.\n"); 286 printf(" Or, build a kernel with the `MEMSIZE' " 287 "option.\n"); 288 panic("mach_init"); 289 } 290 } 291#endif /* MEMSIZE */ 292 printf("Memory size: 0x%08lx\n", memsize); 293 physmem = btoc(memsize); 294 295 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 296 mem_clusters[mem_cluster_cnt].size = 297 memsize - mem_clusters[mem_cluster_cnt].start; 298 mem_cluster_cnt++; 299 300 /* 301 * Load the rest of the available pages into the VM system. 302 */ 303 mips_page_physload(MIPS_KSEG0_START, (vaddr_t)kernend, 304 mem_clusters, mem_cluster_cnt, NULL, 0); 305 306 /* 307 * Initialize message buffer (at end of core). 308 */ 309 mips_init_msgbuf(); 310 311 /* 312 * Initialize the virtual memory system. 313 */ 314 pmap_bootstrap(); 315 316 /* 317 * Allocate uarea page for lwp0 and set it. 318 */ 319 mips_init_lwp0_uarea(); 320 321 /* 322 * Initialize debuggers, and break into them, if appropriate. 323 */ 324#ifdef DDB 325 if (boothowto & RB_KDB) 326 Debugger(); 327#endif 328} 329 330void 331consinit(void) 332{ 333 334 /* 335 * Everything related to console initialization is done 336 * in mach_init(). 337 */ 338} 339 340void 341cpu_startup(void) 342{ 343 cpu_startup_common(); 344} 345 346void 347cpu_reboot(int howto, char *bootstr) 348{ 349 static int waittime = -1; 350 const struct alchemy_board *board; 351 352 /* Take a snapshot before clobbering any registers. */ 353 savectx(curpcb); 354 355 board = board_info(); 356 KASSERT(board != NULL); 357 358 /* If "always halt" was specified as a boot flag, obey. */ 359 if (boothowto & RB_HALT) 360 howto |= RB_HALT; 361 362 boothowto = howto; 363 364 /* If system is cold, just halt. */ 365 if (cold) { 366 boothowto |= RB_HALT; 367 goto haltsys; 368 } 369 370 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 371 waittime = 0; 372 373 /* 374 * Synchronize the disks.... 375 */ 376 vfs_shutdown(); 377 } 378 379 /* Disable interrupts. */ 380 splhigh(); 381 382 if (boothowto & RB_DUMP) 383 dumpsys(); 384 385 haltsys: 386 /* Run any shutdown hooks. */ 387 doshutdownhooks(); 388 389 pmf_system_shutdown(boothowto); 390 391 if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN) 392 if (board && board->ab_poweroff) 393 board->ab_poweroff(); 394 395 /* 396 * YAMON may autoboot (depending on settings), and we cannot pass 397 * flags to it (at least I haven't figured out how to yet), so 398 * we "pseudo-halt" now. 399 */ 400 if (boothowto & RB_HALT) { 401 printf("\n"); 402 printf("The operating system has halted.\n"); 403 printf("Please press any key to reboot.\n\n"); 404 cnpollc(1); /* For proper keyboard command handling */ 405 cngetc(); 406 cnpollc(0); 407 } 408 409 printf("resetting board...\n\n"); 410 411 /* 412 * Try to use board-specific reset logic, which might involve a better 413 * hardware reset. 414 */ 415 if (board->ab_reboot) 416 board->ab_reboot(); 417 418#if 1 419 /* XXX 420 * For some reason we are leaving the ethernet MAC in a state where 421 * YAMON isn't happy with it. So just call the reset vector (grr, 422 * Alchemy YAMON doesn't have a "reset" command). 423 */ 424 mips_icache_sync_all(); 425 mips_dcache_wbinv_all(); 426 __asm volatile("jr %0" :: "r"(MIPS_RESET_EXC_VEC)); 427#else 428 printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting..."); 429 yamon_exit(boothowto); 430 printf("Oops, back from yamon_exit()\n\nSpinning..."); 431#endif 432 for (;;) 433 /* spin forever */ ; /* XXX */ 434 /*NOTREACHED*/ 435} 436 437/* 438 * Export our interrupt map function so aupci can find it. 439 */ 440int 441aupci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 442{ 443 const struct alchemy_board *board; 444 445 board = board_info(); 446 if (board->ab_pci_intr_map != NULL) 447 return (board->ab_pci_intr_map(pa, ihp)); 448 return 1; 449} 450 451struct aupcmcia_machdep * 452aupcmcia_machdep(void) 453{ 454 const struct alchemy_board *board; 455 456 board = board_info(); 457 return (board->ab_pcmcia); 458} 459 460const struct auspi_machdep * 461auspi_machdep(bus_addr_t ba) 462{ 463 const struct alchemy_board *board; 464 465 board = board_info(); 466 if (board->ab_spi != NULL) 467 return (board->ab_spi(ba)); 468 return NULL; 469} 470