Message ID | 1351532157-24173-4-git-send-email-tremyfr@yahoo.fr |
---|---|
State | Changes Requested |
Delegated to: | Albert ARIBAUD |
Headers | show |
On Mon, Oct 29, 2012 at 3:35 PM, Philippe Reynes <tremyfr@yahoo.fr> wrote: > --- /dev/null > +++ b/board/armadeus/apf27/start.S > @@ -0,0 +1,549 @@ > +/* > + * IMX27 NAND Flash SPL (Secondary Program Loader) > + * > + * Copyright (c) 2008 Armadeus Project / eja > + * > + * Based on Freescale NAND SPL Shouldn't this start.S file be placed on some common location rather than board/armadeus directory? Regards, Fabio Estevam
Hi Philippe, On Mon, 29 Oct 2012 18:35:56 +0100, Philippe Reynes <tremyfr@yahoo.fr> wrote: > Signed-off-by: Philippe Reynes <tremyfr@yahoo.fr> > Signed-off-by: Eric Jarrige <eric.jarrige@armadeus.org> > > create mode 100644 board/armadeus/apf27/start.S > create mode 100644 board/armadeus/apf27/u-boot-spl.lds This is needed by 2/4 to get truly useable support. Please merge both patches. Re Fabio's question: the start.S is generic to mx27 -- IIUC, it could also be applied to e.g. imx27lite or magnesium if these boards' maintainers felt so inclined. Therefore it could indeed move into arch/arm/cpu/arm926ejs/mx27. > diff --git a/board/armadeus/apf27/Makefile b/board/armadeus/apf27/Makefile > index 1da9548..f57f405 100644 > --- a/board/armadeus/apf27/Makefile > +++ b/board/armadeus/apf27/Makefile > @@ -27,11 +27,14 @@ include $(TOPDIR)/config.mk > > LIB = $(obj)lib$(BOARD).o > > +ifndef CONFIG_SPL_BUILD > COBJS := apf27.o > +endif > > -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) > +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) > OBJS := $(addprefix $(obj),$(COBJS)) > SOBJS := $(addprefix $(obj),$(SOBJS)) > +START := $(addprefix $(obj),$(START)) > > $(LIB): $(obj).depend $(OBJS) $(SOBJS) > $(call cmd_link_o_target, $(OBJS) $(SOBJS)) > diff --git a/board/armadeus/apf27/start.S b/board/armadeus/apf27/start.S > new file mode 100644 > index 0000000..374b4ea > --- /dev/null > +++ b/board/armadeus/apf27/start.S > @@ -0,0 +1,549 @@ > +/* > + * IMX27 NAND Flash SPL (Secondary Program Loader) > + * > + * Copyright (c) 2008 Armadeus Project / eja > + * > + * Based on Freescale NAND SPL > + * > + * Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. > + * Copyright (c) 2008-2012 Eric Jarrige <eric.jarrige@armadeus.org> > + * > + * 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 > + */ > + > + > +#include <config.h> > +#include <version.h> > +#include <asm/macro.h> > +#include <asm/arch/mxc_nand.h> > +#include <asm/arch/imx-regs.h> > +#include <generated/asm-offsets.h> > +#include "apf27.h" > + > +/* > + * Standard NAND flash commands > + */ > +#define NAND_CMD_READ0 0 > +#define NAND_CMD_READ1 1 > +#define NAND_CMD_PAGEPROG 0x10 > +#define NAND_CMD_READOOB 0x50 > +#define NAND_CMD_ERASE1 0x60 > +#define NAND_CMD_STATUS 0x70 > +#define NAND_CMD_STATUS_MULTI 0x71 > +#define NAND_CMD_SEQIN 0x80 > +#define NAND_CMD_READID 0x90 > +#define NAND_CMD_ERASE2 0xd0 > +#define NAND_CMD_RESET 0xff > + > +/* Extended commands for large page devices */ > +#define NAND_CMD_READSTART 0x30 > +#define NAND_CMD_CACHEDPROG 0x15 > + > +/* Status bits */ > +#define NAND_STATUS_FAIL 0x01 > +#define NAND_STATUS_FAIL_N1 0x02 > +#define NAND_STATUS_TRUE_READY 0x20 > +#define NAND_STATUS_READY 0x40 > +#define NAND_STATUS_WP 0x80 > + > + .macro nand_boot > + > +#ifdef CONFIG_BOOT_TRACE_REG > +/* > + * If CONFIG_BOOT_TRACE_REG is a SDRAM address then be sure to use the following > + * 2 command after SDRAM init > + */ > + > +/* Backup state of previous boot to CONFIG_BOOT_TRACE_REG+4*/ > +#define BACKUP_TRACE() \ > + ldr r4, =CONFIG_BOOT_TRACE_REG; \ > + ldr r3, [r4]; \ > + str r3, [r4, #0x04]; > + > +/* Save a state of boot at CONFIG_BOOT_TRACE_REG */ > +#define BOOT_TRACE(val) \ > + ldr r4, =CONFIG_BOOT_TRACE_REG; \ > + ldr r3, =val; \ > + str r3, [r4]; > +#else > +#define BACKUP_TRACE() > +#define BOOT_TRACE(val) > +#endif > + > +nand_boot_setup: > + > + /* Copy SPL image from flash to SDRAM first */ > + BOOT_TRACE(1) > + ldr r0, =IMX_NFC_MAIN_AREA0 > + add r2, r0, #(IMX_NFC_SPARE_AREA0-IMX_NFC_MAIN_AREA0) //2KB NFC Buff > + ldr r1, =CONFIG_SYS_NAND_U_BOOT_DST > + > + BOOT_TRACE(2) > +1: ldmia r0!, {r3-r10} > + stmia r1!, {r3-r10} > + cmp r0, r2 > + blo 1b > + > + > + > + /* Jump to SDRAM */ > + BOOT_TRACE(3) > + ldr r1, =0x7FF > + and r0, pc, r1 /* offset of pc */ > + ldr r1, =CONFIG_SYS_NAND_U_BOOT_DST > + add r1, r1, #0x10 > + add pc, r0, r1 > + nop > + nop > + nop > + nop > + > +NAND_Copy_Main: > + BOOT_TRACE(4) > + /* r0: nfc base. Reloaded after each page copying */ > + ldr r0, =IMX_NFC_MAIN_AREA0 > + > + /* r1: starting flash addr to be copied. Updated constantly */ > + /* bypass the first preloaded pages */ > + ldr r1, =(IMX_NFC_SPARE_AREA0-IMX_NFC_MAIN_AREA0) > + > + /* r2: end of 1st RAM buf. Doesn't change */ > + ldr r2, =IMX_NFC_MAIN_AREA1 > + > + /* r12: NFC register base. Doesn't change */ > + ldr r12, =IMX_NFC_REGS > + > + ldr r11, =CONFIG_SYS_NAND_U_BOOT_DST > + > + /* r13: end of SDRAM address for copying. Doesn't change */ > + add r13, r11, #CONFIG_SYS_NAND_U_BOOT_SIZE > + > + /* r11: starting SDRAM address for copying. Updated constantly */ > + add r11, r11, r1 > + > + /* unlock internal buffer */ > + ldr r3, =NFC_CONFIG_UNLOCKED > + strh r3, [r12, #NFC_OFFSET_CONFIG] > + > + /* enable ECC and mask interrupts */ > + ldr r3, =(NFC_CONFIG1_ECC_EN | NFC_CONFIG1_INT_MSK) > + strh r3, [r12, #NFC_OFFSET_CONFIG1] > + > +Nfc_Read_Page: > + BOOT_TRACE(5) > + /* send NAND_CMD_READ0 command */ > + ldr r3, =NAND_CMD_READ0; > + strh r3, [r12, #NFC_OFFSET_FLASH_CMD] > + > + ldr r3, =NFC_CONFIG2_FCMD > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + bl do_wait_op_done > + > + /* send NAND address to read. TODO small page support */ > + BOOT_TRACE(6) > + mov r3, r1, lsr #1 > + bl do_addr_input /* 1st addr cycle */ > + > + mov r3, r1, lsr #9 > + and r3, r3, #0x03 > + bl do_addr_input /* 2nd addr cycle */ > + > + mov r3, r1, lsr #11 > + bl do_addr_input /* 3rd addr cycle */ > + > + mov r3, r1, lsr #19 > + bl do_addr_input /* 4th addr cycle */ > + > + /* Small NAND flashs (== 1Gb) support 5 addr cycles */ > + mov r3, r1, lsr #27 > + bl do_addr_input /* 5th addr cycle */ > + > + /* send NAND_CMD_READSTART command. TODO small page support */ > + BOOT_TRACE(7) > + mov r3, #NAND_CMD_READSTART; > + strh r3, [r12, #NFC_OFFSET_FLASH_CMD] > + mov r3, #NFC_CONFIG2_FCMD > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + bl do_wait_op_done > + > + /* read and copy buf 0 */ > + BOOT_TRACE(8) > + mov r3, #0 > + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] > + > + mov r3, #NFC_CONFIG2_FDO_PAGE > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + bl do_wait_op_done > + > + bl Test_And_Copy_Buffer > + > + /* read and copy buf 1 */ > + mov r3, #1 > + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] > + > + mov r3, #NFC_CONFIG2_FDO_PAGE > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + bl do_wait_op_done > + > + bl Test_And_Copy_Buffer > + > + /* here we should test if 512B page flash and bypass next buffers */ > + /* read and copy buf 2. TODO small page support */ > + mov r3, #2 > + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] > + > + mov r3, #NFC_CONFIG2_FDO_PAGE > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + bl do_wait_op_done > + > + bl Test_And_Copy_Buffer > + > + /* read and copy buf 3 */ > + mov r3, #3 > + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] > + > + mov r3, #NFC_CONFIG2_FDO_PAGE > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + bl do_wait_op_done > + > + bl Test_And_Copy_Buffer > + > + /* is the last page ? */ > + BOOT_TRACE(12) > + cmp r11, r13 > + bge NAND_Copy_Main_done > + > + /* r0: nfc base. Reloaded after each page copying */ > + ldr r0, =IMX_NFC_MAIN_AREA0 > + /* r2: end of 1st RAM buf. Doesn't change */ > + ldr r2, =IMX_NFC_MAIN_AREA1 > + b Nfc_Read_Page > + > +NAND_Copy_Main_done: > + BOOT_TRACE(13) > + .endm /* nand_boot */ > + > + .macro init_aipi > + /* > + * setup AIPI1 and AIPI2 > + */ > + write32 AIPI1_PSR0, ACFG_AIPI1_PSR0_VAL > + write32 AIPI1_PSR1, ACFG_AIPI1_PSR1_VAL > + write32 AIPI2_PSR0, ACFG_AIPI2_PSR0_VAL > + write32 AIPI2_PSR1, ACFG_AIPI2_PSR1_VAL > + > + /* Change SDRAM signal strengh */ > + ldr r0, =GPCR > + ldr r1, =ACFG_GPCR_VAL > + ldr r5, [r0] > + orr r5, r5, r1 > + str r5, [r0] > + > + .endm /* init_aipi */ > + > + .macro init_clock > + ldr r0, =CSCR > + /* disable MPLL/SPLL first */ > + ldr r1, [r0] > + bic r1, r1, #(CSCR_MPEN|CSCR_SPEN) > + str r1, [r0] > + > + /* > + * pll clock initialization predefined in apf27.h > + */ > + write32 MPCTL0, ACFG_MPCTL0_VAL > + write32 SPCTL0, ACFG_SPCTL0_VAL > + > + write32 CSCR, ACFG_CSCR_VAL|CSCR_MPLL_RESTART|CSCR_SPLL_RESTART > + > + /* > + * add some delay here > + */ > + mov r1, #0x1000 > + 1: subs r1, r1, #0x1 > + bne 1b > + > + /* peripheral clock divider */ > + write32 PCDR0, ACFG_PCDR0_VAL > + write32 PCDR1, ACFG_PCDR1_VAL > + > + /* Configure PCCR0 and PCCR1 */ > + write32 PCCR0, ACFG_PCCR0_VAL > + write32 PCCR1, ACFG_PCCR1_VAL > + > + .endm /* init_clock */ > + > +/* > + ************************************************************************* > + * > + * No jump vector table. Use reset vector as direct entry point. > + * Do not support any interrupt event within SPL > + * > + ************************************************************************* > + */ > + > + > +.globl _start > +_start: > + > +/* > + ************************************************************************* > + * > + * Startup Code (reset vector) > + * > + * do important init only if we don't start from memory! > + * setup Memory and board specific bits prior to relocation. > + * relocate armboot to ram > + * setup stack > + * > + ************************************************************************* > + */ > + > + > +/* > + * 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 > + > + /* > + * invalidate I/D cache/TLB and drain write buffer > + */ > + mov r0, #0 > + mcr p15, 0, r0, c7, c7, 0 /* invalidate I cache and D cache */ > + mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ > + mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffer */ > + > + /* > + * disable MMU stuff and caches > + */ > + mrc p15, 0, r0, c1, c0, 0 > + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ > + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ > + orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ > + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ > + mcr p15, 0, r0, c1, c0, 0 > + > +init_aipi_start: > + init_aipi > + > + /* check if sdram has been setup (running within sdram) */ > + cmp pc, #0xa0000000 /* start of first sdram memory space */ > + blo init_clock_start > + cmp pc, #0xc0000000 /* end of second sdram memory space */ > + blo regular_boot > + > + /* running from sdram with full code present -> regular_boot */ > +init_clock_start: > + init_clock > + > +init_sdram_start: > + bl setup_sdram_ddr > + > + /* save state of previous boot (SDRAM is configured)*/ > + BACKUP_TRACE() > + > + /* nand_boot BOOT_TRACE(1..13) */ > + > + nand_boot > + > + BOOT_TRACE(14) /* start regular U-Boot */ > + > +regular_boot: /* jump to start of next 2kiB block (U-Boot) */ > + ldr r0, =0xfffff800 > + and r0, r0, pc > + add pc, r0, #0x800 > + > +do_wait_op_done: > + 1: > + ldrh r3, [r12, #NFC_OFFSET_CONFIG2] > + ands r3, r3, #NFC_CONFIG2_INT > + beq 1b > + mov r3, #0x0 > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + mov pc, lr > + > +do_addr_input: > + mov r9, lr > + and r3, r3, #0xFF > + strh r3, [r12, #NFC_OFFSET_FLASH_ADDR] > + mov r3, #NFC_CONFIG2_FADD > + strh r3, [r12, #NFC_OFFSET_CONFIG2] > + bl do_wait_op_done > + mov pc, r9 > + > +Test_And_Copy_Buffer: Please avoid mixed case identifiers. > + /* check for bad block (2 bits error in main or spare are)*/ > + BOOT_TRACE(9) > + ldrh r4, [r12, #NFC_OFFSET_ECC_STATUS_RESULT] > + ands r4, r4, #(NFC_ECC_STAT_ERROR2| \ > + (NFC_ECC_STAT_ERROR2<<NFC_ECC_STAT_ERM_SHFT)) > + bne Skip_Bad_Buffer > + > + /* check BI byte of the current spare buffer */ > + ldr r4, =IMX_NFC_SPARE_AREA0 > + ldrh r3, [r12, #NFC_OFFSET_BUF_ADDR] /* for the current buffer */ > + orr r4, r3, lsl #0x04 > + > + /* at bi word offset 4. */ > + /* Fixme position change betwwen 8 and 16 bits bus */ > + ldrh r4, [r4, #0x04] > + and r4, r4, #0x0FF00 /* has to be 0xFFxx */ > + cmp r4, #0x0FF00 > + bne Skip_Bad_Buffer > + > +Copy_Good_Buffer: > + /* copying 512 bytes buffer */ > + BOOT_TRACE(10) > +1: ldmia r0!, {r3-r10} > + stmia r11!, {r3-r10} > + cmp r0, r2 > + blo 1b > + b End_Of_Copy > + > +Skip_Bad_Buffer: > + BOOT_TRACE(11) > + /* bad pages do not contain valid data and have to be skip */ > + add r0, r0, #0x200 > + > + /* rewind ram addr to start of buffer */ > + ldr r3, =(~0x1FF) > + and r11, r11, r3 > + > +End_Of_Copy: > + add r2, r2, #0x200 > + add r1, r1, #0x200 > + > + mov pc, lr > + > + > +setup_sdram_ddr: > + > + /* wait for SDRAM/LPDDR ready (SDRAMRDY) */ > + ldr r0, =IMX_ESD_BASE > + ldr r4, =ESDMISC_SDRAM_RDY > +2: ldr r1, [r0, #ESDMISC_ROF] > + ands r1, r1, r4 > + bpl 2b > + > + /* LPDDR Soft Reset Mobile/Low Power DDR SDRAM. */ > + ldr r0, =IMX_ESD_BASE > + ldr r4, =ACFG_ESDMISC_VAL > + orr r1, r4, #ESDMISC_MDDR_DL_RST > + str r1, [r0, #ESDMISC_ROF] > + > + /* Hold for more than 200ns */ > + ldr r1, =0x10000 > + 1: subs r1, r1, #0x1 > + bne 1b > + > + str r4, [r0] > + > + /* write32(ESDCFG0, ACFG_SDRAM_ESDCFG_REGISTER_VAL) */ Please avoid comments that paraphrase ASM in pseudo-C. Either remove them or replace them with something that the ASM does not also say. > + ldr r0, =IMX_ESD_BASE > + ldr r1, =ACFG_SDRAM_ESDCFG_REGISTER_VAL > + str r1, [r0, #ESDCFG0_ROF] > + > + /* write32(ESDCTL0, ACFG_PRECHARGE_CMD) */ > + ldr r0, =IMX_ESD_BASE > + ldr r1, =ACFG_PRECHARGE_CMD > + str r1, [r0, #ESDCTL0_ROF] > + > + /* write8(0xA0001000, any value) */ > + ldr r1, =PHYS_SDRAM_1+ACFG_SDRAM_PRECHARGE_ALL_VAL > + strb r2, [r1] > + > + /* write32(ESDCTL0, ACFG_AUTOREFRESH_CMD) */ > + ldr r1, =ACFG_AUTOREFRESH_CMD > + str r1, [r0, #ESDCTL0_ROF] > + > + ldr r4, =PHYS_SDRAM_1 /* CSD0 base address */ > + > + ldr r6,=0x7 /* load loop counter */ > +1: str r5,[r4] /* run auto-refresh cycle to array 0 */ > + subs r6,r6,#1 /* decrease counter value */ > + bne 1b > + > + /* write32(ACFG_PRECHARGE_CMD, ACFG_SET_MODE_REG_CMD) */ > + ldr r1, =ACFG_SET_MODE_REG_CMD > + str r1, [r0, #ESDCTL0_ROF] > + > + /* set standard mode register */ > + ldr r4, = PHYS_SDRAM_1+ACFG_SDRAM_MODE_REGISTER_VAL > + strb r2, [r4] > + > + /* set extended mode register */ > + ldr r4, =PHYS_SDRAM_1+ACFG_SDRAM_EXT_MODE_REGISTER_VAL > + strb r5, [r4] > + > + /* write32(ACFG_PRECHARGE_CMD, ACFG_NORMAL_RW_CMD) */ > + ldr r1, =ACFG_NORMAL_RW_CMD > + str r1, [r0, #ESDCTL0_ROF] > + > + /* 2nd sdram */ > + /* write32(ESDCFG1, ACFG_SDRAM_ESDCFG_REGISTER_VAL ) */ > + ldr r0, =IMX_ESD_BASE > + ldr r1, =ACFG_SDRAM_ESDCFG_REGISTER_VAL > + str r1, [r0, #ESDCFG1_ROF] > + > + /* write32(ESDCTL1, ACFG_PRECHARGE_CMD) */ > + ldr r0, =IMX_ESD_BASE > + ldr r1, =ACFG_PRECHARGE_CMD > + str r1, [r0, #ESDCTL1_ROF] > + > + /* write8(0xB0001000, any value) */ > + ldr r1, =PHYS_SDRAM_2+ACFG_SDRAM_PRECHARGE_ALL_VAL > + strb r2, [r1] > + > + /* write32(ESDCTL1, ACFG_AUTOREFRESH_CMD) */ > + ldr r1, =ACFG_AUTOREFRESH_CMD > + str r1, [r0, #ESDCTL1_ROF] > + > + ldr r4, =PHYS_SDRAM_2 /* CSD1 base address */ > + > + ldr r6,=0x7 /* load loop counter */ > +1: str r5,[r4] /* run auto-refresh cycle to array 0 */ > + subs r6,r6,#1 /* decrease counter value */ > + bne 1b > + > + /* write32(ESDCTL1, ACFG_SET_MODE_REG_CMD) */ > + ldr r1, =ACFG_SET_MODE_REG_CMD > + str r1, [r0, #ESDCTL1_ROF] > + > + /* set standard mode register */ > + ldr r4, =PHYS_SDRAM_2+ACFG_SDRAM_MODE_REGISTER_VAL > + strb r2, [r4] > + > + /* set extended mode register */ > + ldr r4, =PHYS_SDRAM_2+ACFG_SDRAM_EXT_MODE_REGISTER_VAL > + strb r2, [r4] > + > + /* write32(ESDCTL1, ACFG_NORMAL_RW_CMD) */ > + ldr r1, =ACFG_NORMAL_RW_CMD > + str r1, [r0, #ESDCTL1_ROF] > + > + mov pc, lr > + > diff --git a/board/armadeus/apf27/u-boot-spl.lds b/board/armadeus/apf27/u-boot-spl.lds > new file mode 100644 > index 0000000..fdd52f2 > --- /dev/null > +++ b/board/armadeus/apf27/u-boot-spl.lds > @@ -0,0 +1,87 @@ > +/* > + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> > + * on behalf of DENX Software Engineering GmbH > + * > + * January 2004 - Changed to support H4 device > + * Copyright (c) 2004-2008 Texas Instruments > + * > + * (C) Copyright 2002 > + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.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 > + */ > + > +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") > +OUTPUT_ARCH(arm) > +ENTRY(_start) > +SECTIONS > +{ > + . = 0xA0fff800; > + > + . = ALIGN(4); > + .text : > + { > + board/armadeus/apf27/start.o (.text) > + *(.text) > + } > + > + . = ALIGN(4); > + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } > + > + . = ALIGN(4); > + .data : { > + *(.data) > + } > + > + . = ALIGN(4); > + __u_boot_cmd_start = .; > + .u_boot_cmd : { *(.u_boot_cmd) } > + __u_boot_cmd_end = .; > + > + . = ALIGN(4); > + > + .rel.dyn : { > + __rel_dyn_start = .; > + *(.rel*) > + __rel_dyn_end = .; > + } > + > + .dynsym : { > + __dynsym_start = .; > + *(.dynsym) > + } > + > + .bss : { > + . = ALIGN(4); > + __bss_start = .; > + *(.bss*) > + . = ALIGN(4); > + __bss_end__ = .; > + } > + > + _end = .; > + > + /DISCARD/ : { *(.dynstr*) } > + /DISCARD/ : { *(.dynsym*) } > + /DISCARD/ : { *(.dynamic*) } > + /DISCARD/ : { *(.hash*) } > + /DISCARD/ : { *(.plt*) } > + /DISCARD/ : { *(.interp*) } > + /DISCARD/ : { *(.gnu*) } > +} Amicalement,
On 26/11/12 19:02, Albert ARIBAUD wrote: > Hi Philippe, > > On Mon, 29 Oct 2012 18:35:56 +0100, Philippe Reynes<tremyfr@yahoo.fr> > wrote: > >> Signed-off-by: Philippe Reynes<tremyfr@yahoo.fr> >> Signed-off-by: Eric Jarrige<eric.jarrige@armadeus.org> >> >> create mode 100644 board/armadeus/apf27/start.S >> create mode 100644 board/armadeus/apf27/u-boot-spl.lds > > This is needed by 2/4 to get truly useable support. Please merge both > patches. I've done it, and send a v3 this weed-end. Thanks a lot for the review. regards, Philippe
diff --git a/board/armadeus/apf27/Makefile b/board/armadeus/apf27/Makefile index 1da9548..f57f405 100644 --- a/board/armadeus/apf27/Makefile +++ b/board/armadeus/apf27/Makefile @@ -27,11 +27,14 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).o +ifndef CONFIG_SPL_BUILD COBJS := apf27.o +endif -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) SOBJS := $(addprefix $(obj),$(SOBJS)) +START := $(addprefix $(obj),$(START)) $(LIB): $(obj).depend $(OBJS) $(SOBJS) $(call cmd_link_o_target, $(OBJS) $(SOBJS)) diff --git a/board/armadeus/apf27/start.S b/board/armadeus/apf27/start.S new file mode 100644 index 0000000..374b4ea --- /dev/null +++ b/board/armadeus/apf27/start.S @@ -0,0 +1,549 @@ +/* + * IMX27 NAND Flash SPL (Secondary Program Loader) + * + * Copyright (c) 2008 Armadeus Project / eja + * + * Based on Freescale NAND SPL + * + * Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. + * Copyright (c) 2008-2012 Eric Jarrige <eric.jarrige@armadeus.org> + * + * 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 + */ + + +#include <config.h> +#include <version.h> +#include <asm/macro.h> +#include <asm/arch/mxc_nand.h> +#include <asm/arch/imx-regs.h> +#include <generated/asm-offsets.h> +#include "apf27.h" + +/* + * Standard NAND flash commands + */ +#define NAND_CMD_READ0 0 +#define NAND_CMD_READ1 1 +#define NAND_CMD_PAGEPROG 0x10 +#define NAND_CMD_READOOB 0x50 +#define NAND_CMD_ERASE1 0x60 +#define NAND_CMD_STATUS 0x70 +#define NAND_CMD_STATUS_MULTI 0x71 +#define NAND_CMD_SEQIN 0x80 +#define NAND_CMD_READID 0x90 +#define NAND_CMD_ERASE2 0xd0 +#define NAND_CMD_RESET 0xff + +/* Extended commands for large page devices */ +#define NAND_CMD_READSTART 0x30 +#define NAND_CMD_CACHEDPROG 0x15 + +/* Status bits */ +#define NAND_STATUS_FAIL 0x01 +#define NAND_STATUS_FAIL_N1 0x02 +#define NAND_STATUS_TRUE_READY 0x20 +#define NAND_STATUS_READY 0x40 +#define NAND_STATUS_WP 0x80 + + .macro nand_boot + +#ifdef CONFIG_BOOT_TRACE_REG +/* + * If CONFIG_BOOT_TRACE_REG is a SDRAM address then be sure to use the following + * 2 command after SDRAM init + */ + +/* Backup state of previous boot to CONFIG_BOOT_TRACE_REG+4*/ +#define BACKUP_TRACE() \ + ldr r4, =CONFIG_BOOT_TRACE_REG; \ + ldr r3, [r4]; \ + str r3, [r4, #0x04]; + +/* Save a state of boot at CONFIG_BOOT_TRACE_REG */ +#define BOOT_TRACE(val) \ + ldr r4, =CONFIG_BOOT_TRACE_REG; \ + ldr r3, =val; \ + str r3, [r4]; +#else +#define BACKUP_TRACE() +#define BOOT_TRACE(val) +#endif + +nand_boot_setup: + + /* Copy SPL image from flash to SDRAM first */ + BOOT_TRACE(1) + ldr r0, =IMX_NFC_MAIN_AREA0 + add r2, r0, #(IMX_NFC_SPARE_AREA0-IMX_NFC_MAIN_AREA0) //2KB NFC Buff + ldr r1, =CONFIG_SYS_NAND_U_BOOT_DST + + BOOT_TRACE(2) +1: ldmia r0!, {r3-r10} + stmia r1!, {r3-r10} + cmp r0, r2 + blo 1b + + + + /* Jump to SDRAM */ + BOOT_TRACE(3) + ldr r1, =0x7FF + and r0, pc, r1 /* offset of pc */ + ldr r1, =CONFIG_SYS_NAND_U_BOOT_DST + add r1, r1, #0x10 + add pc, r0, r1 + nop + nop + nop + nop + +NAND_Copy_Main: + BOOT_TRACE(4) + /* r0: nfc base. Reloaded after each page copying */ + ldr r0, =IMX_NFC_MAIN_AREA0 + + /* r1: starting flash addr to be copied. Updated constantly */ + /* bypass the first preloaded pages */ + ldr r1, =(IMX_NFC_SPARE_AREA0-IMX_NFC_MAIN_AREA0) + + /* r2: end of 1st RAM buf. Doesn't change */ + ldr r2, =IMX_NFC_MAIN_AREA1 + + /* r12: NFC register base. Doesn't change */ + ldr r12, =IMX_NFC_REGS + + ldr r11, =CONFIG_SYS_NAND_U_BOOT_DST + + /* r13: end of SDRAM address for copying. Doesn't change */ + add r13, r11, #CONFIG_SYS_NAND_U_BOOT_SIZE + + /* r11: starting SDRAM address for copying. Updated constantly */ + add r11, r11, r1 + + /* unlock internal buffer */ + ldr r3, =NFC_CONFIG_UNLOCKED + strh r3, [r12, #NFC_OFFSET_CONFIG] + + /* enable ECC and mask interrupts */ + ldr r3, =(NFC_CONFIG1_ECC_EN | NFC_CONFIG1_INT_MSK) + strh r3, [r12, #NFC_OFFSET_CONFIG1] + +Nfc_Read_Page: + BOOT_TRACE(5) + /* send NAND_CMD_READ0 command */ + ldr r3, =NAND_CMD_READ0; + strh r3, [r12, #NFC_OFFSET_FLASH_CMD] + + ldr r3, =NFC_CONFIG2_FCMD + strh r3, [r12, #NFC_OFFSET_CONFIG2] + bl do_wait_op_done + + /* send NAND address to read. TODO small page support */ + BOOT_TRACE(6) + mov r3, r1, lsr #1 + bl do_addr_input /* 1st addr cycle */ + + mov r3, r1, lsr #9 + and r3, r3, #0x03 + bl do_addr_input /* 2nd addr cycle */ + + mov r3, r1, lsr #11 + bl do_addr_input /* 3rd addr cycle */ + + mov r3, r1, lsr #19 + bl do_addr_input /* 4th addr cycle */ + + /* Small NAND flashs (== 1Gb) support 5 addr cycles */ + mov r3, r1, lsr #27 + bl do_addr_input /* 5th addr cycle */ + + /* send NAND_CMD_READSTART command. TODO small page support */ + BOOT_TRACE(7) + mov r3, #NAND_CMD_READSTART; + strh r3, [r12, #NFC_OFFSET_FLASH_CMD] + mov r3, #NFC_CONFIG2_FCMD + strh r3, [r12, #NFC_OFFSET_CONFIG2] + bl do_wait_op_done + + /* read and copy buf 0 */ + BOOT_TRACE(8) + mov r3, #0 + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] + + mov r3, #NFC_CONFIG2_FDO_PAGE + strh r3, [r12, #NFC_OFFSET_CONFIG2] + bl do_wait_op_done + + bl Test_And_Copy_Buffer + + /* read and copy buf 1 */ + mov r3, #1 + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] + + mov r3, #NFC_CONFIG2_FDO_PAGE + strh r3, [r12, #NFC_OFFSET_CONFIG2] + bl do_wait_op_done + + bl Test_And_Copy_Buffer + + /* here we should test if 512B page flash and bypass next buffers */ + /* read and copy buf 2. TODO small page support */ + mov r3, #2 + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] + + mov r3, #NFC_CONFIG2_FDO_PAGE + strh r3, [r12, #NFC_OFFSET_CONFIG2] + bl do_wait_op_done + + bl Test_And_Copy_Buffer + + /* read and copy buf 3 */ + mov r3, #3 + strh r3, [r12, #NFC_OFFSET_BUF_ADDR] + + mov r3, #NFC_CONFIG2_FDO_PAGE + strh r3, [r12, #NFC_OFFSET_CONFIG2] + bl do_wait_op_done + + bl Test_And_Copy_Buffer + + /* is the last page ? */ + BOOT_TRACE(12) + cmp r11, r13 + bge NAND_Copy_Main_done + + /* r0: nfc base. Reloaded after each page copying */ + ldr r0, =IMX_NFC_MAIN_AREA0 + /* r2: end of 1st RAM buf. Doesn't change */ + ldr r2, =IMX_NFC_MAIN_AREA1 + b Nfc_Read_Page + +NAND_Copy_Main_done: + BOOT_TRACE(13) + .endm /* nand_boot */ + + .macro init_aipi + /* + * setup AIPI1 and AIPI2 + */ + write32 AIPI1_PSR0, ACFG_AIPI1_PSR0_VAL + write32 AIPI1_PSR1, ACFG_AIPI1_PSR1_VAL + write32 AIPI2_PSR0, ACFG_AIPI2_PSR0_VAL + write32 AIPI2_PSR1, ACFG_AIPI2_PSR1_VAL + + /* Change SDRAM signal strengh */ + ldr r0, =GPCR + ldr r1, =ACFG_GPCR_VAL + ldr r5, [r0] + orr r5, r5, r1 + str r5, [r0] + + .endm /* init_aipi */ + + .macro init_clock + ldr r0, =CSCR + /* disable MPLL/SPLL first */ + ldr r1, [r0] + bic r1, r1, #(CSCR_MPEN|CSCR_SPEN) + str r1, [r0] + + /* + * pll clock initialization predefined in apf27.h + */ + write32 MPCTL0, ACFG_MPCTL0_VAL + write32 SPCTL0, ACFG_SPCTL0_VAL + + write32 CSCR, ACFG_CSCR_VAL|CSCR_MPLL_RESTART|CSCR_SPLL_RESTART + + /* + * add some delay here + */ + mov r1, #0x1000 + 1: subs r1, r1, #0x1 + bne 1b + + /* peripheral clock divider */ + write32 PCDR0, ACFG_PCDR0_VAL + write32 PCDR1, ACFG_PCDR1_VAL + + /* Configure PCCR0 and PCCR1 */ + write32 PCCR0, ACFG_PCCR0_VAL + write32 PCCR1, ACFG_PCCR1_VAL + + .endm /* init_clock */ + +/* + ************************************************************************* + * + * No jump vector table. Use reset vector as direct entry point. + * Do not support any interrupt event within SPL + * + ************************************************************************* + */ + + +.globl _start +_start: + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + + +/* + * 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 + + /* + * invalidate I/D cache/TLB and drain write buffer + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* invalidate I cache and D cache */ + mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ + mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffer */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ + orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + +init_aipi_start: + init_aipi + + /* check if sdram has been setup (running within sdram) */ + cmp pc, #0xa0000000 /* start of first sdram memory space */ + blo init_clock_start + cmp pc, #0xc0000000 /* end of second sdram memory space */ + blo regular_boot + + /* running from sdram with full code present -> regular_boot */ +init_clock_start: + init_clock + +init_sdram_start: + bl setup_sdram_ddr + + /* save state of previous boot (SDRAM is configured)*/ + BACKUP_TRACE() + + /* nand_boot BOOT_TRACE(1..13) */ + + nand_boot + + BOOT_TRACE(14) /* start regular U-Boot */ + +regular_boot: /* jump to start of next 2kiB block (U-Boot) */ + ldr r0, =0xfffff800 + and r0, r0, pc + add pc, r0, #0x800 + +do_wait_op_done: + 1: + ldrh r3, [r12, #NFC_OFFSET_CONFIG2] + ands r3, r3, #NFC_CONFIG2_INT + beq 1b + mov r3, #0x0 + strh r3, [r12, #NFC_OFFSET_CONFIG2] + mov pc, lr + +do_addr_input: + mov r9, lr + and r3, r3, #0xFF + strh r3, [r12, #NFC_OFFSET_FLASH_ADDR] + mov r3, #NFC_CONFIG2_FADD + strh r3, [r12, #NFC_OFFSET_CONFIG2] + bl do_wait_op_done + mov pc, r9 + +Test_And_Copy_Buffer: + /* check for bad block (2 bits error in main or spare are)*/ + BOOT_TRACE(9) + ldrh r4, [r12, #NFC_OFFSET_ECC_STATUS_RESULT] + ands r4, r4, #(NFC_ECC_STAT_ERROR2| \ + (NFC_ECC_STAT_ERROR2<<NFC_ECC_STAT_ERM_SHFT)) + bne Skip_Bad_Buffer + + /* check BI byte of the current spare buffer */ + ldr r4, =IMX_NFC_SPARE_AREA0 + ldrh r3, [r12, #NFC_OFFSET_BUF_ADDR] /* for the current buffer */ + orr r4, r3, lsl #0x04 + + /* at bi word offset 4. */ + /* Fixme position change betwwen 8 and 16 bits bus */ + ldrh r4, [r4, #0x04] + and r4, r4, #0x0FF00 /* has to be 0xFFxx */ + cmp r4, #0x0FF00 + bne Skip_Bad_Buffer + +Copy_Good_Buffer: + /* copying 512 bytes buffer */ + BOOT_TRACE(10) +1: ldmia r0!, {r3-r10} + stmia r11!, {r3-r10} + cmp r0, r2 + blo 1b + b End_Of_Copy + +Skip_Bad_Buffer: + BOOT_TRACE(11) + /* bad pages do not contain valid data and have to be skip */ + add r0, r0, #0x200 + + /* rewind ram addr to start of buffer */ + ldr r3, =(~0x1FF) + and r11, r11, r3 + +End_Of_Copy: + add r2, r2, #0x200 + add r1, r1, #0x200 + + mov pc, lr + + +setup_sdram_ddr: + + /* wait for SDRAM/LPDDR ready (SDRAMRDY) */ + ldr r0, =IMX_ESD_BASE + ldr r4, =ESDMISC_SDRAM_RDY +2: ldr r1, [r0, #ESDMISC_ROF] + ands r1, r1, r4 + bpl 2b + + /* LPDDR Soft Reset Mobile/Low Power DDR SDRAM. */ + ldr r0, =IMX_ESD_BASE + ldr r4, =ACFG_ESDMISC_VAL + orr r1, r4, #ESDMISC_MDDR_DL_RST + str r1, [r0, #ESDMISC_ROF] + + /* Hold for more than 200ns */ + ldr r1, =0x10000 + 1: subs r1, r1, #0x1 + bne 1b + + str r4, [r0] + + /* write32(ESDCFG0, ACFG_SDRAM_ESDCFG_REGISTER_VAL) */ + ldr r0, =IMX_ESD_BASE + ldr r1, =ACFG_SDRAM_ESDCFG_REGISTER_VAL + str r1, [r0, #ESDCFG0_ROF] + + /* write32(ESDCTL0, ACFG_PRECHARGE_CMD) */ + ldr r0, =IMX_ESD_BASE + ldr r1, =ACFG_PRECHARGE_CMD + str r1, [r0, #ESDCTL0_ROF] + + /* write8(0xA0001000, any value) */ + ldr r1, =PHYS_SDRAM_1+ACFG_SDRAM_PRECHARGE_ALL_VAL + strb r2, [r1] + + /* write32(ESDCTL0, ACFG_AUTOREFRESH_CMD) */ + ldr r1, =ACFG_AUTOREFRESH_CMD + str r1, [r0, #ESDCTL0_ROF] + + ldr r4, =PHYS_SDRAM_1 /* CSD0 base address */ + + ldr r6,=0x7 /* load loop counter */ +1: str r5,[r4] /* run auto-refresh cycle to array 0 */ + subs r6,r6,#1 /* decrease counter value */ + bne 1b + + /* write32(ACFG_PRECHARGE_CMD, ACFG_SET_MODE_REG_CMD) */ + ldr r1, =ACFG_SET_MODE_REG_CMD + str r1, [r0, #ESDCTL0_ROF] + + /* set standard mode register */ + ldr r4, = PHYS_SDRAM_1+ACFG_SDRAM_MODE_REGISTER_VAL + strb r2, [r4] + + /* set extended mode register */ + ldr r4, =PHYS_SDRAM_1+ACFG_SDRAM_EXT_MODE_REGISTER_VAL + strb r5, [r4] + + /* write32(ACFG_PRECHARGE_CMD, ACFG_NORMAL_RW_CMD) */ + ldr r1, =ACFG_NORMAL_RW_CMD + str r1, [r0, #ESDCTL0_ROF] + + /* 2nd sdram */ + /* write32(ESDCFG1, ACFG_SDRAM_ESDCFG_REGISTER_VAL ) */ + ldr r0, =IMX_ESD_BASE + ldr r1, =ACFG_SDRAM_ESDCFG_REGISTER_VAL + str r1, [r0, #ESDCFG1_ROF] + + /* write32(ESDCTL1, ACFG_PRECHARGE_CMD) */ + ldr r0, =IMX_ESD_BASE + ldr r1, =ACFG_PRECHARGE_CMD + str r1, [r0, #ESDCTL1_ROF] + + /* write8(0xB0001000, any value) */ + ldr r1, =PHYS_SDRAM_2+ACFG_SDRAM_PRECHARGE_ALL_VAL + strb r2, [r1] + + /* write32(ESDCTL1, ACFG_AUTOREFRESH_CMD) */ + ldr r1, =ACFG_AUTOREFRESH_CMD + str r1, [r0, #ESDCTL1_ROF] + + ldr r4, =PHYS_SDRAM_2 /* CSD1 base address */ + + ldr r6,=0x7 /* load loop counter */ +1: str r5,[r4] /* run auto-refresh cycle to array 0 */ + subs r6,r6,#1 /* decrease counter value */ + bne 1b + + /* write32(ESDCTL1, ACFG_SET_MODE_REG_CMD) */ + ldr r1, =ACFG_SET_MODE_REG_CMD + str r1, [r0, #ESDCTL1_ROF] + + /* set standard mode register */ + ldr r4, =PHYS_SDRAM_2+ACFG_SDRAM_MODE_REGISTER_VAL + strb r2, [r4] + + /* set extended mode register */ + ldr r4, =PHYS_SDRAM_2+ACFG_SDRAM_EXT_MODE_REGISTER_VAL + strb r2, [r4] + + /* write32(ESDCTL1, ACFG_NORMAL_RW_CMD) */ + ldr r1, =ACFG_NORMAL_RW_CMD + str r1, [r0, #ESDCTL1_ROF] + + mov pc, lr + diff --git a/board/armadeus/apf27/u-boot-spl.lds b/board/armadeus/apf27/u-boot-spl.lds new file mode 100644 index 0000000..fdd52f2 --- /dev/null +++ b/board/armadeus/apf27/u-boot-spl.lds @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * January 2004 - Changed to support H4 device + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0xA0fff800; + + . = ALIGN(4); + .text : + { + board/armadeus/apf27/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data) + } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + + .dynsym : { + __dynsym_start = .; + *(.dynsym) + } + + .bss : { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end__ = .; + } + + _end = .; + + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynsym*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.hash*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +}