octeon_machdep.c revision 202867
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 202867 2010-01-23 06:42:47Z imp $ 27 */ 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_machdep.c 202867 2010-01-23 06:42:47Z 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 <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 79static struct pcpu pcpu0; 80extern int *edata; 81extern int *end; 82 83uint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip); 84void ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip); 85 86static void octeon_boot_params_init(register_t ptr); 87static uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx); 88static uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx); 89 90static __inline void 91mips_wr_ebase(u_int32_t a0) 92{ 93 __asm __volatile("mtc0 %[a0], $15, 1 ;" 94 : 95 : [a0] "r"(a0)); 96 97 mips_barrier(); 98} 99 100void 101platform_cpu_init() 102{ 103 /* Nothing special yet */ 104} 105 106/* 107 * Perform a board-level soft-reset. 108 */ 109void 110platform_reset(void) 111{ 112 mips_generic_reset(); 113} 114 115 116static inline uint32_t 117octeon_disable_interrupts(void) 118{ 119 uint32_t status_bits; 120 121 status_bits = mips_rd_status(); 122 mips_wr_status(status_bits & ~MIPS_SR_INT_IE); 123 return (status_bits); 124} 125 126 127static inline void 128octeon_set_interrupts(uint32_t status_bits) 129{ 130 mips_wr_status(status_bits); 131} 132 133 134void 135octeon_led_write_char(int char_position, char val) 136{ 137 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 138 139 if (!octeon_board_real()) 140 return; 141 142 char_position &= 0x7; /* only 8 chars */ 143 ptr += char_position; 144 oct_write8_x8(ptr, val); 145} 146 147void 148octeon_led_write_char0(char val) 149{ 150 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 151 152 if (!octeon_board_real()) 153 return; 154 oct_write8_x8(ptr, val); 155} 156 157void 158octeon_led_write_hexchar(int char_position, char hexval) 159{ 160 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 161 char char1, char2; 162 163 if (!octeon_board_real()) 164 return; 165 166 char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7'; 167 char2 = (hexval & 0x0f); char2 = (char2 < 10)?char2+'0':char2+'7'; 168 char_position &= 0x7; /* only 8 chars */ 169 if (char_position > 6) 170 char_position = 6; 171 ptr += char_position; 172 oct_write8_x8(ptr, char1); 173 ptr++; 174 oct_write8_x8(ptr, char2); 175} 176 177void 178octeon_led_write_string(const char *str) 179{ 180 uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8); 181 int i; 182 183 if (!octeon_board_real()) 184 return; 185 186 for (i=0; i<8; i++, ptr++) { 187 if (str && *str) 188 oct_write8_x8(ptr, *str++); 189 else 190 oct_write8_x8(ptr, ' '); 191 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 192 } 193} 194 195static char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'}; 196 197void 198octeon_led_run_wheel(int *prog_count, int led_position) 199{ 200 if (!octeon_board_real()) 201 return; 202 octeon_led_write_char(led_position, progress[*prog_count]); 203 *prog_count += 1; 204 *prog_count &= 0x7; 205} 206 207#define LSR_DATAREADY 0x01 /* Data ready */ 208#define LSR_THRE 0x20 /* Transmit holding register empty */ 209#define LSR_TEMT 0x40 /* Transmitter Empty. THR, TSR & FIFO */ 210#define USR_TXFIFO_NOTFULL 0x02 /* Uart TX FIFO Not full */ 211 212/* 213 * octeon_uart_write_byte 214 * 215 * Put out a single byte off of uart port. 216 */ 217 218void 219octeon_uart_write_byte(int uart_index, uint8_t ch) 220{ 221 uint64_t val, val2; 222 if (uart_index < 0 || uart_index > 1) 223 return; 224 225 while (1) { 226 val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 227 val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400)); 228 if ((((uint8_t) val) & LSR_THRE) || 229 (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 230 break; 231 } 232 } 233 234 /* Write the byte */ 235 oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch); 236 237 /* Force Flush the IOBus */ 238 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 239} 240 241 242void 243octeon_uart_write_byte0(uint8_t ch) 244{ 245 uint64_t val, val2; 246 247 while (1) { 248 val = oct_read64(OCTEON_MIO_UART0_LSR); 249 val2 = oct_read64(OCTEON_MIO_UART0_USR); 250 if ((((uint8_t) val) & LSR_THRE) || 251 (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { 252 break; 253 } 254 } 255 256 /* Write the byte */ 257 oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch); 258 259 /* Force Flush the IOBus */ 260 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 261} 262 263/* 264 * octeon_uart_write_string 265 * 266 */ 267void 268octeon_uart_write_string(int uart_index, const char *str) 269{ 270 /* Just loop writing one byte at a time */ 271 272 while (*str) { 273 octeon_uart_write_byte(uart_index, *str); 274 if (*str == '\n') { 275 octeon_uart_write_byte(uart_index, '\r'); 276 } 277 str++; 278 } 279} 280 281static char wstr[30]; 282 283void 284octeon_led_write_hex(uint32_t wl) 285{ 286 char nbuf[80]; 287 288 sprintf(nbuf, "%X", wl); 289 octeon_led_write_string(nbuf); 290} 291 292 293void octeon_uart_write_hex2(uint32_t wl, uint32_t wh) 294{ 295 sprintf(wstr, "0x%X-0x%X ", wh, wl); 296 octeon_uart_write_string(0, wstr); 297} 298 299void 300octeon_uart_write_hex(uint32_t wl) 301{ 302 sprintf(wstr, " 0x%X ", wl); 303 octeon_uart_write_string(0, wstr); 304} 305 306/* 307 * octeon_wait_uart_flush 308 */ 309void 310octeon_wait_uart_flush(int uart_index, uint8_t ch) 311{ 312 uint64_t val; 313 int64_t val3; 314 uint32_t cpu_status_bits; 315 316 if (uart_index < 0 || uart_index > 1) 317 return; 318 319 cpu_status_bits = octeon_disable_interrupts(); 320 /* Force Flush the IOBus */ 321 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); 322 for (val3 = 0xfffffffff; val3 > 0; val3--) { 323 val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); 324 if (((uint8_t) val) & LSR_TEMT) 325 break; 326 } 327 octeon_set_interrupts(cpu_status_bits); 328} 329 330 331/* 332 * octeon_debug_symbol 333 * 334 * Does nothing. 335 * Used to mark the point for simulator to begin tracing 336 */ 337void 338octeon_debug_symbol(void) 339{ 340} 341 342void 343octeon_ciu_stop_gtimer(int timer) 344{ 345 oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll); 346} 347 348void 349octeon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles) 350{ 351 octeon_ciu_gentimer gentimer; 352 353 gentimer.word64 = 0; 354 gentimer.bits.one_shot = one_shot; 355 gentimer.bits.len = time_cycles - 1; 356 oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64); 357} 358 359/* 360 * octeon_ciu_reset 361 * 362 * Shutdown all CIU to IP2, IP3 mappings 363 */ 364void 365octeon_ciu_reset(void) 366{ 367 368 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0); 369 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1); 370 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2); 371 octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3); 372 373 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0); 374 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1); 375 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0); 376 ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1); 377 378 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll); 379 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll); 380 ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll); 381} 382 383/* 384 * mips_disable_interrupt_controllers 385 * 386 * Disable interrupts in the CPU controller 387 */ 388void 389mips_disable_interrupt_controls(void) 390{ 391 /* 392 * Disable interrupts in CIU. 393 */ 394 octeon_ciu_reset(); 395} 396 397/* 398 * ciu_get_intr_sum_reg_addr 399 */ 400static uint64_t 401ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx) 402{ 403 uint64_t ciu_intr_sum_reg_addr; 404 405 if (enx == CIU_EN_0) 406 ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR + 407 (core_num * 0x10) + (intx * 0x8); 408 else 409 ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR; 410 411 return (ciu_intr_sum_reg_addr); 412} 413 414 415/* 416 * ciu_get_intr_en_reg_addr 417 */ 418static uint64_t 419ciu_get_intr_en_reg_addr(int core_num, int intx, int enx) 420{ 421 uint64_t ciu_intr_reg_addr; 422 423 ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR + 424 ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) + (core_num * 0x20); 425 return (ciu_intr_reg_addr); 426} 427 428 429 430 431/* 432 * ciu_get_intr_reg_addr 433 * 434 * 200 ---int0,en0 ip2 435 * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog 436 * 437 * 210 ---int0,en0 ip3 -- 438 * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right? 439 * 440 * 220 ---int1,en0 ip2 441 * 228 ---int1,en1 ip2 442 * 230 ---int1,en0 ip3 -- 443 * 238 ---int1,en1 ip3 444 * 445 */ 446uint64_t 447ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip) 448{ 449 uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR; 450 451 /* XXX kasserts? */ 452 if (enx < CIU_EN_0 || enx > CIU_EN_1) { 453 printf("%s: invalid enx value %d, should be %d or %d\n", 454 __FUNCTION__, enx, CIU_EN_0, CIU_EN_1); 455 return 0; 456 } 457 if (intx < CIU_INT_0 || intx > CIU_INT_1) { 458 printf("%s: invalid intx value %d, should be %d or %d\n", 459 __FUNCTION__, enx, CIU_INT_0, CIU_INT_1); 460 return 0; 461 } 462 if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) { 463 printf("%s: invalid ciu_ip value %d, should be %d or %d\n", 464 __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); 465 return 0; 466 } 467 468 ciu_intr_reg_addr += (enx * 0x8); 469 ciu_intr_reg_addr += (ciu_ip * 0x10); 470 ciu_intr_reg_addr += (intx * 0x20); 471 return (ciu_intr_reg_addr); 472} 473 474/* 475 * ciu_get_int_summary 476 */ 477uint64_t 478ciu_get_int_summary(int core_num, int intx, int enx) 479{ 480 uint64_t ciu_intr_sum_reg_addr; 481 482 if (core_num == CIU_THIS_CORE) 483 core_num = octeon_get_core_num(); 484 ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 485 return (oct_read64(ciu_intr_sum_reg_addr)); 486} 487 488//#define DEBUG_CIU 1 489 490#ifdef DEBUG_CIU 491#define DEBUG_CIU_SUM 1 492#define DEBUG_CIU_EN 1 493#endif 494 495 496/* 497 * ciu_clear_int_summary 498 */ 499void 500ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits) 501{ 502 uint32_t cpu_status_bits; 503 uint64_t ciu_intr_sum_reg_addr; 504 505//#define DEBUG_CIU_SUM 1 506 507#ifdef DEBUG_CIU_SUM 508 uint64_t ciu_intr_sum_bits; 509#endif 510 511 512 if (core_num == CIU_THIS_CORE) { 513 core_num = octeon_get_core_num(); 514 } 515 516#ifdef DEBUG_CIU_SUM 517 printf(" CIU: core %u clear sum IntX %u Enx %u Bits: 0x%llX\n", 518 core_num, intx, enx, write_bits); 519#endif 520 521 cpu_status_bits = octeon_disable_interrupts(); 522 523 ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); 524 525#ifdef DEBUG_CIU_SUM 526 ciu_intr_sum_bits = oct_read64(ciu_intr_sum_reg_addr); /* unneeded dummy read */ 527 printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 528 cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits, 529 ciu_intr_sum_bits | write_bits); 530#endif 531 532 oct_write64(ciu_intr_sum_reg_addr, write_bits); 533 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 534 535#ifdef DEBUG_CIU_SUM 536 printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr)); 537#endif 538 539 octeon_set_interrupts(cpu_status_bits); 540} 541 542/* 543 * ciu_disable_intr 544 */ 545void 546ciu_disable_intr(int core_num, int intx, int enx) 547{ 548 uint32_t cpu_status_bits; 549 uint64_t ciu_intr_reg_addr; 550 551 if (core_num == CIU_THIS_CORE) 552 core_num = octeon_get_core_num(); 553 554 cpu_status_bits = octeon_disable_interrupts(); 555 556 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 557 558 oct_read64(ciu_intr_reg_addr); /* Dummy read */ 559 560 oct_write64(ciu_intr_reg_addr, 0LL); 561 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 562 563 octeon_set_interrupts(cpu_status_bits); 564} 565 566void 567ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip) 568{ 569 570 uint64_t ciu_intr_reg_addr; 571 uint64_t ciu_intr_bits; 572 573 if (core_num == CIU_THIS_CORE) { 574 core_num = octeon_get_core_num(); 575 } 576 577#ifndef OCTEON_SMP_1 578 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 579#else 580 ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 581#endif 582 583 if (!ciu_intr_reg_addr) { 584 printf("Bad call to %s\n", __FUNCTION__); 585 while(1); 586 return; 587 } 588 589 ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 590 printf(" CIU core %d int: %d en: %d ip: %d Add: %#llx enabled: %#llx SR: %x\n", 591 core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr, 592 (unsigned long long)ciu_intr_bits, mips_rd_status()); 593} 594 595 596/* 597 * ciu_enable_interrupts 598 */ 599void ciu_enable_interrupts(int core_num, int intx, int enx, 600 uint64_t set_these_interrupt_bits, int ciu_ip) 601{ 602 uint32_t cpu_status_bits; 603 uint64_t ciu_intr_reg_addr; 604 uint64_t ciu_intr_bits; 605 606 if (core_num == CIU_THIS_CORE) 607 core_num = octeon_get_core_num(); 608 609//#define DEBUG_CIU_EN 1 610 611#ifdef DEBUG_CIU_EN 612 printf(" CIU: core %u enabling Intx %u Enx %u IP %d Bits: 0x%llX\n", 613 core_num, intx, enx, ciu_ip, set_these_interrupt_bits); 614#endif 615 616 cpu_status_bits = octeon_disable_interrupts(); 617 618#ifndef OCTEON_SMP_1 619 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); 620#else 621 ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip); 622#endif 623 624 if (!ciu_intr_reg_addr) { 625 printf("Bad call to %s\n", __FUNCTION__); 626 while(1); 627 return; /* XXX */ 628 } 629 630 ciu_intr_bits = oct_read64(ciu_intr_reg_addr); 631 632#ifdef DEBUG_CIU_EN 633 printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX", 634 cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits); 635#endif 636 ciu_intr_bits |= set_these_interrupt_bits; 637 oct_write64(ciu_intr_reg_addr, ciu_intr_bits); 638#ifdef OCTEON_SMP 639 mips_wbflush(); 640#endif 641 oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ 642 643#ifdef DEBUG_CIU_EN 644 printf(" Readback: 0x%llX\n\n ", 645 (uint64_t)oct_read64(ciu_intr_reg_addr)); 646#endif 647 648 octeon_set_interrupts(cpu_status_bits); 649} 650 651unsigned long 652octeon_get_clock_rate(void) 653{ 654 return octeon_cpu_clock; 655} 656 657static void 658octeon_memory_init(void) 659{ 660 uint32_t realmem_bytes; 661 662 if (octeon_board_real()) { 663 printf("octeon_dram == %llx\n", octeon_dram); 664 printf("reduced to ram: %u MB", (uint32_t) octeon_dram >> 20); 665 666 realmem_bytes = (octeon_dram - PAGE_SIZE); 667 realmem_bytes &= ~(PAGE_SIZE - 1); 668 printf("Real memory bytes is %x\n", realmem_bytes); 669 } else { 670 /* Simulator we limit to 96 meg */ 671 realmem_bytes = (96 << 20); 672 } 673 /* phys_avail regions are in bytes */ 674 phys_avail[0] = (MIPS_KSEG0_TO_PHYS((vm_offset_t)&end) + PAGE_SIZE) & ~(PAGE_SIZE - 1); 675 if (octeon_board_real()) { 676 if (realmem_bytes > OCTEON_DRAM_FIRST_256_END) 677 phys_avail[1] = OCTEON_DRAM_FIRST_256_END; 678 else 679 phys_avail[1] = realmem_bytes; 680 realmem_bytes -= OCTEON_DRAM_FIRST_256_END; 681 realmem_bytes &= ~(PAGE_SIZE - 1); 682 printf("phys_avail[0] = %x phys_avail[1] = %x\n", 683 phys_avail[0], phys_avail[1]); 684 } else { 685 /* Simulator gets 96Meg period. */ 686 phys_avail[1] = (96 << 20); 687 } 688 /*- 689 * Octeon Memory looks as follows: 690 * PA 691 * 0000 0000 to 0x0 0000 0000 0000 692 * 0FFF FFFF First 256 MB memory Maps to 0x0 0000 0FFF FFFF 693 * 694 * 1000 0000 to 0x1 0000 1000 0000 695 * 1FFF FFFF Uncached Bu I/O space.converted to 0x1 0000 1FFF FFFF 696 * 697 * 2FFF FFFF to Cached 0x0 0000 2000 0000 698 * FFFF FFFF all dram mem above the first 512M 0x3 FFFF FFFF FFFF 699 * 700 */ 701 physmem = btoc(phys_avail[1] - phys_avail[0]); 702 if ((octeon_board_real()) && 703 (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) { 704 /* take out the upper non-cached 1/2 */ 705 realmem_bytes -= OCTEON_DRAM_FIRST_256_END; 706 realmem_bytes &= ~(PAGE_SIZE - 1); 707 /* Now map the rest of the memory */ 708 phys_avail[2] = 0x20000000; 709 printf("realmem_bytes is now at %x\n", realmem_bytes); 710 phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes); 711 printf("Next block of memory goes from %x to %x\n", 712 phys_avail[2], phys_avail[3]); 713 physmem += btoc(phys_avail[3] - phys_avail[2]); 714 } else { 715 printf("realmem_bytes is %d\n", realmem_bytes); 716 } 717 realmem = physmem; 718 719 printf("\nTotal DRAM Size 0x%X", (uint32_t) octeon_dram); 720 printf("\nBank 0 = 0x%8X -> 0x%8X", phys_avail[0], phys_avail[1]); 721 printf("\nBank 1 = 0x%8X -> 0x%8X\n", phys_avail[2], phys_avail[3]); 722 printf("\nphysmem: 0x%lx", physmem); 723 724 Maxmem = physmem; 725 726} 727 728void 729platform_start(__register_t a0, __register_t a1, __register_t a2 __unused, 730 __register_t a3) 731{ 732 uint64_t platform_counter_freq; 733 734 /* Initialize pcpu stuff */ 735 mips_pcpu0_init(); 736 mips_timer_early_init(OCTEON_CLOCK_DEFAULT); 737 cninit(); 738 739 octeon_ciu_reset(); 740 octeon_boot_params_init(a3); 741 bootverbose = 1; 742 cpuid_to_pcpu[0] = &pcpu0; 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 bad_desc = octeon_process_app_desc_ver_6(); 966 } 967 if (bad_desc) 968 octeon_process_app_desc_ver_unknown(); 969 970 printf("Boot Descriptor Ver: %u -> %u/%u", 971 octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100); 972 printf(" CPU clock: %uMHz\n", octeon_cpu_clock/1000000); 973 printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20)); 974 printf(" Board Type: %u Revision: %u/%u\n", 975 octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor); 976 printf(" Octeon Chip: %u Rev %u/%u", 977 octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor); 978 979 printf(" Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n", 980 octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2], 981 octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5], 982 octeon_mac_addr_count); 983} 984/* impEND: This stuff should move back into the Cavium SDK */ 985