ARM: implement relocation for ARM11
authorHeiko Schocher <hs@denx.de>
Fri, 17 Sep 2010 11:10:40 +0000 (13:10 +0200)
committerWolfgang Denk <wd@denx.de>
Sun, 19 Sep 2010 17:29:53 +0000 (19:29 +0200)
Change the implementation for ARM11 to relocate the code to an
arbitrary address in RAM.

Tested on the qong board.

Portions of this work were supported by funding from
the CE Linux Forum.

Signed-off-by: Heiko Schocher <hs@denx.de>
arch/arm/cpu/arm1136/start.S
arch/arm/cpu/arm1136/u-boot.lds
board/davedenx/qong/config.mk
board/davedenx/qong/qong.c
include/configs/qong.h

index 1c58abdcd05dcc4ba0426180fd88f7e16d0962ad..8b631920c94f53e2acec88898a362f878edcc1c9 100644 (file)
@@ -85,12 +85,15 @@ _end_vect:
  *************************************************************************
  */
 
+.globl _TEXT_BASE
 _TEXT_BASE:
        .word   TEXT_BASE
 
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 .globl _armboot_start
 _armboot_start:
        .word _start
+#endif
 
 /*
  * These are defined in the board-specific linker script.
@@ -103,6 +106,32 @@ _bss_start:
 _bss_end:
        .word _end
 
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+.globl _datarel_start
+_datarel_start:
+       .word __datarel_start
+
+.globl _datarelrolocal_start
+_datarelrolocal_start:
+       .word __datarelrolocal_start
+
+.globl _datarellocal_start
+_datarellocal_start:
+       .word __datarellocal_start
+
+.globl _datarelro_start
+_datarelro_start:
+       .word __datarelro_start
+
+.globl _got_start
+_got_start:
+       .word __got_start
+
+.globl _got_end
+_got_end:
+       .word __got_end
+#endif
+
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
 .globl IRQ_STACK_START
@@ -115,6 +144,164 @@ FIQ_STACK_START:
        .word 0x0badc0de
 #endif
 
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
+       .word   0x0badc0de
+#endif
+
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+/*
+ * the actual reset code
+ */
+
+reset:
+       /*
+        * set the cpu to SVC32 mode
+        */
+       mrs     r0,cpsr
+       bic     r0,r0,#0x1f
+       orr     r0,r0,#0xd3
+       msr     cpsr,r0
+
+#ifdef CONFIG_OMAP2420H4
+       /* Copy vectors to mask ROM indirect addr */
+       adr     r0, _start              /* r0 <- current position of code   */
+               add     r0, r0, #4                              /* skip reset vector                    */
+       mov     r2, #64                 /* r2 <- size to copy  */
+       add     r2, r0, r2              /* r2 <- source end address         */
+       mov     r1, #SRAM_OFFSET0         /* build vect addr */
+       mov     r3, #SRAM_OFFSET1
+       add     r1, r1, r3
+       mov     r3, #SRAM_OFFSET2
+       add     r1, r1, r3
+next:
+       ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
+       stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
+       cmp     r0, r2                  /* until source end address [r2]    */
+       bne     next                    /* loop until equal */
+       bl      cpy_clk_code            /* put dpll adjust code behind vectors */
+#endif
+       /* the mask ROM code should have PLL and others stable */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+       bl  cpu_init_crit
+#endif
+
+/* Set stackpointer in internal RAM to call board_init_f */
+call_board_init_f:
+       ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
+       ldr     r0,=0x00000000
+
+#ifdef CONFIG_NAND_SPL
+       bl      nand_boot
+#else
+#ifdef CONFIG_ONENAND_IPL
+       bl      start_oneboot
+#else
+       bl      board_init_f
+#endif /* CONFIG_ONENAND_IPL */
+#endif /* CONFIG_NAND_SPL */
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ */
+       .globl  relocate_code
+relocate_code:
+       mov     r4, r0  /* save addr_sp */
+       mov     r5, r1  /* save addr of gd */
+       mov     r6, r2  /* save addr of destination */
+       mov     r7, r2  /* save addr of destination */
+
+       /* Set up the stack                                                 */
+stack_setup:
+       mov     sp, r4
+
+       adr     r0, _start
+       ldr     r2, _TEXT_BASE
+       ldr     r3, _bss_start
+       sub     r2, r3, r2              /* r2 <- size of armboot            */
+       add     r2, r0, r2              /* r2 <- source end address         */
+       cmp     r0, r6
+       beq     clear_bss
+
+#ifndef CONFIG_SKIP_RELOCATE_UBOOT
+copy_loop:
+       ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */
+       stmia   r6!, {r9-r10}           /* copy to   target address [r1]    */
+       cmp     r0, r2                  /* until source end addreee [r2]    */
+       ble     copy_loop
+
+#ifndef CONFIG_PRELOADER
+       /* fix got entries */
+       ldr     r1, _TEXT_BASE
+       mov     r0, r7                  /* reloc addr */
+       ldr     r2, _got_start          /* addr in Flash */
+       ldr     r3, _got_end            /* addr in Flash */
+       sub     r3, r3, r1
+       add     r3, r3, r0
+       sub     r2, r2, r1
+       add     r2, r2, r0
+
+fixloop:
+       ldr     r4, [r2]
+       sub     r4, r4, r1
+       add     r4, r4, r0
+       str     r4, [r2]
+       add     r2, r2, #4
+       cmp     r2, r3
+       bne     fixloop
+#endif
+#endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
+
+clear_bss:
+#ifndef CONFIG_PRELOADER
+       ldr     r0, _bss_start
+       ldr     r1, _bss_end
+       ldr     r3, _TEXT_BASE          /* Text base */
+       mov     r4, r7                  /* reloc addr */
+       sub     r0, r0, r3
+       add     r0, r0, r4
+       sub     r1, r1, r3
+       add     r1, r1, r4
+       mov     r2, #0x00000000         /* clear                            */
+
+clbss_l:str    r2, [r0]                /* clear loop...                    */
+       add     r0, r0, #4
+       cmp     r0, r1
+       bne     clbss_l
+#endif /* #ifndef CONFIG_PRELOADER */
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+#ifdef CONFIG_NAND_SPL
+       ldr     pc, _nand_boot
+
+_nand_boot: .word nand_boot
+#else
+jump_2_ram:
+       ldr     r0, _TEXT_BASE
+       ldr     r2, _board_init_r
+       sub     r2, r2, r0
+       add     r2, r2, r7      /* position from board_init_r in RAM */
+       /* setup parameters for board_init_r */
+       mov     r0, r5          /* gd_t */
+       mov     r1, r7          /* dest_addr */
+       /* jump to it ... */
+       mov     lr, r2
+       mov     pc, lr
+
+_board_init_r: .word board_init_r
+#endif
+#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
 /*
  * the actual reset code
  */
