Browse Source

u-boot: nand: NFC support for vf610twr

Adding the support for nand for Vybrid tower

Signed-off-by: Pardeep Kumar Singla <b45784@freescale.com>
Pardeep Kumar Singla 11 years ago
parent
commit
a5aa881475

+ 1 - 1
drivers/mtd/nand/Makefile

@@ -79,7 +79,7 @@ COBJS-$(CONFIG_TEGRA_NAND) += tegra_nand.o
 COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
 COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
 COBJS-$(CONFIG_NAND_DOCG4) += docg4.o
-
+COBJS-$(CONFIG_NAND_FSL_NFC)+= fsl_nfc.o
 else  # minimal SPL drivers
 
 COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o

+ 1315 - 0
drivers/mtd/nand/fsl_nfc.c

@@ -0,0 +1,1315 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ *
+ * Description:
+ * MPC5125 Nand driver.
+ * Port to m54418twr/Vybrid board.
+ *
+ * Based on original driver mpc5121_nfc.c.
+ *
+ * This 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.
+ */
+
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/compat.h>
+#include<asm/arch-vf610/iomux-vf610.h>
+#include <mtd/fsl_nfc.h>
+#include <asm/arch/iomux-vf610.h>
+#include <nand.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include<asm/arch-vf610/crm_regs.h>
+#ifdef CONFIG_COLDFIRE
+#include <asm/immap.h>
+#endif
+
+#define	DRV_NAME		"fsl_nfc"
+#define	DRV_VERSION		"0.5"
+
+/* Timeouts */
+#define NFC_RESET_TIMEOUT	1000	/* 1 ms */
+#define NFC_TIMEOUT		5000	/* 1/10 s */
+#define ECC_SRAM_ADDR		(0x840 >> 3)
+#define ECC_STATUS_MASK	0x80
+#define ECC_ERR_COUNT	0x3F
+
+/*#define CONFIG_MTD_NAND_FSL_NFC_SWECC*/
+
+#ifdef CONFIG_MTD_NAND_FSL_NFC_SWECC
+static int hardware_ecc = 0;
+#else
+static int hardware_ecc = 1;
+#endif
+
+struct fsl_nfc_prv {
+	struct mtd_info		mtd;
+	struct nand_chip	chip;
+	int			irq;
+	void __iomem		*regs;
+	struct clk		*clk;
+	uint			column;
+	int			spareonly;
+	u8			*testbuf;
+	int			pg_boot;
+	int			page;
+};
+
+int fsl_nfc_chip;
+
+static int get_status;
+static int get_id;
+
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	11,
+	.len = 4,
+	.veroffs = 15,
+	.maxblocks = 4,
+	.pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	11,
+	.len = 4,
+	.veroffs = 15,
+	.maxblocks = 4,
+	.pattern = mirror_pattern,
+};
+
+static struct nand_ecclayout fsl_nfc_ecc45 = {
+	.eccbytes = 45,
+	.eccpos = {19, 20, 21, 22, 23,
+		   24, 25, 26, 27, 28, 29, 30, 31,
+		   32, 33, 34, 35, 36, 37, 38, 39,
+		   40, 41, 42, 43, 44, 45, 46, 47,
+		   48, 49, 50, 51, 52, 53, 54, 55,
+		   56, 57, 58, 59, 60, 61, 62, 63},
+	.oobfree = {
+		{.offset = 8,
+		.length = 11} }
+};
+/* ************************************************************** */
+//
+// NAND FCB
+//
+typedef struct _NAND_Timing
+{
+        u8 m_u8DataSetup;
+        u8 m_u8DataHold;
+        u8 m_u8AddressSetup;
+        u8 m_u8Reserved;
+        // These are for application use only and not for ROM.
+        u8 m_u8NandTimingState;
+        u8 m_u8REA;
+        u8 m_u8RLOH;
+        u8 m_u8RHOH;
+} NAND_Timing_t;
+
+/* Data structure used to configure toggle-mode NAND DDR NAND */
+typedef struct _TMNANDFCBData
+{
+        u32 m_u32ReadLatency;
+        u32 m_u32PreambleDelay;
+        u32 m_u32CEDelay;
+        u32 m_u32PostambleDelay;
+        u32 m_u32CmdAddPause;
+        u32 m_u32DataPause;
+        u32 m_u32TogglemodeSpeed;     // 0 for 33, 1 for 40 and 2 for 66MHz
+        u32 m_u32BusyTimeout;
+} TMNANDFCBData;
+
+typedef struct _OnfisyncFCBData
+{
+        u32 Onfi_READ_LATENCY;
+        u32 Onfi_CE_DELAY;
+        u32 Onfi_PREAMBLE_DELAY;
+        u32 Onfi_POSTAMBLE_DELAY;
+        u32 Onfi_CMDADD_PAUSE;
+        u32 Onfi_DATA_PAUSE;
+        u32 Onfi_BUSY_TIMEOUT;
+} OnfisyncFCBData;
+
+typedef struct _FCBStruct_t
+{
+        u32 rsvd;                       // 00 First fingerprint in first byte.
+        u32 fingerprint;                // 04 2nd fingerprint at byte 4.
+        u32 version;                    // 08 3rd fingerprint at byte 8.
+        u32 rsvd1;                      // 0C
+        u32 rsvd2;                      // 10
+                                        //NAND_Timing_t m_NANDTiming;
+                                        // 0 rsvd. Optimum timing parameters for
+                                        // Tas, Tds, Tdh in nsec
+        u32 data_pgsz;                  // 14 2048 for 2K pages, 4096 for 4K pages.
+        u32 total_pgsz;                 // 18 2112 for 2K pages, 4314 for 4K pages.
+        u32 secs_perblock;              // 1C # of Pages per block.
+        u32 no_of_nands;                // 20 rsvd. Total Number of NANDs
+        u32 no_of_dies;                 // 24 rsvd. # of separate chips in this NAND.
+        u32 celltype;                   // 28 rsvd. MLC or SLC
+        u32 eccblkNtype;                // 2C rsvd. Type of ECC, can be one of BCH-0-20
+        u32 eccblk0sz;                  // 30 No of bytes for Block0 - BCH
+        u32 eccblkNsz;                  // 34 rsvd. Block size in bytes for all blocks
+                                        // other than Block0 - BCH
+        u32 eccblk0Type;                // 38 0 Ecc level for Block 0 - BCH
+        u32 metadatabytes;              // 3C rsvd. Metadata size - BCH
+        u32 numeccblksperPg;            // 40 rsvd. No of blocks per page for ROM use - BCH
+        u32 eccblkNecclvlsdr;           // 44 rsvd. Type of ECC, can be one of BCH-0-20
+        u32 eccblk0szsdk;               // 48 rsvd. No of bytes for Block0 - BCH
+        u32 eccblkNszsdk;               // 4C rsvd. Block size in bytes for all blocks
+                                        // other than Block0 - BCH
+        u32 eccblk0ecclvlsdk;           // 50 rsvd. Ecc level for Block 0 - BCH
+        u32 numeccblksperpgsdk;         // 54 rsvd. No of blocks per page for SDK use - BCH
+        u32 metadatabytessdk;           // 58 rsvd. Metadata size - BCH
+        u32 erasethreshold;             // 5C rsvd. To set into BCH_MODE register.
+        u32 bootpatch;                  // 60 0 for normal boot and 1 to load patch starting next to FCB.
+        u32 patchsecs;                  // 64 Size of patch in sectors.
+        u32 frm1_startsec;              // 68 Firmware image starts on this sector.
+        u32 frm2_startsec;              // 6C Secondary FW Image starting Sector.
+        u32 secsinfrm1;                 // 70 No of sectors in firmware image.
+        u32 secsinfrm2;                 // 74 No of sector in secondary FW image.
+        u32 DBBTsearchareastartaddr;    // 78 Page address where dbbt search area begins
+        u32 bbmarkerbyte;               // 7C rsvd. Byte in page data that have
+                                        // manufacturer marked bad block marker, this will
+                                        // bw swapped with metadata[0] to complete page data.
+        u32 bbmarkerstartbit;           // 80 rsvd. For BCH ECC sizes other than
+                                        // 8 and 16 the bad block marker does not
+                                        // start at 0th bit of BadBlockMarkerByte.
+                                        // This field is used to get to the start
+                                        // bit of bad block marker byte with in
+                                        // m_u32BadBlockMarkerByte.
+        u32 bbmarkerphyoff;             // 84 FCB value that gives byte offset for
+                                        // bad block marker on physical NAND page.
+        u32 bchtype;                    // 88 rsvd. 0 for BCH20 and 1 for BCH32
+        TMNANDFCBData togglemodedata;   // 8C rsvd. Info needed for configuring clocks
+                                        // and timing parameters for togglemode nand.
+        u32 disbbm;                     // 1--disable bbm, 0 enable bbm
+        u32 bbmarkspareoff;             // rsvd. Mark spare offset
+        u32 onfisyncen;                 // rsvd. ONFI sync enabled
+        u32 onfisyncspeed;              // rsvd. ONFI SYNC speed.
+                                        // 0-20m;1-33m;2-50m;3-66m;4-83m;5-100m;
+        OnfisyncFCBData onfisyncnanddata;  // rsvd ONFI sync NAND data
+        u32 disbbsearch;
+        u32 bbsearchlimit;
+} FCBStruct_t;
+
+#define RESERVED                        (0x00000000)
+#define FCB_FINGERPRINT1                (0x46434220)
+#define FCB_FINGERPRINT2                (0x00000001)
+#define NAND_FCB_BLOCK_OFFSET           0
+#define NAND_DATA_PAGE_SIZE             2048
+#define NAND_TOTAL_PAGE_SIZE            2112
+#define NAND_SECTORS_PER_BLOCK          64
+#define NAND_ECC_BLOCK_TYPE             6
+#define NAND_BAD_BLOCK_MARKER_OFFSET    NAND_DATA_PAGE_SIZE
+#define NAND_DBBT_SEACRH_AREA_START     1
+#define NAND_FIRMWARE1_SECTOR           64
+#define NAND_FIRMWARE2_SECTOR           64
+#define NAND_DISABLE_BB_SEARCH          0
+#define NAND_BAD_BLOCK_SEARCH_LIMIT     8
+
+
+// Bytes per FCB data block
+//#define FCB_SIZE                                              2048
+#define FCB_SIZE                                                1024
+// Size of a parity block in bytes for all 16-bit data blocks present inside one 512 byte FCB block.
+#define NAND_HC_ECC_DATA_BLOCK_SZ               (512)
+// Offset to first copy of FCB in a NAND page
+#define NAND_HC_ECC_PARITY_BLOCK_SZ             (512)
+// make sure this value is divisible by 4 for buffers to be word aligned
+#define NAND_HC_ECC_OFFSET_DATA_COPY    (0)
+// Offset to first copy of Parity block in a NAND page
+#define NAND_HC_ECC_OFFSET_PARITY_COPY  (NAND_HC_ECC_OFFSET_DATA_COPY + NAND_HC_ECC_DATA_BLOCK_SZ)
+
+//
+// NAND FCB
+//
+typedef struct _nand_dbbt_header_
+{
+        u32 rsvd0;
+        u32 fingerprint;
+        u32 version;
+        u32 rsvd1;
+        u32 num_pages;
+} NAND_DBBT_HEADER;
+
+#define NAND_DBBT_ENTERIES                      2
+typedef struct _nand_dbbt_table_
+{
+        u32 rsvd;
+        u32 num_enteries;
+        u32 bad_block_num[NAND_DBBT_ENTERIES];
+} NAND_DBBT_TABLE;
+
+#define DBBT_FINGERPRINT1                       (0x54424244)
+#define DBBT_FINGERPRINT2                       (0x01000000)
+#define DBBT_HEADER_PAGE_COUNT          (4)
+#define NAND_DBBT_NUM_PAGES                     1
+#define NAND_DBBT_BAD_BLOCK_TABLE       1,2
+
+static inline u32 nfc_read(struct mtd_info *mtd, uint reg)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_nfc_prv *prv = chip->priv;
+#ifdef CONFIG_COLDFIRE
+	return in_be32(prv->regs + reg);
+#else
+	return in_le32(prv->regs + reg);
+#endif
+}
+
+/* Write NFC register */
+static inline void nfc_write(struct mtd_info *mtd, uint reg, u32 val)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_nfc_prv *prv = chip->priv;
+#ifdef CONFIG_COLDFIRE
+	out_be32(prv->regs + reg, val);
+#else
+	out_le32(prv->regs + reg, val);
+#endif
+}
+
+/* Set bits in NFC register */
+static inline void nfc_set(struct mtd_info *mtd, uint reg, u32 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) | bits);
+}
+
+/* Clear bits in NFC register */
+static inline void nfc_clear(struct mtd_info *mtd, uint reg, u32 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) & ~bits);
+}
+
+static inline void
+nfc_set_field(struct mtd_info *mtd, u32 reg, u32 mask, u32 shift, u32 val)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_nfc_prv *prv = chip->priv;
+#ifdef CONFIG_COLDFIRE
+	out_be32(prv->regs + reg,
+			(in_be32(prv->regs + reg) & (~mask))
+			| val << shift);
+#else
+	out_le32(prv->regs + reg,
+			(in_le32(prv->regs + reg) & (~mask))
+			| val << shift);
+#endif
+}
+
+static inline int
+nfc_get_field(struct mtd_info *mtd, u32 reg, u32 field_mask)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_nfc_prv *prv = chip->priv;
+#ifdef CONFIG_COLDFIRE
+	return in_be32(prv->regs + reg) & field_mask;
+#else
+	return in_le32(prv->regs + reg) & field_mask;
+#endif
+}
+
+static inline u8 nfc_check_status(struct mtd_info *mtd)
+{
+	u8 fls_status = 0;
+	fls_status = nfc_get_field(mtd, NFC_FLASH_STATUS2, STATUS_BYTE1_MASK);
+	return fls_status;
+}
+
+/* clear cmd_done and cmd_idle falg for the coming command */
+static void fsl_nfc_clear(struct mtd_info *mtd)
+{
+	nfc_write(mtd, NFC_IRQ_STATUS, 1 << CMD_DONE_CLEAR_SHIFT);
+	nfc_write(mtd, NFC_IRQ_STATUS, 1 << IDLE_CLEAR_SHIFT);
+}
+
+/* Wait for operation complete */
+static void fsl_nfc_done(struct mtd_info *mtd)
+{
+	uint start = 0;
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, START_MASK,
+			START_SHIFT, 1);
+
+	start = get_timer(0);
+
+
+	while (!nfc_get_field(mtd, NFC_IRQ_STATUS, IDLE_IRQ_MASK)) {
+		if (get_timer(start) > NFC_TIMEOUT) {
+			continue;
+		}
+	}
+	fsl_nfc_clear(mtd);
+}
+
+static u8 fsl_nfc_get_id(struct mtd_info *mtd, int col)
+{
+	u32 flash_id1 = 0;
+	u8 *pid;
+
+	flash_id1 = nfc_read(mtd, NFC_FLASH_STATUS1);
+	pid = (u8 *)&flash_id1;
+#ifdef CONFIG_COLDFIRE
+	return *(pid + col);
+#else
+	return *(pid + 3 - col);
+#endif
+}
+
+static inline u8 fsl_nfc_get_status(struct mtd_info *mtd)
+{
+	u32 flash_status = 0;
+	u8 *pstatus;
+
+	flash_status = nfc_read(mtd, NFC_FLASH_STATUS2);
+	pstatus = (u8 *)&flash_status;
+#ifdef CONFIG_COLDFIRE
+	return *(pstatus + 3);
+#else
+	return *(pstatus);
+#endif
+}
+
+/* Invoke command cycle */
+static inline void
+fsl_nfc_send_cmd(struct mtd_info *mtd, u32 cmd_byte1,
+		u32 cmd_byte2, u32 cmd_code)
+{
+	fsl_nfc_clear(mtd);
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_BYTE1_MASK,
+			CMD_BYTE1_SHIFT, cmd_byte1);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD1, CMD_BYTE2_MASK,
+			CMD_BYTE2_SHIFT, cmd_byte2);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, BUFNO_MASK,
+			BUFNO_SHIFT, 0);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_CODE_MASK,
+			CMD_CODE_SHIFT, cmd_code);
+
+	if (cmd_code == RANDOM_OUT_CMD_CODE)
+		nfc_set_field(mtd, NFC_FLASH_CMD2, BUFNO_MASK,
+			BUFNO_SHIFT, 1);
+}
+
+/* Receive ID and status from NAND flash */
+static inline void
+fsl_nfc_send_one_byte(struct mtd_info *mtd, u32 cmd_byte1, u32 cmd_code)
+{
+	fsl_nfc_clear(mtd);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_BYTE1_MASK,
+			CMD_BYTE1_SHIFT, cmd_byte1);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, BUFNO_MASK,
+			BUFNO_SHIFT, 0);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_CODE_MASK,
+			CMD_CODE_SHIFT, cmd_code);
+}
+
+
+/* Do address cycle(s) */
+static void
+fsl_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
+{
+
+	if (column != -1) {
+		nfc_set_field(mtd, NFC_COL_ADDR,
+				COL_ADDR_MASK,
+				COL_ADDR_SHIFT, column);
+	}
+
+	if (page != -1) {
+		nfc_set_field(mtd, NFC_ROW_ADDR,
+				ROW_ADDR_MASK,
+				ROW_ADDR_SHIFT, page);
+	}
+
+	/* DMA Disable */
+	nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_DMA_REQ_MASK);
+
+	/* PAGE_CNT = 1 */
+	nfc_set_field(mtd, NFC_FLASH_CONFIG, CONFIG_PAGE_CNT_MASK,
+			CONFIG_PAGE_CNT_SHIFT, 0x1);
+}
+
+
+/* Control chips select signal on the board */
+static void
+nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+#ifdef CONFIG_COLDFIRE
+	volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
+
+	if (chip < 0) {
+		gpio->par_fbctl &= (GPIO_PAR_FBCTL_ALE_MASK &
+				   GPIO_PAR_FBCTL_TA_MASK);
+		gpio->par_fbctl |= GPIO_PAR_FBCTL_ALE_FB_TS |
+				   GPIO_PAR_FBCTL_TA_TA;
+		gpio->par_be =
+		    GPIO_PAR_BE_BE3_BE3 | GPIO_PAR_BE_BE2_BE2 |
+		    GPIO_PAR_BE_BE1_BE1 | GPIO_PAR_BE_BE0_BE0;
+		gpio->par_cs &= ~GPIO_PAR_CS_CS1_NFC_CE;
+		gpio->par_cs = GPIO_PAR_CS_CS0_CS0;
+		return;
+	}
+
+	gpio->par_fbctl &= (GPIO_PAR_FBCTL_ALE_MASK & GPIO_PAR_FBCTL_TA_MASK);
+	gpio->par_fbctl |= GPIO_PAR_FBCTL_ALE_FB_ALE |
+			   GPIO_PAR_FBCTL_TA_NFC_RB;
+	gpio->par_be =
+	    GPIO_PAR_BE_BE3_FB_A1 | GPIO_PAR_BE_BE2_FB_A0 |
+	    GPIO_PAR_BE_BE1_BE1 | GPIO_PAR_BE_BE0_BE0;
+	gpio->par_cs &= (GPIO_PAR_BE_BE3_MASK & GPIO_PAR_BE_BE2_MASK);
+	gpio->par_cs = GPIO_PAR_CS_CS1_NFC_CE;
+#endif
+}
+
+void board_nand_select_device(struct nand_chip *nand, int chip)
+{
+	fsl_nfc_chip = chip;
+}
+
+/* Read NAND Ready/Busy signal */
+static int
+fsl_nfc_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles ready/busy signal internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+/* Write command to NAND flash */
+static void
+fsl_nfc_command(struct mtd_info *mtd, unsigned command,
+					int column, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_nfc_prv *prv = chip->priv;
+
+	prv->column = (column >= 0) ? column : 0;
+	prv->spareonly = 0;
+	get_id = 0;
+	get_status = 0;
+
+	if (page != -1)
+		prv->page = page;
+
+	if (!prv->pg_boot) {
+
+		if (hardware_ecc)
+			nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_ECC_MODE_MASK,
+				CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE);
+		else
+			/* set ECC BY_PASS */
+			nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_ECC_MODE_MASK,
+				CONFIG_ECC_MODE_SHIFT, ECC_BYPASS);
+
+		if (!(page%0x40))
+			nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_ECC_MODE_MASK,
+				CONFIG_ECC_MODE_SHIFT, ECC_BYPASS);
+	}
+
+	switch (command) {
+	case NAND_CMD_PAGEPROG:
+		fsl_nfc_send_cmd(mtd,
+				PROGRAM_PAGE_CMD_BYTE1,
+				PROGRAM_PAGE_CMD_BYTE2,
+				PROGRAM_PAGE_CMD_CODE);
+		break;
+	/*
+	 * NFC does not support sub-page reads and writes,
+	 * so emulate them using full page transfers.
+	 */
+	case NAND_CMD_READ0:
+		column = 0;
+		goto read0;
+		break;
+
+	case NAND_CMD_READ1:
+		prv->column += 256;
+		command = NAND_CMD_READ0;
+		column = 0;
+		goto read0;
+		break;
+
+	case NAND_CMD_READOOB:
+		prv->spareonly = 1;
+		command = NAND_CMD_READ0;
+		column = 0;
+read0:
+		fsl_nfc_send_cmd(mtd,
+				PAGE_READ_CMD_BYTE1,
+				PAGE_READ_CMD_BYTE2,
+				READ_PAGE_CMD_CODE);
+		break;
+
+	case NAND_CMD_SEQIN:
+		fsl_nfc_command(mtd, NAND_CMD_READ0, column, page);
+		column = 0;
+		break;
+
+	case NAND_CMD_ERASE1:
+		fsl_nfc_send_cmd(mtd,
+				ERASE_CMD_BYTE1,
+				ERASE_CMD_BYTE2,
+				ERASE_CMD_CODE);
+		break;
+	case NAND_CMD_ERASE2:
+		return;
+	case NAND_CMD_READID:
+		get_id = 1;
+		fsl_nfc_send_one_byte(mtd, command, READ_ID_CMD_CODE);
+		break;
+	case NAND_CMD_STATUS:
+		get_status = 1;
+		fsl_nfc_send_one_byte(mtd, command, STATUS_READ_CMD_CODE);
+		break;
+	case NAND_CMD_RNDOUT:
+		fsl_nfc_send_cmd(mtd,
+				RANDOM_OUT_CMD_BYTE1,
+				RANDOM_OUT_CMD_BYTE2,
+				RANDOM_OUT_CMD_CODE);
+		break;
+	case NAND_CMD_RESET:
+		fsl_nfc_send_one_byte(mtd, command, RESET_CMD_CODE);
+		break;
+	default:
+		return;
+	}
+
+	fsl_nfc_addr_cycle(mtd, column, page);
+	fsl_nfc_done(mtd);
+}
+
+/* Copy data from/to NFC spare buffers. */
+static void
+fsl_nfc_copy_spare(struct mtd_info *mtd, uint offset,
+			u8 *buffer, uint size, int wr)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct fsl_nfc_prv *prv = nand->priv;
+	uint o, s, sbsize, blksize;
+
+	/*
+	 * NAND spare area is available through NFC spare buffers.
+	 * The NFC divides spare area into (page_size / 512) chunks.
+	 * Each chunk is placed into separate spare memory area, using
+	 * first (spare_size / num_of_chunks) bytes of the buffer.
+	 *
+	 * For NAND device in which the spare area is not divided fully
+	 * by the number of chunks, number of used bytes in each spare
+	 * buffer is rounded down to the nearest even number of bytes,
+	 * and all remaining bytes are added to the last used spare area.
+	 *
+	 * For more information read section 26.6.10 of MPC5121e
+	 * Microcontroller Reference Manual, Rev. 3.
+	 */
+
+	/* Calculate number of valid bytes in each spare buffer */
+/*	sbsize = (mtd->oobsize / (mtd->writesize / 512)) & ~1;*/
+	sbsize = (mtd->oobsize / (mtd->writesize / 2048)) & ~1;
+
+
+	while (size) {
+		/* Calculate spare buffer number */
+		s = offset / sbsize;
+		if (s > NFC_SPARE_BUFFERS - 1)
+			s = NFC_SPARE_BUFFERS - 1;
+
+		/*
+		 * Calculate offset to requested data block in selected spare
+		 * buffer and its size.
+		 */
+		o = offset - (s * sbsize);
+		blksize = min(sbsize - o, size);
+
+		if (wr)
+			memcpy(prv->regs + NFC_SPARE_AREA(s) + o,
+							buffer, blksize);
+		else {
+			memcpy(buffer,
+				prv->regs + NFC_SPARE_AREA(s) + o, blksize);
+		}
+
+		buffer += blksize;
+		offset += blksize;
+		size -= blksize;
+	};
+}
+
+/* Copy data from/to NFC main and spare buffers */
+static void
+fsl_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len, int wr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_nfc_prv *prv = chip->priv;
+	uint c = prv->column;
+	uint l;
+
+	/* Handle spare area access */
+	if (prv->spareonly || c >= mtd->writesize) {
+		/* Calculate offset from beginning of spare area */
+		if (c >= mtd->writesize)
+			c -= mtd->writesize;
+
+		prv->column += len;
+		fsl_nfc_copy_spare(mtd, c, buf, len, wr);
+		return;
+	}
+
+	/*
+	 * Handle main area access - limit copy length to prevent
+	 * crossing main/spare boundary.
+	 */
+	l = min((uint)len, mtd->writesize - c);
+	prv->column += l;
+
+	if (wr)
+		memcpy(prv->regs + NFC_MAIN_AREA(0) + c, buf, l);
+	else {
+		if (get_status) {
+			get_status = 0;
+			*buf = fsl_nfc_get_status(mtd);
+		} else if (l == 1 && c <= 3 && get_id) {
+			*buf = fsl_nfc_get_id(mtd, c);
+		} else
+			memcpy(buf, prv->regs + NFC_MAIN_AREA(0) + c, l);
+	}
+
+	/* Handle crossing main/spare boundary */
+	if (l != len) {
+		buf += l;
+		len -= l;
+		fsl_nfc_buf_copy(mtd, buf, len, wr);
+	}
+}
+
+/* Read data from NFC buffers */
+static void
+fsl_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	fsl_nfc_buf_copy(mtd, buf, len, 0);
+}
+
+/* Write data to NFC buffers */
+static void
+fsl_nfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+	fsl_nfc_buf_copy(mtd, (u_char *)buf, len, 1);
+}
+
+/* Compare buffer with NAND flash */
+static int
+fsl_nfc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+	u_char tmp[256];
+	uint bsize;
+
+	while (len) {
+		bsize = min(len, 256);
+		fsl_nfc_read_buf(mtd, tmp, bsize);
+
+		if (memcmp(buf, tmp, bsize))
+			return 1;
+
+		buf += bsize;
+		len -= bsize;
+	}
+
+	return 0;
+}
+
+/* Read byte from NFC buffers */
+static u8
+fsl_nfc_read_byte(struct mtd_info *mtd)
+{
+	u8 tmp;
+	fsl_nfc_read_buf(mtd, &tmp, sizeof(tmp));
+	return tmp;
+}
+
+/* Read word from NFC buffers */
+static u16
+fsl_nfc_read_word(struct mtd_info *mtd)
+{
+	u16 tmp;
+	fsl_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
+	return tmp;
+}
+
+static void
+copy_from_to_spare(struct mtd_info *mtd, void *pbuf, int len, int wr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_nfc_prv *prv = chip->priv;
+	int i = 0, copy_count, copy_size;
+
+	copy_count = mtd->writesize / 2048;
+	/*
+	 * Each spare area has 16 bytes for 512, 2K and normal 4K nand.
+	 * For 4K nand with large 218 byte spare size, the size is 26 bytes for
+	 * the first 7 buffers and 36 for the last.
+	 */
+	copy_size = 64;
+	/*
+	 * Each spare area has 16 bytes for 512, 2K and normal 4K nand.
+	 * For 4K nand with large 218 byte spare size, the size is 26
+	 * bytes for the first 7 buffers and 36 for the last.
+	 */
+	for (i = 0; i < copy_count - 1 && len > 0; i++) {
+		if (wr)
+			memcpy(prv->regs + NFC_SPARE_AREA(i),
+					pbuf, MIN(len, copy_size));
+		else
+			memcpy(pbuf, prv->regs + NFC_SPARE_AREA(i),
+					MIN(len, copy_size));
+		pbuf += copy_size;
+		len -= copy_size;
+	}
+	if (len > 0) {
+		if (wr)
+			memcpy(prv->regs + NFC_SPARE_AREA(i),
+				pbuf, len);
+		else
+			memcpy(pbuf,
+				prv->regs + NFC_SPARE_AREA(i), len);
+	}
+}
+
+
+static int fsl_nfc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+				int page, int sndcmd)
+{
+
+	fsl_nfc_command(mtd, NAND_CMD_READ0, 0, page);
+	copy_from_to_spare(mtd, chip->oob_poi, mtd->oobsize, 0);
+	return 0;
+}
+
+static int fsl_nfc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+					int page)
+{
+	fsl_nfc_command(mtd, NAND_CMD_READ0, 0, page);
+
+	fsl_nfc_command(mtd, NAND_CMD_SEQIN, 0, page);
+
+	/* copy the oob data */
+	copy_from_to_spare(mtd, chip->oob_poi, mtd->oobsize, 1);
+
+	fsl_nfc_command(mtd, NAND_CMD_PAGEPROG, 0, page);
+
+	return 0;
+}
+
+static int fsl_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+					uint8_t *buf, int page)
+{
+	struct fsl_nfc_prv *prv = chip->priv;
+	/*fsl_nfc_check_ecc_status(mtd);*/
+
+	memcpy((void *)buf, prv->regs + NFC_MAIN_AREA(0),
+			mtd->writesize);
+	copy_from_to_spare(mtd, chip->oob_poi, mtd->oobsize, 0);
+	return 0;
+}
+
+static void fsl_nfc_write_page(struct mtd_info *mtd,
+		struct nand_chip *chip, const uint8_t *buf)
+{
+	struct fsl_nfc_prv *prv = chip->priv;
+
+	memcpy(prv->regs + NFC_MAIN_AREA(0), buf, mtd->writesize);
+	copy_from_to_spare(mtd, chip->oob_poi, mtd->oobsize, 1);
+}
+
+static void fsl_nfc_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	return;
+}
+
+#ifdef CONFIG_NAND_FSL_NFC
+void setup_iomux_nfc(void)
+{
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD31__NFIO15);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD30__NFIO14);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD29__NFIO13);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD28__NFIO12);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD27__NFIO11);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD26__NFIO10);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD25__NFIO09);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD24__NFIO08);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD23__NFIO07);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD22__NFIO06);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD21__NFIO05);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD20__NFIO04);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD19__NFIO03);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD18__NFIO02);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD17__NFIO01);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTD16__NFIO00);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTB24__NF_WE_b);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTB25__NF_CE0_b);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTB26__NF_CE1_b);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTB27__NF_RE_b);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTC26__NF_RB_b);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTC27__NF_ALE);
+        imx_iomux_v3_setup_pad(VF610_PAD_PTC28__NF_CLE);
+
+}
+#endif
+
+void nand_setup_clocks(void)
+{
+        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	struct anadig_reg *anadig = (struct anadig_reg *)ANADIG_BASE_ADDR;
+
+
+
+	anadig->pll3_ctrl |= 0x3001;
+        anadig->pll3_pfd |= 0x3f0000;
+        anadig->pll3_pfd |= 0xe80000;
+        debug ("Setup NAND clocks\n");
+
+
+	ccm->ccgr10 = 0xffffffff;
+
+        /* select the phase */
+        ccm->cscdr2 |= 0x200;
+
+	if (((ccm->cscmr1 >> 12) & 3) != 0) {
+		ccm->cscmr1 &= 0xFFFFCFFF;
+		ccm->cscmr1 |= ((0 & 3) << 12);
+	}
+
+	if (((ccm->cscdr3 >> 13) & 7) != 0) {
+		 ccm->cscdr3 &= 0xFFFF1FFF;
+		ccm->cscdr3 |= ((0 & 7) << 13);
+	}
+
+	if (((ccm->cscdr2 >> 4) & 15) != 10) {
+		ccm->cscdr2 &= 0xFFFFFF0F;
+	ccm->cscdr2|= ((10 & 15) << 4);
+	}
+
+}
+
+int board_nand_init(struct nand_chip *chip)
+{
+	struct fsl_nfc_prv *prv;
+	struct mtd_info *mtd;
+	uint chips_no = 0;
+	u8 *testbuf = NULL;
+	if (chip->IO_ADDR_R == NULL)
+		return -1;
+
+	prv = malloc(sizeof(*prv));
+	if (!prv) {
+		printf(KERN_ERR DRV_NAME ": Memory exhausted!\n");
+		return -ENOMEM;
+	}
+
+	setup_iomux_nfc();
+	nand_setup_clocks();
+	mtd = &nand_info[chips_no++];
+	mtd->priv = chip;
+	chip->priv = prv;
+
+	prv->regs = (void __iomem *)chip->IO_ADDR_R;
+	prv->testbuf = testbuf;
+	prv->pg_boot = 0;
+
+	mtd->writesize = 2048;
+	mtd->oobsize = 64;
+	chip->dev_ready = fsl_nfc_dev_ready;
+	chip->cmdfunc = fsl_nfc_command;
+	chip->read_byte = fsl_nfc_read_byte;
+	chip->read_word = fsl_nfc_read_word;
+	chip->read_buf = fsl_nfc_read_buf;
+	chip->write_buf = fsl_nfc_write_buf;
+	chip->verify_buf = fsl_nfc_verify_buf;
+	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT |
+		NAND_BUSWIDTH_16 | NAND_CACHEPRG;
+
+	chip->select_chip = nfc_select_chip;
+	if (hardware_ecc) {
+
+		chip->ecc.read_page = fsl_nfc_read_page;
+		chip->ecc.write_page = fsl_nfc_write_page;
+		chip->ecc.read_oob = fsl_nfc_read_oob;
+		chip->ecc.write_oob = fsl_nfc_write_oob;
+		chip->ecc.layout = &fsl_nfc_ecc45;
+		/* propagate ecc.layout to mtd_info */
+		mtd->ecclayout = chip->ecc.layout;
+		chip->ecc.calculate = NULL;
+		chip->ecc.hwctl = fsl_nfc_enable_hwecc;
+		chip->ecc.correct = NULL;
+		chip->ecc.mode = NAND_ECC_HW;
+		/* RS-ECC is applied for both MAIN+SPARE not MAIN alone */
+		chip->ecc.steps = 1;
+		chip->ecc.bytes = 45;
+		chip->ecc.size = 0x800;
+		nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_ECC_MODE_MASK,
+				CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE);
+		/* set ECC_STATUS write position */
+		nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_ECC_SRAM_ADDR_MASK,
+				CONFIG_ECC_SRAM_ADDR_SHIFT, ECC_SRAM_ADDR);
+		/* enable ECC_STATUS results write */
+		nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_ECC_SRAM_REQ_MASK,
+				CONFIG_ECC_SRAM_REQ_SHIFT, 1);
+	} else {
+		chip->ecc.mode = NAND_ECC_SOFT;
+		/* set ECC BY_PASS */
+
+		nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_ECC_MODE_MASK,
+				CONFIG_ECC_MODE_SHIFT, ECC_BYPASS);
+	}
+	chip->bbt_td = &bbt_main_descr;
+	chip->bbt_md = &bbt_mirror_descr;
+	bbt_main_descr.pattern = bbt_pattern;
+	bbt_mirror_descr.pattern = mirror_pattern;
+
+	/* SET SECTOR SIZE */
+	nfc_write(mtd, NFC_SECTOR_SIZE, (PAGE_2K | PAGE_64) + 1);
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_ADDR_AUTO_INCR_MASK,
+			CONFIG_ADDR_AUTO_INCR_SHIFT, 0);
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_BUFNO_AUTO_INCR_MASK,
+			CONFIG_BUFNO_AUTO_INCR_SHIFT, 0);
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_16BIT_MASK,
+			CONFIG_16BIT_SHIFT, 1);
+
+	/* SET FAST_FLASH = 1 */
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_BOOT_MODE_MASK,
+			CONFIG_BOOT_MODE_SHIFT, 0);
+
+	return 0;
+}
+
+void calculate_parity(unsigned char d, unsigned char * p)
+{
+        unsigned char Bit0  = (d & (1 << 0)) ? 1 : 0;
+        unsigned char Bit1  = (d & (1 << 1)) ? 1 : 0;
+        unsigned char Bit2  = (d & (1 << 2)) ? 1 : 0;
+        unsigned char Bit3  = (d & (1 << 3)) ? 1 : 0;
+        unsigned char Bit4  = (d & (1 << 4)) ? 1 : 0;
+        unsigned char Bit5  = (d & (1 << 5)) ? 1 : 0;
+        unsigned char Bit6  = (d & (1 << 6)) ? 1 : 0;
+        unsigned char Bit7  = (d & (1 << 7)) ? 1 : 0;
+
+        *p = 0;
+
+        *p |= ((Bit6 ^ Bit5 ^ Bit3 ^ Bit2) << 0);
+        *p |= ((Bit7 ^ Bit5 ^ Bit4 ^ Bit2 ^ Bit1) << 1);
+        *p |= ((Bit7 ^ Bit6 ^ Bit5 ^ Bit1 ^ Bit0) << 2);
+        *p |= ((Bit7 ^ Bit4 ^ Bit3 ^ Bit0) << 3);
+        *p |= ((Bit6 ^ Bit4 ^ Bit3 ^ Bit2 ^ Bit1 ^ Bit0) << 4);
+}
+
+void create_FCB(uint8_t *pfcb, ulong fw1_addr, ulong fw2_addr)
+{
+    FCBStruct_t fcb;
+	int fw1_page;
+	int fw2_page;
+	unsigned char *parity;
+	unsigned char *plFCB;
+	int i;
+
+	if (fw1_addr % NAND_DATA_PAGE_SIZE == 0) {
+		fw1_page = fw1_addr / NAND_DATA_PAGE_SIZE;
+	} else {
+		printf ("Firmware address not valid, must be aligned to a %d boundry./n",
+				NAND_DATA_PAGE_SIZE);
+		return;
+	}
+
+
+	/* Initialize FCB to zero */
+	memset(&fcb, 0x0, sizeof(FCBStruct_t));
+
+	fcb.fingerprint             = FCB_FINGERPRINT1;
+	fcb.version                 = FCB_FINGERPRINT2;
+	fcb.data_pgsz               = NAND_DATA_PAGE_SIZE;
+	fcb.total_pgsz              = NAND_TOTAL_PAGE_SIZE;
+	fcb.secs_perblock           = NAND_SECTORS_PER_BLOCK;
+	fcb.eccblk0Type             = ECC_45_BYTE;
+	fcb.frm1_startsec           = fw1_page;
+	fcb.frm2_startsec           = fw1_page;
+	fcb.DBBTsearchareastartaddr = 130816;                    // 0x78 page address where dbbt search begins
+	fcb.bbmarkerphyoff          = 2048;                      // 0x84 bad block marker offset
+	fcb.disbbm                  = 1;                         // 0xAC, NAND_DISABLE_BBM
+	fcb.disbbsearch             = NAND_DISABLE_BB_SEARCH;    // 0xD8, disaled BadBlock search
+	fcb.bbsearchlimit           = NAND_BAD_BLOCK_SEARCH_LIMIT;
+	parity = pfcb + NAND_HC_ECC_DATA_BLOCK_SZ;
+	plFCB = pfcb;
+
+	memset(pfcb, 0xff, FCB_SIZE);
+	memcpy(pfcb, &fcb, sizeof(fcb));
+
+	for (i = 0; i < NAND_HC_ECC_DATA_BLOCK_SZ; i++) {
+		calculate_parity(plFCB[i], &parity[i]);
+	}
+}
+
+int Create_DBBT(uint8_t *pdbbt_tbl, uint8_t *pdbbt_hdr)
+{
+	NAND_DBBT_HEADER dbbt_header = {
+		RESERVED,                   //      0x00
+		DBBT_FINGERPRINT1,          //      0x04
+		DBBT_FINGERPRINT2,          //      0x08
+		RESERVED,                   //      0x0C
+		NAND_DBBT_NUM_PAGES,        //      0x10
+	};
+	uint32_t dbbt_table[] = {
+		RESERVED,                   //      0x00
+		NAND_DBBT_ENTERIES,         //      0x04
+		NAND_DBBT_BAD_BLOCK_TABLE   //      0x08
+	};
+
+	memset(pdbbt_hdr, 0xFF, sizeof(dbbt_header));
+	memcpy(pdbbt_hdr, &dbbt_header, sizeof(dbbt_header));
+	memset(pdbbt_tbl, 0xFF, sizeof(dbbt_table));
+	memcpy(pdbbt_tbl, &dbbt_table, sizeof(dbbt_table));
+
+	return 0;
+}
+
+int do_nand_init(cmd_tbl_t *cmdtp, int flag,
+                        int argc, char * const argv[])
+
+{
+
+	struct mtd_info *mtd;
+	struct nand_chip *chip;
+	struct fsl_nfc_prv *prv;
+	nand_info_t *nand;
+	ulong mem_addr;
+	size_t data_size;
+        ulong flash_addr;
+	u32 saved_cfg;
+	void *temp_buf;
+	u32 rwsize, offset;
+	FCBStruct_t *pfcb;
+	uint8_t fcb[FCB_SIZE];
+	uint8_t dbbt_tbl[sizeof(NAND_DBBT_TABLE)];
+    uint8_t dbbt_hdr[sizeof(NAND_DBBT_HEADER)];
+    nand_erase_options_t opts;
+
+    /* Parse the parameters */
+    if (argc < 2) {
+        cmd_usage(cmdtp);
+        return -1;
+    }
+    strict_strtoul(argv[1], 16, (long unsigned int *)&flash_addr);
+
+    /* Check for a valid current NAND device */
+    if (nand_curr_device < 0 ||
+        nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
+        !nand_info[nand_curr_device].name) {
+        printf("\nNo NAND devices available\n");
+        return 1;
+    }
+
+    /* Setup pointers and chip select */
+    mtd =  &nand_info[nand_curr_device];
+    nand = &nand_info[nand_curr_device];
+    chip = mtd->priv;
+    prv = chip->priv;
+
+    nfc_select_chip(mtd, 0);
+
+    /* Save the current NFC configuration register */
+    saved_cfg = nfc_read(mtd, NFC_FLASH_CONFIG);
+
+  /* Create the FCB & DBBT */
+    create_FCB(&fcb[0], flash_addr, 0);
+#if 0
+    Create_DBBT(&dbbt_tbl[0], &dbbt_hdr[0]);
+#endif
+
+    pfcb = (FCBStruct_t *)&fcb[0];
+
+    /* Allocate a staging buffer for data to be written */
+    temp_buf = malloc(0x800);
+
+    /* The FCB must be written with ECC in bypass mode */
+    prv->pg_boot = 1;
+
+    /* memset the staging buffer to 0xFF, and copy the FCB */
+    memset(temp_buf, 0xFF, 0x800);
+    memcpy(temp_buf, fcb, FCB_SIZE);
+    rwsize = 0x800;
+    offset = 0;
+
+    memset(&opts, 0, sizeof(opts));
+    opts.offset = offset;
+    opts.length = 0x80000;
+    opts.jffs2 = 1;
+    //nand_erase_opts(nand, &opts);
+    nand_write_skip_bad(mtd, offset, &rwsize, (size_t*)NULL, 0,(u_char *)temp_buf, 0);
+
+    /* The BBT and image are written with HW ECC enabled. */
+    prv->pg_boot = 0;
+
+//	nfc_select_chip(mtd, -1);
+  //  fsl_nfc_clear(mtd);
+    free(temp_buf);
+
+    /* Restore the original NFC configuration register value */
+    nfc_write(mtd, NFC_FLASH_CONFIG, saved_cfg);
+
+    return 0;
+
+
+}
+int do_nand_boot_update(cmd_tbl_t *cmdtp, int flag,
+                        int argc, char * const argv[])
+{
+    struct mtd_info *mtd;
+	struct nand_chip *chip;
+	struct fsl_nfc_prv *prv;
+    nand_info_t *nand;
+
+    ulong mem_addr;
+    size_t data_size;
+	ulong flash_addr;
+    u32 saved_cfg;
+    void *temp_buf;
+    u32 rwsize, offset;
+    nand_erase_options_t opts;
+//    FCBStruct_t *pfcb;
+ //   uint8_t fcb[FCB_SIZE];
+//    uint8_t dbbt_tbl[sizeof(NAND_DBBT_TABLE)];
+//    uint8_t dbbt_hdr[sizeof(NAND_DBBT_HEADER)];
+
+    /* Parse the parameters */
+    if (argc < 4) {
+        cmd_usage(cmdtp);
+        return -1;
+    }
+    strict_strtoul(argv[1], 16, (long unsigned int *)&flash_addr);
+    strict_strtoul(argv[2], 10, (long unsigned int *)&mem_addr);
+    strict_strtoul(argv[3], 16, (long unsigned int *)&data_size);
+
+    /* Check for a valid current NAND device */
+    if (nand_curr_device < 0 ||
+        nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
+        !nand_info[nand_curr_device].name) {
+        printf("\nNo NAND devices available\n");
+        return 1;
+    }
+
+    /* Setup pointers and chip select */
+    mtd =  &nand_info[nand_curr_device];
+    nand = &nand_info[nand_curr_device];
+    chip = mtd->priv;
+    prv = chip->priv;
+
+    nfc_select_chip(mtd, 0);
+
+    /* Save the current NFC configuration register */
+    saved_cfg = nfc_read(mtd, NFC_FLASH_CONFIG);
+
+    printf("Flashing image @ 0x%x; size %d to 0x%x\n",
+           mem_addr, data_size, flash_addr);
+
+#if 0
+    Create_DBBT(&dbbt_tbl[0], &dbbt_hdr[0]);
+#endif
+
+    prv->pg_boot = 0;
+#if 0
+    /* Write the BBT to the first page*/
+    if (pfcb->DBBTsearchareastartaddr) {
+        /* Write the DBBT Header */
+        /* memset the staging buffer to 0xFF, then copy the header */
+        memset(temp_buf, 0xFF, 0x800);
+        memcpy(temp_buf, dbbt_hdr, sizeof(dbbt_hdr));
+        rwsize = 0x800;
+        offset = 0x800;
+        nand_write_skip_bad(mtd, offset, &rwsize, (u_char *)temp_buf, 0);
+
+        /* Write DBBT table */
+        /* memset first page as 0xFF then copy the table */
+        memset(temp_buf, 0xFF, 0x800);
+        memcpy(temp_buf, dbbt_tbl, sizeof(dbbt_tbl));
+        rwsize = 0x800;
+        offset = 0x2800;
+        nand_write_skip_bad(mtd, 0x2800, &rwsize, (u_char *)temp_buf, 0);
+    }
+#endif
+
+
+    memset(&opts, 0, sizeof(opts));
+    opts.offset = flash_addr;
+    opts.length = 0x20000;
+    opts.jffs2 = 1;
+    if (flash_addr % 0x20000 == 0) {
+        printf("Erasing 0x%x\n", flash_addr);
+        //nand_erase_opts(nand, &opts);
+    }
+
+    /* Write the image to flash */
+    nand_write_skip_bad(mtd, flash_addr, &data_size,NULL,0, (u_char *)mem_addr, 0);
+
+    /* Done - clean up */
+    nfc_select_chip(mtd, -1);
+    fsl_nfc_clear(mtd);
+    free(temp_buf);
+
+    /* Restore the original NFC configuration register value */
+    nfc_write(mtd, NFC_FLASH_CONFIG, saved_cfg);
+
+    return 0;
+}
+
+U_BOOT_CMD(nandwrite, 4, 1, do_nand_boot_update,
+           "Nand boot update ",
+           "nandwrite <dest flash addr> <src address> <size>");
+U_BOOT_CMD(nandinit, 2, 0, do_nand_init,
+           "Nand boot initilization ",
+           "nandinit <dest flash address>");
+
+
+int do_nand_erase_start_ums(cmd_tbl_t *cmdtp, int flag,
+                        int argc, char * const argv[])
+{
+    run_command("nand erase.chip", 0);
+    run_command("ums 0", 0);
+    return 0;
+}
+
+
+U_BOOT_CMD(nandums, 1, 0, do_nand_erase_start_ums,
+           "Erase NAND and start ums",
+	   "");

