From d62e9caaaf7e6f5c7d86c9ea19170bfa5adda8be Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Mon, 19 Mar 2012 15:35:25 +0100 Subject: [PATCH 01/18] mtd: support ONFI multi lun NAND With onfi a flash is organized into one or more logical units (LUNs). A logical unit (LUN) is the minimum unit that can independently execute commands and report status. Mtd does not exploit LUN, so make it see a big single flash where size is lun_size * number_of_lun. Without this patch MT29F8G08ADBDAH4 size is 512MiB instead of 1GiB. Artem: split long line on 2 shorter ones. This is commit 637957551c0ac80de8dfc7650d320c5a98c2c0c0 from Linux Signed-off-by: Matthieu Castet Acked-by: Florian Fainelli Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse [scottwood@freescale.com: picked from Linux into U-Boot] Reported-by: Rafael Beims Signed-off-by: Scott Wood --- drivers/mtd/nand/nand_base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index bfd668fa0a..50bfb65f75 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2573,7 +2573,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, mtd->writesize = le32_to_cpu(p->byte_per_page); mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); - chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize; + chip->chipsize = le32_to_cpu(p->blocks_per_lun); + chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; *busw = 0; if (le16_to_cpu(p->features) & 1) *busw = NAND_BUSWIDTH_16; From eee623a5049963d0c085be37128bbd22bee1ba1e Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:42 -0500 Subject: [PATCH 02/18] nand: Add support for unlock.invert NAND unlock command allows an invert bit to be set to unlock all but the selected page range. Signed-off-by: Joe Hershberger [scottwood@freescale.com: updated docs and added comment about invert bit] Signed-off-by: Scott Wood --- common/cmd_nand.c | 13 ++++++++++--- doc/README.nand | 2 ++ drivers/mtd/nand/nand_util.c | 17 ++++++++++++++--- include/nand.h | 4 ++-- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index a91ccf4df3..f737c06f84 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -749,11 +749,18 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) return 0; } - if (strcmp(cmd, "unlock") == 0) { + if (strncmp(cmd, "unlock", 5) == 0) { + int allexcept = 0; + + s = strchr(cmd, '.'); + + if (s && !strcmp(s, ".allexcept")) + allexcept = 1; + if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0) return 1; - if (!nand_unlock(&nand_info[dev], off, size)) { + if (!nand_unlock(&nand_info[dev], off, size, allexcept)) { puts("NAND flash successfully unlocked\n"); } else { puts("Error unlocking NAND flash, " @@ -807,7 +814,7 @@ U_BOOT_CMD( "\n" "nand lock [tight] [status]\n" " bring nand to lock state or display locked pages\n" - "nand unlock [offset] [size] - unlock section" + "nand unlock[.allexcept] [offset] [size] - unlock section" #endif #ifdef CONFIG_ENV_OFFSET_OOB "\n" diff --git a/doc/README.nand b/doc/README.nand index 1602b5eee9..c130189587 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -228,6 +228,8 @@ NAND locking command (for chips with active LOCKPRE pin) "nand unlock [offset] [size]" unlock consecutive area (can be called multiple times for different areas) + "nand unlock.allexcept [offset] [size]" + unlock all except specified consecutive area I have tested the code with board containing 128MiB NAND large page chips and 32MiB small page chips. diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 7ed8b1891c..c66eeefcb6 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -317,18 +317,20 @@ int nand_get_lock_status(struct mtd_info *mtd, loff_t offset) * @param start start byte address * @param length number of bytes to unlock (must be a multiple of * page size nand->writesize) + * @param allexcept if set, unlock everything not selected * * @return 0 on success, -1 in case of error */ -int nand_unlock(struct mtd_info *mtd, ulong start, ulong length) +int nand_unlock(struct mtd_info *mtd, ulong start, ulong length, int allexcept) { int ret = 0; int chipnr; int status; int page; struct nand_chip *chip = mtd->priv; - printf ("nand_unlock: start: %08x, length: %d!\n", - (int)start, (int)length); + + debug("nand_unlock%s: start: %08x, length: %d!\n", + allexcept ? " (allexcept)" : "", start, length); /* select the NAND device */ chipnr = (int)(start >> chip->chip_shift); @@ -368,6 +370,15 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length) /* submit ADDRESS of LAST page to unlock */ page += (int)(length >> chip->page_shift); + + /* + * Page addresses for unlocking are supposed to be block-aligned. + * At least some NAND chips use the low bit to indicate that the + * page range should be inverted. + */ + if (allexcept) + page |= 1; + chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1, page & chip->pagemask); /* call wait ready function */ diff --git a/include/nand.h b/include/nand.h index c554c552f5..e9b47f1b25 100644 --- a/include/nand.h +++ b/include/nand.h @@ -144,8 +144,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); #define NAND_LOCK_STATUS_LOCK 0x02 #define NAND_LOCK_STATUS_UNLOCK 0x04 -int nand_lock( nand_info_t *meminfo, int tight ); -int nand_unlock( nand_info_t *meminfo, ulong start, ulong length ); +int nand_lock(nand_info_t *meminfo, int tight); +int nand_unlock(nand_info_t *meminfo, ulong start, ulong length, int allexcept); int nand_get_lock_status(nand_info_t *meminfo, loff_t offset); int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst); From e331ab2ee9b141f1de2a8fb0bfaf52f6273022f9 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:43 -0500 Subject: [PATCH 03/18] nand: Change ulong to loff_t and size_t Missed in previous cleanup. Signed-off-by: Joe Hershberger Signed-off-by: Scott Wood --- drivers/mtd/nand/nand_util.c | 5 +++-- include/nand.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index c66eeefcb6..5ef7df7401 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -321,7 +321,8 @@ int nand_get_lock_status(struct mtd_info *mtd, loff_t offset) * * @return 0 on success, -1 in case of error */ -int nand_unlock(struct mtd_info *mtd, ulong start, ulong length, int allexcept) +int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length, + int allexcept) { int ret = 0; int chipnr; @@ -329,7 +330,7 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length, int allexcept) int page; struct nand_chip *chip = mtd->priv; - debug("nand_unlock%s: start: %08x, length: %d!\n", + debug("nand_unlock%s: start: %08llx, length: %d!\n", allexcept ? " (allexcept)" : "", start, length); /* select the NAND device */ diff --git a/include/nand.h b/include/nand.h index e9b47f1b25..ff061c0b7c 100644 --- a/include/nand.h +++ b/include/nand.h @@ -145,7 +145,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); #define NAND_LOCK_STATUS_UNLOCK 0x04 int nand_lock(nand_info_t *meminfo, int tight); -int nand_unlock(nand_info_t *meminfo, ulong start, ulong length, int allexcept); +int nand_unlock(nand_info_t *meminfo, loff_t start, size_t length, + int allexcept); int nand_get_lock_status(nand_info_t *meminfo, loff_t offset); int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst); From 33b1d5cae3defdbeb30333ffac41bcbff85c5019 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:44 -0500 Subject: [PATCH 04/18] nand: consolidate duplicated constants NAND_CMD_ constants for lock/unlock should be in the header Signed-off-by: Joe Hershberger Signed-off-by: Scott Wood --- drivers/mtd/nand/nand_util.c | 6 ------ include/linux/mtd/nand.h | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 5ef7df7401..ffcb4f6ab9 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -207,12 +207,6 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) * Support for locking / unlocking operations of some NAND devices *****************************************************************************/ -#define NAND_CMD_LOCK 0x2a -#define NAND_CMD_LOCK_TIGHT 0x2c -#define NAND_CMD_UNLOCK1 0x23 -#define NAND_CMD_UNLOCK2 0x24 -#define NAND_CMD_LOCK_STATUS 0x7a - /** * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT * state diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 82704de083..6c4053151e 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -85,8 +85,10 @@ extern void nand_wait_ready(struct mtd_info *mtd); #define NAND_CMD_RESET 0xff #define NAND_CMD_LOCK 0x2a +#define NAND_CMD_LOCK_TIGHT 0x2c #define NAND_CMD_UNLOCK1 0x23 #define NAND_CMD_UNLOCK2 0x24 +#define NAND_CMD_LOCK_STATUS 0x7a /* Extended commands for large page devices */ #define NAND_CMD_READSTART 0x30 From e70bfa2986f9c028e3c21e0995285047a9baec27 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:45 -0500 Subject: [PATCH 05/18] nand: Make NAND lock status compatible with Micron Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is not the same as others. Instead of bit 1 being lock, it is #lock_tight. To make the driver support either format, ignore bit 1 and use only bit 0 and bit 2. Signed-off-by: Joe Hershberger Signed-off-by: Scott Wood --- common/cmd_nand.c | 8 +++++++- drivers/mtd/nand/nand_util.c | 2 -- include/nand.h | 1 - 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index f737c06f84..9c6dabe589 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -231,12 +231,18 @@ print: #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK static void print_status(ulong start, ulong end, ulong erasesize, int status) { + /* + * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is + * not the same as others. Instead of bit 1 being lock, it is + * #lock_tight. To make the driver support either format, ignore bit 1 + * and use only bit 0 and bit 2. + */ printf("%08lx - %08lx: %08lx blocks %s%s%s\n", start, end - 1, (end - start) / erasesize, ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), - ((status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), + (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""), ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); } diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index ffcb4f6ab9..c4752a7cbf 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -265,7 +265,6 @@ int nand_lock(struct mtd_info *mtd, int tight) * >0 lock status: * bitfield with the following combinations: * NAND_LOCK_STATUS_TIGHT: page in tight state - * NAND_LOCK_STATUS_LOCK: page locked * NAND_LOCK_STATUS_UNLOCK: page unlocked * */ @@ -294,7 +293,6 @@ int nand_get_lock_status(struct mtd_info *mtd, loff_t offset) chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask); ret = chip->read_byte(mtd) & (NAND_LOCK_STATUS_TIGHT - | NAND_LOCK_STATUS_LOCK | NAND_LOCK_STATUS_UNLOCK); out: diff --git a/include/nand.h b/include/nand.h index ff061c0b7c..bbe28b20bb 100644 --- a/include/nand.h +++ b/include/nand.h @@ -141,7 +141,6 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); #define NAND_LOCK_STATUS_TIGHT 0x01 -#define NAND_LOCK_STATUS_LOCK 0x02 #define NAND_LOCK_STATUS_UNLOCK 0x04 int nand_lock(nand_info_t *meminfo, int tight); From 9c790a748f6b61e36f7aaf0c8d5ed35c9b09f454 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 30 Aug 2012 13:39:38 +0000 Subject: [PATCH 06/18] mtd: nand: allow NAND_NO_SUBPAGE_WRITE to be set from driver This is based on Linux kernel -next: commit 14f44abf1dafc20ba42ce8616a8fc8fbd1b3712b Author: Brian Norris Date: Fri Jul 13 09:28:24 2012 -0700 mtd: nand: allow NAND_NO_SUBPAGE_WRITE to be set from driver The NAND_CHIPOPTIONS_MSK has limited utility and is causing real bugs. It silently masks off at least one flag that might be set by the driver (NAND_NO_SUBPAGE_WRITE). This breaks the GPMI NAND driver and possibly others. Really, as long as driver writers exercise a small amount of care with NAND_* options, this mask is not necessary at all; it was only here to prevent certain options from accidentally being set by the driver. But the original thought turns out to be a bad idea occasionally. Thus, kill it. Note, this patch fixes some major gpmi-nand breakage. Signed-off-by: Marek Vasut Cc: Brian Norris Cc: Eric Nelson Cc: Fabio Estevam Cc: Otavio Salvador Cc: Scott Wood Signed-off-by: Scott Wood --- drivers/mtd/nand/nand_base.c | 7 ++----- include/linux/mtd/nand.h | 3 --- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 50bfb65f75..390ff90212 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2579,9 +2579,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, if (le16_to_cpu(p->features) & 1) *busw = NAND_BUSWIDTH_16; - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= (NAND_NO_READRDY | - NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; + chip->options |= NAND_NO_READRDY | NAND_NO_AUTOINCR; return 1; } @@ -2753,8 +2751,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, } } /* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= type->options & NAND_CHIPOPTIONS_MSK; + chip->options |= type->options; /* Check if chip is a not a samsung device. Do not clear the * options for chips which are not having an extended id. diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 6c4053151e..c06866b061 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -207,9 +207,6 @@ typedef enum { #define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \ && (chip->page_shift > 9)) -/* Mask to zero out the chip options, which come from the id table */ -#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) - /* Non chip related options */ /* * Use a flash based bad block table. OOB identifier is saved in OOB area. From 80c8ab7b25579529809792eef51fe660308fecb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:48:12 +0200 Subject: [PATCH 07/18] mxc nand: Merge mtd and spl register definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patches fixes the TODO to use same register definitions in mtd mxc_nand and nand_spl fsl nfc drivers. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- drivers/mtd/nand/mxc_nand.c | 245 +++++++---------------------------- include/fsl_nfc.h | 97 +++++++------- nand_spl/nand_boot_fsl_nfc.c | 58 ++++----- 3 files changed, 127 insertions(+), 273 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 936186f75e..9a9260caf4 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -25,168 +25,23 @@ #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) #include #endif +#include #define DRIVER_NAME "mxc_nand" -/* - * TODO: Use same register defs here as nand_spl mxc nand driver. - */ -/* - * Register map and bit definitions for the Freescale NAND Flash Controller - * present in various i.MX devices. - * - * MX31 and MX27 have version 1 which has - * 4 512 byte main buffers and - * 4 16 byte spare buffers - * to support up to 2K byte pagesize nand. - * Reading or writing a 2K page requires 4 FDI/FDO cycles. - * - * MX25 has version 1.1 which has - * 8 512 byte main buffers and - * 8 64 byte spare buffers - * to support up to 4K byte pagesize nand. - * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. - * Also some of registers are moved and/or changed meaning as seen below. - */ -#if defined(CONFIG_MX31) || defined(CONFIG_MX27) -#define MXC_NFC_V1 -#elif defined(CONFIG_MX25) || defined(CONFIG_MX35) -#define MXC_NFC_V1_1 -#else -#warning "MXC NFC version not defined" -#endif - -#if defined(MXC_NFC_V1) -#define NAND_MXC_NR_BUFS 4 -#define NAND_MXC_SPARE_BUF_SIZE 16 -#define NAND_MXC_REG_OFFSET 0xe00 -#define is_mxc_nfc_11() 0 -#elif defined(MXC_NFC_V1_1) -#define NAND_MXC_NR_BUFS 8 -#define NAND_MXC_SPARE_BUF_SIZE 64 -#define NAND_MXC_REG_OFFSET 0x1e00 -#define is_mxc_nfc_11() 1 -#else -#error "define CONFIG_NAND_MXC_VXXX to use mtd mxc nand driver" -#endif -struct nfc_regs { - uint8_t main_area[NAND_MXC_NR_BUFS][0x200]; - uint8_t spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE]; - /* - * reserved size is offset of nfc registers - * minus total main and spare sizes - */ - uint8_t reserved1[NAND_MXC_REG_OFFSET - - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; -#if defined(MXC_NFC_V1) - uint16_t nfc_buf_size; - uint16_t reserved2; - uint16_t nfc_buf_addr; - uint16_t nfc_flash_addr; - uint16_t nfc_flash_cmd; - uint16_t nfc_config; - uint16_t nfc_ecc_status_result; - uint16_t nfc_rsltmain_area; - uint16_t nfc_rsltspare_area; - uint16_t nfc_wrprot; - uint16_t nfc_unlockstart_blkaddr; - uint16_t nfc_unlockend_blkaddr; - uint16_t nfc_nf_wrprst; - uint16_t nfc_config1; - uint16_t nfc_config2; -#elif defined(MXC_NFC_V1_1) - uint16_t reserved2[2]; - uint16_t nfc_buf_addr; - uint16_t nfc_flash_addr; - uint16_t nfc_flash_cmd; - uint16_t nfc_config; - uint16_t nfc_ecc_status_result; - uint16_t nfc_ecc_status_result2; - uint16_t nfc_spare_area_size; - uint16_t nfc_wrprot; - uint16_t reserved3[2]; - uint16_t nfc_nf_wrprst; - uint16_t nfc_config1; - uint16_t nfc_config2; - uint16_t reserved4; - uint16_t nfc_unlockstart_blkaddr; - uint16_t nfc_unlockend_blkaddr; - uint16_t nfc_unlockstart_blkaddr1; - uint16_t nfc_unlockend_blkaddr1; - uint16_t nfc_unlockstart_blkaddr2; - uint16_t nfc_unlockend_blkaddr2; - uint16_t nfc_unlockstart_blkaddr3; - uint16_t nfc_unlockend_blkaddr3; -#endif -}; - -/* - * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register - * for Command operation - */ -#define NFC_CMD 0x1 - -/* - * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register - * for Address operation - */ -#define NFC_ADDR 0x2 - -/* - * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register - * for Input operation - */ -#define NFC_INPUT 0x4 - -/* - * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register - * for Data Output operation - */ -#define NFC_OUTPUT 0x8 - -/* - * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register - * for Read ID operation - */ -#define NFC_ID 0x10 - -/* - * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register - * for Read Status operation - */ -#define NFC_STATUS 0x20 - -/* - * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read - * Status operation - */ -#define NFC_INT 0x8000 - -#ifdef MXC_NFC_V1_1 -#define NFC_4_8N_ECC (1 << 0) -#else -#define NFC_4_8N_ECC 0 -#endif -#define NFC_SP_EN (1 << 2) -#define NFC_ECC_EN (1 << 3) -#define NFC_BIG (1 << 5) -#define NFC_RST (1 << 6) -#define NFC_CE (1 << 7) -#define NFC_ONE_CYCLE (1 << 8) - typedef enum {false, true} bool; struct mxc_nand_host { - struct mtd_info mtd; - struct nand_chip *nand; + struct mtd_info mtd; + struct nand_chip *nand; - struct nfc_regs __iomem *regs; - int spare_only; - int status_request; - int pagesize_2k; - int clk_act; - uint16_t col_addr; - unsigned int page_addr; + struct fsl_nfc_regs __iomem *regs; + int spare_only; + int status_request; + int pagesize_2k; + int clk_act; + uint16_t col_addr; + unsigned int page_addr; }; static struct mxc_nand_host mxc_host; @@ -304,10 +159,10 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint32_t tmp; while (max_retries-- > 0) { - if (readw(&host->regs->nfc_config2) & NFC_INT) { - tmp = readw(&host->regs->nfc_config2); + if (readw(&host->regs->config2) & NFC_INT) { + tmp = readw(&host->regs->config2); tmp &= ~NFC_INT; - writew(tmp, &host->regs->nfc_config2); + writew(tmp, &host->regs->config2); break; } udelay(1); @@ -326,8 +181,8 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd); - writew(cmd, &host->regs->nfc_flash_cmd); - writew(NFC_CMD, &host->regs->nfc_config2); + writew(cmd, &host->regs->flash_cmd); + writew(NFC_CMD, &host->regs->config2); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, cmd); @@ -342,8 +197,8 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr); - writew(addr, &host->regs->nfc_flash_addr); - writew(NFC_ADDR, &host->regs->nfc_config2); + writew(addr, &host->regs->flash_addr); + writew(NFC_ADDR, &host->regs->config2); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, addr); @@ -375,19 +230,19 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, } } - writew(buf_id, &host->regs->nfc_buf_addr); + writew(buf_id, &host->regs->buf_addr); /* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint16_t config1 = readw(&host->regs->nfc_config1); + uint16_t config1 = readw(&host->regs->config1); if (spare_only) config1 |= NFC_SP_EN; else config1 &= ~(NFC_SP_EN); - writew(config1, &host->regs->nfc_config1); + writew(config1, &host->regs->config1); } - writew(NFC_INPUT, &host->regs->nfc_config2); + writew(NFC_INPUT, &host->regs->config2); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -402,19 +257,19 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only); - writew(buf_id, &host->regs->nfc_buf_addr); + writew(buf_id, &host->regs->buf_addr); /* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint32_t config1 = readw(&host->regs->nfc_config1); + uint32_t config1 = readw(&host->regs->config1); if (spare_only) config1 |= NFC_SP_EN; else config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->nfc_config1); + writew(config1, &host->regs->config1); } - writew(NFC_OUTPUT, &host->regs->nfc_config2); + writew(NFC_OUTPUT, &host->regs->config2); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -442,14 +297,14 @@ static void send_read_id(struct mxc_nand_host *host) uint16_t tmp; /* NANDFC buffer 0 is used for device ID output */ - writew(0x0, &host->regs->nfc_buf_addr); + writew(0x0, &host->regs->buf_addr); /* Read ID into main buffer */ - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); - writew(NFC_ID, &host->regs->nfc_config2); + writew(NFC_ID, &host->regs->config2); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -469,14 +324,14 @@ static uint16_t get_dev_status(struct mxc_nand_host *host) /* store the main area1 first word, later do recovery */ store = readl(main_buf); /* NANDFC buffer 1 is used for device status */ - writew(1, &host->regs->nfc_buf_addr); + writew(1, &host->regs->buf_addr); /* Read status into main buffer */ - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); - writew(NFC_STATUS, &host->regs->nfc_config2); + writew(NFC_STATUS, &host->regs->config2); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -515,13 +370,13 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp = readw(&host->regs->nfc_config1); + uint16_t tmp = readw(&host->regs->config1); if (on) tmp |= NFC_ECC_EN; else tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); } static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, @@ -799,7 +654,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result); + uint16_t ecc_status = readw(&host->regs->ecc_status_result); int subpages = mtd->writesize / nand_chip->subpagesize; int pg2blk_shift = nand_chip->phys_erase_shift - nand_chip->page_shift; @@ -845,7 +700,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result); + uint16_t ecc_status = readw(&host->regs->ecc_status_result); if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { MTDDEBUG(MTD_DEBUG_LEVEL0, @@ -1289,14 +1144,14 @@ static void mxc_setup_config1(void) { uint16_t tmp; - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp |= NFC_ONE_CYCLE; tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); if (host->pagesize_2k) - writew(64/2, &host->regs->nfc_spare_area_size); + writew(64/2, &host->regs->spare_area_size); else - writew(16/2, &host->regs->nfc_spare_area_size); + writew(16/2, &host->regs->spare_area_size); } #else #define mxc_setup_config1() @@ -1359,7 +1214,7 @@ int board_nand_init(struct nand_chip *this) this->read_buf = mxc_nand_read_buf; this->verify_buf = mxc_nand_verify_buf; - host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; + host->regs = (struct fsl_nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; host->clk_act = 1; #ifdef CONFIG_MXC_NAND_HWECC @@ -1383,15 +1238,15 @@ int board_nand_init(struct nand_chip *this) host->pagesize_2k = 0; this->ecc.size = 512; - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp |= NFC_ECC_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); #else this->ecc.layout = &nand_soft_eccoob; this->ecc.mode = NAND_ECC_SOFT; - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); #endif /* Reset NAND */ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); @@ -1400,10 +1255,10 @@ int board_nand_init(struct nand_chip *this) * preset operation * Unlock the internal RAM Buffer */ - writew(0x2, &host->regs->nfc_config); + writew(0x2, &host->regs->config); /* Blocks to be unlocked */ - writew(0x0, &host->regs->nfc_unlockstart_blkaddr); + writew(0x0, &host->regs->unlockstart_blkaddr); /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the * unlockend_blkaddr, but the magic 0x4000 does not always work * when writing more than some 32 megabytes (on 2k page nands) @@ -1415,10 +1270,10 @@ int board_nand_init(struct nand_chip *this) * This might be NAND chip specific and the i.MX31 datasheet is * extremely vague about the semantics of this register. */ - writew(0xFFFF, &host->regs->nfc_unlockend_blkaddr); + writew(0xFFFF, &host->regs->unlockend_blkaddr); /* Unlock Block Command for given address range */ - writew(0x4, &host->regs->nfc_wrprot); + writew(0x4, &host->regs->wrprot); /* NAND bus width determines access functions used by upper layer */ if (is_16bit_nand()) diff --git a/include/fsl_nfc.h b/include/fsl_nfc.h index 279aaa55de..6691e410b6 100644 --- a/include/fsl_nfc.h +++ b/include/fsl_nfc.h @@ -24,28 +24,25 @@ #define __FSL_NFC_H /* - * TODO: Use same register defs for nand_spl mxc nand driver - * and mtd mxc nand driver. + * Register map and bit definitions for the Freescale NAND Flash Controller + * present in various i.MX devices. * - * Register map and bit definitions for the Freescale NAND Flash - * Controller present in various i.MX devices. + * MX31 and MX27 have version 1, which has: + * 4 512-byte main buffers and + * 4 16-byte spare buffers + * to support up to 2K byte pagesize nand. + * Reading or writing a 2K page requires 4 FDI/FDO cycles. * - * MX31 and MX27 have version 1 which has - * 4 512 byte main buffers and - * 4 16 byte spare buffers - * to support up to 2K byte pagesize nand. - * Reading or writing a 2K page requires 4 FDI/FDO cycles. - * - * MX25 has version 1.1 which has - * 8 512 byte main buffers and - * 8 64 byte spare buffers - * to support up to 4K byte pagesize nand. - * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. - * Also some of registers are moved and/or changed meaning as seen below. + * MX25 and MX35 have version 1.1, which has: + * 8 512-byte main buffers and + * 8 64-byte spare buffers + * to support up to 4K byte pagesize nand. + * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. + * Also some of registers are moved and/or changed meaning as seen below. */ -#if defined(CONFIG_MX31) || defined(CONFIG_MX27) +#if defined(CONFIG_MX27) || defined(CONFIG_MX31) #define MXC_NFC_V1 -#elif defined(CONFIG_MX25) +#elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V1_1 #else #warning "MXC NFC version not defined" @@ -55,18 +52,20 @@ #define NAND_MXC_NR_BUFS 4 #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 -#define NAND_MXC_2K_MULTI_CYCLE 1 +#define NAND_MXC_2K_MULTI_CYCLE +#define is_mxc_nfc_11() 0 #elif defined(MXC_NFC_V1_1) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 +#define is_mxc_nfc_11() 1 #else -#error "define CONFIG_NAND_MXC_VXXX to use the mxc spl_nand driver" +#error "define CONFIG_NAND_MXC_VXXX to use the mxc nand driver" #endif struct fsl_nfc_regs { - u32 main_area[NAND_MXC_NR_BUFS][512/4]; - u32 spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE/4]; + u8 main_area[NAND_MXC_NR_BUFS][0x200]; + u8 spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE]; /* * reserved size is offset of nfc registers * minus total main and spare sizes @@ -74,44 +73,44 @@ struct fsl_nfc_regs { u8 reserved1[NAND_MXC_REG_OFFSET - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; #if defined(MXC_NFC_V1) - u16 bufsiz; + u16 buf_size; u16 reserved2; - u16 buffer_address; - u16 flash_add; + u16 buf_addr; + u16 flash_addr; u16 flash_cmd; - u16 configuration; + u16 config; u16 ecc_status_result; - u16 ecc_rslt_main_area; - u16 ecc_rslt_spare_area; - u16 nf_wr_prot; - u16 unlock_start_blk_add; - u16 unlock_end_blk_add; - u16 nand_flash_wr_pr_st; - u16 nand_flash_config1; - u16 nand_flash_config2; + u16 rsltmain_area; + u16 rsltspare_area; + u16 wrprot; + u16 unlockstart_blkaddr; + u16 unlockend_blkaddr; + u16 nf_wrprst; + u16 config1; + u16 config2; #elif defined(MXC_NFC_V1_1) u16 reserved2[2]; - u16 buffer_address; - u16 flash_add; + u16 buf_addr; + u16 flash_addr; u16 flash_cmd; - u16 configuration; + u16 config; u16 ecc_status_result; u16 ecc_status_result2; u16 spare_area_size; - u16 nf_wr_prot; + u16 wrprot; u16 reserved3[2]; - u16 nand_flash_wr_pr_st; - u16 nand_flash_config1; - u16 nand_flash_config2; + u16 nf_wrprst; + u16 config1; + u16 config2; u16 reserved4; - u16 unlock_start_blk_add0; - u16 unlock_end_blk_add0; - u16 unlock_start_blk_add1; - u16 unlock_end_blk_add1; - u16 unlock_start_blk_add2; - u16 unlock_end_blk_add2; - u16 unlock_start_blk_add3; - u16 unlock_end_blk_add3; + u16 unlockstart_blkaddr; + u16 unlockend_blkaddr; + u16 unlockstart_blkaddr1; + u16 unlockend_blkaddr1; + u16 unlockstart_blkaddr2; + u16 unlockend_blkaddr2; + u16 unlockstart_blkaddr3; + u16 unlockend_blkaddr3; #endif }; diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index d6b0d9b6d1..f437debdc1 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -36,13 +36,13 @@ static void nfc_wait_ready(void) { uint32_t tmp; - while (!(readw(&nfc->nand_flash_config2) & NFC_INT)) + while (!(readw(&nfc->config2) & NFC_INT)) ; /* Reset interrupt flag */ - tmp = readw(&nfc->nand_flash_config2); + tmp = readw(&nfc->config2); tmp &= ~NFC_INT; - writew(tmp, &nfc->nand_flash_config2); + writew(tmp, &nfc->config2); } void nfc_nand_init(void) @@ -54,10 +54,10 @@ void nfc_nand_init(void) writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); /* unlocking RAM Buff */ - writew(0x2, &nfc->configuration); + writew(0x2, &nfc->config); /* hardware ECC checking and correct */ - config1 = readw(&nfc->nand_flash_config1) | NFC_ECC_EN | 0x800; + config1 = readw(&nfc->config1) | NFC_ECC_EN | 0x800; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 @@ -66,20 +66,20 @@ void nfc_nand_init(void) config1 &= ~NFC_4_8N_ECC; else config1 |= NFC_4_8N_ECC; - writew(config1, &nfc->nand_flash_config1); + writew(config1, &nfc->config1); #elif defined(MXC_NFC_V1) /* unlocking RAM Buff */ - writew(0x2, &nfc->configuration); + writew(0x2, &nfc->config); /* hardware ECC checking and correct */ - writew(NFC_ECC_EN, &nfc->nand_flash_config1); + writew(NFC_ECC_EN, &nfc->config1); #endif } static void nfc_nand_command(unsigned short command) { writew(command, &nfc->flash_cmd); - writew(NFC_CMD, &nfc->nand_flash_config2); + writew(NFC_CMD, &nfc->config2); nfc_wait_ready(); } @@ -87,14 +87,14 @@ static void nfc_nand_page_address(unsigned int page_address) { unsigned int page_count; - writew(0x00, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(0x00, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready(); /* code only for large page flash */ if (CONFIG_SYS_NAND_PAGE_SIZE > 512) { - writew(0x00, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(0x00, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready(); } @@ -103,30 +103,30 @@ static void nfc_nand_page_address(unsigned int page_address) if (page_address <= page_count) { page_count--; /* transform 0x01000000 to 0x00ffffff */ do { - writew(page_address & 0xff, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(page_address & 0xff, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready(); page_address = page_address >> 8; page_count = page_count >> 8; } while (page_count); } - writew(0x00, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(0x00, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready(); } static void nfc_nand_data_output(void) { - int config1 = readw(&nfc->nand_flash_config1); + int config1 = readw(&nfc->config1); #ifdef NAND_MXC_2K_MULTI_CYCLE int i; #endif config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->nand_flash_config1); - writew(0, &nfc->buffer_address); - writew(NFC_OUTPUT, &nfc->nand_flash_config2); + writew(config1, &nfc->config1); + writew(0, &nfc->buf_addr); + writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready(); #ifdef NAND_MXC_2K_MULTI_CYCLE /* @@ -134,11 +134,11 @@ static void nfc_nand_data_output(void) * for pages larger than 512 bytes. */ for (i = 1; i < (CONFIG_SYS_NAND_PAGE_SIZE / 512); i++) { - config1 = readw(&nfc->nand_flash_config1); + config1 = readw(&nfc->config1); config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->nand_flash_config1); - writew(i, &nfc->buffer_address); - writew(NFC_OUTPUT, &nfc->nand_flash_config2); + writew(config1, &nfc->config1); + writew(i, &nfc->buf_addr); + writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready(); } #endif @@ -155,7 +155,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) u32 *src; u32 *dst; - writew(0, &nfc->buffer_address); /* read in first 0 buffer */ + writew(0, &nfc->buf_addr); /* read in first 0 buffer */ nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address); @@ -167,7 +167,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) if (nfc_nand_check_ecc()) return -1; - src = &nfc->main_area[0][0]; + src = (u32 *)&nfc->main_area[0][0]; dst = (u32 *)buf; /* main copy loop from NAND-buffer to SDRAM memory */ @@ -188,7 +188,7 @@ static int is_badblock(int pagenumber) /* Check the first two pages for bad block markers */ for (page = pagenumber; page < pagenumber + 2; page++) { - writew(0, &nfc->buffer_address); /* read in first 0 buffer */ + writew(0, &nfc->buf_addr); /* read in first 0 buffer */ nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page); @@ -197,7 +197,7 @@ static int is_badblock(int pagenumber) nfc_nand_data_output(); /* fill the main buffer 0 */ - src = &nfc->spare_area[0][0]; + src = (u32 *)&nfc->spare_area[0][0]; /* * IMPORTANT NOTE: The nand flash controller uses a non- From 365b2c0761040764953e659f3385840e33823807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:48:26 +0200 Subject: [PATCH 08/18] mxc nand: cosmectic: Light cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- drivers/mtd/nand/mxc_nand.c | 9 +++------ include/fsl_nfc.h | 1 + nand_spl/nand_boot_fsl_nfc.c | 14 +++++++------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 9a9260caf4..62d8c6b38c 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -123,8 +123,7 @@ static int is_16bit_nand(void) #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) static int is_16bit_nand(void) { - struct ccm_regs *ccm = - (struct ccm_regs *)IMX_CCM_BASE; + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; if (readl(&ccm->rcsr) & CCM_RCSR_NF_16BIT_SEL) return 1; @@ -238,7 +237,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) config1 |= NFC_SP_EN; else - config1 &= ~(NFC_SP_EN); + config1 &= ~NFC_SP_EN; writew(config1, &host->regs->config1); } @@ -687,7 +686,6 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, #define mxc_nand_write_page_syndrome NULL #define mxc_nand_write_page_raw_syndrome NULL #define mxc_nand_write_oob_syndrome NULL -#define mxc_nfc_11_nand_correct_data NULL static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) @@ -1188,7 +1186,6 @@ int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; uint16_t tmp; - int err = 0; #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT this->options |= NAND_USE_FLASH_BBT; @@ -1287,5 +1284,5 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif mxc_setup_config1(); - return err; + return 0; } diff --git a/include/fsl_nfc.h b/include/fsl_nfc.h index 6691e410b6..1c16c71d45 100644 --- a/include/fsl_nfc.h +++ b/include/fsl_nfc.h @@ -166,5 +166,6 @@ struct fsl_nfc_regs { #define NFC_RST (1 << 6) #define NFC_CE (1 << 7) #define NFC_ONE_CYCLE (1 << 8) +#define NFC_FP_INT (1 << 11) #endif /* __FSL_NFC_H */ diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index f437debdc1..b90f93e3b8 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -45,10 +45,10 @@ static void nfc_wait_ready(void) writew(tmp, &nfc->config2); } -void nfc_nand_init(void) +static void nfc_nand_init(void) { #if defined(MXC_NFC_V1_1) - int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1; writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); @@ -57,12 +57,12 @@ void nfc_nand_init(void) writew(0x2, &nfc->config); /* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | 0x800; + config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 */ - if ((CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page) > 16) + if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) config1 &= ~NFC_4_8N_ECC; else config1 |= NFC_4_8N_ECC; @@ -133,7 +133,7 @@ static void nfc_nand_data_output(void) * This NAND controller requires multiple input commands * for pages larger than 512 bytes. */ - for (i = 1; i < (CONFIG_SYS_NAND_PAGE_SIZE / 512); i++) { + for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { config1 = readw(&nfc->config1); config1 |= NFC_ECC_EN | NFC_INT_MSK; writew(config1, &nfc->config1); @@ -171,7 +171,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) dst = (u32 *)buf; /* main copy loop from NAND-buffer to SDRAM memory */ - for (i = 0; i < (CONFIG_SYS_NAND_PAGE_SIZE / 4); i++) { + for (i = 0; i < CONFIG_SYS_NAND_PAGE_SIZE / 4; i++) { writel(readl(src), dst); src++; dst++; @@ -230,7 +230,7 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf) page = from / CONFIG_SYS_NAND_PAGE_SIZE; i = 0; - while (i < (size / CONFIG_SYS_NAND_PAGE_SIZE)) { + while (i < size / CONFIG_SYS_NAND_PAGE_SIZE) { if (nfc_read_page(page, buf) < 0) return -1; From 5d818a2821c3c7cf350ee4a2c67a11f8e1039af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:48:56 +0200 Subject: [PATCH 09/18] spl mxc nand: Merge duplicated code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge duplicated code into functions, which is better for SPL size too. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- nand_spl/nand_boot_fsl_nfc.c | 50 +++++++++++++++++------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index b90f93e3b8..b98fe41620 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -83,37 +83,35 @@ static void nfc_nand_command(unsigned short command) nfc_wait_ready(); } +static void nfc_nand_address(unsigned short address) +{ + writew(address, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); + nfc_wait_ready(); +} + static void nfc_nand_page_address(unsigned int page_address) { unsigned int page_count; - writew(0x00, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); + nfc_nand_address(0x00); /* code only for large page flash */ - if (CONFIG_SYS_NAND_PAGE_SIZE > 512) { - writew(0x00, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); - } + if (CONFIG_SYS_NAND_PAGE_SIZE > 512) + nfc_nand_address(0x00); page_count = CONFIG_SYS_NAND_SIZE / CONFIG_SYS_NAND_PAGE_SIZE; if (page_address <= page_count) { page_count--; /* transform 0x01000000 to 0x00ffffff */ do { - writew(page_address & 0xff, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); + nfc_nand_address(page_address & 0xff); page_address = page_address >> 8; page_count = page_count >> 8; } while (page_count); } - writew(0x00, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); + nfc_nand_address(0x00); } static void nfc_nand_data_output(void) @@ -149,12 +147,8 @@ static int nfc_nand_check_ecc(void) return readw(&nfc->ecc_status_result); } -static int nfc_read_page(unsigned int page_address, unsigned char *buf) +static void nfc_nand_read_page(unsigned int page_address) { - int i; - u32 *src; - u32 *dst; - writew(0, &nfc->buf_addr); /* read in first 0 buffer */ nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address); @@ -163,6 +157,15 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) nfc_nand_command(NAND_CMD_READSTART); nfc_nand_data_output(); /* fill the main buffer 0 */ +} + +static int nfc_read_page(unsigned int page_address, unsigned char *buf) +{ + int i; + u32 *src; + u32 *dst; + + nfc_nand_read_page(page_address); if (nfc_nand_check_ecc()) return -1; @@ -188,14 +191,7 @@ static int is_badblock(int pagenumber) /* Check the first two pages for bad block markers */ for (page = pagenumber; page < pagenumber + 2; page++) { - writew(0, &nfc->buf_addr); /* read in first 0 buffer */ - nfc_nand_command(NAND_CMD_READ0); - nfc_nand_page_address(page); - - if (CONFIG_SYS_NAND_PAGE_SIZE > 512) - nfc_nand_command(NAND_CMD_READSTART); - - nfc_nand_data_output(); /* fill the main buffer 0 */ + nfc_nand_read_page(page); src = (u32 *)&nfc->spare_area[0][0]; From 0eee20fc1bb16f484771d626e1d7bde7d770a01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:49:15 +0200 Subject: [PATCH 10/18] spl mxc nand: Remove duplicated code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ECC_EN and INT_MSK bits of CONFIG1 are not volatile, so it is sufficient to set them once in nfc_nand_init(). Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- nand_spl/nand_boot_fsl_nfc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index b98fe41620..059969ba9a 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -57,7 +57,7 @@ static void nfc_nand_init(void) writew(0x2, &nfc->config); /* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_FP_INT; + config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | NFC_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 @@ -72,7 +72,7 @@ static void nfc_nand_init(void) writew(0x2, &nfc->config); /* hardware ECC checking and correct */ - writew(NFC_ECC_EN, &nfc->config1); + writew(NFC_ECC_EN | NFC_INT_MSK, &nfc->config1); #endif } @@ -116,13 +116,10 @@ static void nfc_nand_page_address(unsigned int page_address) static void nfc_nand_data_output(void) { - int config1 = readw(&nfc->config1); #ifdef NAND_MXC_2K_MULTI_CYCLE int i; #endif - config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->config1); writew(0, &nfc->buf_addr); writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready(); @@ -132,9 +129,6 @@ static void nfc_nand_data_output(void) * for pages larger than 512 bytes. */ for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { - config1 = readw(&nfc->config1); - config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->config1); writew(i, &nfc->buf_addr); writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready(); From 0e55ad7271259b1de183fb5329ea7f07774e368d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:49:31 +0200 Subject: [PATCH 11/18] spl mxc nand: Set symmetric mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the spl mxc nand driver for IP 1.1 in symmetric mode, like the mtd driver. In this way, for both drivers, one input clock period of the NFC IP will produce one R/W cycle. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- nand_spl/nand_boot_fsl_nfc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index 059969ba9a..842943c651 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -57,7 +57,8 @@ static void nfc_nand_init(void) writew(0x2, &nfc->config); /* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | NFC_FP_INT; + config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | + NFC_ONE_CYCLE | NFC_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 From c1db8dd62b337372a08942e1c5945a8590afbc58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:49:42 +0200 Subject: [PATCH 12/18] mxc nand: Access all ecc_status_result fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the NFC IP 1.1, the 32-bit ecc_status_result value comes from 2 consecutive 16-bit registers. This patch reads all the fields of this value, which makes a difference for 4-kiB NF pages. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- drivers/mtd/nand/mxc_nand.c | 2 +- include/fsl_nfc.h | 3 +-- nand_spl/nand_boot_fsl_nfc.c | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 62d8c6b38c..4564b2509c 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -653,7 +653,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t ecc_status = readw(&host->regs->ecc_status_result); + uint32_t ecc_status = readl(&host->regs->ecc_status_result); int subpages = mtd->writesize / nand_chip->subpagesize; int pg2blk_shift = nand_chip->phys_erase_shift - nand_chip->page_shift; diff --git a/include/fsl_nfc.h b/include/fsl_nfc.h index 1c16c71d45..c248cef654 100644 --- a/include/fsl_nfc.h +++ b/include/fsl_nfc.h @@ -94,8 +94,7 @@ struct fsl_nfc_regs { u16 flash_addr; u16 flash_cmd; u16 config; - u16 ecc_status_result; - u16 ecc_status_result2; + u32 ecc_status_result; u16 spare_area_size; u16 wrprot; u16 reserved3[2]; diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index 842943c651..4c5a7feec1 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -139,7 +139,11 @@ static void nfc_nand_data_output(void) static int nfc_nand_check_ecc(void) { +#if defined(MXC_NFC_V1) return readw(&nfc->ecc_status_result); +#elif defined(MXC_NFC_V1_1) + return readl(&nfc->ecc_status_result); +#endif } static void nfc_nand_read_page(unsigned int page_address) From b8fea2b27d7aeabd2e0bc4242277ff2787c7c622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:49:53 +0200 Subject: [PATCH 13/18] spl mxc nand: Fix broken boot for correctable ECC errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not stop boot as soon as an ECC error is detected. Only stop boot for uncorrectable ECC errors. This fixes boards no longer booting after some time because a NAND Flash bit has flipped. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- nand_spl/nand_boot_fsl_nfc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index 4c5a7feec1..ea05952eb5 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -140,9 +140,21 @@ static void nfc_nand_data_output(void) static int nfc_nand_check_ecc(void) { #if defined(MXC_NFC_V1) - return readw(&nfc->ecc_status_result); + u16 ecc_status = readw(&nfc->ecc_status_result); + return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; #elif defined(MXC_NFC_V1_1) - return readl(&nfc->ecc_status_result); + u32 ecc_status = readl(&nfc->ecc_status_result); + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4; + int subpages = CONFIG_SYS_NAND_PAGE_SIZE / 512; + + do { + if ((ecc_status & 0xf) > err_limit) + return 1; + ecc_status >>= 4; + } while (--subpages); + + return 0; #endif } From 0e499b07ef417b153e3feb54c249d56edbc364b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:50:07 +0200 Subject: [PATCH 14/18] mtd mxc nand: Use _mxc_nand_enable_hwecc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use _mxc_nand_enable_hwecc() instead of duplicating its code. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- drivers/mtd/nand/mxc_nand.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 4564b2509c..7a180e1839 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -355,16 +355,6 @@ static int mxc_nand_dev_ready(struct mtd_info *mtd) return 1; } -#ifdef CONFIG_MXC_NAND_HWECC -static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) -{ - /* - * If HW ECC is enabled, we turn it on during init. There is - * no need to enable again here. - */ -} - -#ifdef MXC_NFC_V1_1 static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; @@ -378,6 +368,16 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) writew(tmp, &host->regs->config1); } +#ifdef CONFIG_MXC_NAND_HWECC +static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{ + /* + * If HW ECC is enabled, we turn it on during init. There is + * no need to enable again here. + */ +} + +#ifdef MXC_NFC_V1_1 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -1235,15 +1235,11 @@ int board_nand_init(struct nand_chip *this) host->pagesize_2k = 0; this->ecc.size = 512; - tmp = readw(&host->regs->config1); - tmp |= NFC_ECC_EN; - writew(tmp, &host->regs->config1); + _mxc_nand_enable_hwecc(mtd, 1); #else this->ecc.layout = &nand_soft_eccoob; this->ecc.mode = NAND_ECC_SOFT; - tmp = readw(&host->regs->config1); - tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->config1); + _mxc_nand_enable_hwecc(mtd, 0); #endif /* Reset NAND */ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); From 7c28a1cfdf5e919f2a09abb644f614f1b67d3322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:50:19 +0200 Subject: [PATCH 15/18] mtd mxc nand: Fix ECC state after read_page_raw_syndrome() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mxc_nand_read_page_raw_syndrome() should reenable ECC upon exit. This fixes ECC errors left uncorrected after a call to this function. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- drivers/mtd/nand/mxc_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 7a180e1839..2ae41dcd1b 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -470,7 +470,7 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, size = mtd->oobsize - (oob - chip->oob_poi); if (size) chip->read_buf(mtd, oob, size); - _mxc_nand_enable_hwecc(mtd, 0); + _mxc_nand_enable_hwecc(mtd, 1); return 0; } From 13927f07334ce47a975c2e2a5bcd6bb708692534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:50:30 +0200 Subject: [PATCH 16/18] mtd mxc nand: Merge init functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge mxc_setup_config1() into board_nand_init() in order to ease the addition of i.MX5 support in the following patches. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- drivers/mtd/nand/mxc_nand.c | 53 ++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 2ae41dcd1b..e743796a09 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1137,24 +1137,6 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command, } } -#ifdef MXC_NFC_V1_1 -static void mxc_setup_config1(void) -{ - uint16_t tmp; - - tmp = readw(&host->regs->config1); - tmp |= NFC_ONE_CYCLE; - tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->config1); - if (host->pagesize_2k) - writew(64/2, &host->regs->spare_area_size); - else - writew(16/2, &host->regs->spare_area_size); -} -#else -#define mxc_setup_config1() -#endif - #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; @@ -1244,6 +1226,29 @@ int board_nand_init(struct nand_chip *this) /* Reset NAND */ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + /* NAND bus width determines access functions used by upper layer */ + if (is_16bit_nand()) + this->options |= NAND_BUSWIDTH_16; + +#ifdef CONFIG_SYS_NAND_LARGEPAGE + host->pagesize_2k = 1; + this->ecc.layout = &nand_hw_eccoob2k; +#else + host->pagesize_2k = 0; + this->ecc.layout = &nand_hw_eccoob; +#endif + +#ifdef MXC_NFC_V1_1 + tmp = readw(&host->regs->config1); + tmp |= NFC_ONE_CYCLE; + tmp |= NFC_4_8N_ECC; + writew(tmp, &host->regs->config1); + if (host->pagesize_2k) + writew(64/2, &host->regs->spare_area_size); + else + writew(16/2, &host->regs->spare_area_size); +#endif + /* * preset operation * Unlock the internal RAM Buffer @@ -1268,17 +1273,5 @@ int board_nand_init(struct nand_chip *this) /* Unlock Block Command for given address range */ writew(0x4, &host->regs->wrprot); - /* NAND bus width determines access functions used by upper layer */ - if (is_16bit_nand()) - this->options |= NAND_BUSWIDTH_16; - -#ifdef CONFIG_SYS_NAND_LARGEPAGE - host->pagesize_2k = 1; - this->ecc.layout = &nand_hw_eccoob2k; -#else - host->pagesize_2k = 0; - this->ecc.layout = &nand_hw_eccoob; -#endif - mxc_setup_config1(); return 0; } From 1884d6577e6b298ab2966d7d8fd7be888c3b7332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:50:42 +0200 Subject: [PATCH 17/18] mxc nand: Let driver detect IP revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no reason to have board configs to select the NFC IP revision. Just let the driver detect it. BTW, remove broken NFC IP revision configs from board config files. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- include/configs/flea3.h | 1 - include/configs/mx35pdk.h | 1 - include/configs/tx25.h | 1 - include/fsl_nfc.h | 8 +++----- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/include/configs/flea3.h b/include/configs/flea3.h index 4350518939..027a5dcefb 100644 --- a/include/configs/flea3.h +++ b/include/configs/flea3.h @@ -213,7 +213,6 @@ * NAND FLASH driver setup */ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (NFC_BASE_ADDR) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (NFC_BASE_ADDR) diff --git a/include/configs/mx35pdk.h b/include/configs/mx35pdk.h index 9bc6bd4470..5816152f92 100644 --- a/include/configs/mx35pdk.h +++ b/include/configs/mx35pdk.h @@ -231,7 +231,6 @@ * NAND FLASH driver setup */ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (NFC_BASE_ADDR) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (NFC_BASE_ADDR) diff --git a/include/configs/tx25.h b/include/configs/tx25.h index c8a49bba14..71b1d326de 100644 --- a/include/configs/tx25.h +++ b/include/configs/tx25.h @@ -107,7 +107,6 @@ /* NAND */ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (0xBB000000) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (0xBB000000) diff --git a/include/fsl_nfc.h b/include/fsl_nfc.h index c248cef654..6618089290 100644 --- a/include/fsl_nfc.h +++ b/include/fsl_nfc.h @@ -42,10 +42,12 @@ */ #if defined(CONFIG_MX27) || defined(CONFIG_MX31) #define MXC_NFC_V1 +#define is_mxc_nfc_11() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V1_1 +#define is_mxc_nfc_11() 1 #else -#warning "MXC NFC version not defined" +#error "MXC NFC implementation not supported" #endif #if defined(MXC_NFC_V1) @@ -53,14 +55,10 @@ #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#define is_mxc_nfc_11() 0 #elif defined(MXC_NFC_V1_1) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 -#define is_mxc_nfc_11() 1 -#else -#error "define CONFIG_NAND_MXC_VXXX to use the mxc nand driver" #endif struct fsl_nfc_regs { From 9c60e75e05dab5a0197728b6a940aaac02762936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 13 Aug 2012 22:50:53 +0200 Subject: [PATCH 18/18] mxc nand: Homogenize IP revisions with Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the same IP revisions as in Linux in order to make the comparison more clear. Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic Signed-off-by: Scott Wood --- drivers/mtd/nand/mxc_nand.c | 16 ++++++++-------- include/fsl_nfc.h | 16 +++++++++------- nand_spl/nand_boot_fsl_nfc.c | 4 ++-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index e743796a09..cf2a7b0866 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -77,7 +77,7 @@ static struct nand_ecclayout nand_hw_eccoob2k = { .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, }; #endif -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) #ifndef CONFIG_SYS_NAND_LARGEPAGE static struct nand_ecclayout nand_hw_eccoob = { .eccbytes = 9, @@ -213,7 +213,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only); - if (is_mxc_nfc_11()) { + if (is_mxc_nfc_21()) { int i; /* * The controller copies the 64 bytes of spare data from @@ -273,7 +273,7 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); - if (is_mxc_nfc_11()) { + if (is_mxc_nfc_21()) { int i; /* @@ -377,7 +377,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) */ } -#ifdef MXC_NFC_V1_1 +#ifdef MXC_NFC_V2_1 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -1061,7 +1061,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_PAGEPROG: send_prog_page(host, 0, host->spare_only); - if (host->pagesize_2k && !is_mxc_nfc_11()) { + if (host->pagesize_2k && is_mxc_nfc_1()) { /* data in 4 areas */ send_prog_page(host, 1, host->spare_only); send_prog_page(host, 2, host->spare_only); @@ -1111,7 +1111,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command, send_cmd(host, NAND_CMD_READSTART); /* read for each AREA */ send_read_page(host, 0, host->spare_only); - if (!is_mxc_nfc_11()) { + if (is_mxc_nfc_1()) { send_read_page(host, 1, host->spare_only); send_read_page(host, 2, host->spare_only); send_read_page(host, 3, host->spare_only); @@ -1200,7 +1200,7 @@ int board_nand_init(struct nand_chip *this) this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; - if (is_mxc_nfc_11()) { + if (is_mxc_nfc_21()) { this->ecc.mode = NAND_ECC_HW_SYNDROME; this->ecc.read_page = mxc_nand_read_page_syndrome; this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; @@ -1238,7 +1238,7 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif -#ifdef MXC_NFC_V1_1 +#ifdef MXC_NFC_V2_1 tmp = readw(&host->regs->config1); tmp |= NFC_ONE_CYCLE; tmp |= NFC_4_8N_ECC; diff --git a/include/fsl_nfc.h b/include/fsl_nfc.h index 6618089290..ff537b49a9 100644 --- a/include/fsl_nfc.h +++ b/include/fsl_nfc.h @@ -33,7 +33,7 @@ * to support up to 2K byte pagesize nand. * Reading or writing a 2K page requires 4 FDI/FDO cycles. * - * MX25 and MX35 have version 1.1, which has: + * MX25 and MX35 have version 2.1, which has: * 8 512-byte main buffers and * 8 64-byte spare buffers * to support up to 4K byte pagesize nand. @@ -42,10 +42,12 @@ */ #if defined(CONFIG_MX27) || defined(CONFIG_MX31) #define MXC_NFC_V1 -#define is_mxc_nfc_11() 0 +#define is_mxc_nfc_1() 1 +#define is_mxc_nfc_21() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) -#define MXC_NFC_V1_1 -#define is_mxc_nfc_11() 1 +#define MXC_NFC_V2_1 +#define is_mxc_nfc_1() 0 +#define is_mxc_nfc_21() 1 #else #error "MXC NFC implementation not supported" #endif @@ -55,7 +57,7 @@ #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 @@ -86,7 +88,7 @@ struct fsl_nfc_regs { u16 nf_wrprst; u16 config1; u16 config2; -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) u16 reserved2[2]; u16 buf_addr; u16 flash_addr; @@ -153,7 +155,7 @@ struct fsl_nfc_regs { */ #define NFC_INT 0x8000 -#ifdef MXC_NFC_V1_1 +#ifdef MXC_NFC_V2_1 #define NFC_4_8N_ECC (1 << 0) #endif #define NFC_SP_EN (1 << 2) diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index ea05952eb5..a40c99877c 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -47,7 +47,7 @@ static void nfc_wait_ready(void) static void nfc_nand_init(void) { -#if defined(MXC_NFC_V1_1) +#if defined(MXC_NFC_V2_1) int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1; @@ -142,7 +142,7 @@ static int nfc_nand_check_ecc(void) #if defined(MXC_NFC_V1) u16 ecc_status = readw(&nfc->ecc_status_result); return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) u32 ecc_status = readl(&nfc->ecc_status_result); int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4;