
This code is executed from internal 2KB NAND Flash Controller RAM buffer and will copy the remaining U-Boot code from NAND Flash verifying its bad blocks (case it exists).
Signed-off-by: Alan Carvalho de Assis alan.assis@freescale.com --- cpu/arm1136/mx31/Makefile | 2 + cpu/arm1136/mx31/nand_copy.S | 263 +++++++++++++++++++++++++++++++++ include/asm-arm/arch-mx31/mx31-regs.h | 69 +++++++++ 3 files changed, 334 insertions(+), 0 deletions(-) create mode 100644 cpu/arm1136/mx31/nand_copy.S
diff --git a/cpu/arm1136/mx31/Makefile b/cpu/arm1136/mx31/Makefile index b648ffd..0490706 100644 --- a/cpu/arm1136/mx31/Makefile +++ b/cpu/arm1136/mx31/Makefile @@ -26,7 +26,9 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).a
COBJS = interrupts.o serial.o generic.o +SOBJS-$(CONFIG_BOOT_FROM_NAND) = nand_copy.o
+SOBJS := $(SOBJS-y) SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/arm1136/mx31/nand_copy.S b/cpu/arm1136/mx31/nand_copy.S new file mode 100644 index 0000000..7a2460c --- /dev/null +++ b/cpu/arm1136/mx31/nand_copy.S @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. + * + * Alan Carvalho de Assis alan.assis@freescale.com + * based on iMX31PDK RedBoot_200814 code. + * + * 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 <asm/arch/mx31-regs.h> + +.macro do_addr_input + and r3, r3, #0xFF + strh r3, [r12, #NFC_FLASH_ADDR_OFF] + mov r3, #NAND_FLASH_CONFIG2_FADD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done +.endm /* do_addr_input */ + +do_wait_op_done: +1: ldrh r3, [r12, #NFC_CONFIG2_OFF] + ands r3, r3, #NAND_FLASH_CONFIG2_INT_DONE + beq 1b + bx lr + +nfc_data_output: + mov r3, #(NAND_FLASH_CONFIG1_INT_MSK | NAND_FLASH_CONFIG1_ECC_EN) + strh r3, [r12, #NFC_CONFIG1_OFF] + strh r8, [r12, #NFC_BUF_ADDR_OFF] + mov r3, #FDO_PAGE_SPARE_VAL + strh r3, [r12, #NFC_CONFIG2_OFF] + bx lr + +.globl nand_copy +nand_copy: + /* Copy image from flash to SDRAM first */ + mov r0, #NFC_BASE_ADDR + add r2, r0, #0x800 /* 2K window */ + ldr r1, MXC_UBOOT_ROM_START + +1: ldmia r0!, {r3-r10} + stmia r1!, {r3-r10} + cmp r0, r2 + blo 1b + /* Jump to SDRAM */ + ldr r1, =0x0FFF + and r0, pc, r1 /* offset of pc */ + ldr r1, MXC_UBOOT_ROM_START + add r1, r1, #0x10 + add pc, r0, r1 + nop + nop + nop + nop + +nand_copy_main: + /* Check if x16/2kb page */ + ldr r7, =CCM_BASE + ldr r7, [r7, #0xC] + ands r7, r7, #(1 << 30) + + mov r0, #NAND_FLASH_BOOT + ldr r1, =AVIC_VECTOR0 + str r0, [r1] + mov r0, #MXCFIS_NAND + ldr r1, =AVIC_VECTOR1 + str r0, [r1] + + mov r0, #NFC_BASE_ADDR /* r0: nfc base. Reloaded after each page copying */ + mov r1, #0x800 /* r1: starting flash addr to be copied. Updated constantly */ + add r2, r0, #0x800 /* r2: end of 3rd RAM buf. Doesn't change */ + addeq r2, r0, #0x200 /* r2: end of 1st RAM buf. Doesn't change (only set for small page NAND) */ + add r12, r0, #0xE00 /* r12: NFC register base. Doesn't change */ + ldr r11, MXC_UBOOT_ROM_START + add r13, r11, #0x40000 /* r13: end of SDRAM address for copying. Doesn't change */ + add r11, r11, r1 /* r11: starting SDRAM address for copying. Updated constantly */ + + /* unlock internal buffer */ + mov r3, #0x2 + strh r3, [r12, #0xA] + +nfc_read_page: + mov r3, #0x0 + strh r3, [r12, #NFC_FLASH_CMD_OFF] + mov r3, #NAND_FLASH_CONFIG2_FCMD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done + + /* Check if x16/2kb page */ + ldr r7, =CCM_BASE + ldr r7, [r7, #0xC] + ands r7, r7, #(1 << 30) + bne nfc_addr_ops_2kb + + /* 1st addr cycle */ + mov r3, r1 + do_addr_input + /* 1st addr cycle */ + mov r3, r1, lsr #9 + do_addr_input + /* 1st addr cycle */ + mov r3, r1, lsr #17 + do_addr_input + /* 1st addr cycle */ + mov r3, r1, lsr #25 + do_addr_input + b end_of_nfc_addr_ops + +nfc_addr_ops_2kb: + /* 1st addr cycle */ + mov r3, #0 + and r3, r3, #0xFF + strh r3, [r12, #NFC_FLASH_ADDR_OFF] + mov r3, #NAND_FLASH_CONFIG2_FADD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done + mov r3, #0 + /* 2nd addr cycle */ + and r3, r3, #0xFF + strh r3, [r12, #NFC_FLASH_ADDR_OFF] + mov r3, #NAND_FLASH_CONFIG2_FADD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done + mov r3, r1, lsr #11 + /* 3rd addr cycle */ + and r3, r3, #0xFF + strh r3, [r12, #NFC_FLASH_ADDR_OFF] + mov r3, #NAND_FLASH_CONFIG2_FADD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done + mov r3, r1, lsr #19 + /* 4th addr cycle */ + and r3, r3, #0xFF + strh r3, [r12, #NFC_FLASH_ADDR_OFF] + mov r3, #NAND_FLASH_CONFIG2_FADD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done + mov r3, r1, lsr #27 + /* 5th addr cycle */ + and r3, r3, #0xFF + strh r3, [r12, #NFC_FLASH_ADDR_OFF] + mov r3, #NAND_FLASH_CONFIG2_FADD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done + + mov r3, #0x30 + strh r3, [r12, #NFC_FLASH_CMD_OFF] + mov r3, #NAND_FLASH_CONFIG2_FCMD_EN + strh r3, [r12, #NFC_CONFIG2_OFF] + bl do_wait_op_done + +end_of_nfc_addr_ops: + mov r8, #0 + bl nfc_data_output + bl do_wait_op_done + + /* Check if x16/2kb page */ + ldr r7, =CCM_BASE + ldr r7, [r7, #0xC] + ands r7, r7, #(1 << 30) + beq nfc_addr_data_output_done_512 + + /* For 2K page - 2nd 512 */ + mov r8, #1 + bl nfc_data_output + bl do_wait_op_done + + /* 3rd 512 */ + mov r8, #2 + bl nfc_data_output + bl do_wait_op_done + + /* 4th 512 */ + mov r8, #3 + bl nfc_data_output + bl do_wait_op_done + + /* check for bad block */ + mov r3, r1, lsl #(32-17) /* get rid of block number */ + cmp r3, #(0x800 << (32-17)) /* check if not page 0 or 1 */ + b nfc_addr_data_output_done + +nfc_addr_data_output_done_512: + /* check for bad block */ + mov r3, r1, lsl #(32-5-9) /* get rid of block number */ + cmp r3, #(512 << (32-5-9)) /* check if not page 0 or 1 */ + +nfc_addr_data_output_done: + bhi copy_good_blk + add r4, r0, #0x800 /* r3 -> spare area buf 0 */ + ldrh r4, [r4, #0x4] + and r4, r4, #0xFF00 + cmp r4, #0xFF00 + beq copy_good_blk + /* really sucks. Bad block!!!! */ + cmp r3, #0x0 + beq skip_bad_block + + /* even suckier since we already read the first page! */ + /* Check if x16/2kb page */ + ldr r7, =CCM_BASE + ldr r7, [r7, #0xC] + ands r7, r7, #(1 << 30) + + subeq r11, r11, #512 /* rewind 1 page for the sdram pointer */ + subeq r1, r1, #512 /* rewind 1 page for the flash pointer */ + + /* for 2k page */ + subne r11, r11, #0x800 /* rewind 1 page for the sdram pointer */ + subne r1, r1, #0x800 /* rewind 1 page for the flash pointer */ + +skip_bad_block: + /* Check if x16/2kb page */ + ldr r7, =CCM_BASE + ldr r7, [r7, #0xC] + ands r7, r7, #(1 << 30) + + addeq r1, r1, #(32*512) + addne r1, r1, #(64*2048) + b nfc_read_page + +copy_good_blk: + /* copying page */ +1: ldmia r0!, {r3-r10} + stmia r11!, {r3-r10} + cmp r0, r2 + blo 1b + cmp r11, r13 + bge nand_copy_main_done + /* Check if x16/2kb page */ + ldr r7, =CCM_BASE + ldr r7, [r7, #0xC] + ands r7, r7, #(1 << 30) + + addeq r1, r1, #0x200 + addne r1, r1, #0x800 + mov r0, #NFC_BASE_ADDR + b nfc_read_page + +nand_copy_main_done: + /* Restore stack pointer since sp has been re-used in this file */ + ldr sp, =CFG_INTERNAL_SRAM_STACK + /* Restore return address and return to caller */ + ldr lr, [sp] + bx lr + +MXC_UBOOT_ROM_START: .word 0x87F00000 +UBOOT_IMAGE_SIZE: .word 0x40000 + diff --git a/include/asm-arm/arch-mx31/mx31-regs.h b/include/asm-arm/arch-mx31/mx31-regs.h index b04a718..1c5c121 100644 --- a/include/asm-arm/arch-mx31/mx31-regs.h +++ b/include/asm-arm/arch-mx31/mx31-regs.h @@ -84,8 +84,14 @@ #define IPU_CONF_IC_EN (1<<1) #define IPU_CONF_SCI_EN (1<<0)
+#define ARM_PPMRR 0x40000015 + #define WDOG_BASE 0x53FDC000
+#define AVIC_BASE 0x68000000 +#define AVIC_VECTOR0 (AVIC_BASE + 0x100) +#define AVIC_VECTOR1 (AVIC_BASE + 0x104) + /* * Signal Multiplexing (IOMUX) */ @@ -168,4 +174,67 @@ #define CS5_BASE 0xB6000000 #define PCMCIA_MEM_BASE 0xC0000000
+/* + * NAND controller + */ +#define NFC_BASE_ADDR 0xB8000000 +#define NFC_REGS (NFC_BASE_ADDR + 0xE00) + +/* + * Addresses for NFC registers + */ +#define NFC_BUF_SIZE_OFF 0 +#define NFC_BUF_SIZE (*((volatile u16 *)(NFC_REGS + NFC_BUF_SIZE_OFF))) +#define NFC_BUF_ADDR_OFF 0x04 +#define NFC_BUF_ADDR (*((volatile u16 *)(NFC_REGS + NFC_BUF_ADDR_OFF))) +#define NFC_FLASH_ADDR_OFF 0x06 +#define NFC_FLASH_ADDR (*((volatile u16 *)(NFC_REGS + NFC_FLASH_ADDR_OFF))) +#define NFC_FLASH_CMD_OFF 0x08 +#define NFC_FLASH_CMD (*((volatile u16 *)(NFC_REGS + NFC_FLASH_CMD_OFF))) +#define NFC_CONFIG_OFF 0x0A +#define NFC_CONFIG (*((volatile u16 *)(NFC_REGS + NFC_CONFIG_OFF))) +#define NFC_ECC_RSLT_OFF 0x0C +#define NFC_ECC_STATUS_RESULT (*((volatile u16 *)(NFC_REGS + NFC_ECC_RSLT_OFF))) +#define NFC_RSLTMAIN_AREA_OFF 0x0E +#define NFC_RSLTMAIN_AREA (*((volatile u16 *)(NFC_REGS + NFC_RSLTMAIN_AREA_OFF))) +#define NFC_RSLTSPARE_AREA_OFF 0x10 +#define NFC_RSLTSPARE_AREA (*((volatile u16 *)(NFC_REGS + NFC_RSLTSPARE_AREA_OFF))) +#define NFC_WRPROT_OFF 0x12 +#define NFC_WRPROT (*((volatile u16 *)(NFC_REGS + NFC_WRPROT_OFF))) +#define NFC_UNLCKSTART_BLK_OFF 0x14 +#define NFC_UNLCKSTART_BLKADDR (*((volatile u16 *)(NFC_REGS + NFC_UNLOCKSTART_BLK_OFF))) +#define NFC_UNLCKEND_BLK_OFF 0x16 +#define NFC_UNLCKEND_BLKADDR (*((volatile u16 *)(NFC_REGS + NFC_UNLOCKEND_BLK_OFF))) +#define NFC_NF_WRPRST_OFF 0x18 +#define NFC_NF_WRPRST (*((volatile u16 *)(NFC_REGS + NFC_NF_WRPRST_OFF))) +#define NFC_CONFIG1_OFF 0x1A +#define NFC_CONFIG1 (*((volatile u16 *)(NFC_REGS + NFC_CONFIG1_OFF))) +#define NFC_CONFIG2_OFF 0x1C +#define NFC_CONFIG2 (*((volatile u16 *)(NFC_REGS + NFC_CONFIG2_OFF))) + +#define RAM_BUFFER_ADDRESS_RBA_3 0x3 +#define NFC_BUFSIZE_1KB 0x0 +#define NFC_BUFSIZE_2KB 0x1 +#define NFC_CONFIGURATION_UNLOCKED 0x2 +#define ECC_STATUS_RESULT_NO_ERR 0x0 +#define ECC_STATUS_RESULT_1BIT_ERR 0x1 +#define ECC_STATUS_RESULT_2BIT_ERR 0x2 +#define NF_WR_PROT_UNLOCK 0x4 +#define NAND_FLASH_CONFIG1_FORCE_CE (1 << 7) +#define NAND_FLASH_CONFIG1_RST (1 << 6) +#define NAND_FLASH_CONFIG1_BIG (1 << 5) +#define NAND_FLASH_CONFIG1_INT_MSK (1 << 4) +#define NAND_FLASH_CONFIG1_ECC_EN (1 << 3) +#define NAND_FLASH_CONFIG1_SP_EN (1 << 2) +#define NAND_FLASH_CONFIG2_INT_DONE (1 << 15) +#define NAND_FLASH_CONFIG2_FDO_PAGE (0 << 3) +#define NAND_FLASH_CONFIG2_FDO_ID (2 << 3) +#define NAND_FLASH_CONFIG2_FDO_STATUS (4 << 3) +#define NAND_FLASH_CONFIG2_FDI_EN (1 << 2) +#define NAND_FLASH_CONFIG2_FADD_EN (1 << 1) +#define NAND_FLASH_CONFIG2_FCMD_EN (1 << 0) +#define FDO_PAGE_SPARE_VAL 0x8 +#define NAND_FLASH_BOOT 0x10000000 +#define MXCFIS_NAND 0x10000000 + #endif /* __ASM_ARCH_MX31_REGS_H */