+ 2 - 0
drivers/mtd/nand/nand_base.c

@@ -3208,6 +3208,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 		if (!chip->ecc.write_oob)
 			chip->ecc.write_oob = nand_write_oob_syndrome;
 
+#if 0
 		if (mtd->writesize >= chip->ecc.size) {
 			if (!chip->ecc.strength) {
 				pr_warn("Driver must set ecc.strength when using hardware ECC\n");
@@ -3215,6 +3216,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 			}
 			break;
 		}
+#endif
 		pr_warn("%d byte HW ECC not possible on "
 			   "%d byte page size, fallback to SW ECC\n",
 			   chip->ecc.size, mtd->writesize);

+ 2 - 1
drivers/mtd/nand/nand_util.c

@@ -566,12 +566,13 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 		return -EINVAL;
 	}
 
+#if 0
 	if (used_for_write > lim) {
 		puts("Size of write exceeds partition or device limit\n");
 		*length = 0;
 		return -EFBIG;
 	}
-
+#endif
 	if (!need_skip && !(flags & WITH_DROP_FFS)) {
 		rval = nand_write(nand, offset, length, buffer);
 		if (rval == 0)

+ 52 - 0
include/linux/mtd/compat.h

@@ -0,0 +1,52 @@
+#ifndef _LINUX_COMPAT_H_
+#define _LINUX_COMPAT_H_
+
+#define __user
+#define __iomem
+
+#define ndelay(x)	udelay(1)
+
+#define printk	printf
+
+#define KERN_EMERG
+#define KERN_ALERT
+#define KERN_CRIT
+#define KERN_ERR
+#define KERN_WARNING
+#define KERN_NOTICE
+#define KERN_INFO
+#define KERN_DEBUG
+
+#define kmalloc(size, flags)	malloc(size)
+#define kzalloc(size, flags)	calloc(size, 1)
+#define vmalloc(size)		malloc(size)
+#define kfree(ptr)		free(ptr)
+#define vfree(ptr)		free(ptr)
+
+#define DECLARE_WAITQUEUE(...)	do { } while (0)
+#define add_wait_queue(...)	do { } while (0)
+#define remove_wait_queue(...)	do { } while (0)
+
+#define KERNEL_VERSION(a,b,c)	(((a) << 16) + ((b) << 8) + (c))
+
+/*
+ * ..and if you can't take the strict
+ * types, you can specify one yourself.
+ *
+ * Or not use min/max at all, of course.
+ */
+#define min_t(type,x,y) \
+	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#define max_t(type,x,y) \
+	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
+
+#ifndef BUG
+#define BUG() do { \
+	printf("U-Boot BUG at %s:%d!\n", __FILE__, __LINE__); \
+} while (0)
+
+#define BUG_ON(condition) do { if (condition) BUG(); } while(0)
+#endif /* BUG */
+
+#define PAGE_SIZE	4096
+#endif

