>From 473120de8390abd78014cac9fe0925cb49f57fbe Mon Sep 17 00:00:00 2001
From: Alan Carvalho de Assis <[EMAIL PROTECTED]>
Date: Sun, 5 Oct 2008 19:59:47 -0300
Subject: [PATCH] iMX31: Add support to copy NAND Flash code to RAM

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 <[EMAIL PROTECTED]>
---
 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 <[EMAIL PROTECTED]>
+ * 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
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to