octeon_machdep.c revision 216069
1209878Snwhitehorn/*- 2209878Snwhitehorn * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org> 3209878Snwhitehorn * All rights reserved. 4209878Snwhitehorn * 5209878Snwhitehorn * Redistribution and use in source and binary forms, with or without 6209878Snwhitehorn * modification, are permitted provided that the following conditions 7209878Snwhitehorn * are met: 8209878Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9209878Snwhitehorn * notice, this list of conditions and the following disclaimer. 10209878Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11209878Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12209878Snwhitehorn * documentation and/or other materials provided with the distribution. 13209878Snwhitehorn * 14209878Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15209878Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16209878Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17209878Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18209878Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19209878Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20209878Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21209878Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22209878Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23209878Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24209878Snwhitehorn * SUCH DAMAGE. 25209878Snwhitehorn * 26209878Snwhitehorn * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 216069 2010-11-30 01:27:54Z jmallett $ 27209878Snwhitehorn */ 28209878Snwhitehorn#include <sys/cdefs.h> 29209878Snwhitehorn__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 216069 2010-11-30 01:27:54Z jmallett $"); 30209878Snwhitehorn 31209878Snwhitehorn#include <sys/param.h> 32209878Snwhitehorn#include <sys/conf.h> 33209878Snwhitehorn#include <sys/kernel.h> 34209878Snwhitehorn#include <sys/systm.h> 35209878Snwhitehorn#include <sys/imgact.h> 36209878Snwhitehorn#include <sys/bio.h> 37209878Snwhitehorn#include <sys/buf.h> 38209878Snwhitehorn#include <sys/bus.h> 39209878Snwhitehorn#include <sys/cpu.h> 40209878Snwhitehorn#include <sys/cons.h> 41209878Snwhitehorn#include <sys/exec.h> 42209878Snwhitehorn#include <sys/ucontext.h> 43209878Snwhitehorn#include <sys/proc.h> 44209878Snwhitehorn#include <sys/kdb.h> 45209878Snwhitehorn#include <sys/ptrace.h> 46209878Snwhitehorn#include <sys/reboot.h> 47209878Snwhitehorn#include <sys/signalvar.h> 48209878Snwhitehorn#include <sys/sysent.h> 49209878Snwhitehorn#include <sys/sysproto.h> 50209878Snwhitehorn#include <sys/time.h> 51209878Snwhitehorn#include <sys/timetc.h> 52209878Snwhitehorn#include <sys/user.h> 53209878Snwhitehorn 54209878Snwhitehorn#include <vm/vm.h> 55209878Snwhitehorn#include <vm/vm_object.h> 56209878Snwhitehorn#include <vm/vm_page.h> 57209878Snwhitehorn#include <vm/vm_pager.h> 58209878Snwhitehorn 59209878Snwhitehorn#include <machine/atomic.h> 60209878Snwhitehorn#include <machine/cache.h> 61209878Snwhitehorn#include <machine/clock.h> 62209878Snwhitehorn#include <machine/cpu.h> 63209878Snwhitehorn#include <machine/cpuregs.h> 64209878Snwhitehorn#include <machine/cpufunc.h> 65209878Snwhitehorn#include <mips/cavium/octeon_pcmap_regs.h> 66209878Snwhitehorn#include <machine/hwfunc.h> 67209878Snwhitehorn#include <machine/intr_machdep.h> 68209878Snwhitehorn#include <machine/locore.h> 69209878Snwhitehorn#include <machine/md_var.h> 70209878Snwhitehorn#include <machine/pcpu.h> 71209878Snwhitehorn#include <machine/pte.h> 72209878Snwhitehorn#include <machine/trap.h> 73209878Snwhitehorn#include <machine/vmparam.h> 74209878Snwhitehorn 75209878Snwhitehorn#include <contrib/octeon-sdk/cvmx.h> 76209878Snwhitehorn#include <contrib/octeon-sdk/cvmx-bootmem.h> 77209878Snwhitehorn#include <contrib/octeon-sdk/cvmx-interrupt.h> 78209878Snwhitehorn#include <contrib/octeon-sdk/cvmx-version.h> 79209878Snwhitehorn 80209878Snwhitehorn#if defined(__mips_n64) 81209878Snwhitehorn#define MAX_APP_DESC_ADDR 0xffffffffafffffff 82209878Snwhitehorn#else 83209878Snwhitehorn#define MAX_APP_DESC_ADDR 0xafffffff 84209878Snwhitehorn#endif 85209878Snwhitehorn 86209878Snwhitehorn#define OCTEON_CLOCK_DEFAULT (500 * 1000 * 1000) 87209878Snwhitehorn 88209878Snwhitehornstruct octeon_feature_description { 89209878Snwhitehorn octeon_feature_t ofd_feature; 90209878Snwhitehorn const char *ofd_string; 91209878Snwhitehorn}; 92209878Snwhitehorn 93209878Snwhitehornextern int *edata; 94209878Snwhitehornextern int *end; 95209878Snwhitehorn 96209878Snwhitehornstatic const struct octeon_feature_description octeon_feature_descriptions[] = { 97209878Snwhitehorn { OCTEON_FEATURE_SAAD, "SAAD" }, 98209878Snwhitehorn { OCTEON_FEATURE_ZIP, "ZIP" }, 99209878Snwhitehorn { OCTEON_FEATURE_CRYPTO, "CRYPTO" }, 100209878Snwhitehorn { OCTEON_FEATURE_DORM_CRYPTO, "DORM_CRYPTO" }, 101209878Snwhitehorn { OCTEON_FEATURE_PCIE, "PCIE" }, 102209878Snwhitehorn { OCTEON_FEATURE_SRIO, "SRIO" }, 103209878Snwhitehorn { OCTEON_FEATURE_KEY_MEMORY, "KEY_MEMORY" }, 104209878Snwhitehorn { OCTEON_FEATURE_LED_CONTROLLER, "LED_CONTROLLER" }, 105209878Snwhitehorn { OCTEON_FEATURE_TRA, "TRA" }, 106209878Snwhitehorn { OCTEON_FEATURE_MGMT_PORT, "MGMT_PORT" }, 107209878Snwhitehorn { OCTEON_FEATURE_RAID, "RAID" }, 108209878Snwhitehorn { OCTEON_FEATURE_USB, "USB" }, 109209878Snwhitehorn { OCTEON_FEATURE_NO_WPTR, "NO_WPTR" }, 110209878Snwhitehorn { OCTEON_FEATURE_DFA, "DFA" }, 111209878Snwhitehorn { OCTEON_FEATURE_MDIO_CLAUSE_45, "MDIO_CLAUSE_45" }, 112209878Snwhitehorn { OCTEON_FEATURE_NPEI, "NPEI" }, 113209878Snwhitehorn { 0, NULL } 114209878Snwhitehorn}; 115209878Snwhitehorn 116209878Snwhitehornuint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip); 117209878Snwhitehornvoid ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip); 118209878Snwhitehorn 119209878Snwhitehornstatic uint64_t octeon_get_ticks(void); 120209878Snwhitehornstatic unsigned octeon_get_timecount(struct timecounter *tc); 121209878Snwhitehorn 122209878Snwhitehornstatic void octeon_boot_params_init(register_t ptr); 123209878Snwhitehorn 124209878Snwhitehornstatic struct timecounter octeon_timecounter = { 125209878Snwhitehorn octeon_get_timecount, /* get_timecount */ 126209878Snwhitehorn 0, /* no poll_pps */ 127209878Snwhitehorn 0xffffffffu, /* octeon_mask */ 128209878Snwhitehorn 0, /* frequency */ 129209878Snwhitehorn "Octeon", /* name */ 130209878Snwhitehorn 900, /* quality (adjusted in code) */ 131209878Snwhitehorn}; 132209878Snwhitehorn 133209878Snwhitehornvoid 134209878Snwhitehornplatform_cpu_init() 135209878Snwhitehorn{ 136209878Snwhitehorn /* Nothing special yet */ 137209878Snwhitehorn} 138209878Snwhitehorn 139209878Snwhitehorn/* 140209878Snwhitehorn * Perform a board-level soft-reset. 141209878Snwhitehorn */ 142209878Snwhitehornvoid 143209878Snwhitehornplatform_reset(void) 144209878Snwhitehorn{ 145209878Snwhitehorn cvmx_write_csr(CVMX_CIU_SOFT_RST, 1); 146209878Snwhitehorn} 147209878Snwhitehorn 148209878Snwhitehornvoid 149209878Snwhitehornocteon_led_write_char(int char_position, char val) 150209878Snwhitehorn{ 151209878Snwhitehorn uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 152209878Snwhitehorn 153209878Snwhitehorn if (octeon_is_simulation()) 154209878Snwhitehorn return; 155209878Snwhitehorn 156209878Snwhitehorn char_position &= 0x7; /* only 8 chars */ 157209878Snwhitehorn ptr += char_position; 158209878Snwhitehorn oct_write8_x8(ptr, val); 159209878Snwhitehorn} 160209878Snwhitehorn 161209878Snwhitehornvoid 162209878Snwhitehornocteon_led_write_char0(char val) 163209878Snwhitehorn{ 164209878Snwhitehorn uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 165209878Snwhitehorn 166209878Snwhitehorn if (octeon_is_simulation()) 167209878Snwhitehorn return; 168209878Snwhitehorn oct_write8_x8(ptr, val); 169209878Snwhitehorn} 170209878Snwhitehorn 171209878Snwhitehornvoid 172209878Snwhitehornocteon_led_write_hexchar(int char_position, char hexval) 173209878Snwhitehorn{ 174209878Snwhitehorn uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 175209878Snwhitehorn char char1, char2; 176209878Snwhitehorn 177209878Snwhitehorn if (octeon_is_simulation()) 178209878Snwhitehorn return; 179209878Snwhitehorn 180209878Snwhitehorn char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7'; 181209878Snwhitehorn char2 = (hexval & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7'; 182209878Snwhitehorn char_position &= 0x7; /* only 8 chars */ 183209878Snwhitehorn if (char_position > 6) 184209878Snwhitehorn char_position = 6; 185209878Snwhitehorn ptr += char_position; 186209878Snwhitehorn oct_write8_x8(ptr, char1); 187209878Snwhitehorn ptr++; 188209878Snwhitehorn oct_write8_x8(ptr, char2); 189209878Snwhitehorn} 190209878Snwhitehorn 191209878Snwhitehornvoid 192209878Snwhitehornocteon_led_write_string(const char *str) 193209878Snwhitehorn{ 194209878Snwhitehorn uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 195209878Snwhitehorn int i; 196209878Snwhitehorn 197209878Snwhitehorn if (octeon_is_simulation()) 198209878Snwhitehorn return; 199209878Snwhitehorn 200209878Snwhitehorn for (i=0; i<8; i++, ptr++) { 201209878Snwhitehorn if (str && *str) 202209878Snwhitehorn oct_write8_x8(ptr, *str++); 203209878Snwhitehorn else 204209878Snwhitehorn oct_write8_x8(ptr, ' '); 205209878Snwhitehorn (void)cvmx_read_csr(CVMX_MIO_BOOT_BIST_STAT); 206209878Snwhitehorn } 207209878Snwhitehorn} 208209878Snwhitehorn 209209878Snwhitehornstatic char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'}; 210209878Snwhitehorn 211209878Snwhitehornvoid 212209878Snwhitehornocteon_led_run_wheel(int *prog_count, int led_position) 213209878Snwhitehorn{ 214209878Snwhitehorn if (octeon_is_simulation()) 215209878Snwhitehorn return; 216209878Snwhitehorn octeon_led_write_char(led_position, progress[*prog_count]); 217209878Snwhitehorn *prog_count += 1; 218209878Snwhitehorn *prog_count &= 0x7; 219209878Snwhitehorn} 220209878Snwhitehorn 221209878Snwhitehornvoid 222209878Snwhitehornocteon_led_write_hex(uint32_t wl) 223209878Snwhitehorn{ 224209878Snwhitehorn char nbuf[80]; 225209878Snwhitehorn 226209878Snwhitehorn sprintf(nbuf, "%X", wl); 227209878Snwhitehorn octeon_led_write_string(nbuf); 228209878Snwhitehorn} 229209878Snwhitehorn 230209878Snwhitehorn/* 231209878Snwhitehorn * octeon_debug_symbol 232209878Snwhitehorn * 233209878Snwhitehorn * Does nothing. 234209878Snwhitehorn * Used to mark the point for simulator to begin tracing 235209878Snwhitehorn */ 236209878Snwhitehornvoid 237209878Snwhitehornocteon_debug_symbol(void) 238209878Snwhitehorn{ 239209878Snwhitehorn} 240209878Snwhitehorn 241209878Snwhitehorn/* 242209878Snwhitehorn * octeon_ciu_reset 243209878Snwhitehorn * 244209878Snwhitehorn * Shutdown all CIU to IP2, IP3 mappings 245209878Snwhitehorn */ 246209878Snwhitehornvoid 247209878Snwhitehornocteon_ciu_reset(void) 248209878Snwhitehorn{ 249209878Snwhitehorn /* Disable all CIU interrupts by default */ 250209878Snwhitehorn cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), 0); 251209878Snwhitehorn cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1), 0); 252209878Snwhitehorn cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), 0); 253209878Snwhitehorn cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2+1), 0); 254209878Snwhitehorn 255209878Snwhitehorn#ifdef SMP 256209878Snwhitehorn /* Enable the MBOX interrupts. */ 257209878Snwhitehorn cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1), 258209878Snwhitehorn (1ull << (CVMX_IRQ_MBOX0 - 8)) | 259209878Snwhitehorn (1ull << (CVMX_IRQ_MBOX1 - 8))); 260209878Snwhitehorn#endif 261209878Snwhitehorn} 262209878Snwhitehorn 263209878Snwhitehornstatic void 264209878Snwhitehornocteon_memory_init(void) 265209878Snwhitehorn{ 266209878Snwhitehorn vm_paddr_t phys_end; 267209878Snwhitehorn int64_t addr; 268209878Snwhitehorn unsigned i; 269209878Snwhitehorn 270209878Snwhitehorn phys_end = round_page(MIPS_KSEG0_TO_PHYS((vm_offset_t)&end)); 271209878Snwhitehorn 272209878Snwhitehorn if (octeon_is_simulation()) { 273209878Snwhitehorn /* Simulator we limit to 96 meg */ 274209878Snwhitehorn phys_avail[0] = phys_end; 275209878Snwhitehorn phys_avail[1] = 96 << 20; 276209878Snwhitehorn 277209878Snwhitehorn realmem = physmem = btoc(phys_avail[1] - phys_avail[0]); 278209878Snwhitehorn return; 279209878Snwhitehorn } 280209878Snwhitehorn 281209878Snwhitehorn /* 282209878Snwhitehorn * Allocate memory from bootmem 1MB at a time and merge 283209878Snwhitehorn * adjacent entries. 284209878Snwhitehorn */ 285209878Snwhitehorn i = 0; 286209878Snwhitehorn while (i < PHYS_AVAIL_ENTRIES) { 287209878Snwhitehorn addr = cvmx_bootmem_phy_alloc(1 << 20, phys_end, 288209878Snwhitehorn ~(vm_paddr_t)0, PAGE_SIZE, 0); 289209878Snwhitehorn if (addr == -1) 290209878Snwhitehorn break; 291209878Snwhitehorn 292209878Snwhitehorn /* 293209878Snwhitehorn * The SDK needs to be able to easily map any memory that might 294209878Snwhitehorn * come to it e.g. in the form of an mbuf. Because on !n64 we 295209878Snwhitehorn * can't direct-map some addresses and we don't want to manage 296209878Snwhitehorn * temporary mappings within the SDK, don't feed memory that 297209878Snwhitehorn * can't be direct-mapped to the kernel. 298209878Snwhitehorn */ 299209878Snwhitehorn#if !defined(__mips_n64) 300209878Snwhitehorn if (!MIPS_DIRECT_MAPPABLE(addr + (1 << 20) - 1)) 301209878Snwhitehorn continue; 302209878Snwhitehorn#endif 303209878Snwhitehorn 304209878Snwhitehorn physmem += btoc(1 << 20); 305209878Snwhitehorn 306209878Snwhitehorn if (i > 0 && phys_avail[i - 1] == addr) { 307209878Snwhitehorn phys_avail[i - 1] += 1 << 20; 308 continue; 309 } 310 311 phys_avail[i + 0] = addr; 312 phys_avail[i + 1] = addr + (1 << 20); 313 314 i += 2; 315 } 316 317 realmem = physmem; 318} 319 320void 321platform_start(__register_t a0, __register_t a1, __register_t a2 __unused, 322 __register_t a3) 323{ 324 const struct octeon_feature_description *ofd; 325 uint64_t platform_counter_freq; 326 327 /* 328 * XXX 329 * octeon_boot_params_init() should be called before anything else, 330 * certainly before any output; we may find out from the boot 331 * descriptor's flags that we're supposed to use the PCI or UART1 332 * consoles rather than UART0. No point doing that reorganization 333 * until we actually intercept UART_DEV_CONSOLE for the UART1 case 334 * and somehow handle the PCI console, which we lack code for 335 * entirely. 336 */ 337 338 /* Initialize pcpu stuff */ 339 mips_pcpu0_init(); 340 mips_timer_early_init(OCTEON_CLOCK_DEFAULT); 341 cninit(); 342 343 octeon_ciu_reset(); 344 octeon_boot_params_init(a3); 345 /* 346 * XXX 347 * We can certainly parse command line arguments or U-Boot environment 348 * to determine whether to bootverbose / single user / ... I think 349 * stass has patches to add support for loader things to U-Boot even. 350 */ 351 bootverbose = 1; 352 353 /* 354 * For some reason on the cn38xx simulator ebase register is set to 355 * 0x80001000 at bootup time. Move it back to the default, but 356 * when we move to having support for multiple executives, we need 357 * to rethink this. 358 */ 359 mips_wr_ebase(0x80000000); 360 361 octeon_memory_init(); 362 init_param1(); 363 init_param2(physmem); 364 mips_cpu_init(); 365 pmap_bootstrap(); 366 mips_proc0_init(); 367 mutex_init(); 368 kdb_init(); 369#ifdef KDB 370 if (boothowto & RB_KDB) 371 kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 372#endif 373 platform_counter_freq = cvmx_sysinfo_get()->cpu_clock_hz; 374 375 octeon_timecounter.tc_frequency = cvmx_sysinfo_get()->cpu_clock_hz; 376 platform_timecounter = &octeon_timecounter; 377 378 mips_timer_init_params(platform_counter_freq, 0); 379 380 set_cputicker(octeon_get_ticks, cvmx_sysinfo_get()->cpu_clock_hz, 0); 381 382#ifdef SMP 383 /* 384 * Clear any pending IPIs. 385 */ 386 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(0), 0xffffffff); 387#endif 388 389 printf("Octeon SDK: %s\n", OCTEON_SDK_VERSION_STRING); 390 printf("Available Octeon features:"); 391 for (ofd = octeon_feature_descriptions; ofd->ofd_string != NULL; ofd++) 392 if (octeon_has_feature(ofd->ofd_feature)) 393 printf(" %s", ofd->ofd_string); 394 printf("\n"); 395} 396 397static uint64_t 398octeon_get_ticks(void) 399{ 400 uint64_t cvmcount; 401 402 CVMX_MF_CYCLE(cvmcount); 403 return (cvmcount); 404} 405 406static unsigned 407octeon_get_timecount(struct timecounter *tc) 408{ 409 return ((unsigned)octeon_get_ticks()); 410} 411 412/** 413 * version of printf that works better in exception context. 414 * 415 * @param format 416 * 417 * XXX If this function weren't in cvmx-interrupt.c, we'd use the SDK version. 418 */ 419void cvmx_safe_printf(const char *format, ...) 420{ 421 char buffer[256]; 422 char *ptr = buffer; 423 int count; 424 va_list args; 425 426 va_start(args, format); 427#ifndef __U_BOOT__ 428 count = vsnprintf(buffer, sizeof(buffer), format, args); 429#else 430 count = vsprintf(buffer, format, args); 431#endif 432 va_end(args); 433 434 while (count-- > 0) 435 { 436 cvmx_uart_lsr_t lsrval; 437 438 /* Spin until there is room */ 439 do 440 { 441 lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(0)); 442#if !defined(CONFIG_OCTEON_SIM_SPEED) 443 if (lsrval.s.temt == 0) 444 cvmx_wait(10000); /* Just to reduce the load on the system */ 445#endif 446 } 447 while (lsrval.s.temt == 0); 448 449 if (*ptr == '\n') 450 cvmx_write_csr(CVMX_MIO_UARTX_THR(0), '\r'); 451 cvmx_write_csr(CVMX_MIO_UARTX_THR(0), *ptr++); 452 } 453} 454 455/* impSTART: This stuff should move back into the Cavium SDK */ 456/* 457 **************************************************************************************** 458 * 459 * APP/BOOT DESCRIPTOR STUFF 460 * 461 **************************************************************************************** 462 */ 463 464/* Define the struct that is initialized by the bootloader used by the 465 * startup code. 466 * 467 * Copyright (c) 2004, 2005, 2006 Cavium Networks. 468 * 469 * The authors hereby grant permission to use, copy, modify, distribute, 470 * and license this software and its documentation for any purpose, provided 471 * that existing copyright notices are retained in all copies and that this 472 * notice is included verbatim in any distributions. No written agreement, 473 * license, or royalty fee is required for any of the authorized uses. 474 * Modifications to this software may be copyrighted by their authors 475 * and need not follow the licensing terms described here, provided that 476 * the new terms are clearly indicated on the first page of each file where 477 * they apply. 478 */ 479 480#define OCTEON_CURRENT_DESC_VERSION 6 481#define OCTEON_ARGV_MAX_ARGS (64) 482#define OCTOEN_SERIAL_LEN 20 483 484typedef struct { 485 /* Start of block referenced by assembly code - do not change! */ 486 uint32_t desc_version; 487 uint32_t desc_size; 488 489 uint64_t stack_top; 490 uint64_t heap_base; 491 uint64_t heap_end; 492 uint64_t entry_point; /* Only used by bootloader */ 493 uint64_t desc_vaddr; 494 /* End of This block referenced by assembly code - do not change! */ 495 496 uint32_t exception_base_addr; 497 uint32_t stack_size; 498 uint32_t heap_size; 499 uint32_t argc; /* Argc count for application */ 500 uint32_t argv[OCTEON_ARGV_MAX_ARGS]; 501 uint32_t flags; 502 uint32_t core_mask; 503 uint32_t dram_size; /**< DRAM size in megabyes */ 504 uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/ 505 uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */ 506 uint32_t eclock_hz; /**< CPU clock speed, in hz */ 507 uint32_t dclock_hz; /**< DRAM clock speed, in hz */ 508 uint32_t spi_clock_hz; /**< SPI4 clock in hz */ 509 uint16_t board_type; 510 uint8_t board_rev_major; 511 uint8_t board_rev_minor; 512 uint16_t chip_type; 513 uint8_t chip_rev_major; 514 uint8_t chip_rev_minor; 515 char board_serial_number[OCTOEN_SERIAL_LEN]; 516 uint8_t mac_addr_base[6]; 517 uint8_t mac_addr_count; 518 uint64_t cvmx_desc_vaddr; 519} octeon_boot_descriptor_t; 520 521cvmx_bootinfo_t *octeon_bootinfo; 522 523static octeon_boot_descriptor_t *app_desc_ptr; 524 525int 526octeon_is_simulation(void) 527{ 528 switch (cvmx_sysinfo_get()->board_type) { 529 case CVMX_BOARD_TYPE_SIM: 530 return 1; 531 default: 532 return 0; 533 } 534} 535 536static void 537octeon_process_app_desc_ver_6(void) 538{ 539 /* XXX Why is 0x00000000ffffffffULL a bad value? */ 540 if (app_desc_ptr->cvmx_desc_vaddr == 0 || 541 app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) 542 panic("Bad octeon_bootinfo %p", octeon_bootinfo); 543 544 octeon_bootinfo = 545 (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr; 546 octeon_bootinfo = 547 (cvmx_bootinfo_t *) ((intptr_t)octeon_bootinfo | MIPS_KSEG0_START); 548 if (octeon_bootinfo->major_version != 1) 549 panic("Incompatible CVMX descriptor from bootloader: %d.%d %p", 550 (int) octeon_bootinfo->major_version, 551 (int) octeon_bootinfo->minor_version, octeon_bootinfo); 552 553 cvmx_sysinfo_minimal_initialize(octeon_bootinfo->phy_mem_desc_addr, 554 octeon_bootinfo->board_type, 555 octeon_bootinfo->board_rev_major, 556 octeon_bootinfo->board_rev_minor, 557 octeon_bootinfo->eclock_hz); 558} 559 560static void 561octeon_boot_params_init(register_t ptr) 562{ 563 if (ptr == 0 || ptr >= MAX_APP_DESC_ADDR) 564 panic("app descriptor passed at invalid address %#jx", 565 (uintmax_t)ptr); 566 567 app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr; 568 if (app_desc_ptr->desc_version < 6) 569 panic("Your boot code is too old to be supported."); 570 octeon_process_app_desc_ver_6(); 571 572 KASSERT(octeon_bootinfo != NULL, ("octeon_bootinfo should be set")); 573 574 if (cvmx_sysinfo_get()->phy_mem_desc_addr == (uint64_t)0) 575 panic("Your boot loader did not supply a memory descriptor."); 576 cvmx_bootmem_init(cvmx_sysinfo_get()->phy_mem_desc_addr); 577 578 printf("Boot Descriptor Ver: %u -> %u/%u", 579 app_desc_ptr->desc_version, octeon_bootinfo->major_version, 580 octeon_bootinfo->minor_version); 581 printf(" CPU clock: %uMHz Core Mask: %#x\n", 582 cvmx_sysinfo_get()->cpu_clock_hz / 1000000, 583 cvmx_sysinfo_get()->core_mask); 584 printf(" Board Type: %u Revision: %u/%u\n", 585 cvmx_sysinfo_get()->board_type, 586 cvmx_sysinfo_get()->board_rev_major, 587 cvmx_sysinfo_get()->board_rev_minor); 588 589 printf(" Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n", 590 octeon_bootinfo->mac_addr_base[0], 591 octeon_bootinfo->mac_addr_base[1], 592 octeon_bootinfo->mac_addr_base[2], 593 octeon_bootinfo->mac_addr_base[3], 594 octeon_bootinfo->mac_addr_base[4], 595 octeon_bootinfo->mac_addr_base[5], 596 octeon_bootinfo->mac_addr_count); 597 598#if defined(OCTEON_BOARD_CAPK_0100ND) 599 if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_CN3010_EVB_HS5) 600 printf("Compiled for CAPK-0100ND, but board type is %s\n", 601 cvmx_board_type_to_string(cvmx_sysinfo_get()->board_type)); 602#else 603 printf("Board: %s\n", 604 cvmx_board_type_to_string(cvmx_sysinfo_get()->board_type)); 605#endif 606 printf("Model: %s\n", octeon_model_get_string(cvmx_get_proc_id())); 607} 608/* impEND: This stuff should move back into the Cavium SDK */ 609