cvmx-app-init.c revision 215990
1210284Sjmallett/***********************license start***************
2215990Sjmallett * Copyright (c) 2003-2010  Cavium Networks (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
18215990Sjmallett *   * Neither the name of Cavium Networks 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"
29215990Sjmallett * AND WITH ALL FAULTS AND CAVIUM  NETWORKS 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>
50210284Sjmallett#include "cvmx-config.h"
51210284Sjmallett#include "cvmx.h"
52210284Sjmallett#include "cvmx-spinlock.h"
53210284Sjmallett#include <octeon-app-init.h>
54210284Sjmallett#include "cvmx-sysinfo.h"
55210284Sjmallett#include "cvmx-bootmem.h"
56210284Sjmallett#include "cvmx-uart.h"
57210284Sjmallett#include "cvmx-coremask.h"
58210284Sjmallett#include "cvmx-core.h"
59210284Sjmallett#include "cvmx-interrupt.h"
60210284Sjmallett#include "cvmx-ebt3000.h"
61215990Sjmallett#include "cvmx-sim-magic.h"
62215990Sjmallett#include "cvmx-debug.h"
63210284Sjmallett#include "../../bootloader/u-boot/include/octeon_mem_map.h"
64210284Sjmallett
65215990Sjmallettint cvmx_debug_uart = -1;
66210284Sjmallett
67210284Sjmallett/**
68210284Sjmallett * @file
69210284Sjmallett *
70210284Sjmallett * Main entry point for all simple executive based programs.
71210284Sjmallett */
72210284Sjmallett
73210284Sjmallett
74210284Sjmallettextern void cvmx_interrupt_initialize(void);
75210284Sjmallett
76210284Sjmallett
77210284Sjmallett
78210284Sjmallett/**
79210284Sjmallett * Main entry point for all simple executive based programs.
80210284Sjmallett * This is the first C function called. It completes
81210284Sjmallett * initialization, calls main, and performs C level cleanup.
82210284Sjmallett *
83210284Sjmallett * @param app_desc_addr
84210284Sjmallett *               Address of the application description structure passed
85210284Sjmallett *               brom the boot loader.
86210284Sjmallett */
87210284SjmallettEXTERN_ASM void __cvmx_app_init(uint64_t app_desc_addr);
88210284Sjmallett
89210284Sjmallett
90210284Sjmallett/**
91210284Sjmallett * Set up sysinfo structure from boot descriptor versions 6 and higher.
92210284Sjmallett * In these versions, the interesting data in not in the boot info structure
93210284Sjmallett * defined by the toolchain, but is in the cvmx_bootinfo structure defined in
94210284Sjmallett * the simple exec.
95210284Sjmallett *
96210284Sjmallett * @param app_desc_ptr
97210284Sjmallett *               pointer to boot descriptor block
98210284Sjmallett *
99210284Sjmallett * @param sys_info_ptr
100210284Sjmallett *               pointer to sysinfo structure to fill in
101210284Sjmallett */
102210284Sjmallettstatic void process_boot_desc_ver_6(octeon_boot_descriptor_t *app_desc_ptr, cvmx_sysinfo_t *sys_info_ptr)
103210284Sjmallett{
104210284Sjmallett    cvmx_bootinfo_t *cvmx_bootinfo_ptr = CASTPTR(cvmx_bootinfo_t, app_desc_ptr->cvmx_desc_vaddr);
105210284Sjmallett
106210284Sjmallett    /* copy application information for simple exec use */
107210284Sjmallett    /* Populate the sys_info structure from the boot descriptor block created by the bootloader.
108210284Sjmallett    ** The boot descriptor block is put in the top of the heap, so it will be overwritten when the
109210284Sjmallett    ** heap is fully used.  Information that is to be used must be copied before that.
110210284Sjmallett    ** Applications should only use the sys_info structure, not the boot descriptor
111210284Sjmallett    */
112210284Sjmallett    if (cvmx_bootinfo_ptr->major_version == 1)
113210284Sjmallett    {
114210284Sjmallett        sys_info_ptr->core_mask = cvmx_bootinfo_ptr->core_mask;
115210284Sjmallett        sys_info_ptr->heap_base = cvmx_bootinfo_ptr->heap_base;
116210284Sjmallett        sys_info_ptr->heap_size = cvmx_bootinfo_ptr->heap_end - cvmx_bootinfo_ptr->heap_base;
117210284Sjmallett        sys_info_ptr->stack_top = cvmx_bootinfo_ptr->stack_top;
118210284Sjmallett        sys_info_ptr->stack_size = cvmx_bootinfo_ptr->stack_size;
119210284Sjmallett        sys_info_ptr->init_core = cvmx_get_core_num();
120215990Sjmallett        sys_info_ptr->phy_mem_desc_addr = cvmx_bootinfo_ptr->phy_mem_desc_addr;
121210284Sjmallett        sys_info_ptr->exception_base_addr = cvmx_bootinfo_ptr->exception_base_addr;
122210284Sjmallett        sys_info_ptr->cpu_clock_hz  = cvmx_bootinfo_ptr->eclock_hz;
123210284Sjmallett        sys_info_ptr->dram_data_rate_hz  = cvmx_bootinfo_ptr->dclock_hz * 2;
124210284Sjmallett
125210284Sjmallett        sys_info_ptr->board_type = cvmx_bootinfo_ptr->board_type;
126210284Sjmallett        sys_info_ptr->board_rev_major = cvmx_bootinfo_ptr->board_rev_major;
127210284Sjmallett        sys_info_ptr->board_rev_minor = cvmx_bootinfo_ptr->board_rev_minor;
128210284Sjmallett        memcpy(sys_info_ptr->mac_addr_base, cvmx_bootinfo_ptr->mac_addr_base, 6);
129210284Sjmallett        sys_info_ptr->mac_addr_count = cvmx_bootinfo_ptr->mac_addr_count;
130210284Sjmallett        memcpy(sys_info_ptr->board_serial_number, cvmx_bootinfo_ptr->board_serial_number, CVMX_BOOTINFO_OCTEON_SERIAL_LEN);
131210284Sjmallett        sys_info_ptr->console_uart_num = 0;
132210284Sjmallett        if (cvmx_bootinfo_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1)
133210284Sjmallett            sys_info_ptr->console_uart_num = 1;
134210284Sjmallett
135215990Sjmallett        if (cvmx_bootinfo_ptr->dram_size > 32*1024*1024)
136210284Sjmallett            sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size;  /* older bootloaders incorrectly gave this in bytes, so don't convert */
137210284Sjmallett        else
138210284Sjmallett            sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size * 1024 * 1024;  /* convert from Megabytes to bytes */
139210284Sjmallett        if (cvmx_bootinfo_ptr->minor_version >= 1)
140210284Sjmallett        {
141210284Sjmallett            sys_info_ptr->compact_flash_common_base_addr = cvmx_bootinfo_ptr->compact_flash_common_base_addr;
142210284Sjmallett            sys_info_ptr->compact_flash_attribute_base_addr = cvmx_bootinfo_ptr->compact_flash_attribute_base_addr;
143210284Sjmallett            sys_info_ptr->led_display_base_addr = cvmx_bootinfo_ptr->led_display_base_addr;
144210284Sjmallett        }
145210284Sjmallett        else if (sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT3000 ||
146215990Sjmallett                 sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5800 ||
147215990Sjmallett                 sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5810)
148210284Sjmallett        {
149210284Sjmallett            /* Default these variables so that users of structure can be the same no
150210284Sjmallett            ** matter what version fo boot info block the bootloader passes */
151210284Sjmallett            sys_info_ptr->compact_flash_common_base_addr = 0x1d000000 + 0x800;
152210284Sjmallett            sys_info_ptr->compact_flash_attribute_base_addr = 0x1d010000;
153210284Sjmallett            if (sys_info_ptr->board_rev_major == 1)
154210284Sjmallett                sys_info_ptr->led_display_base_addr = 0x1d020000;
155210284Sjmallett            else
156210284Sjmallett                sys_info_ptr->led_display_base_addr = 0x1d020000 + 0xf8;
157210284Sjmallett        }
158210284Sjmallett        else
159210284Sjmallett        {
160210284Sjmallett            sys_info_ptr->compact_flash_common_base_addr = 0;
161210284Sjmallett            sys_info_ptr->compact_flash_attribute_base_addr = 0;
162210284Sjmallett            sys_info_ptr->led_display_base_addr = 0;
163210284Sjmallett        }
164210284Sjmallett
165210284Sjmallett        if (cvmx_bootinfo_ptr->minor_version >= 2)
166210284Sjmallett        {
167210284Sjmallett            sys_info_ptr->dfa_ref_clock_hz = cvmx_bootinfo_ptr->dfa_ref_clock_hz;
168210284Sjmallett            sys_info_ptr->bootloader_config_flags = cvmx_bootinfo_ptr->config_flags;
169210284Sjmallett        }
170210284Sjmallett        else
171210284Sjmallett        {
172210284Sjmallett            sys_info_ptr->dfa_ref_clock_hz = 0;
173210284Sjmallett            sys_info_ptr->bootloader_config_flags = 0;
174210284Sjmallett            if (app_desc_ptr->flags & OCTEON_BL_FLAG_DEBUG)
175210284Sjmallett                sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_DEBUG;
176210284Sjmallett            if (app_desc_ptr->flags & OCTEON_BL_FLAG_NO_MAGIC)
177210284Sjmallett                sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC;
178210284Sjmallett        }
179210284Sjmallett
180210284Sjmallett    }
181210284Sjmallett    else
182210284Sjmallett    {
183210284Sjmallett        printf("ERROR: Incompatible CVMX descriptor passed by bootloader: %d.%d\n",
184210284Sjmallett               (int)cvmx_bootinfo_ptr->major_version, (int)cvmx_bootinfo_ptr->minor_version);
185215990Sjmallett        exit(-1);
186210284Sjmallett    }
187210284Sjmallett}
188210284Sjmallett
189210284Sjmallett
190210284Sjmallett/**
191210284Sjmallett * Interrupt handler for calling exit on Control-C interrupts.
192210284Sjmallett *
193210284Sjmallett * @param irq_number IRQ interrupt number
194210284Sjmallett * @param registers  CPU registers at the time of the interrupt
195210284Sjmallett * @param user_arg   Unused user argument
196210284Sjmallett */
197210284Sjmallettstatic void process_break_interrupt(int irq_number, uint64_t registers[32], void *user_arg)
198210284Sjmallett{
199210284Sjmallett    /* Exclude new functionality when building with older toolchains */
200210284Sjmallett#if OCTEON_APP_INIT_H_VERSION >= 3
201210284Sjmallett    int uart = irq_number - CVMX_IRQ_UART0;
202210284Sjmallett    cvmx_uart_lsr_t lsrval;
203210284Sjmallett
204210284Sjmallett    /* Check for a Control-C interrupt from the console. This loop will eat
205210284Sjmallett        all input received on the uart */
206210284Sjmallett    lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart));
207210284Sjmallett    while (lsrval.s.dr)
208210284Sjmallett    {
209210284Sjmallett        int c = cvmx_read_csr(CVMX_MIO_UARTX_RBR(uart));
210210284Sjmallett        if (c == '\003')
211210284Sjmallett        {
212210284Sjmallett            register uint64_t tmp;
213210284Sjmallett
214210284Sjmallett	    /* Wait for an another Control-C if right now we have no
215210284Sjmallett	       access to the console.  After this point we hold the
216210284Sjmallett	       lock and use a different lock to synchronize between
217210284Sjmallett	       the memfile dumps from different cores.  As a
218210284Sjmallett	       consequence regular printfs *don't* work after this
219210284Sjmallett	       point! */
220210284Sjmallett	    if (__octeon_uart_trylock () == 1)
221210284Sjmallett		return;
222210284Sjmallett
223210284Sjmallett            /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also
224210284Sjmallett	       set the MCD0 to be not masked by this core so we know
225210284Sjmallett	       the signal is received by someone */
226210284Sjmallett            asm volatile (
227210284Sjmallett                "dmfc0 %0, $22\n"
228210284Sjmallett                "ori   %0, %0, 0x1110\n"
229210284Sjmallett                "dmtc0 %0, $22\n"
230210284Sjmallett                : "=r" (tmp));
231210284Sjmallett        }
232210284Sjmallett        lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart));
233210284Sjmallett    }
234210284Sjmallett#endif
235210284Sjmallett}
236210284Sjmallett
237210284Sjmallett/**
238210284Sjmallett * This is the debug exception handler with "break".  Before calling exit to
239210284Sjmallett * dump the profile-feedback output it releases the lock on the console.
240210284Sjmallett * This way if there is buffered data in stdout it can still be flushed.
241210284Sjmallett * stdio is required to flush all output during an fread.
242210284Sjmallett */
243210284Sjmallett
244210284Sjmallettstatic void exit_on_break(void)
245210284Sjmallett{
246210284Sjmallett#if OCTEON_APP_INIT_H_VERSION >= 4
247210284Sjmallett    unsigned int coremask = cvmx_sysinfo_get()->core_mask;
248210284Sjmallett
249210284Sjmallett    cvmx_coremask_barrier_sync(coremask);
250210284Sjmallett    if (cvmx_coremask_first_core(coremask))
251210284Sjmallett      __octeon_uart_unlock();
252210284Sjmallett#endif
253210284Sjmallett
254210284Sjmallett    exit(0);
255210284Sjmallett}
256210284Sjmallett
257210284Sjmallett/* Add string signature to applications so that we can easily tell what
258210284Sjmallett** Octeon revision they were compiled for. Don't make static to avoid unused
259210284Sjmallett** variable warning. */
260210284Sjmallett#define xstr(s) str(s)
261210284Sjmallett#define str(s) #s
262210284Sjmallett
263210284Sjmallettint octeon_model_version_check(uint32_t chip_id);
264210284Sjmallett
265210284Sjmallett#define OMS xstr(OCTEON_MODEL)
266210284Sjmallettchar octeon_rev_signature[] =
267210284Sjmallett#ifdef USE_RUNTIME_MODEL_CHECKS
268210284Sjmallett    "Compiled for runtime Octeon model checking";
269210284Sjmallett#else
270210284Sjmallett    "Compiled for Octeon processor id: "OMS;
271210284Sjmallett#endif
272210284Sjmallett
273210284Sjmallettvoid __cvmx_app_init(uint64_t app_desc_addr)
274210284Sjmallett{
275210284Sjmallett    /* App descriptor used by bootloader */
276210284Sjmallett    octeon_boot_descriptor_t *app_desc_ptr = CASTPTR(octeon_boot_descriptor_t, app_desc_addr);
277210284Sjmallett
278210284Sjmallett    /* app info structure used by the simple exec */
279210284Sjmallett    cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
280215990Sjmallett    int breakflag = 0;
281210284Sjmallett
282210284Sjmallett    if (cvmx_coremask_first_core(app_desc_ptr->core_mask))
283210284Sjmallett    {
284210284Sjmallett        /* do once per application setup  */
285210284Sjmallett        if (app_desc_ptr->desc_version < 6)
286210284Sjmallett        {
287210284Sjmallett            printf("Obsolete bootloader, can't run application\n");
288215990Sjmallett            exit(-1);
289210284Sjmallett        }
290210284Sjmallett        else
291210284Sjmallett        {
292210284Sjmallett            /* Handle all newer versions here.... */
293210284Sjmallett            if (app_desc_ptr->desc_version > 7)
294210284Sjmallett            {
295210284Sjmallett                printf("Warning: newer boot descripter version than expected\n");
296210284Sjmallett            }
297210284Sjmallett            process_boot_desc_ver_6(app_desc_ptr,sys_info_ptr);
298210284Sjmallett
299210284Sjmallett        }
300210284Sjmallett    }
301210284Sjmallett    cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
302210284Sjmallett
303215990Sjmallett    breakflag = sys_info_ptr->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_BREAK;
304215990Sjmallett
305215990Sjmallett    /* No need to initialize bootmem, interrupts, interrupt handler and error handler
306215990Sjmallett       if version does not match. */
307215990Sjmallett    if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
308210284Sjmallett    {
309215990Sjmallett        /* Check to make sure the Chip version matches the configured version */
310215990Sjmallett        uint32_t chip_id = cvmx_get_proc_id();
311215990Sjmallett        /* Make sure we can properly run on this chip */
312215990Sjmallett        octeon_model_version_check(chip_id);
313210284Sjmallett    }
314210284Sjmallett
315210284Sjmallett    cvmx_interrupt_initialize();
316210284Sjmallett
317210284Sjmallett    if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
318210284Sjmallett    {
319215990Sjmallett        int break_uart = 0;
320215990Sjmallett        unsigned int i;
321210284Sjmallett
322210284Sjmallett        /* Intialize the bootmem allocator with the descriptor that was provided by
323215990Sjmallett         * the bootloader
324215990Sjmallett         * IMPORTANT:  All printfs must happen after this since PCI console uses named
325215990Sjmallett         * blocks.
326215990Sjmallett         */
327215990Sjmallett        cvmx_bootmem_init(sys_info_ptr->phy_mem_desc_addr);
328215990Sjmallett        if (breakflag && cvmx_debug_booted())
329215990Sjmallett        {
330215990Sjmallett            printf("ERROR: Using debug and break together in not supported.\n");
331215990Sjmallett            while (1)
332215990Sjmallett                ;
333215990Sjmallett        }
334210284Sjmallett
335215990Sjmallett        /* Search through the arguments for a break=X or a debug=X. */
336215990Sjmallett        for (i = 0; i < app_desc_ptr->argc; i++)
337215990Sjmallett        {
338215990Sjmallett            const char *argv = CASTPTR(const char, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, app_desc_ptr->argv[i]));
339215990Sjmallett            if (strncmp(argv, "break=", 6) == 0)
340215990Sjmallett                break_uart = atoi(argv + 6);
341215990Sjmallett            else if (strncmp(argv, "debug=", 6) == 0)
342215990Sjmallett                cvmx_debug_uart = atoi(argv + 6);
343215990Sjmallett        }
344210284Sjmallett
345215990Sjmallett        if (breakflag)
346210284Sjmallett        {
347215990Sjmallett            int32_t *trampoline = CASTPTR(int32_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, BOOTLOADER_DEBUG_TRAMPOLINE));
348215990Sjmallett            /* On debug exception, call exit_on_break from all cores. */
349215990Sjmallett            *trampoline = (int32_t)(long)&exit_on_break;
350215990Sjmallett            cvmx_uart_enable_intr(break_uart, process_break_interrupt);
351210284Sjmallett        }
352210284Sjmallett    }
353210284Sjmallett
354215990Sjmallett    cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
355215990Sjmallett
356210284Sjmallett    /* Clear BEV now that we have installed exception handlers. */
357210284Sjmallett    uint64_t tmp;
358210284Sjmallett    asm volatile (
359210284Sjmallett               "   .set push                  \n"
360210284Sjmallett               "   .set mips64                  \n"
361210284Sjmallett               "   .set noreorder               \n"
362210284Sjmallett               "   .set noat               \n"
363210284Sjmallett               "   mfc0 %[tmp], $12, 0          \n"
364210284Sjmallett               "   li   $at, 1 << 22            \n"
365210284Sjmallett               "   not  $at, $at                \n"
366210284Sjmallett               "   and  %[tmp], $at             \n"
367210284Sjmallett               "   mtc0 %[tmp], $12, 0          \n"
368210284Sjmallett               "   .set pop                  \n"
369210284Sjmallett                  : [tmp] "=&r" (tmp) : );
370210284Sjmallett
371210284Sjmallett    /* Set all cores to stop on MCD0 signals */
372210284Sjmallett    asm volatile(
373210284Sjmallett        "dmfc0 %0, $22, 0\n"
374210284Sjmallett        "or %0, %0, 0x1100\n"
375210284Sjmallett        "dmtc0 %0, $22, 0\n" : "=r" (tmp));
376210284Sjmallett
377210284Sjmallett    CVMX_SYNC;
378215990Sjmallett
379215990Sjmallett    /* Now intialize the debug exception handler as BEV is cleared. */
380215990Sjmallett    if (!breakflag)
381215990Sjmallett        cvmx_debug_init();
382215990Sjmallett
383210284Sjmallett    /* Synchronise all cores at this point */
384210284Sjmallett    cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
385210284Sjmallett
386210284Sjmallett}
387210284Sjmallett
388210284Sjmallettint cvmx_user_app_init(void)
389210284Sjmallett{
390210284Sjmallett    uint64_t bist_val;
391210284Sjmallett    uint64_t mask;
392210284Sjmallett    int bist_errors = 0;
393210284Sjmallett    uint64_t tmp;
394210284Sjmallett    uint64_t base_addr;
395210284Sjmallett
396210284Sjmallett
397210284Sjmallett    /* Put message on LED display */
398210284Sjmallett    if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)
399210284Sjmallett      ebt3000_str_write("CVMX    ");
400210284Sjmallett
401210284Sjmallett    /* Check BIST results for COP0 registers, some values only meaningful in pass 2 */
402210284Sjmallett    CVMX_MF_CACHE_ERR(bist_val);
403210284Sjmallett    mask = (1ULL<<32) | (1ULL<<33) | (1ULL<<34) | (1ULL<<35) | (1ULL<<36);
404210284Sjmallett    bist_val &= mask;
405210284Sjmallett    if (bist_val)
406210284Sjmallett    {
407210284Sjmallett        printf("BIST FAILURE: COP0_CACHE_ERR: 0x%llx\n", (unsigned long long)bist_val);
408210284Sjmallett        bist_errors++;
409210284Sjmallett    }
410210284Sjmallett
411210284Sjmallett    mask = 0xfc00000000000000ull;
412210284Sjmallett    CVMX_MF_CVM_MEM_CTL(bist_val);
413210284Sjmallett    bist_val &=  mask;
414210284Sjmallett    if (bist_val)
415210284Sjmallett    {
416210284Sjmallett        printf("BIST FAILURE: COP0_CVM_MEM_CTL: 0x%llx\n", (unsigned long long)bist_val);
417210284Sjmallett        bist_errors++;
418210284Sjmallett    }
419210284Sjmallett
420210284Sjmallett    /* Set up 4 cache lines of local memory, make available from Kernel space */
421210284Sjmallett    CVMX_MF_CVM_MEM_CTL(tmp);
422210284Sjmallett    tmp &= ~0x1ffull;
423210284Sjmallett    tmp |= 0x104ull;
424215990Sjmallett    /* Set WBTHRESH=4 as per Core-14752 errata in cn63xxp1.X. */
425215990Sjmallett    if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
426215990Sjmallett    {
427215990Sjmallett        tmp &= ~(0xfull << 11);
428215990Sjmallett        tmp |= 4 << 11;
429215990Sjmallett    }
430210284Sjmallett    CVMX_MT_CVM_MEM_CTL(tmp);
431210284Sjmallett
432210284Sjmallett
433210284Sjmallett#if CVMX_USE_1_TO_1_TLB_MAPPINGS
434210284Sjmallett
435210284Sjmallett    /* Check to see if the bootloader is indicating that the application is outside
436210284Sjmallett    ** of the 0x10000000 0x20000000 range, in which case we can't use 1-1 mappings */
437210284Sjmallett    if (cvmx_sysinfo_get()->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING)
438210284Sjmallett    {
439210284Sjmallett        printf("ERROR: 1-1 TLB mappings configured and oversize application loaded.\n");
440210284Sjmallett        printf("ERROR: Either 1-1 TLB mappings must be disabled or application size reduced.\n");
441215990Sjmallett        exit(-1);
442210284Sjmallett    }
443210284Sjmallett
444210284Sjmallett    /* Create 1-1 Mappings for all DRAM up to 8 gigs, excluding the low 1 Megabyte.  This area
445210284Sjmallett    ** is reserved for the bootloader and exception vectors.  By not mapping this area, NULL pointer
446210284Sjmallett    ** dereferences will be caught with TLB exceptions.  Exception handlers should be written
447210284Sjmallett    ** using XKPHYS or KSEG0 addresses. */
448210284Sjmallett#if CVMX_NULL_POINTER_PROTECT
449210284Sjmallett    /* Exclude low 1 MByte from mapping to detect NULL pointer accesses.
450210284Sjmallett    ** The only down side of this is it uses more TLB mappings */
451210284Sjmallett    cvmx_core_add_fixed_tlb_mapping_bits(0x0, 0x0, 0x100000  | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_1M);
452210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x200000, 0x200000, 0x300000, CVMX_TLB_PAGEMASK_1M);
453210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x400000, 0x400000, 0x500000, CVMX_TLB_PAGEMASK_1M);
454210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x600000, 0x600000, 0x700000, CVMX_TLB_PAGEMASK_1M);
455210284Sjmallett
456210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x800000,  0x800000,  0xC00000, CVMX_TLB_PAGEMASK_4M);
457210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x1000000, 0x1000000, 0x1400000, CVMX_TLB_PAGEMASK_4M);
458210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x1800000, 0x1800000, 0x1c00000, CVMX_TLB_PAGEMASK_4M);
459210284Sjmallett
460210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x2000000, 0x2000000, 0x3000000, CVMX_TLB_PAGEMASK_16M);
461210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x4000000, 0x4000000, 0x5000000, CVMX_TLB_PAGEMASK_16M);
462210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x6000000, 0x6000000, 0x7000000, CVMX_TLB_PAGEMASK_16M);
463210284Sjmallett#else
464210284Sjmallett    /* Map entire low 128 Megs, including 0x0 */
465210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x0, 0x0, 0x4000000ULL, CVMX_TLB_PAGEMASK_64M);
466210284Sjmallett#endif
467210284Sjmallett    cvmx_core_add_fixed_tlb_mapping(0x8000000ULL, 0x8000000ULL, 0xc000000ULL, CVMX_TLB_PAGEMASK_64M);
468210284Sjmallett
469215990Sjmallett    if (OCTEON_IS_MODEL(OCTEON_CN6XXX))
470210284Sjmallett    {
471215990Sjmallett        for (base_addr = 0x20000000ULL; base_addr < (cvmx_sysinfo_get()->system_dram_size + 0x10000000ULL); base_addr += 0x20000000ULL)
472210284Sjmallett        {
473210284Sjmallett            if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr,  base_addr,  base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M))
474210284Sjmallett            {
475210284Sjmallett                printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr);
476215990Sjmallett                /* Exit from here, as expected memory mappings aren't set
477215990Sjmallett                   up if this fails */
478215990Sjmallett		exit(-1);
479210284Sjmallett            }
480210284Sjmallett        }
481210284Sjmallett    }
482215990Sjmallett    else
483215990Sjmallett    {
484215990Sjmallett        /* Create 1-1 mapping for next 256 megs
485215990Sjmallett        ** bottom page is not valid */
486215990Sjmallett        cvmx_core_add_fixed_tlb_mapping_bits(0x400000000ULL, 0, 0x410000000ULL  | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_256M);
487210284Sjmallett
488215990Sjmallett        /* Map from 0.5 up to the installed memory size in 512 MByte chunks.  If this loop runs out of memory,
489215990Sjmallett        ** the NULL pointer detection can be disabled to free up more TLB entries. */
490215990Sjmallett        if (cvmx_sysinfo_get()->system_dram_size > 0x20000000ULL)
491215990Sjmallett        {
492215990Sjmallett            for (base_addr = 0x20000000ULL; base_addr <= (cvmx_sysinfo_get()->system_dram_size - 0x20000000ULL); base_addr += 0x20000000ULL)
493215990Sjmallett            {
494215990Sjmallett                if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr,  base_addr,  base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M))
495215990Sjmallett                {
496215990Sjmallett                    printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr);
497215990Sjmallett                    /* Exit from here, as expected memory mappings
498215990Sjmallett                       aren't set up if this fails */
499215990Sjmallett                    exit(-1);
500215990Sjmallett                }
501215990Sjmallett            }
502215990Sjmallett        }
503215990Sjmallett    }
504210284Sjmallett#endif
505210284Sjmallett
506210284Sjmallett
507210284Sjmallett    cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
508215990Sjmallett    cvmx_bootmem_init(sys_info_ptr->phy_mem_desc_addr);
509210284Sjmallett
510210284Sjmallett    return(0);
511210284Sjmallett}
512210284Sjmallett
513210284Sjmallettvoid __cvmx_app_exit(void)
514210284Sjmallett{
515215990Sjmallett    cvmx_debug_finish();
516215990Sjmallett
517215990Sjmallett    if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
518210284Sjmallett    {
519215990Sjmallett	CVMX_BREAK;
520215990Sjmallett    }
521215990Sjmallett    /* Hang forever, until more appropriate stand alone simple executive
522215990Sjmallett       exit() is implemented */
523210284Sjmallett
524215990Sjmallett    while (1);
525210284Sjmallett}
526210284Sjmallett
527210284Sjmallett
528210284Sjmallett
529