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:
parent
df548d3c3e
commit
1f4f2121c2
|
@ -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
|
||||||
}
|
}
|
||||||
. = 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:
|
||||||
* 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 @@
|
||||||
#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)
|
||||||
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)
|
||||||
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:
|
||||||
|
|
||||||
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:
|
||||||
.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 {
|
||||||
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 @@
|
||||||
#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;
|
||||||
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)
|
||||||
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)
|
||||||
/* 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)
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue