octeon_machdep.c revision 202850
1194140Simp/*- 2194140Simp * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org> 3194140Simp * All rights reserved. 4194140Simp * 5194140Simp * Redistribution and use in source and binary forms, with or without 6194140Simp * modification, are permitted provided that the following conditions 7194140Simp * are met: 8194140Simp * 1. Redistributions of source code must retain the above copyright 9194140Simp * notice, this list of conditions and the following disclaimer. 10194140Simp * 2. Redistributions in binary form must reproduce the above copyright 11194140Simp * notice, this list of conditions and the following disclaimer in the 12194140Simp * documentation and/or other materials provided with the distribution. 13194140Simp * 14194140Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15194140Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16194140Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17194140Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18194140Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19194140Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20194140Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21194140Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22194140Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23194140Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24194140Simp * SUCH DAMAGE. 25194140Simp * 26194140Simp * $FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202850 2010-01-23 00:24:31Z imp $ 27194140Simp */ 28194140Simp#include <sys/cdefs.h> 29194140Simp__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202850 2010-01-23 00:24:31Z imp $"); 30194140Simp 31194140Simp#include <sys/param.h> 32196262Simp#include <sys/conf.h> 33196262Simp#include <sys/kernel.h> 34194140Simp#include <sys/systm.h> 35196262Simp#include <sys/imgact.h> 36196262Simp#include <sys/bio.h> 37196262Simp#include <sys/buf.h> 38196262Simp#include <sys/bus.h> 39196262Simp#include <sys/cpu.h> 40196262Simp#include <sys/cons.h> 41196262Simp#include <sys/exec.h> 42196262Simp#include <sys/ucontext.h> 43196262Simp#include <sys/proc.h> 44196262Simp#include <sys/kdb.h> 45196262Simp#include <sys/ptrace.h> 46196262Simp#include <sys/reboot.h> 47196262Simp#include <sys/signalvar.h> 48196262Simp#include <sys/sysent.h> 49196262Simp#include <sys/sysproto.h> 50196262Simp#include <sys/user.h> 51196262Simp 52196262Simp#include <vm/vm.h> 53196262Simp#include <vm/vm_object.h> 54196262Simp#include <vm/vm_page.h> 55196262Simp#include <vm/vm_pager.h> 56196262Simp 57196262Simp#include <machine/atomic.h> 58196262Simp#include <machine/cache.h> 59196262Simp#include <machine/clock.h> 60196262Simp#include <machine/cpu.h> 61194140Simp#include <machine/cpuregs.h> 62194140Simp#include <machine/cpufunc.h> 63202063Simp#include <mips/cavium/octeon_pcmap_regs.h> 64202063Simp#include <mips/cavium/octeonreg.h> 65196262Simp#include <machine/hwfunc.h> 66196262Simp#include <machine/intr_machdep.h> 67196262Simp#include <machine/locore.h> 68196262Simp#include <machine/md_var.h> 69194140Simp#include <machine/pcpu.h> 70196262Simp#include <machine/pte.h> 71196262Simp#include <machine/trap.h> 72196262Simp#include <machine/vmparam.h> 73194140Simp 74194140Simp#if defined(__mips_n64) 75196262Simp#define MAX_APP_DESC_ADDR 0xffffffffafffffff 76194140Simp#else 77196262Simp#define MAX_APP_DESC_ADDR 0xafffffff 78194140Simp#endif 79194140Simp 80202831Simpstatic struct pcpu pcpu0; 81196262Simpextern int *edata; 82196262Simpextern int *end; 83194140Simp 84201530Simpuint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip); 85201530Simpvoid ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip); 86201530Simp 87200344Simpstatic void octeon_boot_params_init(register_t ptr); 88201530Simpstatic uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx); 89201530Simpstatic uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx); 90200344Simp 91202831Simpstatic __inline void 92202831Simpmips_wr_ebase(u_int32_t a0) 93202831Simp{ 94202831Simp __asm __volatile("mtc0 %[a0], $15, 1 ;" 95202831Simp : 96202831Simp : [a0] "r"(a0)); 97202831Simp 98202831Simp mips_barrier(); 99202831Simp} 100202831Simp 101198669Srrsvoid 102198669Srrsplatform_cpu_init() 103198669Srrs{ 104198669Srrs /* Nothing special yet */ 105198669Srrs} 106196262Simp 107194140Simp/* 108194140Simp * Perform a board-level soft-reset. 109194140Simp */ 110196314Simpvoid 111196314Simpplatform_reset(void) 112194140Simp{ 113202850Simp mips_generic_reset(); 114194140Simp} 115194140Simp 116194140Simp 117201530Simpstatic inline uint32_t 118201530Simpocteon_disable_interrupts(void) 119194140Simp{ 120201530Simp uint32_t status_bits; 121194140Simp 122201530Simp status_bits = mips_rd_status(); 123201530Simp mips_wr_status(status_bits & ~MIPS_SR_INT_IE); 124201530Simp return (status_bits); 125194140Simp} 126194140Simp 127194140Simp 128201530Simpstatic inline void 129201530Simpocteon_set_interrupts(uint32_t status_bits) 130194140Simp{ 131201530Simp mips_wr_status(status_bits); 132194140Simp} 133194140Simp 134194140Simp 135201530Simpvoid 136201530Simpocteon_led_write_char(int char_position, char val) 137194140Simp{ 138201530Simp uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 139194140Simp 140201530Simp if (!octeon_board_real()) 141201530Simp return; 142194140Simp 143201530Simp char_position &= 0x7; /* only 8 chars */ 144201530Simp ptr += char_position; 145201530Simp oct_write8_x8(ptr, val); 146194140Simp} 147194140Simp 148201530Simpvoid 149201530Simpocteon_led_write_char0(char val) 150194140Simp{ 151201530Simp uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 152194140Simp 153201530Simp if (!octeon_board_real()) 154201530Simp return; 155201530Simp oct_write8_x8(ptr, val); 156194140Simp} 157194140Simp 158201530Simpvoid 159201530Simpocteon_led_write_hexchar(int char_position, char hexval) 160194140Simp{ 161201530Simp uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 162201530Simp char char1, char2; 163194140Simp 164201530Simp if (!octeon_board_real()) 165201530Simp return; 166194140Simp 167201530Simp char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7'; 168201530Simp char2 = (hexval & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7'; 169201530Simp char_position &= 0x7; /* only 8 chars */ 170201530Simp if (char_position > 6) 171201530Simp char_position = 6; 172201530Simp ptr += char_position; 173201530Simp oct_write8_x8(ptr, char1); 174201530Simp ptr++; 175201530Simp oct_write8_x8(ptr, char2); 176194140Simp} 177194140Simp 178201530Simpvoid 179201530Simpocteon_led_write_string(const char *str) 180194140Simp{ 181201530Simp uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 182201530Simp int i; 183194140Simp 184201530Simp if (!octeon_board_real()) 185201530Simp return; 186194140Simp 187201530Simp for (i=0; i<8; i++, ptr++) { 188201530Simp if (str && *str) 189201530Simp oct_write8_x8(ptr, *str++); 190201530Simp else 191201530Simp oct_write8_x8(ptr, ' '); 192201530Simp oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 193201530Simp } 194194140Simp} 195194140Simp 196194140Simpstatic char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'}; 197194140Simp 198201530Simpvoid 199201530Simpocteon_led_run_wheel(int *prog_count, int led_position) 200194140Simp{ 201201530Simp if (!octeon_board_real()) 202201530Simp return; 203201530Simp octeon_led_write_char(led_position, progress[*prog_count]); 204201530Simp *prog_count += 1; 205201530Simp *prog_count &= 0x7; 206194140Simp} 207194140Simp 208194140Simp#define LSR_DATAREADY 0x01 /* Data ready */ 209194140Simp#define LSR_THRE 0x20 /* Transmit holding register empty */ 210194140Simp#define LSR_TEMT 0x40 /* Transmitter Empty. THR, TSR & FIFO */ 211194140Simp#define USR_TXFIFO_NOTFULL 0x02 /* Uart TX FIFO Not full */ 212194140Simp 213194140Simp/* 214194140Simp * octeon_uart_write_byte 215194140Simp * 216194140Simp * Put out a single byte off of uart port. 217194140Simp */ 218194140Simp 219201530Simpvoid 220201530Simpocteon_uart_write_byte(int uart_index, uint8_t ch) 221194140Simp{ 222201530Simp uint64_t val, val2; 223201530Simp if (uart_index < 0 || uart_index > 1) 224201530Simp return; 225194140Simp 226201530Simp while (1) { 227201530Simp val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 228201530Simp val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400)); 229201530Simp if ((((uint8_t) val) & LSR_THRE) || 230201530Simp (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 231201530Simp break; 232201530Simp } 233201530Simp } 234194140Simp 235201530Simp /* Write the byte */ 236201530Simp oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch); 237194140Simp 238201530Simp /* Force Flush the IOBus */ 239201530Simp oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 240194140Simp} 241194140Simp 242194140Simp 243201530Simpvoid 244201530Simpocteon_uart_write_byte0(uint8_t ch) 245194140Simp{ 246201530Simp uint64_t val, val2; 247194140Simp 248201530Simp while (1) { 249201530Simp val = oct_read64(OCTEON_MIO_UART0_LSR); 250201530Simp val2 = oct_read64(OCTEON_MIO_UART0_USR); 251201530Simp if ((((uint8_t) val) & LSR_THRE) || 252201530Simp (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 253201530Simp break; 254201530Simp } 255201530Simp } 256194140Simp 257201530Simp /* Write the byte */ 258201530Simp oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch); 259194140Simp 260201530Simp /* Force Flush the IOBus */ 261201530Simp oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 262194140Simp} 263194140Simp 264194140Simp/* 265194140Simp * octeon_uart_write_string 266194140Simp * 267194140Simp */ 268201530Simpvoid 269201530Simpocteon_uart_write_string(int uart_index, const char *str) 270194140Simp{ 271201530Simp /* Just loop writing one byte at a time */ 272194140Simp 273201530Simp while (*str) { 274201530Simp octeon_uart_write_byte(uart_index, *str); 275201530Simp if (*str == '\n') { 276201530Simp octeon_uart_write_byte(uart_index, '\r'); 277201530Simp } 278201530Simp str++; 279201530Simp } 280201530Simp} 281194140Simp 282194140Simpstatic char wstr[30]; 283194140Simp 284201530Simpvoid 285201530Simpocteon_led_write_hex(uint32_t wl) 286194140Simp{ 287201530Simp char nbuf[80]; 288194140Simp 289201530Simp sprintf(nbuf, "%X", wl); 290201530Simp octeon_led_write_string(nbuf); 291194140Simp} 292194140Simp 293194140Simp 294201530Simpvoid octeon_uart_write_hex2(uint32_t wl, uint32_t wh) 295194140Simp{ 296201530Simp sprintf(wstr, "0x%X-0x%X ", wh, wl); 297201530Simp octeon_uart_write_string(0, wstr); 298194140Simp} 299194140Simp 300201530Simpvoid 301201530Simpocteon_uart_write_hex(uint32_t wl) 302194140Simp{ 303201530Simp sprintf(wstr, " 0x%X ", wl); 304201530Simp octeon_uart_write_string(0, wstr); 305194140Simp} 306194140Simp 307194140Simp/* 308194140Simp * octeon_wait_uart_flush 309194140Simp */ 310201530Simpvoid 311201530Simpocteon_wait_uart_flush(int uart_index, uint8_t ch) 312194140Simp{ 313201530Simp uint64_t val; 314201530Simp int64_t val3; 315201530Simp uint32_t cpu_status_bits; 316194140Simp 317201530Simp if (uart_index < 0 || uart_index > 1) 318201530Simp return; 319194140Simp 320201530Simp cpu_status_bits = octeon_disable_interrupts(); 321201530Simp /* Force Flush the IOBus */ 322201530Simp oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 323201530Simp for (val3 = 0xfffffffff; val3 > 0; val3--) { 324201530Simp val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 325201530Simp if (((uint8_t) val) & LSR_TEMT) 326201530Simp break; 327201530Simp } 328201530Simp octeon_set_interrupts(cpu_status_bits); 329194140Simp} 330194140Simp 331194140Simp 332194140Simp/* 333194140Simp * octeon_debug_symbol 334194140Simp * 335194140Simp * Does nothing. 336194140Simp * Used to mark the point for simulator to begin tracing 337194140Simp */ 338201530Simpvoid 339201530Simpocteon_debug_symbol(void) 340194140Simp{ 341194140Simp} 342194140Simp 343201530Simpvoid 344201530Simpocteon_ciu_stop_gtimer(int timer) 345194140Simp{ 346201530Simp oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll); 347194140Simp} 348194140Simp 349201530Simpvoid 350201530Simpocteon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles) 351194140Simp{ 352194140Simp octeon_ciu_gentimer gentimer; 353194140Simp 354194140Simp gentimer.word64 = 0; 355194140Simp gentimer.bits.one_shot = one_shot; 356194140Simp gentimer.bits.len = time_cycles - 1; 357194140Simp oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64); 358194140Simp} 359194140Simp 360194140Simp/* 361194140Simp * octeon_ciu_reset 362194140Simp * 363194140Simp * Shutdown all CIU to IP2, IP3 mappings 364194140Simp */ 365201530Simpvoid 366201530Simpocteon_ciu_reset(void) 367194140Simp{ 368194140Simp 369201530Simp octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0); 370201530Simp octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1); 371201530Simp octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2); 372201530Simp octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3); 373194140Simp 374201530Simp ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0); 375201530Simp ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1); 376201530Simp ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0); 377201530Simp ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1); 378194140Simp 379201530Simp ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll); 380201530Simp ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll); 381201530Simp ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll); 382194140Simp} 383194140Simp 384194140Simp/* 385194140Simp * mips_disable_interrupt_controllers 386194140Simp * 387194140Simp * Disable interrupts in the CPU controller 388194140Simp */ 389201530Simpvoid 390201530Simpmips_disable_interrupt_controls(void) 391194140Simp{ 392201530Simp /* 393201530Simp * Disable interrupts in CIU. 394201530Simp */ 395201530Simp octeon_ciu_reset(); 396194140Simp} 397194140Simp 398194140Simp/* 399194140Simp * ciu_get_intr_sum_reg_addr 400194140Simp */ 401201530Simpstatic uint64_t 402201530Simpciu_get_intr_sum_reg_addr(int core_num, int intx, int enx) 403194140Simp{ 404201530Simp uint64_t ciu_intr_sum_reg_addr; 405194140Simp 406201530Simp if (enx == CIU_EN_0) 407201530Simp ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR + 408201530Simp (core_num * 0x10) + (intx * 0x8); 409201530Simp else 410194140Simp ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR; 411194140Simp 412194140Simp return (ciu_intr_sum_reg_addr); 413194140Simp} 414194140Simp 415194140Simp 416194140Simp/* 417194140Simp * ciu_get_intr_en_reg_addr 418194140Simp */ 419201530Simpstatic uint64_t 420201530Simpciu_get_intr_en_reg_addr(int core_num, int intx, int enx) 421194140Simp{ 422201530Simp uint64_t ciu_intr_reg_addr; 423194140Simp 424201530Simp ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR + 425201530Simp ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) + (core_num * 0x20); 426194140Simp return (ciu_intr_reg_addr); 427194140Simp} 428194140Simp 429194140Simp 430194140Simp 431194140Simp 432194140Simp/* 433194140Simp * ciu_get_intr_reg_addr 434194140Simp * 435194140Simp * 200 ---int0,en0 ip2 436194140Simp * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog 437194140Simp * 438194140Simp * 210 ---int0,en0 ip3 -- 439194140Simp * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right? 440194140Simp * 441194140Simp * 220 ---int1,en0 ip2 442194140Simp * 228 ---int1,en1 ip2 443194140Simp * 230 ---int1,en0 ip3 -- 444194140Simp * 238 ---int1,en1 ip3 445194140Simp * 446194140Simp */ 447201530Simpuint64_t 448201530Simpciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip) 449194140Simp{ 450201530Simp uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR; 451194140Simp 452201530Simp /* XXX kasserts? */ 453201530Simp if (enx < CIU_EN_0 || enx > CIU_EN_1) { 454201530Simp printf("%s: invalid enx value %d, should be %d or %d\n", 455201530Simp __FUNCTION__, enx, CIU_EN_0, CIU_EN_1); 456201530Simp return 0; 457201530Simp } 458201530Simp if (intx < CIU_INT_0 || intx > CIU_INT_1) { 459201530Simp printf("%s: invalid intx value %d, should be %d or %d\n", 460201530Simp __FUNCTION__, enx, CIU_INT_0, CIU_INT_1); 461201530Simp return 0; 462201530Simp } 463201530Simp if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) { 464201530Simp printf("%s: invalid ciu_ip value %d, should be %d or %d\n", 465201530Simp __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); 466201530Simp return 0; 467201530Simp } 468194140Simp 469201530Simp ciu_intr_reg_addr += (enx * 0x8); 470201530Simp ciu_intr_reg_addr += (ciu_ip * 0x10); 471201530Simp ciu_intr_reg_addr += (intx * 0x20); 472201530Simp return (ciu_intr_reg_addr); 473194140Simp} 474194140Simp 475194140Simp/* 476194140Simp * ciu_get_int_summary 477194140Simp */ 478201530Simpuint64_t 479201530Simpciu_get_int_summary(int core_num, int intx, int enx) 480194140Simp{ 481201530Simp uint64_t ciu_intr_sum_reg_addr; 482194140Simp 483201530Simp if (core_num == CIU_THIS_CORE) 484194140Simp core_num = octeon_get_core_num(); 485201530Simp ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 486201530Simp return (oct_read64(ciu_intr_sum_reg_addr)); 487194140Simp} 488194140Simp 489194140Simp//#define DEBUG_CIU 1 490194140Simp 491194140Simp#ifdef DEBUG_CIU 492194140Simp#define DEBUG_CIU_SUM 1 493194140Simp#define DEBUG_CIU_EN 1 494194140Simp#endif 495194140Simp 496194140Simp 497194140Simp/* 498194140Simp * ciu_clear_int_summary 499194140Simp */ 500201530Simpvoid 501201530Simpciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits) 502194140Simp{ 503201530Simp uint32_t cpu_status_bits; 504201530Simp uint64_t ciu_intr_sum_reg_addr; 505194140Simp 506194140Simp//#define DEBUG_CIU_SUM 1 507194140Simp 508194140Simp#ifdef DEBUG_CIU_SUM 509201530Simp uint64_t ciu_intr_sum_bits; 510194140Simp#endif 511194140Simp 512194140Simp 513201530Simp if (core_num == CIU_THIS_CORE) { 514194140Simp core_num = octeon_get_core_num(); 515201530Simp } 516194140Simp 517194140Simp#ifdef DEBUG_CIU_SUM 518194140Simp printf(" CIU: core %u clear sum IntX %u Enx %u Bits: 0x%llX\n", 519201530Simp core_num, intx, enx, write_bits); 520194140Simp#endif 521194140Simp 522201530Simp cpu_status_bits = octeon_disable_interrupts(); 523194140Simp 524201530Simp ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 525194140Simp 526194140Simp#ifdef DEBUG_CIU_SUM 527194140Simp ciu_intr_sum_bits = oct_read64(ciu_intr_sum_reg_addr); /* unneeded dummy read */ 528194140Simp printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 529201530Simp cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits, 530201530Simp ciu_intr_sum_bits | write_bits); 531194140Simp#endif 532194140Simp 533201530Simp oct_write64(ciu_intr_sum_reg_addr, write_bits); 534201530Simp oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 535194140Simp 536194140Simp#ifdef DEBUG_CIU_SUM 537194140Simp printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr)); 538194140Simp#endif 539194140Simp 540201530Simp octeon_set_interrupts(cpu_status_bits); 541194140Simp} 542194140Simp 543194140Simp/* 544194140Simp * ciu_disable_intr 545194140Simp */ 546201530Simpvoid 547201530Simpciu_disable_intr(int core_num, int intx, int enx) 548194140Simp{ 549201530Simp uint32_t cpu_status_bits; 550201530Simp uint64_t ciu_intr_reg_addr; 551194140Simp 552201530Simp if (core_num == CIU_THIS_CORE) 553194140Simp core_num = octeon_get_core_num(); 554194140Simp 555201530Simp cpu_status_bits = octeon_disable_interrupts(); 556194140Simp 557201530Simp ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 558194140Simp 559201530Simp oct_read64(ciu_intr_reg_addr); /* Dummy read */ 560194140Simp 561201530Simp oct_write64(ciu_intr_reg_addr, 0LL); 562201530Simp oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 563194140Simp 564201530Simp octeon_set_interrupts(cpu_status_bits); 565194140Simp} 566194140Simp 567201530Simpvoid 568201530Simpciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip) 569194140Simp{ 570194140Simp 571194140Simp uint64_t ciu_intr_reg_addr; 572194140Simp uint64_t ciu_intr_bits; 573194140Simp 574194140Simp if (core_num == CIU_THIS_CORE) { 575194140Simp core_num = octeon_get_core_num(); 576194140Simp } 577194140Simp 578194140Simp#ifndef OCTEON_SMP_1 579194140Simp ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 580194140Simp#else 581194140Simp ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 582194140Simp#endif 583194140Simp 584194140Simp if (!ciu_intr_reg_addr) { 585194140Simp printf("Bad call to %s\n", __FUNCTION__); 586194140Simp while(1); 587194140Simp return; 588194140Simp } 589194140Simp 590194140Simp ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 591199593Simp printf(" CIU core %d int: %d en: %d ip: %d Add: %#llx enabled: %#llx SR: %x\n", 592199593Simp core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr, 593195414Simp (unsigned long long)ciu_intr_bits, mips_rd_status()); 594194140Simp} 595194140Simp 596194140Simp 597194140Simp/* 598194140Simp * ciu_enable_interrupts 599194140Simp */ 600201530Simpvoid ciu_enable_interrupts(int core_num, int intx, int enx, 601201530Simp uint64_t set_these_interrupt_bits, int ciu_ip) 602194140Simp{ 603194140Simp uint32_t cpu_status_bits; 604194140Simp uint64_t ciu_intr_reg_addr; 605194140Simp uint64_t ciu_intr_bits; 606194140Simp 607201530Simp if (core_num == CIU_THIS_CORE) 608194140Simp core_num = octeon_get_core_num(); 609194140Simp 610194140Simp//#define DEBUG_CIU_EN 1 611194140Simp 612194140Simp#ifdef DEBUG_CIU_EN 613194140Simp printf(" CIU: core %u enabling Intx %u Enx %u IP %d Bits: 0x%llX\n", 614201530Simp core_num, intx, enx, ciu_ip, set_these_interrupt_bits); 615194140Simp#endif 616194140Simp 617194140Simp cpu_status_bits = octeon_disable_interrupts(); 618194140Simp 619194140Simp#ifndef OCTEON_SMP_1 620194140Simp ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 621194140Simp#else 622194140Simp ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 623194140Simp#endif 624194140Simp 625194140Simp if (!ciu_intr_reg_addr) { 626201530Simp printf("Bad call to %s\n", __FUNCTION__); 627201530Simp while(1); 628201530Simp return; /* XXX */ 629194140Simp } 630194140Simp 631194140Simp ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 632194140Simp 633194140Simp#ifdef DEBUG_CIU_EN 634194140Simp printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 635201530Simp cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits); 636194140Simp#endif 637194140Simp ciu_intr_bits |= set_these_interrupt_bits; 638194140Simp oct_write64(ciu_intr_reg_addr, ciu_intr_bits); 639194140Simp#ifdef OCTEON_SMP 640194140Simp mips_wbflush(); 641194140Simp#endif 642194140Simp oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 643194140Simp 644194140Simp#ifdef DEBUG_CIU_EN 645201530Simp printf(" Readback: 0x%llX\n\n ", 646201530Simp (uint64_t)oct_read64(ciu_intr_reg_addr)); 647194140Simp#endif 648194140Simp 649194140Simp octeon_set_interrupts(cpu_status_bits); 650194140Simp} 651194140Simp 652202831Simpunsigned long 653202831Simpocteon_get_clock_rate(void) 654202831Simp{ 655202831Simp return octeon_cpu_clock; 656202831Simp} 657202831Simp 658202831Simpstatic void 659202831Simpocteon_memory_init(void) 660202831Simp{ 661202831Simp uint32_t realmem_bytes; 662202831Simp 663202831Simp if (octeon_board_real()) { 664202831Simp printf("octeon_dram == %llx\n", octeon_dram); 665202831Simp printf("reduced to ram: %u MB", (uint32_t) octeon_dram >> 20); 666202831Simp 667202831Simp realmem_bytes = (octeon_dram - PAGE_SIZE); 668202831Simp realmem_bytes &= ~(PAGE_SIZE - 1); 669202831Simp printf("Real memory bytes is %x\n", realmem_bytes); 670202831Simp } else { 671202831Simp /* Simulator we limit to 96 meg */ 672202831Simp realmem_bytes = (96 << 20); 673202831Simp } 674202831Simp /* phys_avail regions are in bytes */ 675202831Simp phys_avail[0] = (MIPS_KSEG0_TO_PHYS((vm_offset_t)&end) + PAGE_SIZE) & ~(PAGE_SIZE - 1); 676202831Simp if (octeon_board_real()) { 677202831Simp if (realmem_bytes > OCTEON_DRAM_FIRST_256_END) 678202831Simp phys_avail[1] = OCTEON_DRAM_FIRST_256_END; 679202831Simp else 680202831Simp phys_avail[1] = realmem_bytes; 681202831Simp realmem_bytes -= OCTEON_DRAM_FIRST_256_END; 682202831Simp realmem_bytes &= ~(PAGE_SIZE - 1); 683202831Simp printf("phys_avail[0] = %x phys_avail[1] = %x\n", 684202831Simp phys_avail[0], phys_avail[1]); 685202831Simp } else { 686202831Simp /* Simulator gets 96Meg period. */ 687202831Simp phys_avail[1] = (96 << 20); 688202831Simp } 689202831Simp /*- 690202831Simp * Octeon Memory looks as follows: 691202831Simp * PA 692202831Simp * 0000 0000 to 0x0 0000 0000 0000 693202831Simp * 0FFF FFFF First 256 MB memory Maps to 0x0 0000 0FFF FFFF 694202831Simp * 695202831Simp * 1000 0000 to 0x1 0000 1000 0000 696202831Simp * 1FFF FFFF Uncached Bu I/O space.converted to 0x1 0000 1FFF FFFF 697202831Simp * 698202831Simp * 2FFF FFFF to Cached 0x0 0000 2000 0000 699202831Simp * FFFF FFFF all dram mem above the first 512M 0x3 FFFF FFFF FFFF 700202831Simp * 701202831Simp */ 702202831Simp physmem = btoc(phys_avail[1] - phys_avail[0]); 703202831Simp if ((octeon_board_real()) && 704202831Simp (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) { 705202831Simp /* take out the upper non-cached 1/2 */ 706202831Simp realmem_bytes -= OCTEON_DRAM_FIRST_256_END; 707202831Simp realmem_bytes &= ~(PAGE_SIZE - 1); 708202831Simp /* Now map the rest of the memory */ 709202831Simp phys_avail[2] = 0x20000000; 710202831Simp printf("realmem_bytes is now at %x\n", realmem_bytes); 711202831Simp phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes); 712202831Simp printf("Next block of memory goes from %x to %x\n", 713202831Simp phys_avail[2], phys_avail[3]); 714202831Simp physmem += btoc(phys_avail[3] - phys_avail[2]); 715202831Simp } else { 716202831Simp printf("realmem_bytes is %d\n", realmem_bytes); 717202831Simp } 718202831Simp realmem = physmem; 719202831Simp 720202831Simp printf("\nTotal DRAM Size 0x%X", (uint32_t) octeon_dram); 721202831Simp printf("\nBank 0 = 0x%8X -> 0x%8X", phys_avail[0], phys_avail[1]); 722202831Simp printf("\nBank 1 = 0x%8X -> 0x%8X\n", phys_avail[2], phys_avail[3]); 723202831Simp printf("\nphysmem: 0x%lx", physmem); 724202831Simp 725202831Simp Maxmem = physmem; 726202831Simp 727202831Simp} 728202831Simp 729196262Simpvoid 730201530Simpplatform_start(__register_t a0, __register_t a1, __register_t a2 __unused, 731201530Simp __register_t a3) 732196262Simp{ 733196262Simp uint64_t platform_counter_freq; 734194140Simp 735201845Simp /* Initialize pcpu stuff */ 736201881Simp mips_pcpu0_init(); 737202831Simp mips_timer_early_init(OCTEON_CLOCK_DEFAULT); 738202831Simp cninit(); 739201845Simp 740202831Simp octeon_ciu_reset(); 741200344Simp octeon_boot_params_init(a3); 742196262Simp bootverbose = 1; 743202831Simp cpuid_to_pcpu[0] = &pcpu0; 744194140Simp 745202831Simp /* 746202831Simp * For some reason on the cn38xx simulator ebase register is set to 747202831Simp * 0x80001000 at bootup time. Move it back to the default, but 748202831Simp * when we move to having support for multiple executives, we need 749202831Simp * to rethink this. 750202831Simp */ 751202831Simp mips_wr_ebase(0x80000000); 752196262Simp 753202831Simp octeon_memory_init(); 754196262Simp init_param1(); 755196262Simp init_param2(physmem); 756196262Simp mips_cpu_init(); 757202831Simp pmap_bootstrap(); 758202831Simp mips_proc0_init(); 759196262Simp mutex_init(); 760196262Simp kdb_init(); 761202850Simp#ifdef KDB 762202850Simp if (boothowto & RB_KDB) 763202850Simp kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 764196262Simp#endif 765202831Simp platform_counter_freq = octeon_get_clock_rate(); 766202831Simp mips_timer_init_params(platform_counter_freq, 1); 767196262Simp} 768196262Simp 769202831Simp/* impSTART: This stuff should move back into the Cavium SDK */ 770194140Simp/* 771194140Simp **************************************************************************************** 772194140Simp * 773194140Simp * APP/BOOT DESCRIPTOR STUFF 774194140Simp * 775194140Simp **************************************************************************************** 776194140Simp */ 777194140Simp 778194140Simp/* Define the struct that is initialized by the bootloader used by the 779194140Simp * startup code. 780194140Simp * 781194140Simp * Copyright (c) 2004, 2005, 2006 Cavium Networks. 782194140Simp * 783194140Simp * The authors hereby grant permission to use, copy, modify, distribute, 784194140Simp * and license this software and its documentation for any purpose, provided 785194140Simp * that existing copyright notices are retained in all copies and that this 786194140Simp * notice is included verbatim in any distributions. No written agreement, 787194140Simp * license, or royalty fee is required for any of the authorized uses. 788194140Simp * Modifications to this software may be copyrighted by their authors 789194140Simp * and need not follow the licensing terms described here, provided that 790194140Simp * the new terms are clearly indicated on the first page of each file where 791194140Simp * they apply. 792194140Simp */ 793194140Simp 794194140Simp#define OCTEON_CURRENT_DESC_VERSION 6 795194140Simp#define OCTEON_ARGV_MAX_ARGS (64) 796194140Simp#define OCTOEN_SERIAL_LEN 20 797194140Simp 798194140Simp 799194140Simptypedef struct { 800200344Simp /* Start of block referenced by assembly code - do not change! */ 801200344Simp uint32_t desc_version; 802200344Simp uint32_t desc_size; 803194140Simp 804200344Simp uint64_t stack_top; 805200344Simp uint64_t heap_base; 806200344Simp uint64_t heap_end; 807200344Simp uint64_t entry_point; /* Only used by bootloader */ 808200344Simp uint64_t desc_vaddr; 809200344Simp /* End of This block referenced by assembly code - do not change! */ 810194140Simp 811200344Simp uint32_t exception_base_addr; 812200344Simp uint32_t stack_size; 813200344Simp uint32_t heap_size; 814200344Simp uint32_t argc; /* Argc count for application */ 815200344Simp uint32_t argv[OCTEON_ARGV_MAX_ARGS]; 816200344Simp uint32_t flags; 817200344Simp uint32_t core_mask; 818200344Simp uint32_t dram_size; /**< DRAM size in megabyes */ 819200344Simp uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/ 820200344Simp uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */ 821200344Simp uint32_t eclock_hz; /**< CPU clock speed, in hz */ 822200344Simp uint32_t dclock_hz; /**< DRAM clock speed, in hz */ 823200344Simp uint32_t spi_clock_hz; /**< SPI4 clock in hz */ 824200344Simp uint16_t board_type; 825200344Simp uint8_t board_rev_major; 826200344Simp uint8_t board_rev_minor; 827200344Simp uint16_t chip_type; 828200344Simp uint8_t chip_rev_major; 829200344Simp uint8_t chip_rev_minor; 830200344Simp char board_serial_number[OCTOEN_SERIAL_LEN]; 831200344Simp uint8_t mac_addr_base[6]; 832200344Simp uint8_t mac_addr_count; 833200344Simp uint64_t cvmx_desc_vaddr; 834194140Simp} octeon_boot_descriptor_t; 835194140Simp 836194140Simp 837194140Simptypedef struct { 838200344Simp uint32_t major_version; 839200344Simp uint32_t minor_version; 840194140Simp 841200344Simp uint64_t stack_top; 842200344Simp uint64_t heap_base; 843200344Simp uint64_t heap_end; 844200344Simp uint64_t desc_vaddr; 845194140Simp 846200344Simp uint32_t exception_base_addr; 847200344Simp uint32_t stack_size; 848200344Simp uint32_t flags; 849200344Simp uint32_t core_mask; 850200344Simp uint32_t dram_size; /**< DRAM size in megabyes */ 851200344Simp uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/ 852200344Simp uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */ 853200344Simp uint32_t eclock_hz; /**< CPU clock speed, in hz */ 854200344Simp uint32_t dclock_hz; /**< DRAM clock speed, in hz */ 855200344Simp uint32_t spi_clock_hz; /**< SPI4 clock in hz */ 856200344Simp uint16_t board_type; 857200344Simp uint8_t board_rev_major; 858200344Simp uint8_t board_rev_minor; 859200344Simp uint16_t chip_type; 860200344Simp uint8_t chip_rev_major; 861200344Simp uint8_t chip_rev_minor; 862200344Simp char board_serial_number[OCTOEN_SERIAL_LEN]; 863200344Simp uint8_t mac_addr_base[6]; 864200344Simp uint8_t mac_addr_count; 865194140Simp} cvmx_bootinfo_t; 866194140Simp 867194140Simpuint32_t octeon_cpu_clock; 868194140Simpuint64_t octeon_dram; 869194140Simpuint32_t octeon_bd_ver = 0, octeon_cvmx_bd_ver = 0, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type; 870194140Simpuint8_t octeon_mac_addr[6] = { 0 }; 871194140Simpint octeon_core_mask, octeon_mac_addr_count; 872194140Simpint octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0; 873194140Simp 874194140Simpstatic octeon_boot_descriptor_t *app_desc_ptr; 875194140Simpstatic cvmx_bootinfo_t *cvmx_desc_ptr; 876194140Simp 877194140Simp#define OCTEON_BOARD_TYPE_NONE 0 878194140Simp#define OCTEON_BOARD_TYPE_SIM 1 879194140Simp 880194140Simp#define OCTEON_CLOCK_MIN (100 * 1000 * 1000) 881194140Simp#define OCTEON_CLOCK_MAX (800 * 1000 * 1000) 882194140Simp#define OCTEON_DRAM_DEFAULT (256 * 1024 * 1024) 883194140Simp#define OCTEON_DRAM_MIN 30 884194140Simp#define OCTEON_DRAM_MAX 3000 885194140Simp 886194140Simp 887200344Simpint 888200344Simpocteon_board_real(void) 889194140Simp{ 890200344Simp if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) || 891200344Simp (octeon_board_type == OCTEON_BOARD_TYPE_SIM) || 892200344Simp !octeon_board_rev_major) 893200344Simp return 0; 894200344Simp return 1; 895194140Simp} 896194140Simp 897200344Simpstatic void 898200344Simpocteon_process_app_desc_ver_unknown(void) 899194140Simp{ 900194140Simp printf(" Unknown Boot-Descriptor: Using Defaults\n"); 901194140Simp 902194140Simp octeon_cpu_clock = OCTEON_CLOCK_DEFAULT; 903194140Simp octeon_dram = OCTEON_DRAM_DEFAULT; 904194140Simp octeon_board_rev_major = octeon_board_rev_minor = octeon_board_type = 0; 905194140Simp octeon_core_mask = 1; 906194140Simp octeon_chip_type = octeon_chip_rev_major = octeon_chip_rev_minor = 0; 907194140Simp octeon_mac_addr[0] = 0x00; octeon_mac_addr[1] = 0x0f; 908194140Simp octeon_mac_addr[2] = 0xb7; octeon_mac_addr[3] = 0x10; 909194140Simp octeon_mac_addr[4] = 0x09; octeon_mac_addr[5] = 0x06; 910194140Simp octeon_mac_addr_count = 1; 911194140Simp} 912194140Simp 913200344Simpstatic int 914200344Simpocteon_process_app_desc_ver_6(void) 915194140Simp{ 916200344Simp /* XXX Why is 0x00000000ffffffffULL a bad value? */ 917200344Simp if (app_desc_ptr->cvmx_desc_vaddr == 0 || 918200344Simp app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) { 919194174Simp printf ("Bad cvmx_desc_ptr %p\n", cvmx_desc_ptr); 920194140Simp return 1; 921200344Simp } 922200344Simp cvmx_desc_ptr = 923200344Simp (cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr; 924200344Simp cvmx_desc_ptr = 925200344Simp (cvmx_bootinfo_t *) ((intptr_t)cvmx_desc_ptr | MIPS_KSEG0_START); 926194140Simp octeon_cvmx_bd_ver = (cvmx_desc_ptr->major_version * 100) + 927200344Simp cvmx_desc_ptr->minor_version; 928194140Simp if (cvmx_desc_ptr->major_version != 1) { 929202831Simp panic("Incompatible CVMX descriptor from bootloader: %d.%d %p\n", 930194140Simp (int) cvmx_desc_ptr->major_version, 931194140Simp (int) cvmx_desc_ptr->minor_version, cvmx_desc_ptr); 932194140Simp } 933194140Simp 934194140Simp octeon_core_mask = cvmx_desc_ptr->core_mask; 935194140Simp octeon_cpu_clock = cvmx_desc_ptr->eclock_hz; 936194140Simp octeon_board_type = cvmx_desc_ptr->board_type; 937194140Simp octeon_board_rev_major = cvmx_desc_ptr->board_rev_major; 938194140Simp octeon_board_rev_minor = cvmx_desc_ptr->board_rev_minor; 939194140Simp octeon_chip_type = cvmx_desc_ptr->chip_type; 940194140Simp octeon_chip_rev_major = cvmx_desc_ptr->chip_rev_major; 941194140Simp octeon_chip_rev_minor = cvmx_desc_ptr->chip_rev_minor; 942194140Simp octeon_mac_addr[0] = cvmx_desc_ptr->mac_addr_base[0]; 943194140Simp octeon_mac_addr[1] = cvmx_desc_ptr->mac_addr_base[1]; 944194140Simp octeon_mac_addr[2] = cvmx_desc_ptr->mac_addr_base[2]; 945194140Simp octeon_mac_addr[3] = cvmx_desc_ptr->mac_addr_base[3]; 946194140Simp octeon_mac_addr[4] = cvmx_desc_ptr->mac_addr_base[4]; 947194140Simp octeon_mac_addr[5] = cvmx_desc_ptr->mac_addr_base[5]; 948194140Simp octeon_mac_addr_count = cvmx_desc_ptr->mac_addr_count; 949194140Simp 950200344Simp if (app_desc_ptr->dram_size > 16*1024*1024) 951194140Simp octeon_dram = (uint64_t)app_desc_ptr->dram_size; 952200344Simp else 953200344Simp octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20; 954194140Simp return 0; 955194140Simp} 956194140Simp 957200344Simpstatic void 958200344Simpocteon_boot_params_init(register_t ptr) 959194140Simp{ 960200344Simp int bad_desc = 1; 961202831Simp 962200344Simp if (ptr != 0 && ptr < MAX_APP_DESC_ADDR) { 963200344Simp app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr; 964194140Simp octeon_bd_ver = app_desc_ptr->desc_version; 965202831Simp if (app_desc_ptr->desc_version == 6) 966200344Simp bad_desc = octeon_process_app_desc_ver_6(); 967194140Simp } 968200344Simp if (bad_desc) 969194140Simp octeon_process_app_desc_ver_unknown(); 970194140Simp 971194140Simp printf("Boot Descriptor Ver: %u -> %u/%u", 972194140Simp octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100); 973194140Simp printf(" CPU clock: %uMHz\n", octeon_cpu_clock/1000000); 974194140Simp printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20)); 975194140Simp printf(" Board Type: %u Revision: %u/%u\n", 976194140Simp octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor); 977194140Simp printf(" Octeon Chip: %u Rev %u/%u", 978194140Simp octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor); 979194140Simp 980202831Simp printf(" Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n", 981202831Simp octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2], 982202831Simp octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5], 983202831Simp octeon_mac_addr_count); 984194140Simp} 985202831Simp/* impEND: This stuff should move back into the Cavium SDK */ 986