AVR32: Relocate u-boot to SDRAM

Relocate the u-boot image into SDRAM like everyone else does. This
means that we can handle much larger .data and .bss than we used to.

Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
This commit is contained in:
Haavard Skinnemoen 2006-11-20 15:53:10 +01:00
parent df548d3c3e
commit 1f4f2121c2
9 changed files with 218 additions and 68 deletions

View File

@ -57,7 +57,7 @@ unsigned long flash_init(void)
gd->bd->bi_flashstart = CFG_FLASH_BASE;
gd->bd->bi_flashsize = CFG_FLASH_SIZE;
gd->bd->bi_flashoffset = __edata_lma - _text;
gd->bd->bi_flashoffset = _edata - _text;
flash_info[0].size = CFG_FLASH_SIZE;
flash_info[0].sector_count = 135;

View File

@ -40,35 +40,38 @@ SECTIONS
}
. = ALIGN(32);
__flashprog_end = .;
_etext = .;
. = ALIGN(8);
.rodata : {
*(.rodata)
*(.rodata.*)
}
_etext = .;
__data_lma = ALIGN(8);
. = 0x24000000;
. = ALIGN(8);
_data = .;
.data : AT(__data_lma) {
.data : {
*(.data)
*(.data.*)
}
. = ALIGN(4);
__u_boot_cmd_start = .;
__u_boot_cmd_lma = __data_lma + (__u_boot_cmd_start - _data);
.u_boot_cmd : AT(__u_boot_cmd_lma) {
.u_boot_cmd : {
KEEP(*(.u_boot_cmd))
}
__u_boot_cmd_end = .;
. = ALIGN(4);
_got = .;
.got : {
*(.got)
}
_egot = .;
. = ALIGN(8);
_edata = .;
__edata_lma = __u_boot_cmd_lma + (_edata - __u_boot_cmd_start);
.bss : AT(__edata_lma) {
.bss : {
*(.bss)
*(.bss.*)
}

View File

@ -42,8 +42,7 @@ timer_interrupt_handler:
* We're running at interrupt level 3, so we don't need to save
* r8-r12 or lr to the stack.
*/
mov r8, lo(timer_overflow)
orh r8, hi(timer_overflow)
lda.w r8, timer_overflow
ld.w r9, r8[0]
mov r10, -1
mtsr SYSREG_COMPARE, r10

View File

@ -24,6 +24,8 @@
#include <asm/sysreg.h>
#include <asm/ptrace.h>
DECLARE_GLOBAL_DATA_PTR;
static const char * const cpu_modes[8] = {
"Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
"Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
@ -109,11 +111,10 @@ void do_unknown_exception(unsigned int ecr, struct pt_regs *regs)
printf("CPU Mode: %s\n", cpu_modes[mode]);
/* Avoid exception loops */
if (regs->sp >= CFG_INIT_SP_ADDR
|| regs->sp < (CFG_INIT_SP_ADDR - CONFIG_STACKSIZE))
if (regs->sp < CFG_SDRAM_BASE || regs->sp >= gd->stack_end)
printf("\nStack pointer seems bogus, won't do stack dump\n");
else
dump_mem("\nStack: ", regs->sp, CFG_INIT_SP_ADDR);
dump_mem("\nStack: ", regs->sp, gd->stack_end);
panic("Unhandled exception\n");
}

View File

@ -115,9 +115,12 @@ void udelay(unsigned long usec)
static int set_interrupt_handler(unsigned int nr, void (*handler)(void),
unsigned int priority)
{
extern void _evba(void);
unsigned long intpr;
unsigned long handler_addr = (unsigned long)handler;
handler_addr -= (unsigned long)&_evba;
if ((handler_addr & HANDLER_MASK) != handler_addr
|| (priority & INTLEV_MASK) != priority)
return -EINVAL;

View File

@ -70,32 +70,12 @@ _start:
2: lddpc sp, sp_init
/*
* Relocate the data section and initialize .bss. Everything
* is guaranteed to be at least doubleword aligned by the
* linker script.
*/
lddpc r12, .Ldata_vma
lddpc r11, .Ldata_lma
lddpc r10, .Ldata_end
sub r10, r12
4: ld.d r8, r11++
sub r10, 8
st.d r12++, r8
brne 4b
mov r8, 0
mov r9, 0
lddpc r10, .Lbss_end
sub r10, r12
4: sub r10, 8
st.d r12++, r8
brne 4b
/* Initialize the GOT pointer */
lddpc r6, got_init
3: rsub r6, pc
ld.w pc, r6[board_init_f@got]
/* Let's go */
rjmp board_init_f
.align 2
.type sp_init,@object
@ -103,11 +83,82 @@ sp_init:
.long CFG_INIT_SP_ADDR
got_init:
.long 3b - _GLOBAL_OFFSET_TABLE_
.Ldata_lma:
.long __data_lma
.Ldata_vma:
.long _data
.Ldata_end:
.long _edata
.Lbss_end:
.long _end
/*
* void relocate_code(new_sp, new_gd, monitor_addr)
*
* Relocate the u-boot image into RAM and continue from there.
* Does not return.
*/
.global relocate_code
.type relocate_code,@function
relocate_code:
mov sp, r12 /* use new stack */
mov r12, r11 /* save new_gd */
mov r11, r10 /* save destination address */
/* copy .text section and flush the cache along the way */
lda.w r8, _text
lda.w r9, _etext
sub lr, r10, r8 /* relocation offset */
1: ldm r8++, r0-r3
stm r10, r0-r3
sub r10, -16
ldm r8++, r0-r3
stm r10, r0-r3
sub r10, -16
cp.w r8, r9
cache r10[-4], 0x0d /* dcache clean/invalidate */
cache r10[-4], 0x01 /* icache invalidate */
brlt 1b
/* flush write buffer */
sync 0
/* copy data sections */
lda.w r9, _edata
1: ld.d r0, r8++
st.d r10++, r0
cp.w r8, r9
brlt 1b
/* zero out .bss */
mov r0, 0
mov r1, 0
lda.w r9, _end
sub r9, r8
1: st.d r10++, r0
sub r9, 8
brgt 1b
/* jump to RAM */
sub r0, pc, . - in_ram
add pc, r0, lr
.align 2
in_ram:
/* find the new GOT and relocate it */
lddpc r6, got_init_reloc
3: rsub r6, pc
mov r8, r6
lda.w r9, _egot
lda.w r10, _got
sub r9, r10
1: ld.w r0, r8[0]
add r0, lr
st.w r8++, r0
sub r9, 4
brgt 1b
/* Move the exception handlers */
mfsr r2, SYSREG_EVBA
add r2, lr
mtsr SYSREG_EVBA, r2
/* Do the rest of the initialization sequence */
call board_init_r
.align 2
got_init_reloc:
.long 3b - _GLOBAL_OFFSET_TABLE_

View File

@ -37,6 +37,7 @@ typedef struct global_data {
unsigned long flags;
unsigned long baudrate;
unsigned long sdram_size;
unsigned long stack_end; /* highest stack address */
unsigned long have_console; /* serial_init() was called */
unsigned long reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of env struct */

View File

@ -151,16 +151,8 @@
#define CFG_INIT_SP_ADDR (CFG_INTRAM_BASE + CFG_INTRAM_SIZE)
#define CFG_MALLOC_LEN (256*1024)
#define CFG_MALLOC_END \
({ \
DECLARE_GLOBAL_DATA_PTR; \
CFG_SDRAM_BASE + gd->sdram_size; \
})
#define CFG_MALLOC_START (CFG_MALLOC_END - CFG_MALLOC_LEN)
#define CFG_DMA_ALLOC_LEN (16384)
#define CFG_DMA_ALLOC_END (CFG_MALLOC_START)
#define CFG_DMA_ALLOC_START (CFG_DMA_ALLOC_END - CFG_DMA_ALLOC_LEN)
/* Allow 2MB for the kernel run-time image */
#define CFG_LOAD_ADDR (CFG_SDRAM_BASE + 0x00200000)
#define CFG_BOOTPARAMS_LEN (16 * 1024)

View File

@ -47,11 +47,14 @@ static unsigned long mem_malloc_start = 0;
static unsigned long mem_malloc_end = 0;
static unsigned long mem_malloc_brk = 0;
/* The malloc area is wherever the board wants it to be */
/* The malloc area is right below the monitor image in RAM */
static void mem_malloc_init(void)
{
mem_malloc_start = CFG_MALLOC_START;
mem_malloc_end = CFG_MALLOC_END;
unsigned long monitor_addr;
monitor_addr = CFG_MONITOR_BASE + gd->reloc_off;
mem_malloc_end = monitor_addr;
mem_malloc_start = mem_malloc_end - CFG_MALLOC_LEN;
mem_malloc_brk = mem_malloc_start;
printf("malloc: Using memory from 0x%08lx to 0x%08lx\n",
@ -125,6 +128,12 @@ static void display_flash_config (void)
void board_init_f(ulong unused)
{
gd_t gd_data;
gd_t *new_gd;
bd_t *bd;
unsigned long *new_sp;
unsigned long monitor_len;
unsigned long monitor_addr;
unsigned long addr;
/* Initialize the global data pointer */
memset(&gd_data, 0, sizeof(gd_data));
@ -133,7 +142,6 @@ void board_init_f(ulong unused)
/* Perform initialization sequence */
board_early_init_f();
cpu_init();
timer_init();
env_init();
init_baudrate();
serial_init();
@ -141,28 +149,120 @@ void board_init_f(ulong unused)
display_banner();
board_init_memories();
board_init_r(gd, CFG_MONITOR_BASE);
/* If we have no SDRAM, we can't go on */
if (!gd->sdram_size)
panic("No working SDRAM available\n");
/*
* Now that we have DRAM mapped and working, we can
* relocate the code and continue running from DRAM.
*
* Reserve memory at end of RAM for (top down in that order):
* - u-boot image
* - heap for malloc()
* - board info struct
* - global data struct
* - stack
*/
addr = CFG_SDRAM_BASE + gd->sdram_size;
monitor_len = _end - _text;
/*
* Reserve memory for u-boot code, data and bss.
* Round down to next 4 kB limit.
*/
addr -= monitor_len;
addr &= ~(4096UL - 1);
monitor_addr = addr;
/* Reserve memory for malloc() */
addr -= CFG_MALLOC_LEN;
/* Allocate a Board Info struct on a word boundary */
addr -= sizeof(bd_t);
addr &= ~3UL;
gd->bd = bd = (bd_t *)addr;
/* Allocate a new global data copy on a 8-byte boundary. */
addr -= sizeof(gd_t);
addr &= ~7UL;
new_gd = (gd_t *)addr;
/* And finally, a new, bigger stack. */
new_sp = (unsigned long *)addr;
gd->stack_end = addr;
*(--new_sp) = 0;
*(--new_sp) = 0;
/*
* Initialize the board information struct with the
* information we have.
*/
bd->bi_dram[0].start = CFG_SDRAM_BASE;
bd->bi_dram[0].size = gd->sdram_size;
bd->bi_baudrate = gd->baudrate;
memcpy(new_gd, gd, sizeof(gd_t));
relocate_code((unsigned long)new_sp, new_gd, monitor_addr);
}
void board_init_r(gd_t *new_gd, ulong dest_addr)
{
extern void malloc_bin_reloc (void);
#ifndef CFG_ENV_IS_NOWHERE
extern char * env_name_spec;
#endif
cmd_tbl_t *cmdtp;
bd_t *bd;
gd = new_gd;
bd = gd->bd;
gd->flags |= GD_FLG_RELOC;
gd->reloc_off = dest_addr - CFG_MONITOR_BASE;
monitor_flash_len = _edata - _text;
mem_malloc_init();
gd->bd = malloc(sizeof(bd_t));
memset(gd->bd, 0, sizeof(bd_t));
gd->bd->bi_baudrate = gd->baudrate;
gd->bd->bi_dram[0].start = CFG_SDRAM_BASE;
gd->bd->bi_dram[0].size = gd->sdram_size;
/*
* We have to relocate the command table manually
*/
for (cmdtp = &__u_boot_cmd_start;
cmdtp != &__u_boot_cmd_end; cmdtp++) {
unsigned long addr;
addr = (unsigned long)cmdtp->cmd + gd->reloc_off;
cmdtp->cmd = (typeof(cmdtp->cmd))addr;
addr = (unsigned long)cmdtp->name + gd->reloc_off;
cmdtp->name = (typeof(cmdtp->name))addr;
if (cmdtp->usage) {
addr = (unsigned long)cmdtp->usage + gd->reloc_off;
cmdtp->usage = (typeof(cmdtp->usage))addr;
}
#ifdef CFG_LONGHELP
if (cmdtp->help) {
addr = (unsigned long)cmdtp->help + gd->reloc_off;
cmdtp->help = (typeof(cmdtp->help))addr;
}
#endif
}
/* there are some other pointer constants we must deal with */
#ifndef CFG_ENV_IS_NOWHERE
env_name_spec += gd->reloc_off;
#endif
timer_init();
mem_malloc_init();
malloc_bin_reloc();
board_init_info();
flash_init();
if (gd->bd->bi_flashsize)
if (bd->bi_flashsize)
display_flash_config();
if (gd->bd->bi_dram[0].size)
if (bd->bi_dram[0].size)
display_dram_config();
gd->bd->bi_boot_params = malloc(CFG_BOOTPARAMS_LEN);