Skip to content
Snippets Groups Projects
Commit 1f4f2121 authored by Haavard Skinnemoen's avatar Haavard Skinnemoen
Browse files

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: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent df548d3c
No related branches found
No related tags found
No related merge requests found
...@@ -57,7 +57,7 @@ unsigned long flash_init(void) ...@@ -57,7 +57,7 @@ unsigned long flash_init(void)
gd->bd->bi_flashstart = CFG_FLASH_BASE; gd->bd->bi_flashstart = CFG_FLASH_BASE;
gd->bd->bi_flashsize = CFG_FLASH_SIZE; 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].size = CFG_FLASH_SIZE;
flash_info[0].sector_count = 135; flash_info[0].sector_count = 135;
......
...@@ -40,35 +40,38 @@ SECTIONS ...@@ -40,35 +40,38 @@ SECTIONS
} }
. = ALIGN(32); . = ALIGN(32);
__flashprog_end = .; __flashprog_end = .;
_etext = .;
. = ALIGN(8);
.rodata : { .rodata : {
*(.rodata) *(.rodata)
*(.rodata.*) *(.rodata.*)
} }
_etext = .;
__data_lma = ALIGN(8); . = ALIGN(8);
. = 0x24000000;
_data = .; _data = .;
.data : AT(__data_lma) { .data : {
*(.data) *(.data)
*(.data.*) *(.data.*)
} }
. = ALIGN(4); . = ALIGN(4);
__u_boot_cmd_start = .; __u_boot_cmd_start = .;
__u_boot_cmd_lma = __data_lma + (__u_boot_cmd_start - _data); .u_boot_cmd : {
.u_boot_cmd : AT(__u_boot_cmd_lma) {
KEEP(*(.u_boot_cmd)) KEEP(*(.u_boot_cmd))
} }
__u_boot_cmd_end = .; __u_boot_cmd_end = .;
. = ALIGN(4);
_got = .;
.got : {
*(.got)
}
_egot = .;
. = ALIGN(8); . = ALIGN(8);
_edata = .; _edata = .;
__edata_lma = __u_boot_cmd_lma + (_edata - __u_boot_cmd_start);
.bss : AT(__edata_lma) { .bss : {
*(.bss) *(.bss)
*(.bss.*) *(.bss.*)
} }
......
...@@ -42,8 +42,7 @@ timer_interrupt_handler: ...@@ -42,8 +42,7 @@ timer_interrupt_handler:
* We're running at interrupt level 3, so we don't need to save * We're running at interrupt level 3, so we don't need to save
* r8-r12 or lr to the stack. * r8-r12 or lr to the stack.
*/ */
mov r8, lo(timer_overflow) lda.w r8, timer_overflow
orh r8, hi(timer_overflow)
ld.w r9, r8[0] ld.w r9, r8[0]
mov r10, -1 mov r10, -1
mtsr SYSREG_COMPARE, r10 mtsr SYSREG_COMPARE, r10
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <asm/sysreg.h> #include <asm/sysreg.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
DECLARE_GLOBAL_DATA_PTR;
static const char * const cpu_modes[8] = { static const char * const cpu_modes[8] = {
"Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
"Interrupt level 2", "Interrupt level 3", "Exception", "NMI" "Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
...@@ -109,11 +111,10 @@ void do_unknown_exception(unsigned int ecr, struct pt_regs *regs) ...@@ -109,11 +111,10 @@ void do_unknown_exception(unsigned int ecr, struct pt_regs *regs)
printf("CPU Mode: %s\n", cpu_modes[mode]); printf("CPU Mode: %s\n", cpu_modes[mode]);
/* Avoid exception loops */ /* Avoid exception loops */
if (regs->sp >= CFG_INIT_SP_ADDR if (regs->sp < CFG_SDRAM_BASE || regs->sp >= gd->stack_end)
|| regs->sp < (CFG_INIT_SP_ADDR - CONFIG_STACKSIZE))
printf("\nStack pointer seems bogus, won't do stack dump\n"); printf("\nStack pointer seems bogus, won't do stack dump\n");
else else
dump_mem("\nStack: ", regs->sp, CFG_INIT_SP_ADDR); dump_mem("\nStack: ", regs->sp, gd->stack_end);
panic("Unhandled exception\n"); panic("Unhandled exception\n");
} }
...@@ -115,9 +115,12 @@ void udelay(unsigned long usec) ...@@ -115,9 +115,12 @@ void udelay(unsigned long usec)
static int set_interrupt_handler(unsigned int nr, void (*handler)(void), static int set_interrupt_handler(unsigned int nr, void (*handler)(void),
unsigned int priority) unsigned int priority)
{ {
extern void _evba(void);
unsigned long intpr; unsigned long intpr;
unsigned long handler_addr = (unsigned long)handler; unsigned long handler_addr = (unsigned long)handler;
handler_addr -= (unsigned long)&_evba;
if ((handler_addr & HANDLER_MASK) != handler_addr if ((handler_addr & HANDLER_MASK) != handler_addr
|| (priority & INTLEV_MASK) != priority) || (priority & INTLEV_MASK) != priority)
return -EINVAL; return -EINVAL;
......
...@@ -70,32 +70,12 @@ _start: ...@@ -70,32 +70,12 @@ _start:
2: lddpc sp, sp_init 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 */ /* Initialize the GOT pointer */
lddpc r6, got_init lddpc r6, got_init
3: rsub r6, pc 3: rsub r6, pc
ld.w pc, r6[board_init_f@got]
/* Let's go */
rjmp board_init_f
.align 2 .align 2
.type sp_init,@object .type sp_init,@object
...@@ -103,11 +83,82 @@ sp_init: ...@@ -103,11 +83,82 @@ sp_init:
.long CFG_INIT_SP_ADDR .long CFG_INIT_SP_ADDR
got_init: got_init:
.long 3b - _GLOBAL_OFFSET_TABLE_ .long 3b - _GLOBAL_OFFSET_TABLE_
.Ldata_lma:
.long __data_lma /*
.Ldata_vma: * void relocate_code(new_sp, new_gd, monitor_addr)
.long _data *
.Ldata_end: * Relocate the u-boot image into RAM and continue from there.
.long _edata * Does not return.
.Lbss_end: */
.long _end .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_
...@@ -37,6 +37,7 @@ typedef struct global_data { ...@@ -37,6 +37,7 @@ typedef struct global_data {
unsigned long flags; unsigned long flags;
unsigned long baudrate; unsigned long baudrate;
unsigned long sdram_size; unsigned long sdram_size;
unsigned long stack_end; /* highest stack address */
unsigned long have_console; /* serial_init() was called */ unsigned long have_console; /* serial_init() was called */
unsigned long reloc_off; /* Relocation Offset */ unsigned long reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of env struct */ unsigned long env_addr; /* Address of env struct */
......
...@@ -151,16 +151,8 @@ ...@@ -151,16 +151,8 @@
#define CFG_INIT_SP_ADDR (CFG_INTRAM_BASE + CFG_INTRAM_SIZE) #define CFG_INIT_SP_ADDR (CFG_INTRAM_BASE + CFG_INTRAM_SIZE)
#define CFG_MALLOC_LEN (256*1024) #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_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 */ /* Allow 2MB for the kernel run-time image */
#define CFG_LOAD_ADDR (CFG_SDRAM_BASE + 0x00200000) #define CFG_LOAD_ADDR (CFG_SDRAM_BASE + 0x00200000)
#define CFG_BOOTPARAMS_LEN (16 * 1024) #define CFG_BOOTPARAMS_LEN (16 * 1024)
......
...@@ -47,11 +47,14 @@ static unsigned long mem_malloc_start = 0; ...@@ -47,11 +47,14 @@ static unsigned long mem_malloc_start = 0;
static unsigned long mem_malloc_end = 0; static unsigned long mem_malloc_end = 0;
static unsigned long mem_malloc_brk = 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) static void mem_malloc_init(void)
{ {
mem_malloc_start = CFG_MALLOC_START; unsigned long monitor_addr;
mem_malloc_end = CFG_MALLOC_END;
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; mem_malloc_brk = mem_malloc_start;
printf("malloc: Using memory from 0x%08lx to 0x%08lx\n", printf("malloc: Using memory from 0x%08lx to 0x%08lx\n",
...@@ -125,6 +128,12 @@ static void display_flash_config (void) ...@@ -125,6 +128,12 @@ static void display_flash_config (void)
void board_init_f(ulong unused) void board_init_f(ulong unused)
{ {
gd_t gd_data; 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 */ /* Initialize the global data pointer */
memset(&gd_data, 0, sizeof(gd_data)); memset(&gd_data, 0, sizeof(gd_data));
...@@ -133,7 +142,6 @@ void board_init_f(ulong unused) ...@@ -133,7 +142,6 @@ void board_init_f(ulong unused)
/* Perform initialization sequence */ /* Perform initialization sequence */
board_early_init_f(); board_early_init_f();
cpu_init(); cpu_init();
timer_init();
env_init(); env_init();
init_baudrate(); init_baudrate();
serial_init(); serial_init();
...@@ -141,28 +149,120 @@ void board_init_f(ulong unused) ...@@ -141,28 +149,120 @@ void board_init_f(ulong unused)
display_banner(); display_banner();
board_init_memories(); 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) 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; gd = new_gd;
bd = gd->bd;
gd->flags |= GD_FLG_RELOC;
gd->reloc_off = dest_addr - CFG_MONITOR_BASE;
monitor_flash_len = _edata - _text; monitor_flash_len = _edata - _text;
mem_malloc_init(); /*
gd->bd = malloc(sizeof(bd_t)); * We have to relocate the command table manually
memset(gd->bd, 0, sizeof(bd_t)); */
gd->bd->bi_baudrate = gd->baudrate; for (cmdtp = &__u_boot_cmd_start;
gd->bd->bi_dram[0].start = CFG_SDRAM_BASE; cmdtp != &__u_boot_cmd_end; cmdtp++) {
gd->bd->bi_dram[0].size = gd->sdram_size; 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(); board_init_info();
flash_init(); flash_init();
if (gd->bd->bi_flashsize) if (bd->bi_flashsize)
display_flash_config(); display_flash_config();
if (gd->bd->bi_dram[0].size) if (bd->bi_dram[0].size)
display_dram_config(); display_dram_config();
gd->bd->bi_boot_params = malloc(CFG_BOOTPARAMS_LEN); gd->bd->bi_boot_params = malloc(CFG_BOOTPARAMS_LEN);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment