946 lines
24 KiB
C
946 lines
24 KiB
C
|
/*
|
|||
|
* (C) Copyright 2002-2006
|
|||
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
|||
|
*
|
|||
|
* (C) Copyright 2002
|
|||
|
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
|||
|
* Marius Groeger <mgroeger@sysgo.de>
|
|||
|
*
|
|||
|
* See file CREDITS for list of people who contributed to this
|
|||
|
* project.
|
|||
|
*
|
|||
|
* This program is free software; you can redistribute it and/or
|
|||
|
* modify it under the terms of the GNU General Public License as
|
|||
|
* published by the Free Software Foundation; either version 2 of
|
|||
|
* the License, or (at your option) any later version.
|
|||
|
*
|
|||
|
* This program is distributed in the hope that it will be useful,
|
|||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
|
* GNU General Public License for more details.
|
|||
|
*
|
|||
|
* You should have received a copy of the GNU General Public License
|
|||
|
* along with this program; if not, write to the Free Software
|
|||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|||
|
* MA 02111-1307 USA
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
* To match the U-Boot user interface on ARM platforms to the U-Boot
|
|||
|
* standard (as on PPC platforms), some messages with debug character
|
|||
|
* are removed from the default U-Boot build.
|
|||
|
*
|
|||
|
* Define DEBUG here if you want additional info as shown below
|
|||
|
* printed upon startup:
|
|||
|
*
|
|||
|
* U-Boot code: 00F00000 -> 00F3C774 BSS: -> 00FC3274
|
|||
|
* IRQ Stack: 00ebff7c
|
|||
|
* FIQ Stack: 00ebef7c
|
|||
|
*/
|
|||
|
|
|||
|
#include <common.h>
|
|||
|
#include <command.h>
|
|||
|
#include <malloc.h>
|
|||
|
#include <stdio_dev.h>
|
|||
|
#include <version.h>
|
|||
|
#include <net.h>
|
|||
|
#include <serial.h>
|
|||
|
#include <nand.h>
|
|||
|
#include <onenand_uboot.h>
|
|||
|
#include <mmc.h>
|
|||
|
|
|||
|
#ifdef CONFIG_BITBANGMII
|
|||
|
#include <miiphy.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_DRIVER_SMC91111
|
|||
|
#include "../drivers/net/smc91111.h"
|
|||
|
#endif
|
|||
|
#ifdef CONFIG_DRIVER_LAN91C96
|
|||
|
#include "../drivers/net/lan91c96.h"
|
|||
|
#endif
|
|||
|
|
|||
|
DECLARE_GLOBAL_DATA_PTR;
|
|||
|
|
|||
|
ulong monitor_flash_len;
|
|||
|
#ifdef CONFIG_USE_IRQ
|
|||
|
unsigned int gd_bk_addr;
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_HAS_DATAFLASH
|
|||
|
extern int AT91F_DataflashInit(void);
|
|||
|
extern void dataflash_print_info(void);
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_DRIVER_RTL8019
|
|||
|
extern void rtl8019_get_enetaddr(uchar *addr);
|
|||
|
#endif
|
|||
|
|
|||
|
extern int auto_update_check(void);
|
|||
|
|
|||
|
|
|||
|
#if defined(CONFIG_SUNXI_I2C)
|
|||
|
#include <i2c.h>
|
|||
|
#elif defined(CONFIG_PMU_USE_P2WI)
|
|||
|
#include <p2wi.h>
|
|||
|
#elif defined(CONFIG_PMU_USE_RSB)
|
|||
|
#include <rsb.h>
|
|||
|
#else
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
#if defined(CONFIG_ALLWINNER)
|
|||
|
#include <boot_type.h>
|
|||
|
#include <sys_config.h>
|
|||
|
#include <sys_partition.h>
|
|||
|
#include <sunxi_board.h>
|
|||
|
#include <asm/arch/dma.h>
|
|||
|
#include <pmu.h>
|
|||
|
#include <../fs/aw_fs/ff.h>
|
|||
|
#include <securestorage.h>
|
|||
|
#include <smc.h>
|
|||
|
#endif
|
|||
|
|
|||
|
int sunxi_keydata_burn_by_usb(void);
|
|||
|
int sunxi_sprite_download_boot0_simple(void);
|
|||
|
/************************************************************************
|
|||
|
* Coloured LED functionality
|
|||
|
************************************************************************
|
|||
|
* May be supplied by boards if desired
|
|||
|
*/
|
|||
|
inline void __coloured_LED_init(void) {}
|
|||
|
void coloured_LED_init(void)
|
|||
|
__attribute__((weak, alias("__coloured_LED_init")));
|
|||
|
inline void __red_LED_on(void) {}
|
|||
|
void red_LED_on(void) __attribute__((weak, alias("__red_LED_on")));
|
|||
|
inline void __red_LED_off(void) {}
|
|||
|
void red_LED_off(void) __attribute__((weak, alias("__red_LED_off")));
|
|||
|
inline void __green_LED_on(void) {}
|
|||
|
void green_LED_on(void) __attribute__((weak, alias("__green_LED_on")));
|
|||
|
inline void __green_LED_off(void) {}
|
|||
|
void green_LED_off(void) __attribute__((weak, alias("__green_LED_off")));
|
|||
|
inline void __yellow_LED_on(void) {}
|
|||
|
void yellow_LED_on(void) __attribute__((weak, alias("__yellow_LED_on")));
|
|||
|
inline void __yellow_LED_off(void) {}
|
|||
|
void yellow_LED_off(void) __attribute__((weak, alias("__yellow_LED_off")));
|
|||
|
inline void __blue_LED_on(void) {}
|
|||
|
void blue_LED_on(void) __attribute__((weak, alias("__blue_LED_on")));
|
|||
|
inline void __blue_LED_off(void) {}
|
|||
|
void blue_LED_off(void) __attribute__((weak, alias("__blue_LED_off")));
|
|||
|
|
|||
|
/*
|
|||
|
************************************************************************
|
|||
|
* Init Utilities *
|
|||
|
************************************************************************
|
|||
|
* Some of this code should be moved into the core functions,
|
|||
|
* or dropped completely,
|
|||
|
* but let's get it working (again) first...
|
|||
|
*/
|
|||
|
|
|||
|
#if defined(CONFIG_ARM_DCC) && !defined(CONFIG_BAUDRATE)
|
|||
|
#define CONFIG_BAUDRATE 115200
|
|||
|
#endif
|
|||
|
static int init_baudrate(void)
|
|||
|
{
|
|||
|
char tmp[64]; /* long enough for environment variables */
|
|||
|
int i = getenv_f("baudrate", tmp, sizeof(tmp));
|
|||
|
|
|||
|
gd->baudrate = (i > 0)
|
|||
|
? (int) simple_strtoul(tmp, NULL, 10)
|
|||
|
: CONFIG_BAUDRATE;
|
|||
|
|
|||
|
return (0);
|
|||
|
}
|
|||
|
|
|||
|
static int display_banner(void)
|
|||
|
{
|
|||
|
tick_printf("\n\n%s\n\n", version_string);
|
|||
|
debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
|
|||
|
_TEXT_BASE,
|
|||
|
_bss_start_ofs + _TEXT_BASE, _bss_end_ofs + _TEXT_BASE);
|
|||
|
#ifdef CONFIG_MODEM_SUPPORT
|
|||
|
debug("Modem Support enabled\n");
|
|||
|
#endif
|
|||
|
#ifdef CONFIG_USE_IRQ
|
|||
|
debug("IRQ Stack: %08lx\n", IRQ_STACK_START);
|
|||
|
debug("FIQ Stack: %08lx\n", FIQ_STACK_START);
|
|||
|
#endif
|
|||
|
|
|||
|
return (0);
|
|||
|
}
|
|||
|
#ifdef SUNXI_OTA_TEST
|
|||
|
static int display_ota_test(void)
|
|||
|
{
|
|||
|
printf("*********************************************\n");
|
|||
|
printf("*********************************************\n");
|
|||
|
printf("*********************************************\n");
|
|||
|
printf("*********************************************\n");
|
|||
|
printf("********[OTA TEST]:update uboot sucess*******\n");
|
|||
|
printf("*********************************************\n");
|
|||
|
printf("*********************************************\n");
|
|||
|
printf("*********************************************\n");
|
|||
|
printf("*********************************************\n");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
#endif
|
|||
|
/*
|
|||
|
* WARNING: this code looks "cleaner" than the PowerPC version, but
|
|||
|
* has the disadvantage that you either get nothing, or everything.
|
|||
|
* On PowerPC, you might see "DRAM: " before the system hangs - which
|
|||
|
* gives a simple yet clear indication which part of the
|
|||
|
* initialization if failing.
|
|||
|
*/
|
|||
|
static int display_dram_config(void)
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
/* #ifdef DEBUG */
|
|||
|
#if 0
|
|||
|
puts("RAM Configuration:\n");
|
|||
|
|
|||
|
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
|||
|
printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
|
|||
|
print_size(gd->bd->bi_dram[i].size, "\n");
|
|||
|
}
|
|||
|
#else
|
|||
|
ulong size = 0;
|
|||
|
|
|||
|
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
|
|||
|
size += gd->bd->bi_dram[i].size;
|
|||
|
|
|||
|
tick_printf("DRAM: ");
|
|||
|
/* puts("DRAM: "); */
|
|||
|
print_size(size, "\n");
|
|||
|
#endif
|
|||
|
|
|||
|
return (0);
|
|||
|
}
|
|||
|
|
|||
|
extern char uboot_hash_value[64];
|
|||
|
static int print_commit_log(void)
|
|||
|
{
|
|||
|
tick_printf("uboot commit : %s\n", uboot_hash_value);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
static int init_func_pmubus(void)
|
|||
|
{
|
|||
|
tick_printf("pmbus: ");
|
|||
|
|
|||
|
#if defined(CONFIG_PMU_USE_I2C)
|
|||
|
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
|
|||
|
#elif defined(CONFIG_PMU_USE_P2WI)
|
|||
|
p2wi_init();
|
|||
|
#elif defined(CONFIG_PMU_USE_RSB)
|
|||
|
sunxi_rsb_init(0);
|
|||
|
#endif
|
|||
|
puts("ready\n");
|
|||
|
return (0);
|
|||
|
}
|
|||
|
|
|||
|
#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
|
|||
|
#include <pci.h>
|
|||
|
static int arm_pci_init(void)
|
|||
|
{
|
|||
|
pci_init();
|
|||
|
return 0;
|
|||
|
}
|
|||
|
#endif /* CONFIG_CMD_PCI || CONFIG_PCI */
|
|||
|
|
|||
|
#if defined(CONFIG_SUNXI_AXP)
|
|||
|
extern int power_init(void);
|
|||
|
#endif
|
|||
|
extern int check_update_key(void);
|
|||
|
extern int display_inner(void);
|
|||
|
extern int script_init(void);
|
|||
|
extern int get_debugmode_flag(void);
|
|||
|
extern int check_uart_input(void);
|
|||
|
extern int power_source_init(void);
|
|||
|
#if defined(CONFIG_USE_NEON_SIMD)
|
|||
|
extern int arm_neon_init(void);
|
|||
|
#endif
|
|||
|
extern int smc_init(void);
|
|||
|
extern int sunxi_probe_securemode(void);
|
|||
|
extern int sunxi_probe_enable_securebit(void);
|
|||
|
/*
|
|||
|
* Breathe some life into the board...
|
|||
|
*
|
|||
|
* Initialize a serial port as console, and carry out some hardware
|
|||
|
* tests.
|
|||
|
*
|
|||
|
* The first part of initialization is running from Flash memory;
|
|||
|
* its main purpose is to initialize the RAM so that we
|
|||
|
* can relocate the monitor code to RAM.
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
* All attempts to come up with a "common" initialization sequence
|
|||
|
* that works for all boards and architectures failed: some of the
|
|||
|
* requirements are just _too_ different. To get rid of the resulting
|
|||
|
* mess of board dependent #ifdef'ed code we now make the whole
|
|||
|
* initialization sequence configurable to the user.
|
|||
|
*
|
|||
|
* The requirements for any new initalization function is simple: it
|
|||
|
* receives a pointer to the "global data" structure as it's only
|
|||
|
* argument, and returns an integer return code, where 0 means
|
|||
|
* "continue" and != 0 means "fatal error, hang the system".
|
|||
|
*/
|
|||
|
typedef int (init_fnc_t) (void);
|
|||
|
int print_cpuinfo(void);
|
|||
|
|
|||
|
void __dram_init_banksize(void)
|
|||
|
{
|
|||
|
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
|
|||
|
gd->bd->bi_dram[0].size = gd->ram_size;
|
|||
|
}
|
|||
|
void dram_init_banksize(void)
|
|||
|
__attribute__((weak, alias("__dram_init_banksize")));
|
|||
|
|
|||
|
int __sunxi_probe_securemode(void)
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
int sunxi_probe_securemode(void)
|
|||
|
__attribute__((weak, alias("__sunxi_probe_securemode")));
|
|||
|
|
|||
|
int __smc_init(void)
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
int smc_init(void)
|
|||
|
__attribute__((weak, alias("__smc_init")));
|
|||
|
|
|||
|
#ifdef CONFIG_SUNXI_SECURE_SYSTEM
|
|||
|
int __sunxi_probe_enable_securebit(void)
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
int sunxi_probe_enable_securebit(void)
|
|||
|
__attribute__((weak, alias("__sunxi_probe_enable_securebit")));
|
|||
|
#endif
|
|||
|
|
|||
|
init_fnc_t *init_sequence[] = {
|
|||
|
/* #if defined(CONFIG_ARCH_CPU_INIT) */
|
|||
|
arch_cpu_init, /* basic arch cpu dependent setup */
|
|||
|
/* #endif */
|
|||
|
sunxi_probe_securemode,
|
|||
|
#if defined(CONFIG_USE_NEON_SIMD)
|
|||
|
arm_neon_init,
|
|||
|
#endif
|
|||
|
#if defined(CONFIG_BOARD_EARLY_INIT_F)
|
|||
|
board_early_init_f,
|
|||
|
#endif
|
|||
|
timer_init, /* initialize timer */
|
|||
|
#ifdef CONFIG_FSL_ESDHC
|
|||
|
get_clocks,
|
|||
|
#endif
|
|||
|
env_init, /* initialize environment */
|
|||
|
init_baudrate, /* initialze baudrate settings */
|
|||
|
serial_init, /* serial communications setup */
|
|||
|
console_init_f, /* stage 1 init of console */
|
|||
|
display_banner, /* say that we are here */
|
|||
|
display_inner, /* show the inner version */
|
|||
|
print_commit_log,
|
|||
|
script_init,
|
|||
|
#if defined(SUNXI_OTA_TEST)
|
|||
|
display_ota_test,
|
|||
|
#endif
|
|||
|
get_debugmode_flag,
|
|||
|
#if defined(CONFIG_DISPLAY_CPUINFO)
|
|||
|
print_cpuinfo, /* display cpu info (and speed) */
|
|||
|
#endif
|
|||
|
#if defined(CONFIG_DISPLAY_BOARDINFO)
|
|||
|
checkboard, /* display board info */
|
|||
|
#endif
|
|||
|
smc_init,
|
|||
|
init_func_pmubus,
|
|||
|
power_source_init,
|
|||
|
check_update_key,
|
|||
|
check_uart_input,
|
|||
|
dram_init, /* configure available RAM banks */
|
|||
|
#ifdef CONFIG_SUNXI_SECURE_SYSTEM
|
|||
|
sunxi_probe_enable_securebit,
|
|||
|
#endif
|
|||
|
NULL,
|
|||
|
};
|
|||
|
|
|||
|
#if defined(CONFIG_CPUS_STANDBY)
|
|||
|
extern void do_box_standby(void);
|
|||
|
#endif
|
|||
|
void board_init_f(ulong bootflag)
|
|||
|
{
|
|||
|
bd_t *bd;
|
|||
|
init_fnc_t **init_fnc_ptr;
|
|||
|
gd_t *id;
|
|||
|
ulong addr, addr_sp;
|
|||
|
|
|||
|
#if defined(CONFIG_ARCH_SUN8IW6P1)|defined(CONFIG_ARCH_SUN8IW9P1)
|
|||
|
memset((void *)CONFIG_SYS_SRAM_BASE, 0, 4*1024);
|
|||
|
#endif
|
|||
|
/* Pointer is writable since we allocated a register for it */
|
|||
|
gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
|
|||
|
/* compiler optimization barrier needed for GCC >= 3.4 */
|
|||
|
__asm__ __volatile__("" : : : "memory");
|
|||
|
|
|||
|
memset((void *)gd, 0, sizeof(gd_t));
|
|||
|
gd->mon_len = _bss_end_ofs + sizeof(struct spare_boot_head_t);
|
|||
|
gd->debug_mode = 1;
|
|||
|
|
|||
|
/* while((*(volatile unsigned int *)(0)) != 1); */
|
|||
|
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
|
|||
|
if ((*init_fnc_ptr)() != 0) {
|
|||
|
/* hang (); */
|
|||
|
sunxi_board_run_fel_eraly(); /* modify by jerry */
|
|||
|
}
|
|||
|
}
|
|||
|
debug("monitor len: %08lX\n", gd->mon_len);
|
|||
|
/*
|
|||
|
* Ram is setup, size stored in gd !!
|
|||
|
*/
|
|||
|
debug("ramsize: %08lX\n", gd->ram_size);
|
|||
|
#if defined(CONFIG_SYS_MEM_TOP_HIDE)
|
|||
|
/*
|
|||
|
* Subtract specified amount of memory to hide so that it won't
|
|||
|
* get "touched" at all by U-Boot. By fixing up gd->ram_size
|
|||
|
* the Linux kernel should now get passed the now "corrected"
|
|||
|
* memory size and won't touch it either. This should work
|
|||
|
* for arch/ppc and arch/powerpc. Only Linux board ports in
|
|||
|
* arch/powerpc with bootwrapper support, that recalculate the
|
|||
|
* memory size from the SDRAM controller setup will have to
|
|||
|
* get fixed.
|
|||
|
*/
|
|||
|
gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
|
|||
|
#endif
|
|||
|
if (gd->ram_size)
|
|||
|
addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
|
|||
|
else
|
|||
|
addr = CONFIG_SYS_SDRAM_BASE + (1U<<30);
|
|||
|
|
|||
|
#ifdef CONFIG_LOGBUFFER
|
|||
|
#ifndef CONFIG_ALT_LB_ADDR
|
|||
|
/* reserve kernel log buffer */
|
|||
|
addr -= (LOGBUFF_RESERVE);
|
|||
|
debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN,
|
|||
|
addr);
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_SUNXI_LOGBUFFER
|
|||
|
addr -= (SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_PRAM
|
|||
|
/*
|
|||
|
* reserve protected RAM
|
|||
|
*/
|
|||
|
i = getenv_r("pram", (char *)tmp, sizeof(tmp));
|
|||
|
reg = (i > 0) ? simple_strtoul((const char *)tmp, NULL, 10) :
|
|||
|
CONFIG_PRAM;
|
|||
|
addr -= (reg << 10); /* size is in kB */
|
|||
|
debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
|
|||
|
#endif /* CONFIG_PRAM */
|
|||
|
|
|||
|
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
|
|||
|
/* reserve TLB table */
|
|||
|
addr -= (4096 * 4);
|
|||
|
|
|||
|
/* round down to next 64 kB limit */
|
|||
|
addr &= ~(0x10000 - 1);
|
|||
|
|
|||
|
gd->tlb_addr = addr;
|
|||
|
debug("TLB table at: %08lx\n", addr);
|
|||
|
#endif
|
|||
|
|
|||
|
/* round down to next 4 kB limit */
|
|||
|
addr &= ~(4096 - 1);
|
|||
|
debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
|
|||
|
|
|||
|
#ifdef CONFIG_LCD
|
|||
|
#ifdef CONFIG_FB_ADDR
|
|||
|
gd->fb_base = CONFIG_FB_ADDR;
|
|||
|
#else
|
|||
|
/* reserve memory for LCD display (always full pages) */
|
|||
|
addr = lcd_setmem(addr);
|
|||
|
gd->fb_base = addr;
|
|||
|
#endif /* CONFIG_FB_ADDR */
|
|||
|
#endif /* CONFIG_LCD */
|
|||
|
|
|||
|
/*
|
|||
|
* reserve memory for U-Boot code, data & bss
|
|||
|
* round down to next 4 kB limit
|
|||
|
*/
|
|||
|
addr -= gd->mon_len;
|
|||
|
addr &= ~(4096 - 1);
|
|||
|
|
|||
|
debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
|
|||
|
|
|||
|
#ifndef CONFIG_SPL_BUILD
|
|||
|
/*
|
|||
|
* reserve memory for malloc() arena
|
|||
|
*/
|
|||
|
addr_sp = addr - TOTAL_MALLOC_LEN;
|
|||
|
debug("Reserving %dk for malloc() at: %08lx\n",
|
|||
|
TOTAL_MALLOC_LEN >> 10, addr_sp);
|
|||
|
#ifdef CONFIG_NONCACHE_MEMORY
|
|||
|
addr_sp &= (~(0x00100000 - 1));
|
|||
|
addr_sp -= CONFIG_NONCACHE_MEMORY_SIZE;
|
|||
|
#endif
|
|||
|
/*
|
|||
|
* (permanently) allocate a Board Info struct
|
|||
|
* and a permanent copy of the "global" data
|
|||
|
*/
|
|||
|
addr_sp -= sizeof(bd_t);
|
|||
|
bd = (bd_t *) addr_sp;
|
|||
|
gd->bd = bd;
|
|||
|
debug("Reserving %zu Bytes for Board Info at: %08lx\n",
|
|||
|
sizeof(bd_t), addr_sp);
|
|||
|
|
|||
|
#ifdef CONFIG_MACH_TYPE
|
|||
|
gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
|
|||
|
#endif
|
|||
|
|
|||
|
addr_sp -= sizeof(gd_t);
|
|||
|
id = (gd_t *) addr_sp;
|
|||
|
debug("Reserving %zu Bytes for Global Data at: %08lx\n",
|
|||
|
sizeof(gd_t), addr_sp);
|
|||
|
|
|||
|
/* setup stackpointer for exeptions */
|
|||
|
gd->irq_sp = addr_sp;
|
|||
|
#ifdef CONFIG_USE_IRQ
|
|||
|
addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
|
|||
|
debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
|
|||
|
CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
|
|||
|
#endif
|
|||
|
/* leave 3 words for abort-stack */
|
|||
|
addr_sp -= 12;
|
|||
|
|
|||
|
/* 8-byte alignment for ABI compliance */
|
|||
|
addr_sp &= ~0x07;
|
|||
|
#else
|
|||
|
addr_sp += 128; /* leave 32 words for abort-stack */
|
|||
|
gd->irq_sp = addr_sp;
|
|||
|
#endif
|
|||
|
|
|||
|
debug("New Stack Pointer is: %08lx\n", addr_sp);
|
|||
|
|
|||
|
#ifdef CONFIG_POST
|
|||
|
post_bootmode_init();
|
|||
|
post_run(NULL, POST_ROM | post_bootmode_get(0));
|
|||
|
#endif
|
|||
|
|
|||
|
gd->bd->bi_baudrate = gd->baudrate;
|
|||
|
/* Ram ist board specific, so move it to board code ... */
|
|||
|
dram_init_banksize();
|
|||
|
display_dram_config(); /* and display it */
|
|||
|
gd->relocaddr = addr + sizeof(struct spare_boot_head_t) + sizeof(uboot_hash_value);
|
|||
|
gd->start_addr_sp = addr_sp;
|
|||
|
gd->reloc_off = addr - _TEXT_BASE;
|
|||
|
printf("relocation Offset is: %08lx\n", gd->reloc_off);
|
|||
|
memcpy((void *)addr, (void *)_TEXT_BASE, sizeof(uboot_hash_value)+sizeof(struct spare_boot_head_t));
|
|||
|
debug("from %x to %x, size %x\n", (void *)_TEXT_BASE, (void *)addr, sizeof(struct spare_boot_head_t));
|
|||
|
memcpy(id, (void *)gd, sizeof(gd_t));
|
|||
|
|
|||
|
relocate_code(addr_sp, id, addr + sizeof(struct spare_boot_head_t)+sizeof(uboot_hash_value));
|
|||
|
|
|||
|
/* NOTREACHED - relocate_code() does not return */
|
|||
|
}
|
|||
|
|
|||
|
#if !defined(CONFIG_SYS_NO_FLASH)
|
|||
|
static char *failed = "*** failed ***\n";
|
|||
|
#endif
|
|||
|
|
|||
|
/*
|
|||
|
************************************************************************
|
|||
|
*
|
|||
|
* This is the next part if the initialization sequence: we are now
|
|||
|
* running from RAM and have a "normal" C environment, i. e. global
|
|||
|
* data can be written, BSS has been cleared, the stack size in not
|
|||
|
* that critical any more, etc.
|
|||
|
*
|
|||
|
************************************************************************
|
|||
|
*/
|
|||
|
void board_init_r(gd_t *id, ulong dest_addr)
|
|||
|
{
|
|||
|
char *s;
|
|||
|
/* bd_t *bd; */
|
|||
|
ulong malloc_start;
|
|||
|
#ifdef CONFIG_NONCACHE_MEMORY
|
|||
|
uint malloc_noncache_start;
|
|||
|
#endif
|
|||
|
#if !defined(CONFIG_SYS_NO_FLASH)
|
|||
|
ulong flash_size;
|
|||
|
#endif
|
|||
|
int workmode;
|
|||
|
int ret;
|
|||
|
#ifdef CONFIG_SUNXI_HDCP_IN_SECURESTORAGE
|
|||
|
int hdcpkey_enable = 0;
|
|||
|
#endif
|
|||
|
gd = id;
|
|||
|
gd_bk_addr = (unsigned int)id;
|
|||
|
/* bd = gd->bd; */
|
|||
|
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
|
|||
|
|
|||
|
monitor_flash_len = _end_ofs;
|
|||
|
|
|||
|
malloc_start = dest_addr - TOTAL_MALLOC_LEN - sizeof(struct spare_boot_head_t);
|
|||
|
#ifdef CONFIG_NONCACHE_MEMORY_SIZE
|
|||
|
malloc_start &= (~(0x00100000 - 1));
|
|||
|
malloc_noncache_start = malloc_start - CONFIG_NONCACHE_MEMORY_SIZE;
|
|||
|
gd->malloc_noncache_start = malloc_noncache_start;
|
|||
|
#endif
|
|||
|
/* Enable caches */
|
|||
|
enable_caches();
|
|||
|
debug("monitor flash len: %08lX\n", monitor_flash_len);
|
|||
|
board_init(); /* Setup chipselects */
|
|||
|
#ifdef CONFIG_SERIAL_MULTI
|
|||
|
serial_initialize();
|
|||
|
#endif
|
|||
|
debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
|
|||
|
|
|||
|
#ifdef CONFIG_LOGBUFFER
|
|||
|
logbuff_init_ptrs();
|
|||
|
#endif
|
|||
|
#ifdef CONFIG_POST
|
|||
|
post_output_backlog();
|
|||
|
#endif
|
|||
|
|
|||
|
/* The Malloc area is immediately below the monitor copy in DRAM */
|
|||
|
mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN);
|
|||
|
#ifdef CONFIG_SMALL_MEMSIZE
|
|||
|
save_config();
|
|||
|
#endif
|
|||
|
#ifdef CONFIG_NONCACHE_MEMORY
|
|||
|
mem_noncache_malloc_init(malloc_noncache_start, CONFIG_NONCACHE_MEMORY_SIZE);
|
|||
|
#endif
|
|||
|
#if defined(CONFIG_ARCH_HOMELET)
|
|||
|
check_physical_key_early();
|
|||
|
#endif
|
|||
|
|
|||
|
workmode = uboot_spare_head.boot_data.work_mode;
|
|||
|
debug("work mode %d\n", workmode);
|
|||
|
|
|||
|
axp_reinit();
|
|||
|
/* uboot_spare_head.boot_data.work_mode = WORK_MODE_CARD_PRODUCT; */
|
|||
|
printf("%s %d\n", __FILE__, __LINE__);
|
|||
|
#if defined(CONFIG_CPUS_STANDBY) /* Ŀǰֻ<C7B0><D6BB>homelet<65><74>ʹ<EFBFBD><CAB9> */
|
|||
|
do_box_standby();
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_ARCH_HOMELET
|
|||
|
gpio_control();
|
|||
|
#endif
|
|||
|
#if 0
|
|||
|
#if !defined(CONFIG_SYS_NO_FLASH)
|
|||
|
puts("Flash: ");
|
|||
|
|
|||
|
flash_size = flash_init();
|
|||
|
if (flash_size > 0) {
|
|||
|
# ifdef CONFIG_SYS_FLASH_CHECKSUM
|
|||
|
print_size(flash_size, "");
|
|||
|
/*
|
|||
|
* Compute and print flash CRC if flashchecksum is set to 'y'
|
|||
|
*
|
|||
|
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
|
|||
|
*/
|
|||
|
s = getenv("flashchecksum");
|
|||
|
if (s && (*s == 'y')) {
|
|||
|
printf(" CRC: %08X", crc32(0,
|
|||
|
(const unsigned char *) CONFIG_SYS_FLASH_BASE,
|
|||
|
flash_size));
|
|||
|
}
|
|||
|
putc('\n');
|
|||
|
# else /* !CONFIG_SYS_FLASH_CHECKSUM */
|
|||
|
print_size(flash_size, "\n");
|
|||
|
# endif /* CONFIG_SYS_FLASH_CHECKSUM */
|
|||
|
} else {
|
|||
|
puts(failed);
|
|||
|
hang();
|
|||
|
}
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
/* set up exceptions */
|
|||
|
interrupt_init();
|
|||
|
/* enable exceptions */
|
|||
|
enable_interrupts();
|
|||
|
sunxi_dma_init();
|
|||
|
#ifdef DEBUG
|
|||
|
puts("ready to config storage\n");
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_ARCH_HOMELET /* for homlet to use one-key-recovery */
|
|||
|
ret = sunxi_flash_handle_init();
|
|||
|
if (!ret)
|
|||
|
{
|
|||
|
sunxi_partition_init();
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if ((workmode == WORK_MODE_BOOT) || (workmode == WORK_MODE_CARD_PRODUCT) || (workmode == WORK_MODE_SPRITE_RECOVERY))
|
|||
|
{
|
|||
|
#if (defined(CONFIG_SUNXI_DISPLAY) || defined(CONFIG_SUN7I_DISPLAY))
|
|||
|
drv_disp_init();
|
|||
|
#endif
|
|||
|
#ifdef CONFIG_SUNXI_HDCP_IN_SECURESTORAGE
|
|||
|
ret = script_parser_fetch("hdmi_para", "hdmi_hdcp_enable", &hdcpkey_enable, 1);
|
|||
|
if ((ret) || (hdcpkey_enable != 1))
|
|||
|
{
|
|||
|
board_display_device_open();
|
|||
|
board_display_layer_request();
|
|||
|
}
|
|||
|
ret = 0;
|
|||
|
#else
|
|||
|
board_display_device_open();
|
|||
|
board_display_layer_request();
|
|||
|
#endif
|
|||
|
}
|
|||
|
#ifdef CONFIG_AUTO_UPDATE
|
|||
|
auto_update_check();
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef CONFIG_ARCH_HOMELET /* for pad used */
|
|||
|
ret = sunxi_flash_handle_init();
|
|||
|
if (!ret)
|
|||
|
{
|
|||
|
sunxi_partition_init();
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_SUNXI_HDCP_IN_SECURESTORAGE
|
|||
|
/* here: write key to hardware */
|
|||
|
if (hdcpkey_enable == 1)
|
|||
|
{
|
|||
|
char buffer[4096];
|
|||
|
int data_len;
|
|||
|
int ret0;
|
|||
|
|
|||
|
memset(buffer, 0, 4096);
|
|||
|
ret0 = sunxi_secure_storage_init();
|
|||
|
if (ret0)
|
|||
|
{
|
|||
|
printf("sunxi init secure storage failed\n");
|
|||
|
} else
|
|||
|
{
|
|||
|
ret0 = sunxi_secure_object_read("hdcpkey", buffer, 4096, &data_len);
|
|||
|
if (ret0)
|
|||
|
{
|
|||
|
printf("probe hdcp key failed\n");
|
|||
|
} else
|
|||
|
{
|
|||
|
ret0 = smc_aes_bssk_decrypt_to_keysram(buffer, data_len);
|
|||
|
if (ret0)
|
|||
|
{
|
|||
|
printf("push hdcp key failed\n");
|
|||
|
} else
|
|||
|
{
|
|||
|
board_display_device_open();
|
|||
|
board_display_layer_request();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_BOOT_A15
|
|||
|
if (sunxi_sprite_download_boot0_simple())
|
|||
|
{
|
|||
|
printf("rewrite boot0 to save boot cpu failed\n");
|
|||
|
}
|
|||
|
#endif
|
|||
|
/* #else */
|
|||
|
/* #if defined(CONFIG_CMD_NAND) */
|
|||
|
/* if(!storage_type){ */
|
|||
|
/* puts("NAND: "); */
|
|||
|
/* nand_init(); */ /* go init the NAND */
|
|||
|
/* } */
|
|||
|
/* #endif */
|
|||
|
/*CONFIG_CMD_NAND*/
|
|||
|
/* */
|
|||
|
/* #if defined(CONFIG_GENERIC_MMC) */
|
|||
|
/* if(storage_type){ */
|
|||
|
/* puts("MMC: "); */
|
|||
|
/* mmc_initialize(bd); */
|
|||
|
/* } */
|
|||
|
/* #endif */ /* CONFIG_GENERIC_MMC*/
|
|||
|
|
|||
|
#ifdef CONFIG_HAS_DATAFLASH
|
|||
|
AT91F_DataflashInit();
|
|||
|
dataflash_print_info();
|
|||
|
#endif
|
|||
|
|
|||
|
/* initialize environment */
|
|||
|
env_relocate();
|
|||
|
#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
|
|||
|
arm_pci_init();
|
|||
|
#endif
|
|||
|
|
|||
|
/* IP Address */
|
|||
|
gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr");
|
|||
|
stdio_init(); /* get the devices list going. */
|
|||
|
jumptable_init();
|
|||
|
#if defined(CONFIG_API)
|
|||
|
/* Initialize API */
|
|||
|
api_init();
|
|||
|
#endif
|
|||
|
|
|||
|
console_init_r(); /* fully init console as a device */
|
|||
|
#if defined(CONFIG_ARCH_MISC_INIT)
|
|||
|
/* miscellaneous arch dependent initialisations */
|
|||
|
arch_misc_init();
|
|||
|
#endif
|
|||
|
#if defined(CONFIG_MISC_INIT_R)
|
|||
|
/* miscellaneous platform dependent initialisations */
|
|||
|
misc_init_r();
|
|||
|
#endif
|
|||
|
/* Perform network card initialisation if necessary */
|
|||
|
#if defined(CONFIG_DRIVER_SMC91111) || defined(CONFIG_DRIVER_LAN91C96)
|
|||
|
/* XXX: this needs to be moved to board init */
|
|||
|
if (getenv("ethaddr")) {
|
|||
|
uchar enetaddr[6];
|
|||
|
|
|||
|
eth_getenv_enetaddr("ethaddr", enetaddr);
|
|||
|
smc_set_mac_addr(enetaddr);
|
|||
|
}
|
|||
|
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
|
|||
|
|
|||
|
/* Initialize from environment */
|
|||
|
s = getenv("loadaddr");
|
|||
|
if (s != NULL)
|
|||
|
load_addr = simple_strtoul(s, NULL, 16);
|
|||
|
#if defined(CONFIG_CMD_NET)
|
|||
|
s = getenv("bootfile");
|
|||
|
if (s != NULL)
|
|||
|
copy_filename(BootFile, s, sizeof(BootFile));
|
|||
|
#endif
|
|||
|
#ifdef BOARD_LATE_INIT
|
|||
|
board_late_init();
|
|||
|
#endif
|
|||
|
#ifdef CONFIG_BITBANGMII
|
|||
|
bb_miiphy_init();
|
|||
|
#endif
|
|||
|
#if defined(CONFIG_CMD_NET)
|
|||
|
#if defined(CONFIG_NET_MULTI)
|
|||
|
puts("Net: ");
|
|||
|
#endif
|
|||
|
eth_initialize(gd->bd);
|
|||
|
#if defined(CONFIG_RESET_PHY_R)
|
|||
|
debug("Reset Ethernet PHY\n");
|
|||
|
reset_phy();
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_POST
|
|||
|
post_run(NULL, POST_RAM | post_bootmode_get(0));
|
|||
|
#endif
|
|||
|
|
|||
|
#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
|
|||
|
/*
|
|||
|
* Export available size of memory for Linux,
|
|||
|
* taking into account the protected RAM at top of memory
|
|||
|
*/
|
|||
|
{
|
|||
|
ulong pram;
|
|||
|
uchar memsz[32];
|
|||
|
#ifdef CONFIG_PRAM
|
|||
|
char *s;
|
|||
|
|
|||
|
s = getenv("pram");
|
|||
|
if (s != NULL)
|
|||
|
pram = simple_strtoul(s, NULL, 10);
|
|||
|
else
|
|||
|
pram = CONFIG_PRAM;
|
|||
|
#else
|
|||
|
pram = 0;
|
|||
|
#endif
|
|||
|
#ifdef CONFIG_LOGBUFFER
|
|||
|
#ifndef CONFIG_ALT_LB_ADDR
|
|||
|
/* Also take the logbuffer into account (pram is in kB) */
|
|||
|
pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024;
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram);
|
|||
|
setenv("mem", (char *)memsz);
|
|||
|
}
|
|||
|
#endif
|
|||
|
/* sprite_cartoon_test(); */
|
|||
|
if (workmode == WORK_MODE_BOOT) {
|
|||
|
#if defined(CONFIG_SUNXI_SCRIPT_REINIT)
|
|||
|
{
|
|||
|
FATFS script_mount;
|
|||
|
int ret;
|
|||
|
uint read_bytes = 0;
|
|||
|
FILE script_fs;
|
|||
|
uchar *buf = NULL;
|
|||
|
|
|||
|
f_mount_ex(0, &script_mount, 0);
|
|||
|
ret = f_open(&script_fs, "0:script.bin",
|
|||
|
FA_OPEN_EXISTING | FA_READ | FA_WRITE);
|
|||
|
if (ret)
|
|||
|
printf("cant open script.bin, maybe it is not exist\n");
|
|||
|
else {
|
|||
|
buf = (uchar *)malloc(100 * 1024);
|
|||
|
memset(buf, 0, 100 * 1024);
|
|||
|
|
|||
|
if (!f_read(&script_fs, buf, 100 * 1024,
|
|||
|
&read_bytes)) {
|
|||
|
printf("f_read read bytes = %d\n",
|
|||
|
read_bytes);
|
|||
|
}
|
|||
|
f_close(&script_fs);
|
|||
|
puts("try to unlink file ");
|
|||
|
printf("%d\n", f_unlink("0:script.bin"));
|
|||
|
}
|
|||
|
f_mount(0, NULL, NULL);
|
|||
|
if (read_bytes > 0) {
|
|||
|
char *tmp_target_buffer = (char *)(CONFIG_SYS_TEXT_BASE - 0x01000000);
|
|||
|
|
|||
|
sunxi_flash_exit(1);
|
|||
|
|
|||
|
memcpy(tmp_target_buffer + uboot_spare_head.boot_head.uboot_length, buf, read_bytes);
|
|||
|
sunxi_sprite_download_uboot(tmp_target_buffer, uboot_spare_head.boot_data.storage_type, 1);
|
|||
|
|
|||
|
reset_cpu(0);
|
|||
|
}
|
|||
|
if (buf)
|
|||
|
free(buf);
|
|||
|
}
|
|||
|
#endif
|
|||
|
printf("WORK_MODE_BOOT\n");
|
|||
|
#if (defined(CONFIG_SUNXI_DISPLAY) || defined(CONFIG_SUN7I_DISPLAY))
|
|||
|
if (!ret) {
|
|||
|
#ifndef CONFIG_ARCH_HOMELET
|
|||
|
#ifndef CONFIG_SUNXI_SPINOR_PLATFORM
|
|||
|
printf("board_status_probe\n");
|
|||
|
board_status_probe(0);
|
|||
|
#endif
|
|||
|
#endif /* CONFIG_ARCH_HOMELET */
|
|||
|
if (!gd->chargemode) {
|
|||
|
printf("sunxi_bmp_logo_display\n");
|
|||
|
sunxi_bmp_display("bootlogo.bmp");
|
|||
|
} else {
|
|||
|
printf("sunxi_bmp_charger_display\n");
|
|||
|
sunxi_bmp_display("bat\\battery_charge.bmp");
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* (defined(CONFIG_SUNXI_DISPLAY) || defined(CONFIG_SUN7I_DISPLAY)) */
|
|||
|
#ifdef CONFIG_READ_LOGO_FOR_KERNEL
|
|||
|
sunxi_read_bootlogo("bootlogo");
|
|||
|
#endif
|
|||
|
|
|||
|
sunxi_keydata_burn_by_usb();
|
|||
|
|
|||
|
}
|
|||
|
/* main_loop() can return to retry autoboot, if so just run it again. */
|
|||
|
for (;;)
|
|||
|
{
|
|||
|
main_loop();
|
|||
|
}
|
|||
|
hang();
|
|||
|
/* NOTREACHED - no way out of command loop except booting */
|
|||
|
}
|
|||
|
|
|||
|
void hang(void)
|
|||
|
{
|
|||
|
puts("### ERROR ### Please RESET the board ###\n");
|
|||
|
for (;;);
|
|||
|
}
|