/* ********************************************************************* * Broadcom Common Firmware Environment (CFE) * * Main Module File: cfe_main.c * * This module contains the main "C" routine for CFE and * the main processing loop. There should not be any board-specific * stuff in here. * * Author: Mitch Lichtenberg (mpl@broadcom.com) * ********************************************************************* * * Copyright 2000,2001,2002,2003 * Broadcom Corporation. All rights reserved. * * This software is furnished under license and may be used and * copied only in accordance with the following terms and * conditions. Subject to these conditions, you may download, * copy, install, use, modify and distribute modified or unmodified * copies of this software in source and/or binary form. No title * or ownership is transferred hereby. * * 1) Any source code used, modified or distributed must reproduce * and retain this copyright notice and list of conditions * as they appear in the source file. * * 2) No right is granted to use any trade name, trademark, or * logo of Broadcom Corporation. The "Broadcom Corporation" * name may not be used to endorse or promote products derived * from this software without the prior written permission of * Broadcom Corporation. * * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************* */ #include "lib_types.h" #include "lib_string.h" #include "lib_malloc.h" #include "lib_printf.h" #include "cfe_iocb.h" #include "cfe_device.h" #include "cfe_console.h" #include "cfe_timer.h" #include "env_subr.h" #include "cfe_mem.h" #include "cfe.h" #include "exception.h" #include "bsp_config.h" #include "bcm_hwdefs.h" #include "boardparms.h" #include "bcm_map.h" #include "bcm_cpu.h" #include "bcm63xx_util.h" #include "segtable.h" #include "initdata.h" /* ********************************************************************* * Constants ********************************************************************* */ #ifndef CFG_STACK_SIZE #define STACK_SIZE 8192 #else #define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) #endif /* ********************************************************************* * Externs ********************************************************************* */ void cfe_main(int,int); void cfe_command_restart(uint64_t status); extern void cfe_device_poll(void *x); extern int cfe_web_check(void); extern void cfe_web_fg_process(void); extern void cfe_web_poll(void *x); extern const char *builddate; extern const char *builduser; /* Foxconn add start by Cliff Wang, 03/23/2010 */ extern int ui_init_netcmds(void); /* Foxconn add end by Cliff Wang, 03/23/2010 */ /* ********************************************************************* * Globals ********************************************************************* */ const char *cfe_boardname = CFG_BOARDNAME; unsigned int cfe_startflags = 0; #if defined (_BCM96368_) static int cfe_bus_speed = 0; static int cfe_ref_speed = 0; #endif #if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_) static int cfe_bus_speed = 0; static int cfe_ddr_speed = 0; #endif unsigned long cfe_sdramsize = 8 * 1024 * 1024; static void calculateCpuSpeed(void); #if defined (_BCM96328_) const uint32 cpu_speed_table[0x20] = { 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 0, 320, 160, 200, 160, 200, 400, 320, 320, 160, 384, 320, 192, 320, 320, 320 }; const uint32 ddr_speed_table[0x20] = { 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 0, 80, 100, 100, 160, 200, 400, 400, 80, 160, 160, 160, 192, 192, 240, 320 }; const uint32 bus_speed_table[0x20] = { 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 0, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160 }; #endif #if defined (_BCM96362_) const uint32 cpu_speed_table[0x20] = { 320, 320, 320, 240, 160, 400, 440, 384, 320, 320, 320, 240, 160, 320, 400, 320, 320, 320, 320, 240, 160, 200, 400, 384, 320, 320, 320, 240, 160, 200, 400, 400 }; const uint32 ddr_speed_table[0x20] = { 320, 400, 192, 320, 200, 400, 367, 320, 320, 400, 192, 320, 200, 400, 400, 320, 320, 400, 192, 320, 200, 267, 400, 320, 320, 320, 192, 320, 200, 200, 400, 333 }; const uint32 bus_speed_table[0x20] = { 160, 200, 96, 160, 100, 160, 183, 160, 160, 200, 96, 160, 100, 160, 200, 160, 160, 200, 96, 160, 100, 100, 200, 160, 160, 160, 96, 160, 100, 100, 200, 166 }; #endif #if defined (_BCM96816_) const uint32 cpu_speed_table[0x20] = { 200, 400, 400, 320, 200, 400, 333, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 400, 400, 200, 360, 400, 400, 300, 300, 320, 320, 400, 400 }; const uint32 ddr_speed_table[0x20] = { 200, 333, 200, 200, 200, 333, 333, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 400, 200, 200, 300, 300, 300, 300, 300, 400, 400, 400, 400 }; const uint32 bus_speed_table[0x20] = { 200, 200, 200, 160, 100, 167, 200, 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 200, 160, 180, 171, 200, 171, 200, 160, 200, 160, 200 }; #endif static unsigned long cfe_get_sdram_size(void); /* ********************************************************************* * cfe_setup_default_env() * * Initialize the default environment for CFE. These are all * the temporary variables that do not get stored in the NVRAM * but are available to other programs and command-line macros. * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ static void cfe_setup_default_env(void) { char buffer[80]; xsprintf(buffer,"%d.%d.%d",CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD); env_setenv("CFE_VERSION",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY); if (cfe_boardname) { env_setenv("CFE_BOARDNAME",(char *) cfe_boardname, ENV_FLG_BUILTIN | ENV_FLG_READONLY); } } /* ********************************************************************* * cfe_ledstr(leds) * * Display a string on the board's LED display, if it has one. * This routine depends on the board-support package to * include a "driver" to write to the actual LED, if the board * does not have one this routine will do nothing. * * The LEDs are written at various places in the initialization * sequence, to debug board problems. * * Input parameters: * leds - pointer to four-character ASCII string * * Return value: * nothing ********************************************************************* */ void cfe_ledstr(const char *leds) { #if 0 unsigned int val; val = ((((unsigned int) leds[0]) << 24) | (((unsigned int) leds[1]) << 16) | (((unsigned int) leds[2]) << 8) | ((unsigned int) leds[3])); cfe_leds(val); #endif } /* ********************************************************************* * cfe_say_hello() * * Print out the CFE startup message and copyright notice * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ void cfe_command_restart(uint64_t status) { } static void cfe_say_hello(void) { xprintf("\n\n"); xprintf("CFE version 2.0.3" #ifdef CFE_VER_RELEASE ".%d" #endif " for DGN2200v2 (%s)\n", //CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD, BCM63XX_MAJOR, BCM63XX_MINOR, #ifdef CFE_VER_RELEASE CFE_VER_RELEASE, #endif //cfe_boardname, #ifdef __long64 "64bit," #else "32bit," #endif #if CFG_MULTI_CPUS "MP," #else "SP," #endif #ifdef __MIPSEL "LE" #endif #ifdef __MIPSEB "BE" #endif #if CFG_VAPI ",VAPI" #endif ); xprintf("Build Date: %s (%s)\n",builddate,builduser); xprintf("Copyright (C) 2000-2009 Broadcom Corporation.\n"); xprintf("\n"); } /* ********************************************************************* * cfe_restart() * * Restart CFE from scratch, jumping back to the boot vector. * * Input parameters: * nothing * * Return value: * does not return ********************************************************************* */ void cfe_restart(void) { _exc_restart(); } /* ********************************************************************* * cfe_start(ept) * * Start a user program * * Input parameters: * ept - entry point * * Return value: * nothing ********************************************************************* */ void cfe_start(unsigned long ept) { cfe_launch(ept); } /* ********************************************************************* * cfe_startup_info() * * Display startup memory configuration messages * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ static void cfe_startup_info(void) { xprintf("Chip ID: BCM%X%X, ", (PERF->RevID & 0xFFFF0000) >> 16, PERF->RevID & 0xFF); xprintf("MIPS: %dMHz",cfe_cpu_speed/1000000); #if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_) xprintf(", DDR: %dMHz, Bus: %dMHz\n", cfe_ddr_speed/1000000, cfe_bus_speed/1000000); #else xprintf("\n"); #endif { unsigned long tp; __asm __volatile( "mfc0 $9, $22, 3;" "move %0, $9" :"=r" (tp)); tp = ((tp & CP0_CMT_TPID) == CP0_CMT_TPID) ? 1 : 0; xprintf("Main Thread: TP%d\n", tp); } #if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_) if (DDR->TEST_CFG1 & 0x2) { /* Memory Test is finished */ xprintf("Memory Test "); if (DDR->TEST_CFG1 & 0x4) { xprintf("Failed\n"); } else { xprintf("Passed\n"); } } #endif cfe_sdramsize = cfe_get_sdram_size(); xprintf("Total Memory: %lu bytes (%luMB)\n", cfe_sdramsize, cfe_sdramsize >> 20); xprintf("Boot Address: 0x%x\n\n", FLASH_BASE); } #if defined (_BCM96816_) /* ********************************************************************* * apm_hvg_init() * * Work around 6816-specific reset logic * * Input parameters: * nothing * * Return value: * does not return ********************************************************************* */ static void apm_hvg_init(void) { HVG->reg_hvg_cha_misc ^= HVG_SOFT_INIT_0; HVG->reg_hvg_chb_misc ^= HVG_SOFT_INIT_0; } #endif /* ********************************************************************* * cfe_main(a,b) * * It's gotta start somewhere. * * Input parameters: * a,b - not used * * Return value: * does not return ********************************************************************* */ void cfe_main(int a,int b) { /* * By the time this routine is called, the following things have * already been done: * * 1. The processor(s) is(are) initialized. * 2. The caches are initialized. * 3. The memory controller is initialized. * 4. BSS has been zeroed. * 5. The data has been moved to R/W space. * 6. The "C" Stack has been initialized. */ cfe_bg_init(); /* init background processing */ cfe_attach_init(); calculateCpuSpeed(); cfe_timer_init(); /* Timer process */ cfe_bg_add(cfe_device_poll,NULL); /* * Initialize the memory allocator */ KMEMINIT((unsigned char *) (uintptr_t) mem_heapstart, ((CFG_HEAP_SIZE)*1024)); /* * Initialize the console. It is done before the other devices * get turned on. */ board_console_init(); cfe_setup_exceptions(); cfe_say_hello(); #if defined(CONFIG_BRCM_IKOS) { /*0x694b6f32 (iKo2) is replaced with actual addr during the build process*/ static unsigned long linuxStartAddr=0x694b6f32; printf("IKOS Build: Jump to Linux start address 0x%8.8lx.\n\n", linuxStartAddr); cfe_launch(linuxStartAddr); } #endif cfe_arena_init(); board_device_init(); cfe_startup_info(); cfe_setup_default_env(); ui_init_cmddisp(); getBootLine(); getBoardParam(); #if defined (_BCM96816_) apm_hvg_init(); #endif /* Foxconn add start by Cliff Wang, 03/23/2010 */ ui_init_netcmds(); /* Foxconn add end by Cliff Wang, 03/23/2010 */ board_final_init(); cfe_command_loop(); } /* ********************************************************************* * cfe_command_loop() * * This routine reads and processes user commands * * Input parameters: * nothing * * Return value: * does not return ********************************************************************* */ void cfe_command_loop() { char buffer[300]; int status; char *prompt; /* Start Web interface. */ cfe_bg_add(cfe_web_poll,NULL); for (;;) { prompt = env_getenv("PROMPT"); if (!prompt) prompt = "CFE> "; console_readline(prompt,buffer,sizeof(buffer)); if (cfe_web_check()) cfe_web_fg_process(); else { status = ui_docommands(buffer); if (status != CMD_ERR_BLANK) { xprintf("*** command status = %d\n", status); } } } } /* ********************************************************************* * cfe_errortext(err) * * Returns an error message with a number in it. The number can be * looked up in cfe_error.h. * * Input parameters: * err - error code * * Return value: * string description of error ********************************************************************* */ const char *cfe_errortext(int err) { static char err_buf[20]; sprintf(err_buf, "CFE error %d", err); return (const char *) err_buf; } #if defined (_BCM96368_) /* ********************************************************************* * calculateCpuSpeed() * Calculate BCM6368 CPU speed by reading the PLL Config register * and applying the following formula: * Fref_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / REF_MDIV) * Fbus_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / DDR_MDIV) * Fcpu_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / CPU_MDIV) * Input parameters: * none * Return value: * none ********************************************************************* */ void static calculateCpuSpeed(void) { UINT32 numerator; UINT32 pllConfig = DDR->MIPSDDRPLLConfig; UINT32 pllMDiv = DDR->MIPSDDRPLLMDiv; numerator = 64000000 / ((pllConfig & MIPSDDR_P1_MASK) >> MIPSDDR_P1_SHFT) * ((pllConfig & MIPSDDR_P2_MASK) >> MIPSDDR_P2_SHFT) * ((pllConfig & MIPSDDR_NDIV_MASK) >> MIPSDDR_NDIV_SHFT); cfe_cpu_speed = numerator / ((pllMDiv & MIPS_MDIV_MASK) >> MIPS_MDIV_SHFT); cfe_bus_speed = numerator / ((pllMDiv & DDR_MDIV_MASK) >> DDR_MDIV_SHFT); cfe_ref_speed = numerator / ((pllConfig & REF_MDIV_MASK) >> REF_MDIV_SHFT); } #endif #if defined (_BCM96328_) || defined (_BCM96362_) || (_BCM96816_) /* ********************************************************************* * calculateCpuSpeed() * Calculate CPU speed by reading strap register * Input parameters: * none * Return value: * none ********************************************************************* */ void static calculateCpuSpeed(void) { uint32 mips_pll_fvco; mips_pll_fvco = MISC->miscStrapBus & MISC_STRAP_BUS_MIPS_PLL_FVCO_MASK; mips_pll_fvco >>= MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT; cfe_cpu_speed = cpu_speed_table[mips_pll_fvco] * 1000000; cfe_ddr_speed = ddr_speed_table[mips_pll_fvco] * 1000000; cfe_bus_speed = bus_speed_table[mips_pll_fvco] * 1000000; } #endif /* ********************************************************************* * cfe_get_sdram_size(void) * * Return amount of SDRAM on the board. * * Input parameters: * None. * * Return value: * Amount of SDRAM on the board. ********************************************************************* */ static unsigned long cfe_get_sdram_size(void) { #if defined (_BCM96368_) uint32 size; uint32 memCfg; size = 1; memCfg = MEMC->Config; /* Number of column bits */ size <<= (((memCfg & MEMC_COL_MASK) >> MEMC_COL_SHFT) + 8); /* Plus number of row bits */ size <<= (((memCfg & MEMC_ROW_MASK) >> MEMC_ROW_SHFT) + 11); /* Plus bus width */ if (((memCfg & MEMC_WIDTH_MASK) >> MEMC_WIDTH_SHFT) == MEMC_32BIT_BUS) size <<= 2; else size <<= 1; /* Plus number of banks */ size <<= 2; return( size ); #else return (DDR->CSEND << 24); #endif }