@@ -211,6 +398,8 @@ _start_armboot: .word start_armboot
 #endif /* CONFIG_ONENAND_IPL */
 #endif /* CONFIG_NAND_SPL */
 
+#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
+
 /*
  *************************************************************************
  *
@@ -295,9 +484,13 @@ cpu_init_crit:
        sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current user stack
        stmia   sp, {r0 - r12}                  @ Save user registers (now in svc mode) r0-r12
 
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+       ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort stack
+#else
        ldr     r2, _armboot_start
        sub     r2, r2, #(CONFIG_SYS_MALLOC_LEN)
        sub     r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)   @ set base 2 words into abort stack
+#endif
        ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc and cpsr (into parm regs)
        add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
 
@@ -328,9 +521,13 @@ cpu_init_crit:
        .endm
 
        .macro get_bad_stack
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+       ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter in banked mode)
+#else
        ldr     r13, _armboot_start             @ setup our mode stack (enter in banked mode)
        sub     r13, r13, #(CONFIG_SYS_MALLOC_LEN)      @ move past malloc pool
        sub     r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack
+#endif
 
        str     lr, [r13]                       @ save caller lr in position 0 of saved stack
        mrs     lr, spsr                        @ get the spsr
@@ -346,9 +543,13 @@ cpu_init_crit:
        .macro get_bad_stack_swi
        sub     r13, r13, #4                    @ space on current stack for scratch reg.
        str     r0, [r13]                       @ save R0's value.
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+       ldr     r0, IRQ_STACK_START_IN          @ get data regions start
+#else
        ldr     r0, _armboot_start              @ get data regions start
        sub     r0, r0, #(CONFIG_SYS_MALLOC_LEN)        @ move past malloc pool
        sub     r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE+8)   @ move past gbl and a couple spots for abort stack
+#endif
        str     lr, [r0]                        @ save caller lr in position 0 of saved stack
        mrs     r0, spsr                        @ get the spsr
        str     lr, [r0, #4]                    @ save spsr in position 1 of saved stack
index e7eefc972c4262ca3f5e22712c15272a3523c2a2..1db4b49cc759c411cfada23ba777827a338e4afd 100644 (file)
@@ -47,11 +47,23 @@ SECTIONS
        .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 
        . = ALIGN(4);
-       .data : { *(.data) }
+       .data : {
+               *(.data)
+       __datarel_start = .;
+               *(.data.rel)
+       __datarelrolocal_start = .;
+               *(.data.rel.ro.local)
+       __datarellocal_start = .;
+               *(.data.rel.local)
+       __datarelro_start = .;
+               *(.data.rel.ro)
+       }
 
+       __got_start = .;
        . = ALIGN(4);
        .got : { *(.got) }
 
+       __got_end = .;
        . = .;
        __u_boot_cmd_start = .;
        .u_boot_cmd : { *(.u_boot_cmd) }
index d8d0a5714b813e5ce87fd8befb48d00eeab3d459..39c1203f5bc4172ff0000da814c294c64de16d40 100644 (file)
@@ -1 +1,3 @@
-TEXT_BASE = 0x8ff00000
+TEXT_BASE = 0xa0000000
+
+# PLATFORM_CPPFLAGS += -DDEBUG
index 781333b8ceb93e41c63a33a0af1c719edca2f826..e509383e8fd0df54988840401c0f1dbc4804da23 100644 (file)
@@ -33,10 +33,9 @@ DECLARE_GLOBAL_DATA_PTR;
 
 int dram_init (void)
 {
-       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-       gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1,
-                       PHYS_SDRAM_1_SIZE);
-
+       /* dram_init must store complete ramsize in gd->ram_size */
+       gd->ram_size = get_ram_size((volatile void *)CONFIG_SYS_SDRAM_BASE,
+                               PHYS_SDRAM_1_SIZE);
        return 0;
 }
 
