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