cvmx-app-init.c revision 232812
1210284Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett#include <stdio.h> 47210284Sjmallett#include <stdint.h> 48210284Sjmallett#include <stdlib.h> 49210284Sjmallett#include <string.h> 50232812Sjmallett#include "executive-config.h" 51210284Sjmallett#include "cvmx-config.h" 52210284Sjmallett#include "cvmx.h" 53210284Sjmallett#include "cvmx-spinlock.h" 54210284Sjmallett#include <octeon-app-init.h> 55210284Sjmallett#include "cvmx-sysinfo.h" 56210284Sjmallett#include "cvmx-bootmem.h" 57210284Sjmallett#include "cvmx-uart.h" 58210284Sjmallett#include "cvmx-coremask.h" 59210284Sjmallett#include "cvmx-core.h" 60210284Sjmallett#include "cvmx-interrupt.h" 61210284Sjmallett#include "cvmx-ebt3000.h" 62215990Sjmallett#include "cvmx-sim-magic.h" 63215990Sjmallett#include "cvmx-debug.h" 64232812Sjmallett#include "cvmx-qlm.h" 65232812Sjmallett#include "cvmx-scratch.h" 66232812Sjmallett#include "cvmx-helper-cfg.h" 67232812Sjmallett#include "cvmx-helper-jtag.h" 68232812Sjmallett#include <octeon_mem_map.h> 69232812Sjmallett#include "libfdt.h" 70215990Sjmallettint cvmx_debug_uart = -1; 71210284Sjmallett 72210284Sjmallett/** 73210284Sjmallett * @file 74210284Sjmallett * 75210284Sjmallett * Main entry point for all simple executive based programs. 76210284Sjmallett */ 77210284Sjmallett 78210284Sjmallett 79210284Sjmallettextern void cvmx_interrupt_initialize(void); 80210284Sjmallett 81210284Sjmallett 82210284Sjmallett 83210284Sjmallett/** 84210284Sjmallett * Main entry point for all simple executive based programs. 85210284Sjmallett * This is the first C function called. It completes 86210284Sjmallett * initialization, calls main, and performs C level cleanup. 87210284Sjmallett * 88210284Sjmallett * @param app_desc_addr 89210284Sjmallett * Address of the application description structure passed 90210284Sjmallett * brom the boot loader. 91210284Sjmallett */ 92210284SjmallettEXTERN_ASM void __cvmx_app_init(uint64_t app_desc_addr); 93210284Sjmallett 94210284Sjmallett 95210284Sjmallett/** 96210284Sjmallett * Set up sysinfo structure from boot descriptor versions 6 and higher. 97210284Sjmallett * In these versions, the interesting data in not in the boot info structure 98210284Sjmallett * defined by the toolchain, but is in the cvmx_bootinfo structure defined in 99210284Sjmallett * the simple exec. 100210284Sjmallett * 101210284Sjmallett * @param app_desc_ptr 102210284Sjmallett * pointer to boot descriptor block 103210284Sjmallett * 104210284Sjmallett * @param sys_info_ptr 105210284Sjmallett * pointer to sysinfo structure to fill in 106210284Sjmallett */ 107210284Sjmallettstatic void process_boot_desc_ver_6(octeon_boot_descriptor_t *app_desc_ptr, cvmx_sysinfo_t *sys_info_ptr) 108210284Sjmallett{ 109210284Sjmallett cvmx_bootinfo_t *cvmx_bootinfo_ptr = CASTPTR(cvmx_bootinfo_t, app_desc_ptr->cvmx_desc_vaddr); 110210284Sjmallett 111210284Sjmallett /* copy application information for simple exec use */ 112210284Sjmallett /* Populate the sys_info structure from the boot descriptor block created by the bootloader. 113210284Sjmallett ** The boot descriptor block is put in the top of the heap, so it will be overwritten when the 114210284Sjmallett ** heap is fully used. Information that is to be used must be copied before that. 115210284Sjmallett ** Applications should only use the sys_info structure, not the boot descriptor 116210284Sjmallett */ 117210284Sjmallett if (cvmx_bootinfo_ptr->major_version == 1) 118210284Sjmallett { 119210284Sjmallett sys_info_ptr->core_mask = cvmx_bootinfo_ptr->core_mask; 120210284Sjmallett sys_info_ptr->heap_base = cvmx_bootinfo_ptr->heap_base; 121210284Sjmallett sys_info_ptr->heap_size = cvmx_bootinfo_ptr->heap_end - cvmx_bootinfo_ptr->heap_base; 122210284Sjmallett sys_info_ptr->stack_top = cvmx_bootinfo_ptr->stack_top; 123210284Sjmallett sys_info_ptr->stack_size = cvmx_bootinfo_ptr->stack_size; 124210284Sjmallett sys_info_ptr->init_core = cvmx_get_core_num(); 125215990Sjmallett sys_info_ptr->phy_mem_desc_addr = cvmx_bootinfo_ptr->phy_mem_desc_addr; 126210284Sjmallett sys_info_ptr->exception_base_addr = cvmx_bootinfo_ptr->exception_base_addr; 127210284Sjmallett sys_info_ptr->cpu_clock_hz = cvmx_bootinfo_ptr->eclock_hz; 128210284Sjmallett sys_info_ptr->dram_data_rate_hz = cvmx_bootinfo_ptr->dclock_hz * 2; 129210284Sjmallett 130210284Sjmallett sys_info_ptr->board_type = cvmx_bootinfo_ptr->board_type; 131210284Sjmallett sys_info_ptr->board_rev_major = cvmx_bootinfo_ptr->board_rev_major; 132210284Sjmallett sys_info_ptr->board_rev_minor = cvmx_bootinfo_ptr->board_rev_minor; 133210284Sjmallett memcpy(sys_info_ptr->mac_addr_base, cvmx_bootinfo_ptr->mac_addr_base, 6); 134210284Sjmallett sys_info_ptr->mac_addr_count = cvmx_bootinfo_ptr->mac_addr_count; 135210284Sjmallett memcpy(sys_info_ptr->board_serial_number, cvmx_bootinfo_ptr->board_serial_number, CVMX_BOOTINFO_OCTEON_SERIAL_LEN); 136210284Sjmallett sys_info_ptr->console_uart_num = 0; 137210284Sjmallett if (cvmx_bootinfo_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) 138210284Sjmallett sys_info_ptr->console_uart_num = 1; 139210284Sjmallett 140215990Sjmallett if (cvmx_bootinfo_ptr->dram_size > 32*1024*1024) 141210284Sjmallett sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size; /* older bootloaders incorrectly gave this in bytes, so don't convert */ 142210284Sjmallett else 143210284Sjmallett sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size * 1024 * 1024; /* convert from Megabytes to bytes */ 144210284Sjmallett if (cvmx_bootinfo_ptr->minor_version >= 1) 145210284Sjmallett { 146210284Sjmallett sys_info_ptr->compact_flash_common_base_addr = cvmx_bootinfo_ptr->compact_flash_common_base_addr; 147210284Sjmallett sys_info_ptr->compact_flash_attribute_base_addr = cvmx_bootinfo_ptr->compact_flash_attribute_base_addr; 148210284Sjmallett sys_info_ptr->led_display_base_addr = cvmx_bootinfo_ptr->led_display_base_addr; 149210284Sjmallett } 150210284Sjmallett else if (sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT3000 || 151215990Sjmallett sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5800 || 152215990Sjmallett sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5810) 153210284Sjmallett { 154210284Sjmallett /* Default these variables so that users of structure can be the same no 155210284Sjmallett ** matter what version fo boot info block the bootloader passes */ 156210284Sjmallett sys_info_ptr->compact_flash_common_base_addr = 0x1d000000 + 0x800; 157210284Sjmallett sys_info_ptr->compact_flash_attribute_base_addr = 0x1d010000; 158210284Sjmallett if (sys_info_ptr->board_rev_major == 1) 159210284Sjmallett sys_info_ptr->led_display_base_addr = 0x1d020000; 160210284Sjmallett else 161210284Sjmallett sys_info_ptr->led_display_base_addr = 0x1d020000 + 0xf8; 162210284Sjmallett } 163210284Sjmallett else 164210284Sjmallett { 165210284Sjmallett sys_info_ptr->compact_flash_common_base_addr = 0; 166210284Sjmallett sys_info_ptr->compact_flash_attribute_base_addr = 0; 167210284Sjmallett sys_info_ptr->led_display_base_addr = 0; 168210284Sjmallett } 169210284Sjmallett 170210284Sjmallett if (cvmx_bootinfo_ptr->minor_version >= 2) 171210284Sjmallett { 172210284Sjmallett sys_info_ptr->dfa_ref_clock_hz = cvmx_bootinfo_ptr->dfa_ref_clock_hz; 173210284Sjmallett sys_info_ptr->bootloader_config_flags = cvmx_bootinfo_ptr->config_flags; 174210284Sjmallett } 175210284Sjmallett else 176210284Sjmallett { 177210284Sjmallett sys_info_ptr->dfa_ref_clock_hz = 0; 178210284Sjmallett sys_info_ptr->bootloader_config_flags = 0; 179210284Sjmallett if (app_desc_ptr->flags & OCTEON_BL_FLAG_DEBUG) 180210284Sjmallett sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_DEBUG; 181210284Sjmallett if (app_desc_ptr->flags & OCTEON_BL_FLAG_NO_MAGIC) 182210284Sjmallett sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC; 183210284Sjmallett } 184210284Sjmallett 185210284Sjmallett } 186210284Sjmallett else 187210284Sjmallett { 188210284Sjmallett printf("ERROR: Incompatible CVMX descriptor passed by bootloader: %d.%d\n", 189210284Sjmallett (int)cvmx_bootinfo_ptr->major_version, (int)cvmx_bootinfo_ptr->minor_version); 190215990Sjmallett exit(-1); 191210284Sjmallett } 192232812Sjmallett if ((cvmx_bootinfo_ptr->minor_version >= 3) && (cvmx_bootinfo_ptr->fdt_addr != 0)) 193232812Sjmallett { 194232812Sjmallett sys_info_ptr->fdt_addr = UNMAPPED_PTR(cvmx_bootinfo_ptr->fdt_addr); 195232812Sjmallett if (fdt_check_header((const void *)sys_info_ptr->fdt_addr)) 196232812Sjmallett { 197232812Sjmallett printf("ERROR : Corrupt Device Tree.\n"); 198232812Sjmallett exit(-1); 199232812Sjmallett } 200232812Sjmallett printf("Using device tree\n"); 201232812Sjmallett } 202232812Sjmallett else 203232812Sjmallett { 204232812Sjmallett sys_info_ptr->fdt_addr = 0; 205232812Sjmallett } 206210284Sjmallett} 207210284Sjmallett 208210284Sjmallett 209210284Sjmallett/** 210210284Sjmallett * Interrupt handler for calling exit on Control-C interrupts. 211210284Sjmallett * 212210284Sjmallett * @param irq_number IRQ interrupt number 213210284Sjmallett * @param registers CPU registers at the time of the interrupt 214210284Sjmallett * @param user_arg Unused user argument 215210284Sjmallett */ 216210284Sjmallettstatic void process_break_interrupt(int irq_number, uint64_t registers[32], void *user_arg) 217210284Sjmallett{ 218210284Sjmallett /* Exclude new functionality when building with older toolchains */ 219210284Sjmallett#if OCTEON_APP_INIT_H_VERSION >= 3 220210284Sjmallett int uart = irq_number - CVMX_IRQ_UART0; 221210284Sjmallett cvmx_uart_lsr_t lsrval; 222210284Sjmallett 223210284Sjmallett /* Check for a Control-C interrupt from the console. This loop will eat 224210284Sjmallett all input received on the uart */ 225210284Sjmallett lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart)); 226210284Sjmallett while (lsrval.s.dr) 227210284Sjmallett { 228210284Sjmallett int c = cvmx_read_csr(CVMX_MIO_UARTX_RBR(uart)); 229210284Sjmallett if (c == '\003') 230210284Sjmallett { 231210284Sjmallett register uint64_t tmp; 232210284Sjmallett 233232812Sjmallett /* Wait for an another Control-C if right now we have no 234232812Sjmallett access to the console. After this point we hold the 235232812Sjmallett lock and use a different lock to synchronize between 236232812Sjmallett the memfile dumps from different cores. As a 237232812Sjmallett consequence regular printfs *don't* work after this 238232812Sjmallett point! */ 239232812Sjmallett if (__octeon_uart_trylock () == 1) 240232812Sjmallett return; 241210284Sjmallett 242210284Sjmallett /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also 243232812Sjmallett set the MCD0 to be not masked by this core so we know 244232812Sjmallett the signal is received by someone */ 245210284Sjmallett asm volatile ( 246210284Sjmallett "dmfc0 %0, $22\n" 247210284Sjmallett "ori %0, %0, 0x1110\n" 248210284Sjmallett "dmtc0 %0, $22\n" 249210284Sjmallett : "=r" (tmp)); 250210284Sjmallett } 251210284Sjmallett lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart)); 252210284Sjmallett } 253210284Sjmallett#endif 254210284Sjmallett} 255210284Sjmallett 256210284Sjmallett/** 257210284Sjmallett * This is the debug exception handler with "break". Before calling exit to 258210284Sjmallett * dump the profile-feedback output it releases the lock on the console. 259210284Sjmallett * This way if there is buffered data in stdout it can still be flushed. 260210284Sjmallett * stdio is required to flush all output during an fread. 261210284Sjmallett */ 262210284Sjmallett 263210284Sjmallettstatic void exit_on_break(void) 264210284Sjmallett{ 265210284Sjmallett#if OCTEON_APP_INIT_H_VERSION >= 4 266210284Sjmallett unsigned int coremask = cvmx_sysinfo_get()->core_mask; 267210284Sjmallett 268210284Sjmallett cvmx_coremask_barrier_sync(coremask); 269210284Sjmallett if (cvmx_coremask_first_core(coremask)) 270210284Sjmallett __octeon_uart_unlock(); 271210284Sjmallett#endif 272210284Sjmallett 273210284Sjmallett exit(0); 274210284Sjmallett} 275210284Sjmallett 276210284Sjmallett/* Add string signature to applications so that we can easily tell what 277210284Sjmallett** Octeon revision they were compiled for. Don't make static to avoid unused 278210284Sjmallett** variable warning. */ 279210284Sjmallett#define xstr(s) str(s) 280210284Sjmallett#define str(s) #s 281210284Sjmallett 282210284Sjmallettint octeon_model_version_check(uint32_t chip_id); 283210284Sjmallett 284210284Sjmallett#define OMS xstr(OCTEON_MODEL) 285210284Sjmallettchar octeon_rev_signature[] = 286210284Sjmallett#ifdef USE_RUNTIME_MODEL_CHECKS 287210284Sjmallett "Compiled for runtime Octeon model checking"; 288210284Sjmallett#else 289210284Sjmallett "Compiled for Octeon processor id: "OMS; 290210284Sjmallett#endif 291210284Sjmallett 292232812Sjmallett#define OCTEON_BL_FLAG_HPLUG_CORES (1 << 6) 293210284Sjmallettvoid __cvmx_app_init(uint64_t app_desc_addr) 294210284Sjmallett{ 295210284Sjmallett /* App descriptor used by bootloader */ 296210284Sjmallett octeon_boot_descriptor_t *app_desc_ptr = CASTPTR(octeon_boot_descriptor_t, app_desc_addr); 297210284Sjmallett 298210284Sjmallett /* app info structure used by the simple exec */ 299210284Sjmallett cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get(); 300215990Sjmallett int breakflag = 0; 301210284Sjmallett 302232812Sjmallett //printf("coremask=%08x flags=%08x \n", app_desc_ptr->core_mask, app_desc_ptr->flags); 303210284Sjmallett if (cvmx_coremask_first_core(app_desc_ptr->core_mask)) 304210284Sjmallett { 305232812Sjmallett /* Intialize the bootmem allocator with the descriptor that was provided by 306232812Sjmallett * the bootloader 307232812Sjmallett * IMPORTANT: All printfs must happen after this since PCI console uses named 308232812Sjmallett * blocks. 309232812Sjmallett */ 310232812Sjmallett cvmx_bootmem_init(CASTPTR(cvmx_bootinfo_t, app_desc_ptr->cvmx_desc_vaddr)->phy_mem_desc_addr); 311232812Sjmallett 312210284Sjmallett /* do once per application setup */ 313210284Sjmallett if (app_desc_ptr->desc_version < 6) 314210284Sjmallett { 315210284Sjmallett printf("Obsolete bootloader, can't run application\n"); 316215990Sjmallett exit(-1); 317210284Sjmallett } 318210284Sjmallett else 319210284Sjmallett { 320210284Sjmallett /* Handle all newer versions here.... */ 321210284Sjmallett if (app_desc_ptr->desc_version > 7) 322210284Sjmallett { 323210284Sjmallett printf("Warning: newer boot descripter version than expected\n"); 324210284Sjmallett } 325210284Sjmallett process_boot_desc_ver_6(app_desc_ptr,sys_info_ptr); 326210284Sjmallett 327210284Sjmallett } 328232812Sjmallett 329232812Sjmallett /* 330232812Sjmallett * set up the feature map and config. 331232812Sjmallett */ 332232812Sjmallett octeon_feature_init(); 333232812Sjmallett 334232812Sjmallett __cvmx_helper_cfg_init(); 335210284Sjmallett } 336232812Sjmallett /* The flags varibale get copied over at some places and tracing the origins 337232812Sjmallett found that 338232812Sjmallett ** In octeon_setup_boot_desc_block 339232812Sjmallett . cvmx_bootinfo_array[core].flags is initialized and the various bits are set 340232812Sjmallett . cvmx_bootinfo_array[core].flags gets copied to boot_desc[core].flags 341232812Sjmallett . Then boot_desc then get copied over to the end of the application heap and 342232812Sjmallett boot_info_block_array[core].boot_descr_addr is set to point to the boot_desc 343232812Sjmallett in heap. 344232812Sjmallett ** In start_app boot_vect->boot_info_addr->boot_desc_addr is referenced and passed on 345232812Sjmallett to octeon_setup_crt0_tlb() and this puts it into r16 346232812Sjmallett ** In ctr0.S of the toolchain r16 is picked up and passed on as a parameter to 347232812Sjmallett __cvmx_app_init 348210284Sjmallett 349232812Sjmallett Note : boot_vect->boot_info_addr points to boot_info_block_array[core] and this 350232812Sjmallett pointer is setup in octeon_setup_boot_vector() 351232812Sjmallett */ 352232812Sjmallett 353232812Sjmallett if (!(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES)) 354232812Sjmallett cvmx_coremask_barrier_sync(app_desc_ptr->core_mask); 355232812Sjmallett 356232812Sjmallett 357215990Sjmallett breakflag = sys_info_ptr->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_BREAK; 358215990Sjmallett 359215990Sjmallett /* No need to initialize bootmem, interrupts, interrupt handler and error handler 360215990Sjmallett if version does not match. */ 361215990Sjmallett if (cvmx_coremask_first_core(sys_info_ptr->core_mask)) 362210284Sjmallett { 363215990Sjmallett /* Check to make sure the Chip version matches the configured version */ 364215990Sjmallett uint32_t chip_id = cvmx_get_proc_id(); 365215990Sjmallett /* Make sure we can properly run on this chip */ 366215990Sjmallett octeon_model_version_check(chip_id); 367210284Sjmallett } 368210284Sjmallett cvmx_interrupt_initialize(); 369210284Sjmallett if (cvmx_coremask_first_core(sys_info_ptr->core_mask)) 370210284Sjmallett { 371215990Sjmallett int break_uart = 0; 372215990Sjmallett unsigned int i; 373210284Sjmallett 374215990Sjmallett if (breakflag && cvmx_debug_booted()) 375215990Sjmallett { 376215990Sjmallett printf("ERROR: Using debug and break together in not supported.\n"); 377215990Sjmallett while (1) 378215990Sjmallett ; 379215990Sjmallett } 380210284Sjmallett 381215990Sjmallett /* Search through the arguments for a break=X or a debug=X. */ 382215990Sjmallett for (i = 0; i < app_desc_ptr->argc; i++) 383215990Sjmallett { 384215990Sjmallett const char *argv = CASTPTR(const char, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, app_desc_ptr->argv[i])); 385215990Sjmallett if (strncmp(argv, "break=", 6) == 0) 386215990Sjmallett break_uart = atoi(argv + 6); 387215990Sjmallett else if (strncmp(argv, "debug=", 6) == 0) 388215990Sjmallett cvmx_debug_uart = atoi(argv + 6); 389215990Sjmallett } 390210284Sjmallett 391215990Sjmallett if (breakflag) 392210284Sjmallett { 393215990Sjmallett int32_t *trampoline = CASTPTR(int32_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, BOOTLOADER_DEBUG_TRAMPOLINE)); 394215990Sjmallett /* On debug exception, call exit_on_break from all cores. */ 395215990Sjmallett *trampoline = (int32_t)(long)&exit_on_break; 396215990Sjmallett cvmx_uart_enable_intr(break_uart, process_break_interrupt); 397210284Sjmallett } 398210284Sjmallett } 399232812Sjmallett if ( !(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES)) 400232812Sjmallett cvmx_coremask_barrier_sync(app_desc_ptr->core_mask); 401210284Sjmallett 402210284Sjmallett /* Clear BEV now that we have installed exception handlers. */ 403210284Sjmallett uint64_t tmp; 404210284Sjmallett asm volatile ( 405210284Sjmallett " .set push \n" 406210284Sjmallett " .set mips64 \n" 407210284Sjmallett " .set noreorder \n" 408210284Sjmallett " .set noat \n" 409210284Sjmallett " mfc0 %[tmp], $12, 0 \n" 410210284Sjmallett " li $at, 1 << 22 \n" 411210284Sjmallett " not $at, $at \n" 412210284Sjmallett " and %[tmp], $at \n" 413210284Sjmallett " mtc0 %[tmp], $12, 0 \n" 414210284Sjmallett " .set pop \n" 415210284Sjmallett : [tmp] "=&r" (tmp) : ); 416210284Sjmallett 417210284Sjmallett /* Set all cores to stop on MCD0 signals */ 418210284Sjmallett asm volatile( 419210284Sjmallett "dmfc0 %0, $22, 0\n" 420210284Sjmallett "or %0, %0, 0x1100\n" 421210284Sjmallett "dmtc0 %0, $22, 0\n" : "=r" (tmp)); 422210284Sjmallett 423210284Sjmallett CVMX_SYNC; 424215990Sjmallett /* Now intialize the debug exception handler as BEV is cleared. */ 425232812Sjmallett if ((!breakflag) && (!(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES))) 426215990Sjmallett cvmx_debug_init(); 427215990Sjmallett 428210284Sjmallett /* Synchronise all cores at this point */ 429232812Sjmallett if ( !(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES)) 430232812Sjmallett cvmx_coremask_barrier_sync(app_desc_ptr->core_mask); 431210284Sjmallett 432210284Sjmallett} 433210284Sjmallett 434210284Sjmallettint cvmx_user_app_init(void) 435210284Sjmallett{ 436210284Sjmallett uint64_t bist_val; 437210284Sjmallett uint64_t mask; 438210284Sjmallett int bist_errors = 0; 439210284Sjmallett uint64_t tmp; 440210284Sjmallett uint64_t base_addr; 441210284Sjmallett 442210284Sjmallett 443210284Sjmallett /* Put message on LED display */ 444210284Sjmallett if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) 445232812Sjmallett ebt3000_str_write("CVMX "); 446210284Sjmallett 447210284Sjmallett /* Check BIST results for COP0 registers, some values only meaningful in pass 2 */ 448210284Sjmallett CVMX_MF_CACHE_ERR(bist_val); 449232812Sjmallett mask = (0x3fULL<<32); // Icache;BHT;AES;HSH/GFM;LRU;register file 450210284Sjmallett bist_val &= mask; 451210284Sjmallett if (bist_val) 452210284Sjmallett { 453210284Sjmallett printf("BIST FAILURE: COP0_CACHE_ERR: 0x%llx\n", (unsigned long long)bist_val); 454210284Sjmallett bist_errors++; 455210284Sjmallett } 456210284Sjmallett 457210284Sjmallett mask = 0xfc00000000000000ull; 458210284Sjmallett CVMX_MF_CVM_MEM_CTL(bist_val); 459210284Sjmallett bist_val &= mask; 460210284Sjmallett if (bist_val) 461210284Sjmallett { 462210284Sjmallett printf("BIST FAILURE: COP0_CVM_MEM_CTL: 0x%llx\n", (unsigned long long)bist_val); 463210284Sjmallett bist_errors++; 464210284Sjmallett } 465210284Sjmallett 466210284Sjmallett /* Set up 4 cache lines of local memory, make available from Kernel space */ 467210284Sjmallett CVMX_MF_CVM_MEM_CTL(tmp); 468210284Sjmallett tmp &= ~0x1ffull; 469210284Sjmallett tmp |= 0x104ull; 470215990Sjmallett /* Set WBTHRESH=4 as per Core-14752 errata in cn63xxp1.X. */ 471215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 472215990Sjmallett { 473215990Sjmallett tmp &= ~(0xfull << 11); 474215990Sjmallett tmp |= 4 << 11; 475215990Sjmallett } 476210284Sjmallett CVMX_MT_CVM_MEM_CTL(tmp); 477210284Sjmallett 478232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X)) 479232812Sjmallett { 480232812Sjmallett /* Clear the lines of scratch memory configured, for 481232812Sjmallett ** 63XX pass 2 errata Core-15169. */ 482232812Sjmallett uint64_t addr; 483232812Sjmallett unsigned num_lines; 484232812Sjmallett CVMX_MF_CVM_MEM_CTL(tmp); 485232812Sjmallett num_lines = tmp & 0x3f; 486232812Sjmallett for (addr = 0; addr < CVMX_CACHE_LINE_SIZE * num_lines; addr += 8) 487232812Sjmallett cvmx_scratch_write64(addr, 0); 488232812Sjmallett } 489210284Sjmallett 490210284Sjmallett#if CVMX_USE_1_TO_1_TLB_MAPPINGS 491210284Sjmallett 492210284Sjmallett /* Check to see if the bootloader is indicating that the application is outside 493210284Sjmallett ** of the 0x10000000 0x20000000 range, in which case we can't use 1-1 mappings */ 494210284Sjmallett if (cvmx_sysinfo_get()->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING) 495210284Sjmallett { 496210284Sjmallett printf("ERROR: 1-1 TLB mappings configured and oversize application loaded.\n"); 497210284Sjmallett printf("ERROR: Either 1-1 TLB mappings must be disabled or application size reduced.\n"); 498215990Sjmallett exit(-1); 499210284Sjmallett } 500210284Sjmallett 501210284Sjmallett /* Create 1-1 Mappings for all DRAM up to 8 gigs, excluding the low 1 Megabyte. This area 502210284Sjmallett ** is reserved for the bootloader and exception vectors. By not mapping this area, NULL pointer 503210284Sjmallett ** dereferences will be caught with TLB exceptions. Exception handlers should be written 504210284Sjmallett ** using XKPHYS or KSEG0 addresses. */ 505210284Sjmallett#if CVMX_NULL_POINTER_PROTECT 506210284Sjmallett /* Exclude low 1 MByte from mapping to detect NULL pointer accesses. 507210284Sjmallett ** The only down side of this is it uses more TLB mappings */ 508210284Sjmallett cvmx_core_add_fixed_tlb_mapping_bits(0x0, 0x0, 0x100000 | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_1M); 509210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x200000, 0x200000, 0x300000, CVMX_TLB_PAGEMASK_1M); 510210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x400000, 0x400000, 0x500000, CVMX_TLB_PAGEMASK_1M); 511210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x600000, 0x600000, 0x700000, CVMX_TLB_PAGEMASK_1M); 512210284Sjmallett 513210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x800000, 0x800000, 0xC00000, CVMX_TLB_PAGEMASK_4M); 514210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x1000000, 0x1000000, 0x1400000, CVMX_TLB_PAGEMASK_4M); 515210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x1800000, 0x1800000, 0x1c00000, CVMX_TLB_PAGEMASK_4M); 516210284Sjmallett 517210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x2000000, 0x2000000, 0x3000000, CVMX_TLB_PAGEMASK_16M); 518210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x4000000, 0x4000000, 0x5000000, CVMX_TLB_PAGEMASK_16M); 519210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x6000000, 0x6000000, 0x7000000, CVMX_TLB_PAGEMASK_16M); 520210284Sjmallett#else 521210284Sjmallett /* Map entire low 128 Megs, including 0x0 */ 522210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x0, 0x0, 0x4000000ULL, CVMX_TLB_PAGEMASK_64M); 523210284Sjmallett#endif 524210284Sjmallett cvmx_core_add_fixed_tlb_mapping(0x8000000ULL, 0x8000000ULL, 0xc000000ULL, CVMX_TLB_PAGEMASK_64M); 525210284Sjmallett 526215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 527210284Sjmallett { 528215990Sjmallett for (base_addr = 0x20000000ULL; base_addr < (cvmx_sysinfo_get()->system_dram_size + 0x10000000ULL); base_addr += 0x20000000ULL) 529210284Sjmallett { 530210284Sjmallett if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr, base_addr, base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M)) 531210284Sjmallett { 532210284Sjmallett printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr); 533215990Sjmallett /* Exit from here, as expected memory mappings aren't set 534215990Sjmallett up if this fails */ 535232812Sjmallett exit(-1); 536210284Sjmallett } 537210284Sjmallett } 538210284Sjmallett } 539215990Sjmallett else 540215990Sjmallett { 541215990Sjmallett /* Create 1-1 mapping for next 256 megs 542215990Sjmallett ** bottom page is not valid */ 543215990Sjmallett cvmx_core_add_fixed_tlb_mapping_bits(0x400000000ULL, 0, 0x410000000ULL | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_256M); 544210284Sjmallett 545215990Sjmallett /* Map from 0.5 up to the installed memory size in 512 MByte chunks. If this loop runs out of memory, 546215990Sjmallett ** the NULL pointer detection can be disabled to free up more TLB entries. */ 547215990Sjmallett if (cvmx_sysinfo_get()->system_dram_size > 0x20000000ULL) 548215990Sjmallett { 549215990Sjmallett for (base_addr = 0x20000000ULL; base_addr <= (cvmx_sysinfo_get()->system_dram_size - 0x20000000ULL); base_addr += 0x20000000ULL) 550215990Sjmallett { 551215990Sjmallett if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr, base_addr, base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M)) 552215990Sjmallett { 553215990Sjmallett printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr); 554215990Sjmallett /* Exit from here, as expected memory mappings 555215990Sjmallett aren't set up if this fails */ 556215990Sjmallett exit(-1); 557215990Sjmallett } 558215990Sjmallett } 559215990Sjmallett } 560215990Sjmallett } 561210284Sjmallett#endif 562210284Sjmallett 563210284Sjmallett 564210284Sjmallett cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get(); 565215990Sjmallett cvmx_bootmem_init(sys_info_ptr->phy_mem_desc_addr); 566210284Sjmallett 567232812Sjmallett /* Initialize QLM and JTAG settings. Also apply any erratas. */ 568232812Sjmallett if (cvmx_coremask_first_core(cvmx_sysinfo_get()->core_mask)) 569232812Sjmallett cvmx_qlm_init(); 570232812Sjmallett 571210284Sjmallett return(0); 572210284Sjmallett} 573210284Sjmallett 574210284Sjmallettvoid __cvmx_app_exit(void) 575210284Sjmallett{ 576215990Sjmallett cvmx_debug_finish(); 577215990Sjmallett 578215990Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 579210284Sjmallett { 580232812Sjmallett CVMX_BREAK; 581215990Sjmallett } 582215990Sjmallett /* Hang forever, until more appropriate stand alone simple executive 583215990Sjmallett exit() is implemented */ 584210284Sjmallett 585215990Sjmallett while (1); 586210284Sjmallett} 587210284Sjmallett 588210284Sjmallett 589210284Sjmallett 590