octeon_machdep.c revision 201921
1/*- 2 * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 201881 2010-01-09 03:08:22Z imp $ 27 */ 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 201881 2010-01-09 03:08:22Z imp $"); 30 31#include <sys/param.h> 32#include <sys/conf.h> 33#include <sys/kernel.h> 34#include <sys/systm.h> 35#include <sys/imgact.h> 36#include <sys/bio.h> 37#include <sys/buf.h> 38#include <sys/bus.h> 39#include <sys/cpu.h> 40#include <sys/cons.h> 41#include <sys/exec.h> 42#include <sys/ucontext.h> 43#include <sys/proc.h> 44#include <sys/kdb.h> 45#include <sys/ptrace.h> 46#include <sys/reboot.h> 47#include <sys/signalvar.h> 48#include <sys/sysent.h> 49#include <sys/sysproto.h> 50#include <sys/user.h> 51 52#include <vm/vm.h> 53#include <vm/vm_object.h> 54#include <vm/vm_page.h> 55#include <vm/vm_pager.h> 56 57#include <machine/atomic.h> 58#include <machine/cache.h> 59#include <machine/clock.h> 60#include <machine/cpu.h> 61#include <machine/cpuregs.h> 62#include <machine/cpufunc.h> 63#include <mips/octeon1/octeon_pcmap_regs.h> 64#include <mips/octeon1/octeonreg.h> 65#include <machine/hwfunc.h> 66#include <machine/intr_machdep.h> 67#include <machine/locore.h> 68#include <machine/md_var.h> 69#include <machine/pcpu.h> 70#include <machine/pte.h> 71#include <machine/trap.h> 72#include <machine/vmparam.h> 73 74#if defined(__mips_n64) 75#define MAX_APP_DESC_ADDR 0xffffffffafffffff 76#else 77#define MAX_APP_DESC_ADDR 0xafffffff 78#endif 79 80extern int *edata; 81extern int *end; 82 83uint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip); 84void ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip); 85 86static void octeon_boot_params_init(register_t ptr); 87static uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx); 88static uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx); 89 90void 91platform_cpu_init() 92{ 93 /* Nothing special yet */ 94} 95 96/* 97 * Perform a board-level soft-reset. 98 */ 99void 100platform_reset(void) 101{ 102 ((void(*)(void))0x1fc00000)(); /* Jump to this hex address */ 103} 104 105 106static inline uint32_t 107octeon_disable_interrupts(void) 108{ 109 uint32_t status_bits; 110 111 status_bits = mips_rd_status(); 112 mips_wr_status(status_bits & ~MIPS_SR_INT_IE); 113 return (status_bits); 114} 115 116 117static inline void 118octeon_set_interrupts(uint32_t status_bits) 119{ 120 mips_wr_status(status_bits); 121} 122 123 124void 125octeon_led_write_char(int char_position, char val) 126{ 127 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 128 129 if (!octeon_board_real()) 130 return; 131 132 char_position &= 0x7; /* only 8 chars */ 133 ptr += char_position; 134 oct_write8_x8(ptr, val); 135} 136 137void 138octeon_led_write_char0(char val) 139{ 140 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 141 142 if (!octeon_board_real()) 143 return; 144 oct_write8_x8(ptr, val); 145} 146 147void 148octeon_led_write_hexchar(int char_position, char hexval) 149{ 150 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 151 char char1, char2; 152 153 if (!octeon_board_real()) 154 return; 155 156 char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7'; 157 char2 = (hexval & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7'; 158 char_position &= 0x7; /* only 8 chars */ 159 if (char_position > 6) 160 char_position = 6; 161 ptr += char_position; 162 oct_write8_x8(ptr, char1); 163 ptr++; 164 oct_write8_x8(ptr, char2); 165} 166 167void 168octeon_led_write_string(const char *str) 169{ 170 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 171 int i; 172 173 if (!octeon_board_real()) 174 return; 175 176 for (i=0; i<8; i++, ptr++) { 177 if (str && *str) 178 oct_write8_x8(ptr, *str++); 179 else 180 oct_write8_x8(ptr, ' '); 181 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 182 } 183} 184 185static char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'}; 186 187void 188octeon_led_run_wheel(int *prog_count, int led_position) 189{ 190 if (!octeon_board_real()) 191 return; 192 octeon_led_write_char(led_position, progress[*prog_count]); 193 *prog_count += 1; 194 *prog_count &= 0x7; 195} 196 197#define LSR_DATAREADY 0x01 /* Data ready */ 198#define LSR_THRE 0x20 /* Transmit holding register empty */ 199#define LSR_TEMT 0x40 /* Transmitter Empty. THR, TSR & FIFO */ 200#define USR_TXFIFO_NOTFULL 0x02 /* Uart TX FIFO Not full */ 201 202/* 203 * octeon_uart_write_byte 204 * 205 * Put out a single byte off of uart port. 206 */ 207 208void 209octeon_uart_write_byte(int uart_index, uint8_t ch) 210{ 211 uint64_t val, val2; 212 if (uart_index < 0 || uart_index > 1) 213 return; 214 215 while (1) { 216 val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 217 val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400)); 218 if ((((uint8_t) val) & LSR_THRE) || 219 (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 220 break; 221 } 222 } 223 224 /* Write the byte */ 225 oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch); 226 227 /* Force Flush the IOBus */ 228 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 229} 230 231 232void 233octeon_uart_write_byte0(uint8_t ch) 234{ 235 uint64_t val, val2; 236 237 while (1) { 238 val = oct_read64(OCTEON_MIO_UART0_LSR); 239 val2 = oct_read64(OCTEON_MIO_UART0_USR); 240 if ((((uint8_t) val) & LSR_THRE) || 241 (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 242 break; 243 } 244 } 245 246 /* Write the byte */ 247 oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch); 248 249 /* Force Flush the IOBus */ 250 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 251} 252 253/* 254 * octeon_uart_write_string 255 * 256 */ 257void 258octeon_uart_write_string(int uart_index, const char *str) 259{ 260 /* Just loop writing one byte at a time */ 261 262 while (*str) { 263 octeon_uart_write_byte(uart_index, *str); 264 if (*str == '\n') { 265 octeon_uart_write_byte(uart_index, '\r'); 266 } 267 str++; 268 } 269} 270 271static char wstr[30]; 272 273void 274octeon_led_write_hex(uint32_t wl) 275{ 276 char nbuf[80]; 277 278 sprintf(nbuf, "%X", wl); 279 octeon_led_write_string(nbuf); 280} 281 282 283void octeon_uart_write_hex2(uint32_t wl, uint32_t wh) 284{ 285 sprintf(wstr, "0x%X-0x%X ", wh, wl); 286 octeon_uart_write_string(0, wstr); 287} 288 289void 290octeon_uart_write_hex(uint32_t wl) 291{ 292 sprintf(wstr, " 0x%X ", wl); 293 octeon_uart_write_string(0, wstr); 294} 295 296/* 297 * octeon_wait_uart_flush 298 */ 299void 300octeon_wait_uart_flush(int uart_index, uint8_t ch) 301{ 302 uint64_t val; 303 int64_t val3; 304 uint32_t cpu_status_bits; 305 306 if (uart_index < 0 || uart_index > 1) 307 return; 308 309 cpu_status_bits = octeon_disable_interrupts(); 310 /* Force Flush the IOBus */ 311 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 312 for (val3 = 0xfffffffff; val3 > 0; val3--) { 313 val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 314 if (((uint8_t) val) & LSR_TEMT) 315 break; 316 } 317 octeon_set_interrupts(cpu_status_bits); 318} 319 320 321/* 322 * octeon_debug_symbol 323 * 324 * Does nothing. 325 * Used to mark the point for simulator to begin tracing 326 */ 327void 328octeon_debug_symbol(void) 329{ 330} 331 332void 333octeon_ciu_stop_gtimer(int timer) 334{ 335 oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll); 336} 337 338void 339octeon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles) 340{ 341 octeon_ciu_gentimer gentimer; 342 343 gentimer.word64 = 0; 344 gentimer.bits.one_shot = one_shot; 345 gentimer.bits.len = time_cycles - 1; 346 oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64); 347} 348 349/* 350 * octeon_ciu_reset 351 * 352 * Shutdown all CIU to IP2, IP3 mappings 353 */ 354void 355octeon_ciu_reset(void) 356{ 357 358 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0); 359 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1); 360 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2); 361 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3); 362 363 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0); 364 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1); 365 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0); 366 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1); 367 368 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll); 369 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll); 370 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll); 371} 372 373/* 374 * mips_disable_interrupt_controllers 375 * 376 * Disable interrupts in the CPU controller 377 */ 378void 379mips_disable_interrupt_controls(void) 380{ 381 /* 382 * Disable interrupts in CIU. 383 */ 384 octeon_ciu_reset(); 385} 386 387/* 388 * ciu_get_intr_sum_reg_addr 389 */ 390static uint64_t 391ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx) 392{ 393 uint64_t ciu_intr_sum_reg_addr; 394 395 if (enx == CIU_EN_0) 396 ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR + 397 (core_num * 0x10) + (intx * 0x8); 398 else 399 ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR; 400 401 return (ciu_intr_sum_reg_addr); 402} 403 404 405/* 406 * ciu_get_intr_en_reg_addr 407 */ 408static uint64_t 409ciu_get_intr_en_reg_addr(int core_num, int intx, int enx) 410{ 411 uint64_t ciu_intr_reg_addr; 412 413 ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR + 414 ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) + (core_num * 0x20); 415 return (ciu_intr_reg_addr); 416} 417 418 419 420 421/* 422 * ciu_get_intr_reg_addr 423 * 424 * 200 ---int0,en0 ip2 425 * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog 426 * 427 * 210 ---int0,en0 ip3 -- 428 * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right? 429 * 430 * 220 ---int1,en0 ip2 431 * 228 ---int1,en1 ip2 432 * 230 ---int1,en0 ip3 -- 433 * 238 ---int1,en1 ip3 434 * 435 */ 436uint64_t 437ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip) 438{ 439 uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR; 440 441 /* XXX kasserts? */ 442 if (enx < CIU_EN_0 || enx > CIU_EN_1) { 443 printf("%s: invalid enx value %d, should be %d or %d\n", 444 __FUNCTION__, enx, CIU_EN_0, CIU_EN_1); 445 return 0; 446 } 447 if (intx < CIU_INT_0 || intx > CIU_INT_1) { 448 printf("%s: invalid intx value %d, should be %d or %d\n", 449 __FUNCTION__, enx, CIU_INT_0, CIU_INT_1); 450 return 0; 451 } 452 if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) { 453 printf("%s: invalid ciu_ip value %d, should be %d or %d\n", 454 __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); 455 return 0; 456 } 457 458 ciu_intr_reg_addr += (enx * 0x8); 459 ciu_intr_reg_addr += (ciu_ip * 0x10); 460 ciu_intr_reg_addr += (intx * 0x20); 461 return (ciu_intr_reg_addr); 462} 463 464/* 465 * ciu_get_int_summary 466 */ 467uint64_t 468ciu_get_int_summary(int core_num, int intx, int enx) 469{ 470 uint64_t ciu_intr_sum_reg_addr; 471 472 if (core_num == CIU_THIS_CORE) 473 core_num = octeon_get_core_num(); 474 ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 475 return (oct_read64(ciu_intr_sum_reg_addr)); 476} 477 478//#define DEBUG_CIU 1 479 480#ifdef DEBUG_CIU 481#define DEBUG_CIU_SUM 1 482#define DEBUG_CIU_EN 1 483#endif 484 485 486/* 487 * ciu_clear_int_summary 488 */ 489void 490ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits) 491{ 492 uint32_t cpu_status_bits; 493 uint64_t ciu_intr_sum_reg_addr; 494 495//#define DEBUG_CIU_SUM 1 496 497#ifdef DEBUG_CIU_SUM 498 uint64_t ciu_intr_sum_bits; 499#endif 500 501 502 if (core_num == CIU_THIS_CORE) { 503 core_num = octeon_get_core_num(); 504 } 505 506#ifdef DEBUG_CIU_SUM 507 printf(" CIU: core %u clear sum IntX %u Enx %u Bits: 0x%llX\n", 508 core_num, intx, enx, write_bits); 509#endif 510 511 cpu_status_bits = octeon_disable_interrupts(); 512 513 ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 514 515#ifdef DEBUG_CIU_SUM 516 ciu_intr_sum_bits = oct_read64(ciu_intr_sum_reg_addr); /* unneeded dummy read */ 517 printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 518 cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits, 519 ciu_intr_sum_bits | write_bits); 520#endif 521 522 oct_write64(ciu_intr_sum_reg_addr, write_bits); 523 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 524 525#ifdef DEBUG_CIU_SUM 526 printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr)); 527#endif 528 529 octeon_set_interrupts(cpu_status_bits); 530} 531 532/* 533 * ciu_disable_intr 534 */ 535void 536ciu_disable_intr(int core_num, int intx, int enx) 537{ 538 uint32_t cpu_status_bits; 539 uint64_t ciu_intr_reg_addr; 540 541 if (core_num == CIU_THIS_CORE) 542 core_num = octeon_get_core_num(); 543 544 cpu_status_bits = octeon_disable_interrupts(); 545 546 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 547 548 oct_read64(ciu_intr_reg_addr); /* Dummy read */ 549 550 oct_write64(ciu_intr_reg_addr, 0LL); 551 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 552 553 octeon_set_interrupts(cpu_status_bits); 554} 555 556void 557ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip) 558{ 559 560 uint64_t ciu_intr_reg_addr; 561 uint64_t ciu_intr_bits; 562 563 if (core_num == CIU_THIS_CORE) { 564 core_num = octeon_get_core_num(); 565 } 566 567#ifndef OCTEON_SMP_1 568 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 569#else 570 ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 571#endif 572 573 if (!ciu_intr_reg_addr) { 574 printf("Bad call to %s\n", __FUNCTION__); 575 while(1); 576 return; 577 } 578 579 ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 580 printf(" CIU core %d int: %d en: %d ip: %d Add: %#llx enabled: %#llx SR: %x\n", 581 core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr, 582 (unsigned long long)ciu_intr_bits, mips_rd_status()); 583} 584 585 586/* 587 * ciu_enable_interrupts 588 */ 589void ciu_enable_interrupts(int core_num, int intx, int enx, 590 uint64_t set_these_interrupt_bits, int ciu_ip) 591{ 592 uint32_t cpu_status_bits; 593 uint64_t ciu_intr_reg_addr; 594 uint64_t ciu_intr_bits; 595 596 if (core_num == CIU_THIS_CORE) 597 core_num = octeon_get_core_num(); 598 599//#define DEBUG_CIU_EN 1 600 601#ifdef DEBUG_CIU_EN 602 printf(" CIU: core %u enabling Intx %u Enx %u IP %d Bits: 0x%llX\n", 603 core_num, intx, enx, ciu_ip, set_these_interrupt_bits); 604#endif 605 606 cpu_status_bits = octeon_disable_interrupts(); 607 608#ifndef OCTEON_SMP_1 609 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 610#else 611 ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 612#endif 613 614 if (!ciu_intr_reg_addr) { 615 printf("Bad call to %s\n", __FUNCTION__); 616 while(1); 617 return; /* XXX */ 618 } 619 620 ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 621 622#ifdef DEBUG_CIU_EN 623 printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 624 cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits); 625#endif 626 ciu_intr_bits |= set_these_interrupt_bits; 627 oct_write64(ciu_intr_reg_addr, ciu_intr_bits); 628#ifdef OCTEON_SMP 629 mips_wbflush(); 630#endif 631 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 632 633#ifdef DEBUG_CIU_EN 634 printf(" Readback: 0x%llX\n\n ", 635 (uint64_t)oct_read64(ciu_intr_reg_addr)); 636#endif 637 638 octeon_set_interrupts(cpu_status_bits); 639} 640 641void 642platform_start(__register_t a0, __register_t a1, __register_t a2 __unused, 643 __register_t a3) 644{ 645 uint64_t platform_counter_freq; 646 vm_offset_t kernend; 647 int argc = a0; 648 char **argv = (char **)a1; 649 int i, mem; 650 651 /* clear the BSS and SBSS segments */ 652 kernend = round_page((vm_offset_t)&end); 653 memset(&edata, 0, kernend - (vm_offset_t)(&edata)); 654 655 /* Initialize pcpu stuff */ 656 mips_pcpu0_init(); 657 658 octeon_boot_params_init(a3); 659 /* XXX octeon boot decriptor has args in it... */ 660 octeon_ciu_reset(); 661 octeon_uart_write_string(0, "Platform Starting\n"); 662 663 /* 664 * Looking for mem=XXM argument 665 */ 666 mem = 0; /* Just something to start with */ 667 for (i=0; i < argc; i++) { 668 if (strncmp(argv[i], "mem=", 4) == 0) { 669 mem = strtol(argv[i] + 4, NULL, 0); 670 break; 671 } 672 } 673 674 bootverbose = 1; 675 if (mem > 0) 676 realmem = btoc(mem << 20); 677 else 678 realmem = btoc(32 << 20); 679 680 for (i = 0; i < 10; i++) 681 phys_avail[i] = 0; 682 683 /* phys_avail regions are in bytes */ 684 phys_avail[0] = MIPS_KSEG0_TO_PHYS((vm_offset_t)&end); 685 phys_avail[1] = ctob(realmem); 686 687 physmem = realmem; 688 689 pmap_bootstrap(); 690 mips_proc0_init(); 691 692 init_param1(); 693 /* TODO: parse argc,argv */ 694 platform_counter_freq = 330000000UL; /* XXX: from idt */ 695 mips_timer_init_params(platform_counter_freq, 1); 696 cninit(); 697 printf("cmd line: "); 698 for (i=0; i < argc; i++) 699 printf("%s ", argv[i]); 700 printf("\n"); 701 init_param2(physmem); 702 mips_cpu_init(); 703 mutex_init(); 704#ifdef DDB 705 kdb_init(); 706#endif 707} 708 709/* 710 **************************************************************************************** 711 * 712 * APP/BOOT DESCRIPTOR STUFF 713 * 714 **************************************************************************************** 715 */ 716 717/* Define the struct that is initialized by the bootloader used by the 718 * startup code. 719 * 720 * Copyright (c) 2004, 2005, 2006 Cavium Networks. 721 * 722 * The authors hereby grant permission to use, copy, modify, distribute, 723 * and license this software and its documentation for any purpose, provided 724 * that existing copyright notices are retained in all copies and that this 725 * notice is included verbatim in any distributions. No written agreement, 726 * license, or royalty fee is required for any of the authorized uses. 727 * Modifications to this software may be copyrighted by their authors 728 * and need not follow the licensing terms described here, provided that 729 * the new terms are clearly indicated on the first page of each file where 730 * they apply. 731 */ 732 733#define OCTEON_CURRENT_DESC_VERSION 6 734#define OCTEON_ARGV_MAX_ARGS (64) 735#define OCTOEN_SERIAL_LEN 20 736 737 738typedef struct { 739 /* Start of block referenced by assembly code - do not change! */ 740 uint32_t desc_version; 741 uint32_t desc_size; 742 743 uint64_t stack_top; 744 uint64_t heap_base; 745 uint64_t heap_end; 746 uint64_t entry_point; /* Only used by bootloader */ 747 uint64_t desc_vaddr; 748 /* End of This block referenced by assembly code - do not change! */ 749 750 uint32_t exception_base_addr; 751 uint32_t stack_size; 752 uint32_t heap_size; 753 uint32_t argc; /* Argc count for application */ 754 uint32_t argv[OCTEON_ARGV_MAX_ARGS]; 755 uint32_t flags; 756 uint32_t core_mask; 757 uint32_t dram_size; /**< DRAM size in megabyes */ 758 uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/ 759 uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */ 760 uint32_t eclock_hz; /**< CPU clock speed, in hz */ 761 uint32_t dclock_hz; /**< DRAM clock speed, in hz */ 762 uint32_t spi_clock_hz; /**< SPI4 clock in hz */ 763 uint16_t board_type; 764 uint8_t board_rev_major; 765 uint8_t board_rev_minor; 766 uint16_t chip_type; 767 uint8_t chip_rev_major; 768 uint8_t chip_rev_minor; 769 char board_serial_number[OCTOEN_SERIAL_LEN]; 770 uint8_t mac_addr_base[6]; 771 uint8_t mac_addr_count; 772 uint64_t cvmx_desc_vaddr; 773} octeon_boot_descriptor_t; 774 775 776typedef struct { 777 uint32_t major_version; 778 uint32_t minor_version; 779 780 uint64_t stack_top; 781 uint64_t heap_base; 782 uint64_t heap_end; 783 uint64_t desc_vaddr; 784 785 uint32_t exception_base_addr; 786 uint32_t stack_size; 787 uint32_t flags; 788 uint32_t core_mask; 789 uint32_t dram_size; /**< DRAM size in megabyes */ 790 uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/ 791 uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */ 792 uint32_t eclock_hz; /**< CPU clock speed, in hz */ 793 uint32_t dclock_hz; /**< DRAM clock speed, in hz */ 794 uint32_t spi_clock_hz; /**< SPI4 clock in hz */ 795 uint16_t board_type; 796 uint8_t board_rev_major; 797 uint8_t board_rev_minor; 798 uint16_t chip_type; 799 uint8_t chip_rev_major; 800 uint8_t chip_rev_minor; 801 char board_serial_number[OCTOEN_SERIAL_LEN]; 802 uint8_t mac_addr_base[6]; 803 uint8_t mac_addr_count; 804} cvmx_bootinfo_t; 805 806uint32_t octeon_cpu_clock; 807uint64_t octeon_dram; 808uint32_t octeon_bd_ver = 0, octeon_cvmx_bd_ver = 0, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type; 809uint8_t octeon_mac_addr[6] = { 0 }; 810int octeon_core_mask, octeon_mac_addr_count; 811int octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0; 812 813extern int32_t app_descriptor_addr; 814static octeon_boot_descriptor_t *app_desc_ptr; 815static cvmx_bootinfo_t *cvmx_desc_ptr; 816 817#define OCTEON_BOARD_TYPE_NONE 0 818#define OCTEON_BOARD_TYPE_SIM 1 819 820#define OCTEON_CLOCK_MIN (100 * 1000 * 1000) 821#define OCTEON_CLOCK_MAX (800 * 1000 * 1000) 822#define OCTEON_DRAM_DEFAULT (256 * 1024 * 1024) 823#define OCTEON_DRAM_MIN 30 824#define OCTEON_DRAM_MAX 3000 825 826 827int 828octeon_board_real(void) 829{ 830 if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) || 831 (octeon_board_type == OCTEON_BOARD_TYPE_SIM) || 832 !octeon_board_rev_major) 833 return 0; 834 return 1; 835} 836 837static void 838octeon_process_app_desc_ver_unknown(void) 839{ 840 printf(" Unknown Boot-Descriptor: Using Defaults\n"); 841 842 octeon_cpu_clock = OCTEON_CLOCK_DEFAULT; 843 octeon_dram = OCTEON_DRAM_DEFAULT; 844 octeon_board_rev_major = octeon_board_rev_minor = octeon_board_type = 0; 845 octeon_core_mask = 1; 846 octeon_cpu_clock = OCTEON_CLOCK_DEFAULT; 847 octeon_chip_type = octeon_chip_rev_major = octeon_chip_rev_minor = 0; 848 octeon_mac_addr[0] = 0x00; octeon_mac_addr[1] = 0x0f; 849 octeon_mac_addr[2] = 0xb7; octeon_mac_addr[3] = 0x10; 850 octeon_mac_addr[4] = 0x09; octeon_mac_addr[5] = 0x06; 851 octeon_mac_addr_count = 1; 852} 853 854static int 855octeon_process_app_desc_ver_6(void) 856{ 857 /* XXX Why is 0x00000000ffffffffULL a bad value? */ 858 if (app_desc_ptr->cvmx_desc_vaddr == 0 || 859 app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) { 860 printf ("Bad cvmx_desc_ptr %p\n", cvmx_desc_ptr); 861 return 1; 862 } 863 cvmx_desc_ptr = 864 (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr; 865 cvmx_desc_ptr = 866 (cvmx_bootinfo_t *) ((intptr_t)cvmx_desc_ptr | MIPS_KSEG0_START); 867 octeon_cvmx_bd_ver = (cvmx_desc_ptr->major_version * 100) + 868 cvmx_desc_ptr->minor_version; 869 /* Too early for panic? */ 870 if (cvmx_desc_ptr->major_version != 1) { 871 printf("Incompatible CVMX descriptor from bootloader: %d.%d %p\n", 872 (int) cvmx_desc_ptr->major_version, 873 (int) cvmx_desc_ptr->minor_version, cvmx_desc_ptr); 874 while (1); /* Never return */ 875 return 1; /* Satisfy the compiler */ 876 } 877 878 octeon_core_mask = cvmx_desc_ptr->core_mask; 879 octeon_cpu_clock = cvmx_desc_ptr->eclock_hz; 880 octeon_board_type = cvmx_desc_ptr->board_type; 881 octeon_board_rev_major = cvmx_desc_ptr->board_rev_major; 882 octeon_board_rev_minor = cvmx_desc_ptr->board_rev_minor; 883 octeon_chip_type = cvmx_desc_ptr->chip_type; 884 octeon_chip_rev_major = cvmx_desc_ptr->chip_rev_major; 885 octeon_chip_rev_minor = cvmx_desc_ptr->chip_rev_minor; 886 octeon_mac_addr[0] = cvmx_desc_ptr->mac_addr_base[0]; 887 octeon_mac_addr[1] = cvmx_desc_ptr->mac_addr_base[1]; 888 octeon_mac_addr[2] = cvmx_desc_ptr->mac_addr_base[2]; 889 octeon_mac_addr[3] = cvmx_desc_ptr->mac_addr_base[3]; 890 octeon_mac_addr[4] = cvmx_desc_ptr->mac_addr_base[4]; 891 octeon_mac_addr[5] = cvmx_desc_ptr->mac_addr_base[5]; 892 octeon_mac_addr_count = cvmx_desc_ptr->mac_addr_count; 893 894 if (app_desc_ptr->dram_size > 16*1024*1024) 895 octeon_dram = (uint64_t)app_desc_ptr->dram_size; 896 else 897 octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20; 898 return 0; 899} 900 901static int 902octeon_process_app_desc_ver_3_4_5(void) 903{ 904 905 octeon_cvmx_bd_ver = octeon_bd_ver; 906 octeon_core_mask = app_desc_ptr->core_mask; 907 908 if (app_desc_ptr->desc_version > 3) 909 octeon_cpu_clock = app_desc_ptr->eclock_hz; 910 else 911 octeon_cpu_clock = OCTEON_CLOCK_DEFAULT; 912 if (app_desc_ptr->dram_size > 16*1024*1024) 913 octeon_dram = (uint64_t)app_desc_ptr->dram_size; 914 else 915 octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20; 916 917 if (app_desc_ptr->desc_version > 4) { 918 octeon_board_type = app_desc_ptr->board_type; 919 octeon_board_rev_major = app_desc_ptr->board_rev_major; 920 octeon_board_rev_minor = app_desc_ptr->board_rev_minor; 921 octeon_chip_type = app_desc_ptr->chip_type; 922 octeon_chip_rev_major = app_desc_ptr->chip_rev_major; 923 octeon_chip_rev_minor = app_desc_ptr->chip_rev_minor; 924 925 octeon_mac_addr[0] = app_desc_ptr->mac_addr_base[0]; 926 octeon_mac_addr[1] = app_desc_ptr->mac_addr_base[1]; 927 octeon_mac_addr[2] = app_desc_ptr->mac_addr_base[2]; 928 octeon_mac_addr[3] = app_desc_ptr->mac_addr_base[3]; 929 octeon_mac_addr[4] = app_desc_ptr->mac_addr_base[4]; 930 octeon_mac_addr[5] = app_desc_ptr->mac_addr_base[5]; 931 octeon_mac_addr_count = app_desc_ptr->mac_addr_count; 932 } 933 return 0; 934} 935 936 937static void 938octeon_boot_params_init(register_t ptr) 939{ 940 int bad_desc = 1; 941 942 if (ptr != 0 && ptr < MAX_APP_DESC_ADDR) { 943 app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr; 944 octeon_bd_ver = app_desc_ptr->desc_version; 945 if ((octeon_bd_ver >= 3) && (octeon_bd_ver <= 5)) 946 bad_desc = octeon_process_app_desc_ver_3_4_5(); 947 else if (app_desc_ptr->desc_version == 6) 948 bad_desc = octeon_process_app_desc_ver_6(); 949 } 950 if (bad_desc) 951 octeon_process_app_desc_ver_unknown(); 952 953 printf("Boot Descriptor Ver: %u -> %u/%u", 954 octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100); 955 printf(" CPU clock: %uMHz\n", octeon_cpu_clock/1000000); 956 printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20)); 957 printf(" Board Type: %u Revision: %u/%u\n", 958 octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor); 959 printf(" Octeon Chip: %u Rev %u/%u", 960 octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor); 961 962 printf(" Mac Address %02X.%02X.%02X.%02X.%02X.%02X\n", 963 octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2], 964 octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5]); 965} 966