mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
f1d2b313c9
!! This breaks support for all arm boards !! To compile in old style, you must define CONFIG_SYS_ARM_WITHOUT_RELOC or you can compile with "CONFIG_SYS_ARM_WITHOUT_RELOC=1 ./MAKEALL board" !! This define will be removed soon, so convert your board to use relocation support Portions of this work were supported by funding from the CE Linux Forum. Signed-off-by: Heiko Schocher <hs@denx.de> Fix boot from NAND for non-ARM systems Signed-off-by: Wolfgang Denk <wd@denx.de>
923 lines
23 KiB
C
923 lines
23 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 <timestamp.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_HAS_DATAFLASH
|
|
extern int AT91F_DataflashInit(void);
|
|
extern void dataflash_print_info(void);
|
|
#endif
|
|
|
|
#ifndef CONFIG_IDENT_STRING
|
|
#define CONFIG_IDENT_STRING ""
|
|
#endif
|
|
|
|
const char version_string[] =
|
|
U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"CONFIG_IDENT_STRING;
|
|
|
|
#ifdef CONFIG_DRIVER_RTL8019
|
|
extern void rtl8019_get_enetaddr (uchar * addr);
|
|
#endif
|
|
|
|
#if defined(CONFIG_HARD_I2C) || \
|
|
defined(CONFIG_SOFT_I2C)
|
|
#include <i2c.h>
|
|
#endif
|
|
|
|
|
|
/************************************************************************
|
|
* Coloured LED functionality
|
|
************************************************************************
|
|
* May be supplied by boards if desired
|
|
*/
|
|
void inline __coloured_LED_init (void) {}
|
|
void coloured_LED_init (void) __attribute__((weak, alias("__coloured_LED_init")));
|
|
void inline __red_LED_on (void) {}
|
|
void red_LED_on (void) __attribute__((weak, alias("__red_LED_on")));
|
|
void inline __red_LED_off(void) {}
|
|
void red_LED_off(void) __attribute__((weak, alias("__red_LED_off")));
|
|
void inline __green_LED_on(void) {}
|
|
void green_LED_on(void) __attribute__((weak, alias("__green_LED_on")));
|
|
void inline __green_LED_off(void) {}
|
|
void green_LED_off(void) __attribute__((weak, alias("__green_LED_off")));
|
|
void inline __yellow_LED_on(void) {}
|
|
void yellow_LED_on(void) __attribute__((weak, alias("__yellow_LED_on")));
|
|
void inline __yellow_LED_off(void) {}
|
|
void yellow_LED_off(void) __attribute__((weak, alias("__yellow_LED_off")));
|
|
void inline __blue_LED_on(void) {}
|
|
void blue_LED_on(void) __attribute__((weak, alias("__blue_LED_on")));
|
|
void inline __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));
|
|
|
|
#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
|
|
gd->baudrate = (i > 0)
|
|
#else
|
|
gd->bd->bi_baudrate = gd->baudrate = (i > 0)
|
|
#endif
|
|
? (int) simple_strtoul (tmp, NULL, 10)
|
|
: CONFIG_BAUDRATE;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int display_banner (void)
|
|
{
|
|
printf ("\n\n%s\n\n", version_string);
|
|
debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
|
|
#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
|
|
_TEXT_BASE,
|
|
#else
|
|
_armboot_start,
|
|
#endif
|
|
_bss_start, _bss_end);
|
|
#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);
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
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;
|
|
}
|
|
puts("DRAM: ");
|
|
print_size(size, "\n");
|
|
#endif
|
|
|
|
return (0);
|
|
}
|
|
|
|
#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
|
|
#ifndef CONFIG_SYS_NO_FLASH
|
|
static void display_flash_config (ulong size)
|
|
{
|
|
puts ("Flash: ");
|
|
print_size (size, "\n");
|
|
}
|
|
#endif /* CONFIG_SYS_NO_FLASH */
|
|
#endif
|
|
|
|
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
|
|
static int init_func_i2c (void)
|
|
{
|
|
puts ("I2C: ");
|
|
i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
|
|
puts ("ready\n");
|
|
return (0);
|
|
}
|
|
#endif
|
|
|
|
#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 */
|
|
|
|
/*
|
|
* 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);
|
|
|
|
#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
|
|
init_fnc_t *init_sequence[] = {
|
|
#if defined(CONFIG_ARCH_CPU_INIT)
|
|
arch_cpu_init, /* basic arch cpu dependent setup */
|
|
#endif
|
|
board_init, /* basic board dependent setup */
|
|
#if defined(CONFIG_USE_IRQ)
|
|
interrupt_init, /* set up exceptions */
|
|
#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 */
|
|
#if defined(CONFIG_DISPLAY_CPUINFO)
|
|
print_cpuinfo, /* display cpu info (and speed) */
|
|
#endif
|
|
#if defined(CONFIG_DISPLAY_BOARDINFO)
|
|
checkboard, /* display board info */
|
|
#endif
|
|
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
|
|
init_func_i2c,
|
|
#endif
|
|
dram_init, /* configure available RAM banks */
|
|
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
|
|
arm_pci_init,
|
|
#endif
|
|
display_dram_config,
|
|
NULL,
|
|
};
|
|
|
|
void start_armboot (void)
|
|
{
|
|
init_fnc_t **init_fnc_ptr;
|
|
char *s;
|
|
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
|
|
unsigned long addr;
|
|
#endif
|
|
|
|
/* Pointer is writable since we allocated a register for it */
|
|
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
|
|
/* compiler optimization barrier needed for GCC >= 3.4 */
|
|
__asm__ __volatile__("": : :"memory");
|
|
|
|
memset ((void*)gd, 0, sizeof (gd_t));
|
|
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
|
|
memset (gd->bd, 0, sizeof (bd_t));
|
|
|
|
gd->flags |= GD_FLG_RELOC;
|
|
|
|
monitor_flash_len = _bss_start - _armboot_start;
|
|
|
|
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
|
|
if ((*init_fnc_ptr)() != 0) {
|
|
hang ();
|
|
}
|
|
}
|
|
|
|
/* armboot_start is defined in the board-specific linker script */
|
|
mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
|
|
CONFIG_SYS_MALLOC_LEN);
|
|
|
|
#ifndef CONFIG_SYS_NO_FLASH
|
|
/* configure available FLASH banks */
|
|
display_flash_config (flash_init ());
|
|
#endif /* CONFIG_SYS_NO_FLASH */
|
|
|
|
#ifdef CONFIG_VFD
|
|
# ifndef PAGE_SIZE
|
|
# define PAGE_SIZE 4096
|
|
# endif
|
|
/*
|
|
* reserve memory for VFD display (always full pages)
|
|
*/
|
|
/* bss_end is defined in the board-specific linker script */
|
|
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
|
|
vfd_setmem (addr);
|
|
gd->fb_base = addr;
|
|
#endif /* CONFIG_VFD */
|
|
|
|
#ifdef CONFIG_LCD
|
|
/* board init may have inited fb_base */
|
|
if (!gd->fb_base) {
|
|
# ifndef PAGE_SIZE
|
|
# define PAGE_SIZE 4096
|
|
# endif
|
|
/*
|
|
* reserve memory for LCD display (always full pages)
|
|
*/
|
|
/* bss_end is defined in the board-specific linker script */
|
|
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
|
|
lcd_setmem (addr);
|
|
gd->fb_base = addr;
|
|
}
|
|
#endif /* CONFIG_LCD */
|
|
|
|
#if defined(CONFIG_CMD_NAND)
|
|
puts ("NAND: ");
|
|
nand_init(); /* go init the NAND */
|
|
#endif
|
|
|
|
#if defined(CONFIG_CMD_ONENAND)
|
|
onenand_init();
|
|
#endif
|
|
|
|
#ifdef CONFIG_HAS_DATAFLASH
|
|
AT91F_DataflashInit();
|
|
dataflash_print_info();
|
|
#endif
|
|
|
|
#ifdef CONFIG_GENERIC_MMC
|
|
/*
|
|
* MMC initialization is called before relocating env.
|
|
* Thus It is required that operations like pin multiplexer
|
|
* be put in board_init.
|
|
*/
|
|
puts ("MMC: ");
|
|
mmc_initialize (gd->bd);
|
|
#endif
|
|
|
|
/* initialize environment */
|
|
env_relocate ();
|
|
|
|
#ifdef CONFIG_VFD
|
|
/* must do this after the framebuffer is allocated */
|
|
drv_vfd_init();
|
|
#endif /* CONFIG_VFD */
|
|
|
|
#ifdef CONFIG_SERIAL_MULTI
|
|
serial_initialize();
|
|
#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
|
|
|
|
/* enable exceptions */
|
|
enable_interrupts ();
|
|
|
|
/* Perform network card initialisation if necessary */
|
|
#ifdef CONFIG_DRIVER_TI_EMAC
|
|
/* XXX: this needs to be moved to board init */
|
|
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
|
|
if (getenv ("ethaddr")) {
|
|
uchar enetaddr[6];
|
|
eth_getenv_enetaddr("ethaddr", enetaddr);
|
|
davinci_eth_set_mac_addr(enetaddr);
|
|
}
|
|
#endif
|
|
|
|
#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 */
|
|
if ((s = getenv ("loadaddr")) != NULL) {
|
|
load_addr = simple_strtoul (s, NULL, 16);
|
|
}
|
|
#if defined(CONFIG_CMD_NET)
|
|
if ((s = getenv ("bootfile")) != 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
|
|
/* main_loop() can return to retry autoboot, if so just run it again. */
|
|
for (;;) {
|
|
main_loop ();
|
|
}
|
|
|
|
/* NOTREACHED - no way out of command loop except booting */
|
|
}
|
|
#else
|
|
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")));
|
|
|
|
init_fnc_t *init_sequence[] = {
|
|
#if defined(CONFIG_ARCH_CPU_INIT)
|
|
arch_cpu_init, /* basic arch cpu dependent setup */
|
|
#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 */
|
|
#if defined(CONFIG_DISPLAY_CPUINFO)
|
|
print_cpuinfo, /* display cpu info (and speed) */
|
|
#endif
|
|
#if defined(CONFIG_DISPLAY_BOARDINFO)
|
|
checkboard, /* display board info */
|
|
#endif
|
|
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
|
|
init_func_i2c,
|
|
#endif
|
|
dram_init, /* configure available RAM banks */
|
|
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
|
|
arm_pci_init,
|
|
#endif
|
|
NULL,
|
|
};
|
|
|
|
void board_init_f (ulong bootflag)
|
|
{
|
|
bd_t *bd;
|
|
init_fnc_t **init_fnc_ptr;
|
|
gd_t *id;
|
|
ulong addr, addr_sp;
|
|
|
|
/* Pointer is writable since we allocated a register for it */
|
|
gd = (gd_t *) (CONFIG_SYS_INIT_SP_ADDR);
|
|
/* compiler optimization barrier needed for GCC >= 3.4 */
|
|
__asm__ __volatile__("": : :"memory");
|
|
|
|
memset ((void*)gd, 0, sizeof (gd_t));
|
|
|
|
gd->mon_len = _bss_end - _TEXT_BASE;
|
|
|
|
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
|
|
if ((*init_fnc_ptr)() != 0) {
|
|
hang ();
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
|
|
|
|
#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_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_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))
|
|
/* 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_VFD
|
|
# ifndef PAGE_SIZE
|
|
# define PAGE_SIZE 4096
|
|
# endif
|
|
/*
|
|
* reserve memory for VFD display (always full pages)
|
|
*/
|
|
addr -= vfd_setmem (addr);
|
|
gd->fb_base = addr;
|
|
#endif /* CONFIG_VFD */
|
|
|
|
#ifdef CONFIG_LCD
|
|
/* reserve memory for LCD display (always full pages) */
|
|
addr = lcd_setmem (addr);
|
|
gd->fb_base = 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_PRELOADER
|
|
/*
|
|
* 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);
|
|
/*
|
|
* (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);
|
|
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 -= 3;
|
|
|
|
/* 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;
|
|
gd->start_addr_sp = addr_sp;
|
|
gd->reloc_off = addr - _TEXT_BASE;
|
|
debug ("relocation Offset is: %08lx\n", gd->reloc_off);
|
|
memcpy (id, (void *)gd, sizeof (gd_t));
|
|
|
|
relocate_code (addr_sp, id, addr);
|
|
|
|
/* 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;
|
|
#if !defined(CONFIG_SYS_NO_FLASH)
|
|
ulong flash_size;
|
|
#endif
|
|
#if !defined(CONFIG_RELOC_FIXUP_WORKS)
|
|
extern void malloc_bin_reloc (void);
|
|
#if defined(CONFIG_CMD_BMP)
|
|
extern void bmp_reloc(void);
|
|
#endif
|
|
#if defined(CONFIG_CMD_I2C)
|
|
extern void i2c_reloc(void);
|
|
#endif
|
|
#endif
|
|
|
|
gd = id;
|
|
bd = gd->bd;
|
|
|
|
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
|
|
|
|
monitor_flash_len = _bss_start - _TEXT_BASE;
|
|
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);
|
|
|
|
#if !defined(CONFIG_RELOC_FIXUP_WORKS)
|
|
/*
|
|
* We have to relocate the command table manually
|
|
*/
|
|
fixup_cmdtable(&__u_boot_cmd_start,
|
|
(ulong)(&__u_boot_cmd_end - &__u_boot_cmd_start));
|
|
#if defined(CONFIG_CMD_BMP)
|
|
bmp_reloc();
|
|
#endif
|
|
#if defined(CONFIG_CMD_I2C)
|
|
i2c_reloc();
|
|
#endif
|
|
#endif /* !defined(CONFIG_RELOC_FIXUP_WORKS) */
|
|
|
|
#ifdef CONFIG_LOGBUFFER
|
|
logbuff_init_ptrs ();
|
|
#endif
|
|
#ifdef CONFIG_POST
|
|
post_output_backlog ();
|
|
#ifndef CONFIG_RELOC_FIXUP_WORKS
|
|
post_reloc ();
|
|
#endif
|
|
#endif
|
|
|
|
/* The Malloc area is immediately below the monitor copy in DRAM */
|
|
malloc_start = dest_addr - TOTAL_MALLOC_LEN;
|
|
mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
|
|
#if !defined(CONFIG_RELOC_FIXUP_WORKS)
|
|
malloc_bin_reloc ();
|
|
#endif
|
|
|
|
#if !defined(CONFIG_SYS_NO_FLASH)
|
|
puts ("FLASH: ");
|
|
|
|
if ((flash_size = flash_init ()) > 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
|
|
|
|
#if defined(CONFIG_CMD_NAND)
|
|
puts ("NAND: ");
|
|
nand_init(); /* go init the NAND */
|
|
#endif
|
|
|
|
#if defined(CONFIG_CMD_ONENAND)
|
|
onenand_init();
|
|
#endif
|
|
|
|
#ifdef CONFIG_HAS_DATAFLASH
|
|
AT91F_DataflashInit();
|
|
dataflash_print_info();
|
|
#endif
|
|
|
|
/* initialize environment */
|
|
env_relocate ();
|
|
|
|
#ifdef CONFIG_VFD
|
|
/* must do this after the framebuffer is allocated */
|
|
drv_vfd_init();
|
|
#endif /* CONFIG_VFD */
|
|
|
|
/* 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
|
|
|
|
/* set up exceptions */
|
|
interrupt_init ();
|
|
/* enable exceptions */
|
|
enable_interrupts ();
|
|
|
|
/* Perform network card initialisation if necessary */
|
|
#ifdef CONFIG_DRIVER_TI_EMAC
|
|
/* XXX: this needs to be moved to board init */
|
|
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
|
|
if (getenv ("ethaddr")) {
|
|
uchar enetaddr[6];
|
|
eth_getenv_enetaddr("ethaddr", enetaddr);
|
|
davinci_eth_set_mac_addr(enetaddr);
|
|
}
|
|
#endif
|
|
|
|
#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 */
|
|
if ((s = getenv ("loadaddr")) != NULL) {
|
|
load_addr = simple_strtoul (s, NULL, 16);
|
|
}
|
|
#if defined(CONFIG_CMD_NET)
|
|
if ((s = getenv ("bootfile")) != NULL) {
|
|
copy_filename (BootFile, s, sizeof (BootFile));
|
|
}
|
|
#endif
|
|
|
|
#ifdef BOARD_LATE_INIT
|
|
board_late_init ();
|
|
#endif
|
|
|
|
#ifdef CONFIG_GENERIC_MMC
|
|
puts ("MMC: ");
|
|
mmc_initialize (gd->bd);
|
|
#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;
|
|
|
|
if ((s = getenv ("pram")) != 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", (bd->bi_memsize / 1024) - pram);
|
|
setenv ("mem", (char *)memsz);
|
|
}
|
|
#endif
|
|
|
|
/* main_loop() can return to retry autoboot, if so just run it again. */
|
|
for (;;) {
|
|
main_loop ();
|
|
}
|
|
|
|
/* NOTREACHED - no way out of command loop except booting */
|
|
}
|
|
#endif /* defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
|
|
|
|
void hang (void)
|
|
{
|
|
puts ("### ERROR ### Please RESET the board ###\n");
|
|
for (;;);
|
|
}
|