[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