From mboxrd@z Thu Jan 1 00:00:00 1970 From: trem Date: Thu, 01 Aug 2013 19:12:53 +0200 Subject: [U-Boot] [PATCH v4 2/4] apf27: add support for the armadeus APF27 board In-Reply-To: <51F6392B.5000503@denx.de> References: <1375042616-24680-1-git-send-email-tremyfr@yahoo.fr> <1375042616-24680-3-git-send-email-tremyfr@yahoo.fr> <51F6392B.5000503@denx.de> Message-ID: <51FA9715.30905@yahoo.fr> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Stefano, On 29/07/13 11:43, Stefano Babic wrote: >> diff --git a/board/armadeus/apf27/splboot.S b/board/armadeus/apf27/splboot.S >> new file mode 100644 >> index 0000000..898e59b >> --- /dev/null >> +++ b/board/armadeus/apf27/splboot.S >> @@ -0,0 +1,528 @@ >> +/* >> + * 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 >> + * >> + * 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 >> +#include >> +#include >> +#include >> +#include >> +/* #include */ >> +#include "apf27.h" >> + >> +/* >> + * Standard NAND flash commands >> + */ >> +#define NAND_CMD_READ0 0 >> + >> +/* 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 >> + >> +#define IMX_NFC_MAIN_AREA0 (0xD8000000) >> +#define IMX_NFC_MAIN_AREA1 (0xD8000200) >> +#define IMX_NFC_SPARE_AREA0 (0xD8000800) >> +#define IMX_NFC_REGS (0xD8000E00) >> + >> +/* >> + * NFC registers address offset >> + */ >> +#define NFC_OFFSET_BUF_ADDR (0x04) /* Buffer Number for Page Data >> + Transfer To/From Flash Mem */ >> +#define NFC_OFFSET_FLASH_ADDR (0x06) /* NAND Flash Address */ >> +#define NFC_OFFSET_FLASH_CMD (0x08) /* NAND Flash Command */ >> +#define NFC_OFFSET_CONFIG (0x0A) /* NFC Internal Buffer Lock >> + Control */ >> +#define NFC_OFFSET_ECC_STATUS_RESULT (0x0C) /* Controller Status/Result of >> + Flash Operation */ >> +#define NFC_OFFSET_CONFIG1 (0x1A) /* Nand Flash Operation >> + Configuration 1 */ >> +#define NFC_OFFSET_CONFIG2 (0x1C) /* Nand Flash Operation >> + Configuration 2 */ >> + >> +/* NFC_ECC_STATUS_RESULT Status Register Bit Fields */ >> +#define NFC_ECC_STAT_ERM_SHFT (2) /* ERM shift */ >> +#define NFC_ECC_STAT_ERROR2 (1<<1) /* non correctable error */ >> + >> +/* NFC_CONFIG Control Register Bit Fields */ >> +#define NFC_CONFIG_UNLOCKED (1<<1) /* unlocked */ >> + >> +/* NFC_CONFIG1 Control Register Bit Fields */ >> +#define NFC_CONFIG1_ECC_EN (1<<3) >> +#define NFC_CONFIG1_INT_MSK (1<<4) >> + >> +/* NFC_CONFIG2 Control Register Bit Fields */ >> +#define NFC_CONFIG2_INT (1<<15) /* Interrupt */ >> +#define NFC_CONFIG2_FDO_PAGE (1<<3) /* Flash data output */ >> +#define NFC_CONFIG2_FDI (1<<2) /* Flash data input */ >> +#define NFC_CONFIG2_FADD (1<<1) /* Flash address input */ >> +#define NFC_CONFIG2_FCMD (1<<0) /* Flash command input */ > > Using SPL, the storage driver (in your case, NAND) is not a special one, > but the usual driver from u-boot is taken. In this case, code in > mxc_nand, that supports mx27, should run. Instead of it, you embedded > your own (ok, from Freescale code) driver in assembly. Is there any > reason that forbid to take the general driver ? > > >> + >> + .macro nand_boot >> + >> +#ifdef CONFIG_BOOT_TRACE_REG > > According to README: each define whose name starts with CONFIG_ is an > option - it can use generally in U-Boot code and must be documented. > If your goal was to add something related to apf27 only, do not use a > CONFIG_ name or add documentation for it. > >> +/* >> + * 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 > > Everything seems to me only for debug purpose. But does not work > CONFIG_SPL_CONSOLE and CONFIG_SPL_SERIAL_SUPPORT ? > >> + >> +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 */ >> + > > Well, this code makes what the driver for NAND is supposed to do. Yes, this is a nand driver written in asm. The goal is the have a spl smaller than 2 KB. > >> +.globl board_init_f >> +board_init_f: >> + >> + /* >> + * 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 >> + > > Ok, this must be done in assembly - normally is part of lowelevel_init, > while board_init_f() is already written in C. > > Really I was waiting that general code is called, that is > spl_nand_load_image() and then the driver function. You are pushing a > parallel way that is, at the end, still the old way to boot (nand_spl). This board boot from nand, so the SPL should be lower than 2KB. The SPL start from NFC (nand) buffer, and It has to : - initialize the ram - copy itself to another location (ram) - jump to this another location - copy u-boot from nand to ram - jump to ram We have tried to use SPL framework (with nand driver), but the result is a SPL bigger than 2 KB, so we can't use it. To have a SPL smaller than 2 KB, we have written everything in assembler. Are you agree with this solution for the SPL ? >> +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<> + 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] >> + >> + ldr r0, =IMX_ESD_BASE >> + ldr r1, =ACFG_SDRAM_ESDCFG_REGISTER_VAL >> + str r1, [r0, #ESDCFG0_ROF] >> + >> + 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] >> + >> + 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 >> + bne 1b >> + >> + 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] >> + >> + ldr r1, =ACFG_NORMAL_RW_CMD >> + str r1, [r0, #ESDCTL0_ROF] >> + >> + /* 2nd sdram */ >> + ldr r0, =IMX_ESD_BASE >> + ldr r1, =ACFG_SDRAM_ESDCFG_REGISTER_VAL >> + str r1, [r0, #ESDCFG1_ROF] >> + >> + 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] >> + >> + 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 >> + bne 1b >> + >> + 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] >> + >> + ldr r1, =ACFG_NORMAL_RW_CMD >> + str r1, [r0, #ESDCTL1_ROF] >> + >> + mov pc, lr Best regards, Philippe