@@ -49,6 +48,49 @@ static void qong_fpga_reset(void)
        udelay(300);
 }
 
+int board_early_init_f (void)
+{
+#ifdef CONFIG_QONG_FPGA
+       /* CS1: FPGA/Network Controller/GPIO */
+       /* 16-bit, no DTACK */
+       __REG(CSCR_U(1)) = 0x00000A01;
+       __REG(CSCR_L(1)) = 0x20040501;
+       __REG(CSCR_A(1)) = 0x04020C00;
+
+       /* setup pins for FPGA */
+       mx31_gpio_mux(IOMUX_MODE(0x76, MUX_CTL_GPIO));
+       mx31_gpio_mux(IOMUX_MODE(0x7e, MUX_CTL_GPIO));
+       mx31_gpio_mux(IOMUX_MODE(0x91, MUX_CTL_OUT_FUNC | MUX_CTL_IN_GPIO));
+       mx31_gpio_mux(IOMUX_MODE(0x92, MUX_CTL_GPIO));
+       mx31_gpio_mux(IOMUX_MODE(0x93, MUX_CTL_GPIO));
+
+       /* FPGA reset  Pin */
+       /* rstn = 0 */
+       mx31_gpio_set(QONG_FPGA_RST_PIN, 0);
+       mx31_gpio_direction(QONG_FPGA_RST_PIN, MX31_GPIO_DIRECTION_OUT);
+
+       /* set interrupt pin as input */
+       mx31_gpio_direction(QONG_FPGA_IRQ_PIN, MX31_GPIO_DIRECTION_IN);
+
+#endif
+
+       /* setup pins for UART1 */
+       mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX);
+       mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX);
+       mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
+       mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
+
+       /* setup pins for SPI (pmic) */
+       mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B);
+       mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI);
+       mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO);
+       mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);
+       mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B);
+
+       return 0;
+
+}
+
 int board_init (void)
 {
        /* Chip selects */
@@ -99,43 +141,6 @@ int board_init (void)
                                                (0 << 0)          /* FCE */
                                           );
 
