octeon_machdep.c revision 202997
138494Sobrien/*- 2174294Sobrien * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org> 338494Sobrien * All rights reserved. 438494Sobrien * 538494Sobrien * Redistribution and use in source and binary forms, with or without 638494Sobrien * modification, are permitted provided that the following conditions 738494Sobrien * are met: 838494Sobrien * 1. Redistributions of source code must retain the above copyright 938494Sobrien * notice, this list of conditions and the following disclaimer. 1038494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1138494Sobrien * notice, this list of conditions and the following disclaimer in the 1238494Sobrien * documentation and/or other materials provided with the distribution. 1338494Sobrien * 1438494Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2042629Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438494Sobrien * SUCH DAMAGE. 2538494Sobrien * 2638494Sobrien * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202997 2010-01-26 02:39:14Z imp $ 2738494Sobrien */ 2838494Sobrien#include <sys/cdefs.h> 2938494Sobrien__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202997 2010-01-26 02:39:14Z imp $"); 3038494Sobrien 3138494Sobrien#include <sys/param.h> 3238494Sobrien#include <sys/conf.h> 3338494Sobrien#include <sys/kernel.h> 3438494Sobrien#include <sys/systm.h> 3538494Sobrien#include <sys/imgact.h> 3638494Sobrien#include <sys/bio.h> 3738494Sobrien#include <sys/buf.h> 3838494Sobrien#include <sys/bus.h> 3938494Sobrien#include <sys/cpu.h> 40174294Sobrien#include <sys/cons.h> 4138494Sobrien#include <sys/exec.h> 4238494Sobrien#include <sys/ucontext.h> 4338494Sobrien#include <sys/proc.h> 4438494Sobrien#include <sys/kdb.h> 4538494Sobrien#include <sys/ptrace.h> 4638494Sobrien#include <sys/reboot.h> 4738494Sobrien#include <sys/signalvar.h> 4838494Sobrien#include <sys/sysent.h> 4938494Sobrien#include <sys/sysproto.h> 5038494Sobrien#include <sys/user.h> 5138494Sobrien 5238494Sobrien#include <vm/vm.h> 5338494Sobrien#include <vm/vm_object.h> 54174294Sobrien#include <vm/vm_page.h> 5538494Sobrien#include <vm/vm_pager.h> 5638494Sobrien 57174294Sobrien#include <machine/atomic.h> 58174294Sobrien#include <machine/cache.h> 59174294Sobrien#include <machine/clock.h> 60174294Sobrien#include <machine/cpu.h> 6138494Sobrien#include <machine/cpuregs.h> 6238494Sobrien#include <machine/cpufunc.h> 6338494Sobrien#include <mips/cavium/octeon_pcmap_regs.h> 6438494Sobrien#include <machine/hwfunc.h> 6538494Sobrien#include <machine/intr_machdep.h> 66174294Sobrien#include <machine/locore.h> 67174294Sobrien#include <machine/md_var.h> 68174294Sobrien#include <machine/pcpu.h> 69174294Sobrien#include <machine/pte.h> 70174294Sobrien#include <machine/trap.h> 71174294Sobrien#include <machine/vmparam.h> 72174294Sobrien 73174294Sobrien#if defined(__mips_n64) 74174294Sobrien#define MAX_APP_DESC_ADDR 0xffffffffafffffff 75174294Sobrien#else 76174294Sobrien#define MAX_APP_DESC_ADDR 0xafffffff 77174294Sobrien#endif 78174294Sobrien 79174294Sobrienextern int *edata; 8038494Sobrienextern int *end; 8138494Sobrien 8238494Sobrienuint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip); 83174294Sobrienvoid ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip); 8438494Sobrien 8538494Sobrienstatic void octeon_boot_params_init(register_t ptr); 8638494Sobrienstatic uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx); 87174294Sobrienstatic uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx); 8838494Sobrien 89174294Sobrienstatic __inline void 9038494Sobrienmips_wr_ebase(u_int32_t a0) 91174294Sobrien{ 9238494Sobrien __asm __volatile("mtc0 %[a0], $15, 1 ;" 9338494Sobrien : 9438494Sobrien : [a0] "r"(a0)); 9538494Sobrien 9638494Sobrien mips_barrier(); 9738494Sobrien} 9838494Sobrien 9938494Sobrienvoid 10038494Sobrienplatform_cpu_init() 10138494Sobrien{ 10238494Sobrien /* Nothing special yet */ 10338494Sobrien} 10438494Sobrien 10538494Sobrien/* 10638494Sobrien * Perform a board-level soft-reset. 10738494Sobrien */ 10838494Sobrienvoid 10938494Sobrienplatform_reset(void) 11038494Sobrien{ 11138494Sobrien oct_write64(OCTEON_CIU_SOFT_RST, 1); 11238494Sobrien} 11338494Sobrien 11438494Sobrien 11538494Sobrienstatic inline uint32_t 11638494Sobrienocteon_disable_interrupts(void) 11738494Sobrien{ 11838494Sobrien uint32_t status_bits; 11938494Sobrien 12038494Sobrien status_bits = mips_rd_status(); 121174294Sobrien mips_wr_status(status_bits & ~MIPS_SR_INT_IE); 122174294Sobrien return (status_bits); 12338494Sobrien} 12438494Sobrien 12538494Sobrien 12638494Sobrienstatic inline void 12738494Sobrienocteon_set_interrupts(uint32_t status_bits) 12838494Sobrien{ 12938494Sobrien mips_wr_status(status_bits); 13038494Sobrien} 13138494Sobrien 13238494Sobrien 13338494Sobrienvoid 13438494Sobrienocteon_led_write_char(int char_position, char val) 13538494Sobrien{ 13638494Sobrien uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 13738494Sobrien 13838494Sobrien if (!octeon_board_real()) 13938494Sobrien return; 140174294Sobrien 141174294Sobrien char_position &= 0x7; /* only 8 chars */ 142174294Sobrien ptr += char_position; 14338494Sobrien oct_write8_x8(ptr, val); 14438494Sobrien} 14538494Sobrien 14638494Sobrienvoid 14738494Sobrienocteon_led_write_char0(char val) 14838494Sobrien{ 14938494Sobrien uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 15038494Sobrien 15138494Sobrien if (!octeon_board_real()) 15238494Sobrien return; 15338494Sobrien oct_write8_x8(ptr, val); 15438494Sobrien} 15538494Sobrien 15638494Sobrienvoid 15738494Sobrienocteon_led_write_hexchar(int char_position, char hexval) 15838494Sobrien{ 15938494Sobrien uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 16038494Sobrien char char1, char2; 16138494Sobrien 16238494Sobrien if (!octeon_board_real()) 16338494Sobrien return; 16438494Sobrien 16538494Sobrien char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7'; 16638494Sobrien char2 = (hexval & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7'; 16738494Sobrien char_position &= 0x7; /* only 8 chars */ 16838494Sobrien if (char_position > 6) 16982794Sobrien char_position = 6; 17082794Sobrien ptr += char_position; 17182794Sobrien oct_write8_x8(ptr, char1); 17238494Sobrien ptr++; 17338494Sobrien oct_write8_x8(ptr, char2); 17438494Sobrien} 17538494Sobrien 176174294Sobrienvoid 177174294Sobrienocteon_led_write_string(const char *str) 178174294Sobrien{ 179174294Sobrien uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 180174294Sobrien int i; 181174294Sobrien 182174294Sobrien if (!octeon_board_real()) 18338494Sobrien return; 18438494Sobrien 18538494Sobrien for (i=0; i<8; i++, ptr++) { 18638494Sobrien if (str && *str) 18738494Sobrien oct_write8_x8(ptr, *str++); 18838494Sobrien else 189174294Sobrien oct_write8_x8(ptr, ' '); 19038494Sobrien oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 19138494Sobrien } 19238494Sobrien} 19338494Sobrien 19438494Sobrienstatic char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'}; 19538494Sobrien 19638494Sobrienvoid 19738494Sobrienocteon_led_run_wheel(int *prog_count, int led_position) 19838494Sobrien{ 19938494Sobrien if (!octeon_board_real()) 20038494Sobrien return; 20138494Sobrien octeon_led_write_char(led_position, progress[*prog_count]); 20238494Sobrien *prog_count += 1; 20338494Sobrien *prog_count &= 0x7; 20438494Sobrien} 20538494Sobrien 206174294Sobrien#define LSR_DATAREADY 0x01 /* Data ready */ 207174294Sobrien#define LSR_THRE 0x20 /* Transmit holding register empty */ 208174294Sobrien#define LSR_TEMT 0x40 /* Transmitter Empty. THR, TSR & FIFO */ 209174294Sobrien#define USR_TXFIFO_NOTFULL 0x02 /* Uart TX FIFO Not full */ 210174294Sobrien 211174294Sobrien/* 212174294Sobrien * octeon_uart_write_byte 213174294Sobrien * 214174294Sobrien * Put out a single byte off of uart port. 215174294Sobrien */ 216174294Sobrien 217174294Sobrienvoid 218174294Sobrienocteon_uart_write_byte(int uart_index, uint8_t ch) 219174294Sobrien{ 220174294Sobrien uint64_t val, val2; 221174294Sobrien if (uart_index < 0 || uart_index > 1) 222174294Sobrien return; 223174294Sobrien 224174294Sobrien while (1) { 225174294Sobrien val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 226174294Sobrien val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400)); 22738494Sobrien if ((((uint8_t) val) & LSR_THRE) || 22838494Sobrien (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 22938494Sobrien break; 230174294Sobrien } 231174294Sobrien } 232174294Sobrien 233174294Sobrien /* Write the byte */ 234174294Sobrien oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch); 23538494Sobrien 23638494Sobrien /* Force Flush the IOBus */ 23738494Sobrien oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 23838494Sobrien} 23938494Sobrien 24038494Sobrien 24138494Sobrienvoid 24238494Sobrienocteon_uart_write_byte0(uint8_t ch) 24338494Sobrien{ 24438494Sobrien uint64_t val, val2; 24538494Sobrien 24638494Sobrien while (1) { 24738494Sobrien val = oct_read64(OCTEON_MIO_UART0_LSR); 24838494Sobrien val2 = oct_read64(OCTEON_MIO_UART0_USR); 24938494Sobrien if ((((uint8_t) val) & LSR_THRE) || 25038494Sobrien (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 251174294Sobrien break; 25238494Sobrien } 25338494Sobrien } 254174294Sobrien 255174294Sobrien /* Write the byte */ 256174294Sobrien oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch); 257174294Sobrien 258174294Sobrien /* Force Flush the IOBus */ 259174294Sobrien oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 26038494Sobrien} 261174294Sobrien 262174294Sobrien/* 263174294Sobrien * octeon_uart_write_string 264174294Sobrien * 265174294Sobrien */ 26638494Sobrienvoid 26738494Sobrienocteon_uart_write_string(int uart_index, const char *str) 26838494Sobrien{ 269174294Sobrien /* Just loop writing one byte at a time */ 27038494Sobrien 27138494Sobrien while (*str) { 27238494Sobrien octeon_uart_write_byte(uart_index, *str); 273174294Sobrien if (*str == '\n') { 274174294Sobrien octeon_uart_write_byte(uart_index, '\r'); 27538494Sobrien } 276174294Sobrien str++; 277174294Sobrien } 278174294Sobrien} 279174294Sobrien 280174294Sobrienstatic char wstr[30]; 281119679Smbr 282119679Smbrvoid 283119679Smbrocteon_led_write_hex(uint32_t wl) 284174294Sobrien{ 285174294Sobrien char nbuf[80]; 286174294Sobrien 287174294Sobrien sprintf(nbuf, "%X", wl); 288174294Sobrien octeon_led_write_string(nbuf); 289174294Sobrien} 290174294Sobrien 291174294Sobrien 292174294Sobrienvoid octeon_uart_write_hex2(uint32_t wl, uint32_t wh) 293119679Smbr{ 294174294Sobrien sprintf(wstr, "0x%X-0x%X ", wh, wl); 295174294Sobrien octeon_uart_write_string(0, wstr); 296174294Sobrien} 297174294Sobrien 298174294Sobrienvoid 299174294Sobrienocteon_uart_write_hex(uint32_t wl) 300174294Sobrien{ 30138494Sobrien sprintf(wstr, " 0x%X ", wl); 302174294Sobrien octeon_uart_write_string(0, wstr); 30338494Sobrien} 304174294Sobrien 305174294Sobrien/* 30638494Sobrien * octeon_wait_uart_flush 30738494Sobrien */ 30838494Sobrienvoid 30938494Sobrienocteon_wait_uart_flush(int uart_index, uint8_t ch) 31038494Sobrien{ 31138494Sobrien uint64_t val; 31238494Sobrien int64_t val3; 313174294Sobrien uint32_t cpu_status_bits; 31438494Sobrien 31538494Sobrien if (uart_index < 0 || uart_index > 1) 316174294Sobrien return; 31738494Sobrien 318174294Sobrien cpu_status_bits = octeon_disable_interrupts(); 31938494Sobrien /* Force Flush the IOBus */ 32038494Sobrien oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 32138494Sobrien for (val3 = 0xfffffffff; val3 > 0; val3--) { 322174294Sobrien val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 32338494Sobrien if (((uint8_t) val) & LSR_TEMT) 32438494Sobrien break; 325174294Sobrien } 32638494Sobrien octeon_set_interrupts(cpu_status_bits); 32738494Sobrien} 328174294Sobrien 329174294Sobrien 330174294Sobrien/* 331174294Sobrien * octeon_debug_symbol 332174294Sobrien * 333174294Sobrien * Does nothing. 334174294Sobrien * Used to mark the point for simulator to begin tracing 335174294Sobrien */ 336174294Sobrienvoid 33738494Sobrienocteon_debug_symbol(void) 33838494Sobrien{ 339174294Sobrien} 340174294Sobrien 341174294Sobrienvoid 342174294Sobrienocteon_ciu_stop_gtimer(int timer) 343174294Sobrien{ 344174294Sobrien oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll); 34538494Sobrien} 34638494Sobrien 34738494Sobrienvoid 34838494Sobrienocteon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles) 34938494Sobrien{ 35038494Sobrien octeon_ciu_gentimer gentimer; 35138494Sobrien 35238494Sobrien gentimer.word64 = 0; 353174294Sobrien gentimer.bits.one_shot = one_shot; 354174294Sobrien gentimer.bits.len = time_cycles - 1; 355174294Sobrien oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64); 356174294Sobrien} 357174294Sobrien 358174294Sobrien/* 359174294Sobrien * octeon_ciu_reset 360174294Sobrien * 361174294Sobrien * Shutdown all CIU to IP2, IP3 mappings 362174294Sobrien */ 363174294Sobrienvoid 364174294Sobrienocteon_ciu_reset(void) 365174294Sobrien{ 366174294Sobrien 367174294Sobrien octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0); 368174294Sobrien octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1); 369174294Sobrien octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2); 370174294Sobrien octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3); 371174294Sobrien 372174294Sobrien ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0); 373174294Sobrien ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1); 374174294Sobrien ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0); 375174294Sobrien ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1); 376174294Sobrien 377174294Sobrien ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll); 378174294Sobrien ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll); 379174294Sobrien ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll); 380174294Sobrien} 381174294Sobrien 382174294Sobrien/* 383174294Sobrien * mips_disable_interrupt_controllers 384174294Sobrien * 385174294Sobrien * Disable interrupts in the CPU controller 386174294Sobrien */ 387174294Sobrienvoid 388174294Sobrienmips_disable_interrupt_controls(void) 389174294Sobrien{ 390174294Sobrien /* 391174294Sobrien * Disable interrupts in CIU. 392174294Sobrien */ 393174294Sobrien octeon_ciu_reset(); 394174294Sobrien} 395174294Sobrien 396174294Sobrien/* 397174294Sobrien * ciu_get_intr_sum_reg_addr 398174294Sobrien */ 399174294Sobrienstatic uint64_t 400174294Sobrienciu_get_intr_sum_reg_addr(int core_num, int intx, int enx) 401174294Sobrien{ 402174294Sobrien uint64_t ciu_intr_sum_reg_addr; 403174294Sobrien 404174294Sobrien if (enx == CIU_EN_0) 405174294Sobrien ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR + 406174294Sobrien (core_num * 0x10) + (intx * 0x8); 407174294Sobrien else 408174294Sobrien ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR; 409174294Sobrien 410174294Sobrien return (ciu_intr_sum_reg_addr); 411174294Sobrien} 412174294Sobrien 413174294Sobrien 414174294Sobrien/* 415174294Sobrien * ciu_get_intr_en_reg_addr 416174294Sobrien */ 417174294Sobrienstatic uint64_t 418174294Sobrienciu_get_intr_en_reg_addr(int core_num, int intx, int enx) 419174294Sobrien{ 420174294Sobrien uint64_t ciu_intr_reg_addr; 421174294Sobrien 422174294Sobrien ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR + 423174294Sobrien ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) + (core_num * 0x20); 424174294Sobrien return (ciu_intr_reg_addr); 425174294Sobrien} 426174294Sobrien 427174294Sobrien 428174294Sobrien 429174294Sobrien 430174294Sobrien/* 431174294Sobrien * ciu_get_intr_reg_addr 432174294Sobrien * 433174294Sobrien * 200 ---int0,en0 ip2 434174294Sobrien * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog 435174294Sobrien * 436174294Sobrien * 210 ---int0,en0 ip3 -- 437174294Sobrien * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right? 438174294Sobrien * 439174294Sobrien * 220 ---int1,en0 ip2 440174294Sobrien * 228 ---int1,en1 ip2 441174294Sobrien * 230 ---int1,en0 ip3 -- 442174294Sobrien * 238 ---int1,en1 ip3 443174294Sobrien * 444174294Sobrien */ 445174294Sobrienuint64_t 44638494Sobrienciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip) 447174294Sobrien{ 44838494Sobrien uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR; 449174294Sobrien 450174294Sobrien /* XXX kasserts? */ 451174294Sobrien if (enx < CIU_EN_0 || enx > CIU_EN_1) { 452174294Sobrien printf("%s: invalid enx value %d, should be %d or %d\n", 453174294Sobrien __FUNCTION__, enx, CIU_EN_0, CIU_EN_1); 454174294Sobrien return 0; 455174294Sobrien } 45638494Sobrien if (intx < CIU_INT_0 || intx > CIU_INT_1) { 457174294Sobrien printf("%s: invalid intx value %d, should be %d or %d\n", 458174294Sobrien __FUNCTION__, enx, CIU_INT_0, CIU_INT_1); 459174294Sobrien return 0; 460174294Sobrien } 46138494Sobrien if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) { 462174294Sobrien printf("%s: invalid ciu_ip value %d, should be %d or %d\n", 463174294Sobrien __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); 464174294Sobrien return 0; 465174294Sobrien } 466174294Sobrien 467174294Sobrien ciu_intr_reg_addr += (enx * 0x8); 468174294Sobrien ciu_intr_reg_addr += (ciu_ip * 0x10); 469174294Sobrien ciu_intr_reg_addr += (intx * 0x20); 470174294Sobrien return (ciu_intr_reg_addr); 471174294Sobrien} 472174294Sobrien 473174294Sobrien/* 474174294Sobrien * ciu_get_int_summary 475174294Sobrien */ 476174294Sobrienuint64_t 477174294Sobrienciu_get_int_summary(int core_num, int intx, int enx) 478174294Sobrien{ 479174294Sobrien uint64_t ciu_intr_sum_reg_addr; 480174294Sobrien 481174294Sobrien if (core_num == CIU_THIS_CORE) 48238494Sobrien core_num = octeon_get_core_num(); 48338494Sobrien ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 484174294Sobrien return (oct_read64(ciu_intr_sum_reg_addr)); 485174294Sobrien} 486174294Sobrien 487174294Sobrien//#define DEBUG_CIU 1 488174294Sobrien 489174294Sobrien#ifdef DEBUG_CIU 490174294Sobrien#define DEBUG_CIU_SUM 1 491174294Sobrien#define DEBUG_CIU_EN 1 492174294Sobrien#endif 493174294Sobrien 494174294Sobrien 495174294Sobrien/* 496174294Sobrien * ciu_clear_int_summary 497174294Sobrien */ 498174294Sobrienvoid 499174294Sobrienciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits) 500174294Sobrien{ 501174294Sobrien uint32_t cpu_status_bits; 502174294Sobrien uint64_t ciu_intr_sum_reg_addr; 503174294Sobrien 504174294Sobrien//#define DEBUG_CIU_SUM 1 505174294Sobrien 506174294Sobrien#ifdef DEBUG_CIU_SUM 507174294Sobrien uint64_t ciu_intr_sum_bits; 508174294Sobrien#endif 509174294Sobrien 510174294Sobrien 511174294Sobrien if (core_num == CIU_THIS_CORE) { 512174294Sobrien core_num = octeon_get_core_num(); 513174294Sobrien } 514174294Sobrien 515174294Sobrien#ifdef DEBUG_CIU_SUM 516174294Sobrien printf(" CIU: core %u clear sum IntX %u Enx %u Bits: 0x%llX\n", 517174294Sobrien core_num, intx, enx, write_bits); 518174294Sobrien#endif 519174294Sobrien 520174294Sobrien cpu_status_bits = octeon_disable_interrupts(); 521174294Sobrien 522174294Sobrien ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 523174294Sobrien 524174294Sobrien#ifdef DEBUG_CIU_SUM 525174294Sobrien ciu_intr_sum_bits = oct_read64(ciu_intr_sum_reg_addr); /* unneeded dummy read */ 526174294Sobrien printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 527174294Sobrien cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits, 528174294Sobrien ciu_intr_sum_bits | write_bits); 529174294Sobrien#endif 530174294Sobrien 531174294Sobrien oct_write64(ciu_intr_sum_reg_addr, write_bits); 532174294Sobrien oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 533174294Sobrien 534174294Sobrien#ifdef DEBUG_CIU_SUM 535174294Sobrien printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr)); 536174294Sobrien#endif 537174294Sobrien 538174294Sobrien octeon_set_interrupts(cpu_status_bits); 539174294Sobrien} 540174294Sobrien 541174294Sobrien/* 542174294Sobrien * ciu_disable_intr 543174294Sobrien */ 544174294Sobrienvoid 545174294Sobrienciu_disable_intr(int core_num, int intx, int enx) 546174294Sobrien{ 547174294Sobrien uint32_t cpu_status_bits; 548174294Sobrien uint64_t ciu_intr_reg_addr; 549174294Sobrien 550174294Sobrien if (core_num == CIU_THIS_CORE) 551174294Sobrien core_num = octeon_get_core_num(); 552174294Sobrien 553174294Sobrien cpu_status_bits = octeon_disable_interrupts(); 554174294Sobrien 555174294Sobrien ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 556174294Sobrien 557174294Sobrien oct_read64(ciu_intr_reg_addr); /* Dummy read */ 558174294Sobrien 559174294Sobrien oct_write64(ciu_intr_reg_addr, 0LL); 560174294Sobrien oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 561174294Sobrien 562174294Sobrien octeon_set_interrupts(cpu_status_bits); 563174294Sobrien} 564174294Sobrien 565174294Sobrienvoid 566174294Sobrienciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip) 567174294Sobrien{ 568174294Sobrien 569174294Sobrien uint64_t ciu_intr_reg_addr; 570174294Sobrien uint64_t ciu_intr_bits; 571174294Sobrien 572174294Sobrien if (core_num == CIU_THIS_CORE) { 573174294Sobrien core_num = octeon_get_core_num(); 574174294Sobrien } 575174294Sobrien 576174294Sobrien#ifndef OCTEON_SMP_1 577174294Sobrien ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 578174294Sobrien#else 579174294Sobrien ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 580174294Sobrien#endif 581174294Sobrien 582174294Sobrien if (!ciu_intr_reg_addr) { 583174294Sobrien printf("Bad call to %s\n", __FUNCTION__); 584174294Sobrien while(1); 585174294Sobrien return; 586174294Sobrien } 587174294Sobrien 588174294Sobrien ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 589174294Sobrien printf(" CIU core %d int: %d en: %d ip: %d Add: %#llx enabled: %#llx SR: %x\n", 590174294Sobrien core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr, 591174294Sobrien (unsigned long long)ciu_intr_bits, mips_rd_status()); 592174294Sobrien} 593174294Sobrien 594174294Sobrien 595174294Sobrien/* 596174294Sobrien * ciu_enable_interrupts 597174294Sobrien */ 598174294Sobrienvoid ciu_enable_interrupts(int core_num, int intx, int enx, 599174294Sobrien uint64_t set_these_interrupt_bits, int ciu_ip) 600174294Sobrien{ 601174294Sobrien uint32_t cpu_status_bits; 602174294Sobrien uint64_t ciu_intr_reg_addr; 603174294Sobrien uint64_t ciu_intr_bits; 604174294Sobrien 605174294Sobrien if (core_num == CIU_THIS_CORE) 606174294Sobrien core_num = octeon_get_core_num(); 607174294Sobrien 608174294Sobrien//#define DEBUG_CIU_EN 1 609174294Sobrien 610174294Sobrien#ifdef DEBUG_CIU_EN 611174294Sobrien printf(" CIU: core %u enabling Intx %u Enx %u IP %d Bits: 0x%llX\n", 612174294Sobrien core_num, intx, enx, ciu_ip, set_these_interrupt_bits); 613174294Sobrien#endif 614174294Sobrien 615174294Sobrien cpu_status_bits = octeon_disable_interrupts(); 616174294Sobrien 617174294Sobrien#ifndef OCTEON_SMP_1 618174294Sobrien ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 619174294Sobrien#else 620174294Sobrien ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 621174294Sobrien#endif 622174294Sobrien 623174294Sobrien if (!ciu_intr_reg_addr) { 624174294Sobrien printf("Bad call to %s\n", __FUNCTION__); 625174294Sobrien while(1); 626174294Sobrien return; /* XXX */ 627174294Sobrien } 628174294Sobrien 629174294Sobrien ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 630174294Sobrien 631174294Sobrien#ifdef DEBUG_CIU_EN 632174294Sobrien printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 633174294Sobrien cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits); 634174294Sobrien#endif 635174294Sobrien ciu_intr_bits |= set_these_interrupt_bits; 636174294Sobrien oct_write64(ciu_intr_reg_addr, ciu_intr_bits); 637174294Sobrien#ifdef OCTEON_SMP 638174294Sobrien mips_wbflush(); 639174294Sobrien#endif 640174294Sobrien oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 641174294Sobrien 642174294Sobrien#ifdef DEBUG_CIU_EN 643174294Sobrien printf(" Readback: 0x%llX\n\n ", 644174294Sobrien (uint64_t)oct_read64(ciu_intr_reg_addr)); 645174294Sobrien#endif 646174294Sobrien 647174294Sobrien octeon_set_interrupts(cpu_status_bits); 648174294Sobrien} 649174294Sobrien 650174294Sobrienunsigned long 651174294Sobrienocteon_get_clock_rate(void) 65238494Sobrien{ 65338494Sobrien return octeon_cpu_clock; 65438494Sobrien} 65538494Sobrien 65638494Sobrienstatic void 65738494Sobrienocteon_memory_init(void) 65838494Sobrien{ 65938494Sobrien uint32_t realmem_bytes; 66038494Sobrien 66138494Sobrien if (octeon_board_real()) { 66238494Sobrien printf("octeon_dram == %llx\n", octeon_dram); 66338494Sobrien printf("reduced to ram: %u MB", (uint32_t) octeon_dram >> 20); 66438494Sobrien 66538494Sobrien realmem_bytes = (octeon_dram - PAGE_SIZE); 66638494Sobrien realmem_bytes &= ~(PAGE_SIZE - 1); 66738494Sobrien printf("Real memory bytes is %x\n", realmem_bytes); 668174294Sobrien } else { 66938494Sobrien /* Simulator we limit to 96 meg */ 67038494Sobrien realmem_bytes = (96 << 20); 671174294Sobrien } 672174294Sobrien /* phys_avail regions are in bytes */ 673174294Sobrien phys_avail[0] = (MIPS_KSEG0_TO_PHYS((vm_offset_t)&end) + PAGE_SIZE) & ~(PAGE_SIZE - 1); 674174294Sobrien if (octeon_board_real()) { 675174294Sobrien if (realmem_bytes > OCTEON_DRAM_FIRST_256_END) 676174294Sobrien phys_avail[1] = OCTEON_DRAM_FIRST_256_END; 677174294Sobrien else 678174294Sobrien phys_avail[1] = realmem_bytes; 679174294Sobrien realmem_bytes -= OCTEON_DRAM_FIRST_256_END; 680174294Sobrien realmem_bytes &= ~(PAGE_SIZE - 1); 681174294Sobrien printf("phys_avail[0] = %x phys_avail[1] = %x\n", 682174294Sobrien phys_avail[0], phys_avail[1]); 683174294Sobrien } else { 684174294Sobrien /* Simulator gets 96Meg period. */ 685174294Sobrien phys_avail[1] = (96 << 20); 686174294Sobrien } 687174294Sobrien /*- 688174294Sobrien * Octeon Memory looks as follows: 689174294Sobrien * PA 690174294Sobrien * 0000 0000 to 0x0 0000 0000 0000 691174294Sobrien * 0FFF FFFF First 256 MB memory Maps to 0x0 0000 0FFF FFFF 692174294Sobrien * 693174294Sobrien * 1000 0000 to 0x1 0000 1000 0000 694174294Sobrien * 1FFF FFFF Uncached Bu I/O space.converted to 0x1 0000 1FFF FFFF 695174294Sobrien * 696174294Sobrien * 2FFF FFFF to Cached 0x0 0000 2000 0000 697174294Sobrien * FFFF FFFF all dram mem above the first 512M 0x3 FFFF FFFF FFFF 698174294Sobrien * 699174294Sobrien */ 700174294Sobrien physmem = btoc(phys_avail[1] - phys_avail[0]); 701174294Sobrien if ((octeon_board_real()) && 702174294Sobrien (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) { 703174294Sobrien /* take out the upper non-cached 1/2 */ 704174294Sobrien realmem_bytes -= OCTEON_DRAM_FIRST_256_END; 705174294Sobrien realmem_bytes &= ~(PAGE_SIZE - 1); 706174294Sobrien /* Now map the rest of the memory */ 707174294Sobrien phys_avail[2] = 0x20000000; 70838494Sobrien printf("realmem_bytes is now at %x\n", realmem_bytes); 70938494Sobrien phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes); 71038494Sobrien printf("Next block of memory goes from %x to %x\n", 711174294Sobrien phys_avail[2], phys_avail[3]); 71238494Sobrien physmem += btoc(phys_avail[3] - phys_avail[2]); 713174294Sobrien } else { 714174294Sobrien printf("realmem_bytes is %d\n", realmem_bytes); 715174294Sobrien } 716174294Sobrien realmem = physmem; 717174294Sobrien 718174294Sobrien printf("\nTotal DRAM Size 0x%X", (uint32_t) octeon_dram); 719174294Sobrien printf("\nBank 0 = 0x%8X -> 0x%8X", phys_avail[0], phys_avail[1]); 720174294Sobrien printf("\nBank 1 = 0x%8X -> 0x%8X\n", phys_avail[2], phys_avail[3]); 721174294Sobrien printf("\nphysmem: 0x%lx", physmem); 722174294Sobrien 723174294Sobrien Maxmem = physmem; 724174294Sobrien 725174294Sobrien} 726174294Sobrien 727174294Sobrienvoid 728174294Sobrienplatform_start(__register_t a0, __register_t a1, __register_t a2 __unused, 729174294Sobrien __register_t a3) 730174294Sobrien{ 731174294Sobrien uint64_t platform_counter_freq; 732174294Sobrien 733174294Sobrien /* Initialize pcpu stuff */ 734174294Sobrien mips_pcpu0_init(); 735174294Sobrien mips_timer_early_init(OCTEON_CLOCK_DEFAULT); 736174294Sobrien cninit(); 737174294Sobrien 738174294Sobrien octeon_ciu_reset(); 739174294Sobrien octeon_boot_params_init(a3); 740174294Sobrien bootverbose = 1; 74138494Sobrien 74238494Sobrien /* 74338494Sobrien * For some reason on the cn38xx simulator ebase register is set to 74438494Sobrien * 0x80001000 at bootup time. Move it back to the default, but 74538494Sobrien * when we move to having support for multiple executives, we need 74638494Sobrien * to rethink this. 74738494Sobrien */ 74838494Sobrien mips_wr_ebase(0x80000000); 74938494Sobrien 75038494Sobrien octeon_memory_init(); 75138494Sobrien init_param1(); 75238494Sobrien init_param2(physmem); 75338494Sobrien mips_cpu_init(); 75438494Sobrien pmap_bootstrap(); 75538494Sobrien mips_proc0_init(); 75638494Sobrien mutex_init(); 75738494Sobrien kdb_init(); 75838494Sobrien#ifdef KDB 75938494Sobrien if (boothowto & RB_KDB) 76038494Sobrien kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 76138494Sobrien#endif 76242629Sobrien platform_counter_freq = octeon_get_clock_rate(); 76338494Sobrien mips_timer_init_params(platform_counter_freq, 1); 76438494Sobrien} 765174294Sobrien 76638494Sobrien/* impSTART: This stuff should move back into the Cavium SDK */ 76738494Sobrien/* 76838494Sobrien **************************************************************************************** 76938494Sobrien * 77038494Sobrien * APP/BOOT DESCRIPTOR STUFF 77138494Sobrien * 77238494Sobrien **************************************************************************************** 77338494Sobrien */ 77438494Sobrien 77538494Sobrien/* Define the struct that is initialized by the bootloader used by the 77638494Sobrien * startup code. 77738494Sobrien * 77838494Sobrien * Copyright (c) 2004, 2005, 2006 Cavium Networks. 77938494Sobrien * 780174294Sobrien * The authors hereby grant permission to use, copy, modify, distribute, 781174294Sobrien * and license this software and its documentation for any purpose, provided 78238494Sobrien * that existing copyright notices are retained in all copies and that this 78338494Sobrien * notice is included verbatim in any distributions. No written agreement, 784 * license, or royalty fee is required for any of the authorized uses. 785 * Modifications to this software may be copyrighted by their authors 786 * and need not follow the licensing terms described here, provided that 787 * the new terms are clearly indicated on the first page of each file where 788 * they apply. 789 */ 790 791#define OCTEON_CURRENT_DESC_VERSION 6 792#define OCTEON_ARGV_MAX_ARGS (64) 793#define OCTOEN_SERIAL_LEN 20 794 795 796typedef struct { 797 /* Start of block referenced by assembly code - do not change! */ 798 uint32_t desc_version; 799 uint32_t desc_size; 800 801 uint64_t stack_top; 802 uint64_t heap_base; 803 uint64_t heap_end; 804 uint64_t entry_point; /* Only used by bootloader */ 805 uint64_t desc_vaddr; 806 /* End of This block referenced by assembly code - do not change! */ 807 808 uint32_t exception_base_addr; 809 uint32_t stack_size; 810 uint32_t heap_size; 811 uint32_t argc; /* Argc count for application */ 812 uint32_t argv[OCTEON_ARGV_MAX_ARGS]; 813 uint32_t flags; 814 uint32_t core_mask; 815 uint32_t dram_size; /**< DRAM size in megabyes */ 816 uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/ 817 uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */ 818 uint32_t eclock_hz; /**< CPU clock speed, in hz */ 819 uint32_t dclock_hz; /**< DRAM clock speed, in hz */ 820 uint32_t spi_clock_hz; /**< SPI4 clock in hz */ 821 uint16_t board_type; 822 uint8_t board_rev_major; 823 uint8_t board_rev_minor; 824 uint16_t chip_type; 825 uint8_t chip_rev_major; 826 uint8_t chip_rev_minor; 827 char board_serial_number[OCTOEN_SERIAL_LEN]; 828 uint8_t mac_addr_base[6]; 829 uint8_t mac_addr_count; 830 uint64_t cvmx_desc_vaddr; 831} octeon_boot_descriptor_t; 832 833 834typedef struct { 835 uint32_t major_version; 836 uint32_t minor_version; 837 838 uint64_t stack_top; 839 uint64_t heap_base; 840 uint64_t heap_end; 841 uint64_t desc_vaddr; 842 843 uint32_t exception_base_addr; 844 uint32_t stack_size; 845 uint32_t flags; 846 uint32_t core_mask; 847 uint32_t dram_size; /**< DRAM size in megabyes */ 848 uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/ 849 uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */ 850 uint32_t eclock_hz; /**< CPU clock speed, in hz */ 851 uint32_t dclock_hz; /**< DRAM clock speed, in hz */ 852 uint32_t spi_clock_hz; /**< SPI4 clock in hz */ 853 uint16_t board_type; 854 uint8_t board_rev_major; 855 uint8_t board_rev_minor; 856 uint16_t chip_type; 857 uint8_t chip_rev_major; 858 uint8_t chip_rev_minor; 859 char board_serial_number[OCTOEN_SERIAL_LEN]; 860 uint8_t mac_addr_base[6]; 861 uint8_t mac_addr_count; 862} cvmx_bootinfo_t; 863 864uint32_t octeon_cpu_clock; 865uint64_t octeon_dram; 866uint32_t octeon_bd_ver = 0, octeon_cvmx_bd_ver = 0, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type; 867uint8_t octeon_mac_addr[6] = { 0 }; 868int octeon_core_mask, octeon_mac_addr_count; 869int octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0; 870 871static octeon_boot_descriptor_t *app_desc_ptr; 872static cvmx_bootinfo_t *cvmx_desc_ptr; 873 874#define OCTEON_BOARD_TYPE_NONE 0 875#define OCTEON_BOARD_TYPE_SIM 1 876 877#define OCTEON_CLOCK_MIN (100 * 1000 * 1000) 878#define OCTEON_CLOCK_MAX (800 * 1000 * 1000) 879#define OCTEON_DRAM_DEFAULT (256 * 1024 * 1024) 880#define OCTEON_DRAM_MIN 30 881#define OCTEON_DRAM_MAX 3000 882 883 884int 885octeon_board_real(void) 886{ 887 if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) || 888 (octeon_board_type == OCTEON_BOARD_TYPE_SIM) || 889 !octeon_board_rev_major) 890 return 0; 891 return 1; 892} 893 894static void 895octeon_process_app_desc_ver_unknown(void) 896{ 897 printf(" Unknown Boot-Descriptor: Using Defaults\n"); 898 899 octeon_cpu_clock = OCTEON_CLOCK_DEFAULT; 900 octeon_dram = OCTEON_DRAM_DEFAULT; 901 octeon_board_rev_major = octeon_board_rev_minor = octeon_board_type = 0; 902 octeon_core_mask = 1; 903 octeon_chip_type = octeon_chip_rev_major = octeon_chip_rev_minor = 0; 904 octeon_mac_addr[0] = 0x00; octeon_mac_addr[1] = 0x0f; 905 octeon_mac_addr[2] = 0xb7; octeon_mac_addr[3] = 0x10; 906 octeon_mac_addr[4] = 0x09; octeon_mac_addr[5] = 0x06; 907 octeon_mac_addr_count = 1; 908} 909 910static int 911octeon_process_app_desc_ver_6(void) 912{ 913 /* XXX Why is 0x00000000ffffffffULL a bad value? */ 914 if (app_desc_ptr->cvmx_desc_vaddr == 0 || 915 app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) { 916 printf ("Bad cvmx_desc_ptr %p\n", cvmx_desc_ptr); 917 return 1; 918 } 919 cvmx_desc_ptr = 920 (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr; 921 cvmx_desc_ptr = 922 (cvmx_bootinfo_t *) ((intptr_t)cvmx_desc_ptr | MIPS_KSEG0_START); 923 octeon_cvmx_bd_ver = (cvmx_desc_ptr->major_version * 100) + 924 cvmx_desc_ptr->minor_version; 925 if (cvmx_desc_ptr->major_version != 1) { 926 panic("Incompatible CVMX descriptor from bootloader: %d.%d %p\n", 927 (int) cvmx_desc_ptr->major_version, 928 (int) cvmx_desc_ptr->minor_version, cvmx_desc_ptr); 929 } 930 931 octeon_core_mask = cvmx_desc_ptr->core_mask; 932 octeon_cpu_clock = cvmx_desc_ptr->eclock_hz; 933 octeon_board_type = cvmx_desc_ptr->board_type; 934 octeon_board_rev_major = cvmx_desc_ptr->board_rev_major; 935 octeon_board_rev_minor = cvmx_desc_ptr->board_rev_minor; 936 octeon_chip_type = cvmx_desc_ptr->chip_type; 937 octeon_chip_rev_major = cvmx_desc_ptr->chip_rev_major; 938 octeon_chip_rev_minor = cvmx_desc_ptr->chip_rev_minor; 939 octeon_mac_addr[0] = cvmx_desc_ptr->mac_addr_base[0]; 940 octeon_mac_addr[1] = cvmx_desc_ptr->mac_addr_base[1]; 941 octeon_mac_addr[2] = cvmx_desc_ptr->mac_addr_base[2]; 942 octeon_mac_addr[3] = cvmx_desc_ptr->mac_addr_base[3]; 943 octeon_mac_addr[4] = cvmx_desc_ptr->mac_addr_base[4]; 944 octeon_mac_addr[5] = cvmx_desc_ptr->mac_addr_base[5]; 945 octeon_mac_addr_count = cvmx_desc_ptr->mac_addr_count; 946 947 if (app_desc_ptr->dram_size > 16*1024*1024) 948 octeon_dram = (uint64_t)app_desc_ptr->dram_size; 949 else 950 octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20; 951 return 0; 952} 953 954static void 955octeon_boot_params_init(register_t ptr) 956{ 957 int bad_desc = 1; 958 959 if (ptr != 0 && ptr < MAX_APP_DESC_ADDR) { 960 app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr; 961 octeon_bd_ver = app_desc_ptr->desc_version; 962 if (app_desc_ptr->desc_version < 6) 963 panic("Your boot code is too old to be supported.\n"); 964 if (app_desc_ptr->desc_version >= 6) 965 bad_desc = octeon_process_app_desc_ver_6(); 966 } 967 if (bad_desc) 968 octeon_process_app_desc_ver_unknown(); 969 970 printf("Boot Descriptor Ver: %u -> %u/%u", 971 octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100); 972 printf(" CPU clock: %uMHz\n", octeon_cpu_clock/1000000); 973 printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20)); 974 printf(" Board Type: %u Revision: %u/%u\n", 975 octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor); 976 printf(" Octeon Chip: %u Rev %u/%u", 977 octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor); 978 979 printf(" Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n", 980 octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2], 981 octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5], 982 octeon_mac_addr_count); 983} 984/* impEND: This stuff should move back into the Cavium SDK */ 985