[PATCH] iMX31: Add support to copy NAND Flash code to RAM
Alan Carvalho de Assis
alan.assis at freescale.com
Mon Oct 6 00:59:47 CEST 2008
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 at 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..591720a
--- /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 at 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 */
--
1.5.4.3
More information about the U-Boot
mailing list