-#ifdef CONFIG_QONG_FPGA
-       /* CS1: FPGA/Network Controller/GPIO */
-       /* 16-bit, no DTACK */
-       __REG(CSCR_U(1)) = 0x00000A01;
-       __REG(CSCR_L(1)) = 0x20040501;
-       __REG(CSCR_A(1)) = 0x04020C00;
-
-       /* setup pins for FPGA */
-       mx31_gpio_mux(IOMUX_MODE(0x76, MUX_CTL_GPIO));
-       mx31_gpio_mux(IOMUX_MODE(0x7e, MUX_CTL_GPIO));
-       mx31_gpio_mux(IOMUX_MODE(0x91, MUX_CTL_OUT_FUNC | MUX_CTL_IN_GPIO));
-       mx31_gpio_mux(IOMUX_MODE(0x92, MUX_CTL_GPIO));
-       mx31_gpio_mux(IOMUX_MODE(0x93, MUX_CTL_GPIO));
-
-       /* FPGA reset  Pin */
-       /* rstn = 0 */
-       mx31_gpio_set(QONG_FPGA_RST_PIN, 0);
-       mx31_gpio_direction(QONG_FPGA_RST_PIN, MX31_GPIO_DIRECTION_OUT);
-
-       /* set interrupt pin as input */
-       mx31_gpio_direction(QONG_FPGA_IRQ_PIN, MX31_GPIO_DIRECTION_IN);
-
-#endif
-
-       /* setup pins for UART1 */
-       mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX);
-       mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX);
-       mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
-       mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
-
-       /* setup pins for SPI (pmic) */
-       mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B);
-       mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI);
-       mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO);
-       mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);
-       mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B);
-
        /* board id for linux */
        gd->bd->bi_arch_number = MACH_TYPE_QONG;
        gd->bd->bi_boot_params = (0x80000100);  /* adress of boot parameters */
index 4735b5eb8824e5fb38848e247c2547e7ceff1025..7a68b7b97ead66b231f47a6de2eb736f5b5ee4f0 100644 (file)
@@ -282,4 +282,14 @@ extern int qong_nand_rdy(void *chip);
        "mtdparts=physmap-flash.0:384k(U-Boot),128k(env1),"     \
        "128k(env2),2432k(kernel),13m(ramdisk),-(user)"
 
+/* additions for new relocation code, must added to all boards */
+#undef CONFIG_SYS_ARM_WITHOUT_RELOC /* This board is tested with relocation support */
+#define CONFIG_SYS_SDRAM_BASE          0x80000000
+#define CONFIG_SYS_INIT_RAM_ADDR       IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_END                IRAM_SIZE
+#define CONFIG_SYS_GBL_DATA_OFFSET     (CONFIG_SYS_INIT_RAM_END - CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR                (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)
+
+#define CONFIG_BOARD_EARLY_INIT_F      1
+
 #endif /* __CONFIG_H */