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