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