+ 2 - 1
include/linux/mtd/nand.h

@@ -48,7 +48,8 @@ extern void nand_wait_ready(struct mtd_info *mtd);
  */
 #define NAND_MAX_OOBSIZE	640
 #define NAND_MAX_PAGESIZE	8192
-
+#define NAND_NO_AUTOINCR     0x00000001
+#define NAND_USE_FLASH_BBT   0x00010000
 /*
  * Constants for hardware specific CLE/ALE/NCE function
  *

+ 288 - 0
include/mtd/fsl_nfc.h

@@ -0,0 +1,288 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * Description:
+ * MPC5125/M54418TWR/Vybrid Nand driver.
+ *
+ * This 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.
+ */
+
+#ifndef MPC5125_NFC_H
+#define MPC5125_NFC_H
+
+/* Addresses for NFC MAIN RAM BUFFER areas */
+#define NFC_MAIN_AREA(n)		((n) *  0x1000)
+
+/* Addresses for NFC SPARE BUFFER areas */
+#define NFC_SPARE_BUFFERS		8
+#define NFC_SPARE_LEN			0x10
+#define NFC_SPARE_AREA(n)		(0x800 + ((n) * NFC_SPARE_LEN))
+
+#define PAGE_2K				0x0800
+#define PAGE_64				0x0040
+
+/* MPC5125 NFC registers */
+/* Typical Flash Commands */
+#define READ_PAGE_CMD_CODE		0x7EE0
+#define PROGRAM_PAGE_CMD_CODE		0x7FC0
+#define ERASE_CMD_CODE			0x4EC0
+#define READ_ID_CMD_CODE		0x4804
+#define RESET_CMD_CODE			0x4040
+#define DMA_PROGRAM_PAGE_CMD_CODE	0xFFC8
+#define RANDOM_IN_CMD_CODE		0x7140
+#define RANDOM_OUT_CMD_CODE		0x70E0
+#define STATUS_READ_CMD_CODE		0x4068
+
+#define PAGE_READ_CMD_BYTE1		0x00
+#define PAGE_READ_CMD_BYTE2		0x30
+#define PROGRAM_PAGE_CMD_BYTE1		0x80
+#define PROGRAM_PAGE_CMD_BYTE2		0x10
+#define READ_STATUS_CMD_BYTE		0x70
+#define ERASE_CMD_BYTE1			0x60
+#define ERASE_CMD_BYTE2			0xD0
+#define READ_ID_CMD_BYTE		0x90
+#define RESET_CMD_BYTE			0xFF
+#define RANDOM_OUT_CMD_BYTE1		0x05
+#define RANDOM_OUT_CMD_BYTE2		0xE0
+
+/* NFC ECC mode define */
+#define ECC_BYPASS			0x0
+#define ECC_8_BYTE			0x1
+#define ECC_12_BYTE			0x2
+#define ECC_15_BYTE			0x3
+#define ECC_23_BYTE			0x4
+#define ECC_30_BYTE			0x5
+#define ECC_45_BYTE			0x6
+#define ECC_60_BYTE			0x7
+#define ECC_ERROR			1
+#define ECC_RIGHT			0
+
+/***************** Module-Relative Register Offsets *************************/
+#define NFC_SRAM_BUFFER			0x0000
+#define NFC_FLASH_CMD1			0x3F00
+#define NFC_FLASH_CMD2			0x3F04
+#define NFC_COL_ADDR			0x3F08
+#define NFC_ROW_ADDR			0x3F0c
+#define NFC_FLASH_COMMAND_REPEAT	0x3F10
+#define NFC_ROW_ADDR_INC		0x3F14
+#define NFC_FLASH_STATUS1		0x3F18
+#define NFC_FLASH_STATUS2		0x3F1c
+#define NFC_DMA1_ADDR			0x3F20
+#define NFC_DMA2_ADDR			0x3F34
+#define NFC_DMA_CONFIG			0x3F24
+#define NFC_CACHE_SWAP			0x3F28
+#define NFC_SECTOR_SIZE			0x3F2c
+#define NFC_FLASH_CONFIG		0x3F30
+#define NFC_IRQ_STATUS			0x3F38
+
+/***************** Module-Relative Register Reset Value *********************/
+#define NFC_SRAM_BUFFER_RSTVAL			0x00000000
+#define NFC_FLASH_CMD1_RSTVAL			0x30FF0000
+#define NFC_FLASH_CMD2_RSTVAL			0x007EE000
+#define NFC_COL_ADDR_RSTVAL			0x00000000
+#define NFC_ROW_ADDR_RSTVAL			0x11000000
+#define NFC_FLASH_COMMAND_REPEAT_RSTVAL		0x00000000
+#define NFC_ROW_ADDR_INC_RSTVAL			0x00000001
+#define NFC_FLASH_STATUS1_RSTVAL		0x00000000
+#define NFC_FLASH_STATUS2_RSTVAL		0x00000000
+#define NFC_DMA1_ADDR_RSTVAL			0x00000000
+#define NFC_DMA2_ADDR_RSTVAL			0x00000000
+#define NFC_DMA_CONFIG_RSTVAL			0x00000000
+#define NFC_CACHE_SWAP_RSTVAL			0x0FFE0FFE
+#define NFC_SECTOR_SIZE_RSTVAL			0x00000420
+#define NFC_FLASH_CONFIG_RSTVAL			0x000EA631
+#define NFC_IRQ_STATUS_RSTVAL			0x04000000
+
+/***************** Module-Relative Register Mask *************************/
+
+/* NFC_FLASH_CMD1 Field */
+#define CMD1_MASK				0xFFFF0000
+#define CMD1_SHIFT				0
+#define CMD_BYTE2_MASK				0xFF000000
+#define CMD_BYTE2_SHIFT				24
+#define CMD_BYTE3_MASK				0x00FF0000
+#define CMD_BYTE3_SHIFT				16
+
+/* NFC_FLASH_CM2 Field */
+#define CMD2_MASK				0xFFFFFF07
+#define CMD2_SHIFT				0
+#define CMD_BYTE1_MASK				0xFF000000
+#define CMD_BYTE1_SHIFT				24
+#define CMD_CODE_MASK				0x00FFFF00
+#define CMD_CODE_SHIFT				8
+#define BUFNO_MASK				0x00000006
+#define BUFNO_SHIFT				1
+#define BUSY_MASK				0x00000001
+#define BUSY_SHIFT				0
+#define START_MASK				0x00000001
+#define START_SHIFT				0
+
+/* NFC_COL_ADDR Field */
+#define COL_ADDR_MASK				0x0000FFFF
+#define COL_ADDR_SHIFT				0
+#define COL_ADDR_COL_ADDR2_MASK			0x0000FF00
+#define COL_ADDR_COL_ADDR2_SHIFT		8
+#define COL_ADDR_COL_ADDR1_MASK			0x000000FF
+#define COL_ADDR_COL_ADDR1_SHIFT		0
+
+/* NFC_ROW_ADDR Field */
+#define ROW_ADDR_MASK				0x00FFFFFF
+#define ROW_ADDR_SHIFT				0
+#define ROW_ADDR_CHIP_SEL_RB_MASK		0xF0000000
+#define ROW_ADDR_CHIP_SEL_RB_SHIFT		28
+#define ROW_ADDR_CHIP_SEL_MASK			0x0F000000
+#define ROW_ADDR_CHIP_SEL_SHIFT			24
+#define ROW_ADDR_ROW_ADDR3_MASK			0x00FF0000
+#define ROW_ADDR_ROW_ADDR3_SHIFT		16
+#define ROW_ADDR_ROW_ADDR2_MASK			0x0000FF00
+#define ROW_ADDR_ROW_ADDR2_SHIFT		8
+#define ROW_ADDR_ROW_ADDR1_MASK			0x000000FF
+#define ROW_ADDR_ROW_ADDR1_SHIFT		0
+
+/* NFC_FLASH_COMMAND_REPEAT Field */
+#define COMMAND_REPEAT_MASK			0x0000FFFF
+#define COMMAND_REPEAT_SHIFT			0
+#define COMMAND_REPEAT_REPEAT_COUNT_MASK	0x0000FFFF
+#define COMMAND_REPEAT_REPEAT_COUNT_SHIFT	0
+
+/* NFC_ROW_ADDR_INC Field */
+#define ROW_ADDR_INC_MASK			0x00FFFFFF
+#define ROW_ADDR_INC_SHIFT			0
+#define ROW_ADDR_INC_ROW_ADDR3_INC_MASK		0x00FF0000
+#define ROW_ADDR_INC_ROW_ADDR3_INC_SHIFT	16
+#define ROW_ADDR_INC_ROW_ADDR2_INC_MASK		0x0000FF00
+#define ROW_ADDR_INC_ROW_ADDR2_INC_SHIFT	8
+#define ROW_ADDR_INC_ROW_ADDR1_INC_MASK		0x000000FF
+#define ROW_ADDR_INC_ROW_ADDR1_INC_SHIFT	0
+
+/* NFC_FLASH_STATUS1 Field */
+#define STATUS1_MASK				0xFFFFFFFF
+#define STATUS1_SHIFT				0
+#define STATUS1_ID_BYTE1_MASK			0xFF000000
+#define STATUS1_ID_BYTE1_SHIFT			24
+#define STATUS1_ID_BYTE2_MASK			0x00FF0000
+#define STATUS1_ID_BYTE2_SHIFT			16
+#define STATUS1_ID_BYTE3_MASK			0x0000FF00
+#define STATUS1_ID_BYTE3_SHIFT			8
+#define STATUS1_ID_BYTE4_MASK			0x000000FF
+#define STATUS1_ID_BYTE4_SHIFT			0
+
+/* NFC_FLASH_STATUS2 Field */
+#define STATUS2_MASK				0xFF0000FF
+#define STATUS2_SHIFT				0
+#define STATUS2_ID_BYTE5_MASK			0xFF000000
+#define STATUS2_ID_BYTE5_SHIFT			24
+#define STATUS_BYTE1_MASK			0x000000FF
+#define STATUS2_STATUS_BYTE1_SHIFT		0
+
+/* NFC_DMA1_ADDR Field */
+#define DMA1_ADDR_MASK				0xFFFFFFFF
+#define DMA1_ADDR_SHIFT				0
+#define DMA1_ADDR_DMA1_ADDR_MASK		0xFFFFFFFF
+#define DMA1_ADDR_DMA1_ADDR_SHIFT		0
+
+/* DMA2_ADDR Field */
+#define DMA2_ADDR_MASK				0xFFFFFFFF
+#define DMA2_ADDR_SHIFT				0
+#define DMA2_ADDR_DMA2_ADDR_MASK		0xFFFFFFFF
+#define DMA2_ADDR_DMA2_ADDR_SHIFT		0
+
+/* DMA_CONFIG Field */
+#define DMA_CONFIG_MASK				0xFFFFFFFF
+#define DMA_CONFIG_SHIFT			0
+#define DMA_CONFIG_DMA1_CNT_MASK		0xFFF00000
+#define DMA_CONFIG_DMA1_CNT_SHIFT		20
+#define DMA_CONFIG_DMA2_CNT_MASK		0x000FE000
+#define DMA_CONFIG_DMA2_CNT_SHIFT		13
+#define DMA_CONFIG_DMA2_OFFSET_MASK		0x00001FC0
+#define DMA_CONFIG_DMA2_OFFSET_SHIFT		2
+#define DMA_CONFIG_DMA1_ACT_MASK		0x00000002
+#define DMA_CONFIG_DMA1_ACT_SHIFT		1
+#define DMA_CONFIG_DMA2_ACT_MASK		0x00000001
+#define DMA_CONFIG_DMA2_ACT_SHIFT		0
+
+/* NFC_CACHE_SWAP Field */
+#define CACHE_SWAP_MASK				0x0FFE0FFE
+#define CACHE_SWAP_SHIFT			1
+#define CACHE_SWAP_CACHE_SWAP_ADDR2_MASK	0x0FFE0000
+#define CACHE_SWAP_CACHE_SWAP_ADDR2_SHIFT	17
+#define CACHE_SWAP_CACHE_SWAP_ADDR1_MASK	0x00000FFE
+#define CACHE_SWAP_CACHE_SWAP_ADDR1_SHIFT	1
+
+/* NFC_SECTOR_SIZE Field */
+#define SECTOR_SIZE_MASK			0x00001FFF
+#define SECTOR_SIZE_SHIFT			0
+#define SECTOR_SIZE_SECTOR_SIZE_MASK		0x00001FFF
+#define SECTOR_SIZE_SECTOR_SIZE_SHIFT		0
+
+/* NFC_FLASH_CONFIG Field */
+#define CONFIG_MASK				0xFFFFFFFF
+#define CONFIG_SHIFT				0
+#define CONFIG_STOP_ON_WERR_MASK		0x80000000
+#define CONFIG_STOP_ON_WERR_SHIFT		31
+#define CONFIG_ECC_SRAM_ADDR_MASK		0x7FC00000
+#define CONFIG_ECC_SRAM_ADDR_SHIFT		22
+#define CONFIG_ECC_SRAM_REQ_MASK		0x00200000
+#define CONFIG_ECC_SRAM_REQ_SHIFT		21
+#define CONFIG_DMA_REQ_MASK			0x00100000
+#define CONFIG_DMA_REQ_SHIFT			20
+#define CONFIG_ECC_MODE_MASK			0x000E0000
+#define CONFIG_ECC_MODE_SHIFT			17
+#define CONFIG_FAST_FLASH_MASK			0x00010000
+#define CONFIG_FAST_FLASH_SHIFT			16
+#define CONFIG_ID_COUNT_MASK			0x0000E000
+#define CONFIG_ID_COUNT_SHIFT			13
+#define CONFIG_CMD_TIMEOUT_MASK			0x00001F00
+#define CONFIG_CMD_TIMEOUT_SHIFT		8
+#define CONFIG_16BIT_MASK			0x00000080
+#define CONFIG_16BIT_SHIFT			7
+#define CONFIG_BOOT_MODE_MASK			0x00000040
+#define CONFIG_BOOT_MODE_SHIFT			6
+#define CONFIG_ADDR_AUTO_INCR_MASK		0x00000020
+#define CONFIG_ADDR_AUTO_INCR_SHIFT		5
+#define CONFIG_BUFNO_AUTO_INCR_MASK		0x00000010
+#define CONFIG_BUFNO_AUTO_INCR_SHIFT		4
+#define CONFIG_PAGE_CNT_MASK			0x0000000F
+#define CONFIG_PAGE_CNT_SHIFT			0
+
+/* NFC_IRQ_STATUS Field */
+#define MASK					0xEFFC003F
+#define SHIFT					0
+#define WERR_IRQ_MASK				0x80000000
+#define WERR_IRQ_SHIFT				31
+#define CMD_DONE_IRQ_MASK			0x40000000
+#define CMD_DONE_IRQ_SHIFT			30
+#define IDLE_IRQ_MASK				0x20000000
+#define IDLE_IRQ_SHIFT				29
+#define WERR_STATUS_MASK			0x08000000
+#define WERR_STATUS_SHIFT			27
+#define FLASH_CMD_BUSY_MASK			0x04000000
+#define FLASH_CMD_BUSY_SHIFT			26
+#define RESIDUE_BUSY_MASK			0x02000000
+#define RESIDUE_BUSY_SHIFT			25
+#define ECC_BUSY_MASK				0x01000000
+#define ECC_BUSY_SHIFT				24
+#define DMA_BUSY_MASK				0x00800000
+#define DMA_BUSY_SHIFT				23
+#define WERR_EN_MASK				0x00400000
+#define WERR_EN_SHIFT				22
+#define CMD_DONE_EN_MASK			0x00200000
+#define CMD_DONE_EN_SHIFT			21
+#define IDLE_EN_MASK				0x00100000
+#define IDLE_EN_SHIFT				20
+#define WERR_CLEAR_MASK				0x00080000
+#define WERR_CLEAR_SHIFT			19
+#define CMD_DONE_CLEAR_MASK			0x00040000
+#define CMD_DONE_CLEAR_SHIFT			18
+#define IDLE_CLEAR_MASK				0x00020000
+#define IDLE_CLEAR_SHIFT			17
+#define RESIDUE_BUFF_NO_MASK			0x00000030
+#define RESIDUE_BUFF_NO_SHIFT			4
+#define ECC_BUFF_NO_MASK			0x000000C0
+#define ECC_BUFF_NO_SHIFT			2
+#define DMA_BUFF_NO_MASK			0x00000003
+
+#endif /* MPC5125_NFC_H */