1 /* $NetBSD: machdep.c,v 1.23 2014/03/24 20:06:31 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or 8 * without modification, are permitted provided that the following 9 * conditions 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 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 3. The names of the authors may not be used to endorse or promote 17 * products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 27 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * 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.23 2014/03/24 20:06:31 christos 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 "opt_pci.h" 83 #include "pci.h" 84 85 #include <sys/param.h> 86 #include <sys/boot_flag.h> 87 #include <sys/buf.h> 88 #include <sys/device.h> 89 #include <sys/kcore.h> 90 #include <sys/kernel.h> 91 #include <sys/ksyms.h> 92 #include <sys/mount.h> 93 #include <sys/reboot.h> 94 #include <sys/systm.h> 95 #include <sys/termios.h> 96 #include <sys/cpu.h> 97 98 #include <net/if.h> 99 #include <net/if_ether.h> 100 101 #include <uvm/uvm_extern.h> 102 103 #include <dev/cons.h> 104 105 #include "ksyms.h" 106 107 #if NKSYMS || defined(DDB) || defined(MODULAR) 108 #include <mips/db_machdep.h> 109 #include <ddb/db_extern.h> 110 #endif 111 112 #include <mips/cache.h> 113 #include <mips/locore.h> 114 115 #include <mips/adm5120/include/adm5120reg.h> 116 #include <mips/adm5120/include/adm5120var.h> 117 #include <mips/adm5120/include/adm5120_extiovar.h> 118 #include <mips/adm5120/include/adm5120_obiovar.h> 119 #include <mips/adm5120/include/adm5120_mainbusvar.h> 120 #include <mips/adm5120/include/adm5120_pcivar.h> 121 #include <mips/adm5120/dev/uart.h> 122 123 #ifndef MEMSIZE 124 #define MEMSIZE 4 * 1024 * 1024 125 #endif /* !MEMSIZE */ 126 127 /* Maps for VM objects. */ 128 struct vm_map *phys_map = NULL; 129 130 int maxmem; /* max memory per process */ 131 132 int mem_cluster_cnt; 133 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 134 135 struct adm5120_config adm5120_configuration; 136 137 void adm5120_setcpufreq(void); 138 139 void 140 adm5120_setcpufreq(void) 141 { 142 uint32_t v, freq; 143 144 v = SW_READ(SW_CODE_REG); 145 switch (v & CLKS_MASK) { 146 case CLKS_175MHZ: 147 freq = 175 * 1000 * 1000; 148 break; 149 case CLKS_200MHZ: 150 freq = 200 * 1000 * 1000; 151 break; 152 default: 153 panic("adm5120: cannot determine CPU clock speed"); 154 } 155 156 curcpu()->ci_cpu_freq = freq; 157 curcpu()->ci_cycles_per_hz = (freq + hz / 2) / hz / 2; 158 curcpu()->ci_divisor_delay = ((freq + 500000) / 1000000) / 2; 159 } 160 161 void mach_init(int, char **, void *, void *); /* XXX */ 162 163 static void 164 copy_args(int argc, char **argv) 165 { 166 struct adm5120_config *admc = &adm5120_configuration; 167 int i; 168 char *buf; 169 size_t buflen, rc; 170 171 buf = admc->args; 172 buflen = sizeof(admc->args); 173 174 if (argc >= __arraycount(admc->argv)) 175 panic("%s: too many boot args\n", __func__); 176 177 for (i = 0; buflen > 0 && i < argc && argv[i] != NULL; i++) { 178 admc->argv[i] = buf; 179 if ((rc = strlcpy(buf, argv[i], buflen)) >= buflen) 180 panic("%s: boot args too long\n", __func__); 181 182 buf += rc; 183 buflen -= rc; 184 *buf++ = '\0'; 185 buflen--; 186 } 187 if (i < argc) 188 panic("%s: boot args too long\n", __func__); 189 190 admc->argc = argc; 191 } 192 193 static void 194 parse_args(prop_dictionary_t properties, int argc, char **argv, 195 uint32_t *memsizep) 196 { 197 char buf[32]; 198 char *key, *val, *valend; 199 unsigned long tmp; 200 int i; 201 uint8_t enaddr[ETHER_ADDR_LEN]; 202 203 if (memsizep != NULL) 204 *memsizep = MEMSIZE; 205 206 for (i = 0; i < argc && argv[i] != NULL; i++) { 207 if (strlcpy(buf, argv[i], sizeof(buf)) >= sizeof(buf)) 208 goto err; 209 val = buf; 210 key = strsep(&val, "="); 211 if (val == NULL) 212 goto err; 213 if (strcmp(key, "mem") == 0) { 214 tmp = strtoul(val, &valend, 10); 215 if (val == valend || *valend != 'M') 216 goto err; 217 if (memsizep != NULL) 218 *memsizep = tmp * 1024 * 1024; 219 } else if (strcmp(key, "HZ") == 0) 220 ; 221 else if (strcmp(key, "gpio") == 0) { 222 prop_number_t pn; 223 224 tmp = strtoul(val, &valend, 10); 225 if (val == valend || *valend != '\0') 226 goto err; 227 if (properties == NULL) 228 continue; 229 pn = prop_number_create_unsigned_integer(tmp); 230 if (pn == NULL) { 231 printf( 232 "%s: prop_number_create_unsigned_integer\n", 233 __func__); 234 continue; 235 } 236 if (!prop_dictionary_set(properties, "initial-gpio", 237 pn)) { 238 printf("%s: prop_dictionary_set(gpio)\n", 239 __func__); 240 } 241 prop_object_release(pn); 242 } else if (strcmp(key, "kmac") == 0) { 243 prop_data_t pd; 244 245 (void)ether_aton_r(enaddr, sizeof(enaddr), val); 246 if (properties == NULL) 247 continue; 248 pd = prop_data_create_data(enaddr, sizeof(enaddr)); 249 if (pd == NULL) { 250 printf("%s: prop_data_create_data\n", __func__); 251 continue; 252 } 253 if (!prop_dictionary_set(properties, "mac-address", pd)) { 254 printf("%s: prop_dictionary_set(mac)\n", 255 __func__); 256 } 257 prop_object_release(pd); 258 } else if (strcmp(key, "board") == 0) 259 printf("Routerboard %s\n", val); 260 else if (strcmp(key, "boot") == 0) 261 ; 262 continue; 263 err: 264 printf("bad argv[%d] (%s)\n", i, argv[i]); 265 } 266 } 267 268 void 269 mach_init(int argc, char **argv, void *a2, void *a3) 270 { 271 struct adm5120_config *admc = &adm5120_configuration; 272 uint32_t memsize; 273 vaddr_t kernend; 274 275 extern char edata[], end[]; /* XXX */ 276 277 /* clear the BSS segment */ 278 kernend = mips_round_page(end); 279 memset(edata, 0, kernend - (vaddr_t)edata); 280 281 /* set CPU model info for sysctl_hw */ 282 cpu_setmodel("Infineon ADM5120"); 283 284 /* 285 * Set up the exception vectors and CPU-specific function 286 * vectors early on. We need the wbflush() vector set up 287 * before comcnattach() is called (or at least before the 288 * first printf() after that is called). 289 * Sets up mips_cpu_flags that may be queried by other 290 * functions called during startup. 291 * Also clears the I+D caches. 292 */ 293 mips_vector_init(NULL, false); 294 295 /* 296 * Set the VM page size. 297 */ 298 uvm_setpagesize(); 299 300 adm5120_setcpufreq(); 301 302 /* 303 * Initialize bus space tags. 304 */ 305 obio_bus_mem_init(&admc->obio_space, admc); 306 extio_bus_mem_init(&admc->extio_space, admc); 307 #if NPCI > 0 308 pciio_bus_mem_init(&admc->pciio_space, admc); 309 pcimem_bus_mem_init(&admc->pcimem_space, admc); 310 #endif 311 312 /* 313 * Initialize bus DMA tag. 314 */ 315 obio_dma_init(&admc->obio_dmat); 316 317 /* 318 * Attach serial console. 319 */ 320 uart_cnattach(); 321 322 /* 323 * Look at arguments passed to us and compute boothowto. 324 */ 325 boothowto = RB_AUTOBOOT; 326 #ifdef KADB 327 boothowto |= RB_KDB; 328 #endif 329 330 parse_args(NULL, argc, argv, &memsize); 331 332 /* 333 * Determine the memory size. 334 * 335 * Note: Reserve the first page! That's where the trap 336 * vectors are located. 337 */ 338 339 #if 0 340 if (GET_MEMSIZE(memsize) == 0) { 341 uint32_t val; 342 343 /* This does not seem to work... --dyoung */ 344 val = SW_READ(SW_MEMCONT_REG); 345 printf("SW_MEMCONT_REG: 0x%08" PRIx32 "\n", val); 346 switch (val & SDRAM_SIZE_MASK) { 347 case SDRAM_SIZE_4MBYTES: 348 memsize = 4 * 1024 * 1024; 349 break; 350 case SDRAM_SIZE_8MBYTES: 351 memsize = 8 * 1024 * 1024; 352 break; 353 case SDRAM_SIZE_16MBYTES: 354 memsize = 16 * 1024 * 1024; 355 break; 356 case SDRAM_SIZE_64MBYTES: 357 memsize = 64 * 1024 * 1024; 358 break; 359 case SDRAM_SIZE_128MBYTES: 360 memsize = 128 * 1024 * 1024; 361 break; 362 default: 363 panic("adm5120: cannot determine memory size"); 364 } 365 } 366 #endif 367 368 physmem = btoc(memsize); 369 370 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 371 mem_clusters[mem_cluster_cnt].size = 372 memsize - mem_clusters[mem_cluster_cnt].start; 373 mem_cluster_cnt++; 374 375 /* 376 * Load the rest of the available pages into the VM system. 377 */ 378 mips_page_physload(MIPS_KSEG0_START, (vaddr_t) kernend, 379 mem_clusters, mem_cluster_cnt, NULL, 0); 380 381 /* 382 * Initialize message buffer (at end of core). 383 */ 384 mips_init_msgbuf(); 385 386 /* 387 * Initialize the virtual memory system. 388 */ 389 pmap_bootstrap(); 390 391 /* 392 * Allocate uarea page for lwp0 and set it. 393 */ 394 mips_init_lwp0_uarea(); 395 396 /* 397 * Initialize debuggers, and break into them, if appropriate. 398 */ 399 #ifdef DDB 400 if (boothowto & RB_KDB) 401 Debugger(); 402 #endif 403 404 copy_args(argc, argv); 405 } 406 407 void 408 consinit(void) 409 { 410 411 /* 412 * Everything related to console initialization is done 413 * in mach_init(). 414 */ 415 } 416 417 void 418 cpu_startup(void) 419 { 420 struct adm5120_config *admc = &adm5120_configuration; 421 char pbuf[9]; 422 vaddr_t minaddr, maxaddr; 423 #ifdef DEBUG 424 extern int pmapdebug; /* XXX */ 425 int opmapdebug = pmapdebug; 426 427 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 428 #endif 429 430 if ((admc->properties = prop_dictionary_create()) == NULL) 431 printf("%s: prop_dictionary_create\n", __func__); 432 parse_args(admc->properties, admc->argc, admc->argv, NULL); 433 434 /* 435 * Good {morning,afternoon,evening,night}. 436 */ 437 printf("%s%s", copyright, version); 438 printf("%s\n", cpu_getmodel()); 439 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 440 printf("total memory = %s\n", pbuf); 441 442 minaddr = 0; 443 444 /* 445 * Allocate a submap for physio 446 */ 447 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 448 VM_PHYS_SIZE, 0, FALSE, NULL); 449 450 /* 451 * No need to allocate an mbuf cluster submap. Mbuf clusters 452 * are allocated via the pool allocator, and we use KSEG to 453 * map those pages. 454 */ 455 456 #ifdef DEBUG 457 pmapdebug = opmapdebug; 458 #endif 459 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 460 printf("avail memory = %s\n", pbuf); 461 } 462 463 void 464 cpu_reboot(int howto, char *bootstr) 465 { 466 static int waittime = -1; 467 468 /* Take a snapshot before clobbering any registers. */ 469 savectx(curpcb); 470 471 /* If "always halt" was specified as a boot flag, obey. */ 472 if (boothowto & RB_HALT) 473 howto |= RB_HALT; 474 475 boothowto = howto; 476 477 /* If system is cold, just halt. */ 478 if (cold) { 479 boothowto |= RB_HALT; 480 goto haltsys; 481 } 482 483 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 484 waittime = 0; 485 486 /* 487 * Synchronize the disks.... 488 */ 489 vfs_shutdown(); 490 491 /* 492 * If we've been adjusting the clock, the todr 493 * will be out of synch; adjust it now. 494 */ 495 resettodr(); 496 } 497 498 /* Disable interrupts. */ 499 splhigh(); 500 501 if (boothowto & RB_DUMP) 502 dumpsys(); 503 504 haltsys: 505 /* Run any shutdown hooks. */ 506 doshutdownhooks(); 507 508 pmf_system_shutdown(boothowto); 509 510 /* 511 * Routerboard BIOS may autoboot, so "pseudo-halt". 512 */ 513 if (boothowto & RB_HALT) { 514 printf("\n"); 515 printf("The operating system has halted.\n"); 516 printf("Please press any key to reboot.\n\n"); 517 cnpollc(1); /* For proper keyboard command handling */ 518 cngetc(); 519 cnpollc(0); 520 } 521 522 printf("reseting board...\n\n"); 523 mips_icache_sync_all(); 524 mips_dcache_wbinv_all(); 525 SW_WRITE(SW_SFTRES_REG, 0); /* reset */ 526 for (;;) 527 /* spin forever */ ; /* XXX */ 528 /*NOTREACHED*/ 529 } 530