From d62e9caaaf7e6f5c7d86c9ea19170bfa5adda8be Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Mon, 19 Mar 2012 15:35:25 +0100 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index bfd668fa0ac..50bfb65f75b 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; -- cgit v1.3.1 From eee623a5049963d0c085be37128bbd22bee1ba1e Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:42 -0500 Subject: 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(-) (limited to 'drivers') diff --git a/common/cmd_nand.c b/common/cmd_nand.c index a91ccf4df37..f737c06f843 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 1602b5eee96..c130189587b 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 7ed8b1891ce..c66eeefcb61 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 c554c552f59..e9b47f1b25a 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); -- cgit v1.3.1 From e331ab2ee9b141f1de2a8fb0bfaf52f6273022f9 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:43 -0500 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index c66eeefcb61..5ef7df74010 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 e9b47f1b25a..ff061c0b7c5 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); -- cgit v1.3.1 From 33b1d5cae3defdbeb30333ffac41bcbff85c5019 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:44 -0500 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 5ef7df74010..ffcb4f6ab9a 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 82704de0835..6c4053151e8 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 -- cgit v1.3.1 From e70bfa2986f9c028e3c21e0995285047a9baec27 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 22 Aug 2012 16:49:45 -0500 Subject: 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(-) (limited to 'drivers') diff --git a/common/cmd_nand.c b/common/cmd_nand.c index f737c06f843..9c6dabe5897 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 ffcb4f6ab9a..c4752a7cbf8 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 ff061c0b7c5..bbe28b20bbc 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); -- cgit v1.3.1 From 9c790a748f6b61e36f7aaf0c8d5ed35c9b09f454 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 30 Aug 2012 13:39:38 +0000 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 50bfb65f75b..390ff902127 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 6c4053151e8..c06866b061c 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. -- cgit v1.3.1 From 80c8ab7b25579529809792eef51fe660308fecb6 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Mon, 13 Aug 2012 22:48:12 +0200 Subject: 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 | 247 +++++++++---------------------------------- include/fsl_nfc.h | 97 +++++++++-------- nand_spl/nand_boot_fsl_nfc.c | 58 +++++----- 3 files changed, 128 insertions(+), 274 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 936186f75e6..9a9260caf47 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 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 mtd_info mtd; + struct nand_chip *nand; + + 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 279aaa55de0..6691e410b65 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 d6b0d9b6d10..f437debdc15 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- -- cgit v1.3.1 From 365b2c0761040764953e659f3385840e33823807 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Mon, 13 Aug 2012 22:48:26 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 9a9260caf47..62d8c6b38cf 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 6691e410b65..1c16c71d45c 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 f437debdc15..b90f93e3b85 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; -- cgit v1.3.1 From c1db8dd62b337372a08942e1c5945a8590afbc58 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Mon, 13 Aug 2012 22:49:42 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 62d8c6b38cf..4564b2509c2 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 1c16c71d45c..c248cef6549 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 842943c651b..4c5a7feec16 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) -- cgit v1.3.1 From 0e499b07ef417b153e3feb54c249d56edbc364b4 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Mon, 13 Aug 2012 22:50:07 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 4564b2509c2..7a180e18390 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); -- cgit v1.3.1 From 7c28a1cfdf5e919f2a09abb644f614f1b67d3322 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Mon, 13 Aug 2012 22:50:19 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 7a180e18390..2ae41dcd1b4 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; } -- cgit v1.3.1 From 13927f07334ce47a975c2e2a5bcd6bb708692534 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Mon, 13 Aug 2012 22:50:30 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 2ae41dcd1b4..e743796a09d 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; } -- cgit v1.3.1 From 9c60e75e05dab5a0197728b6a940aaac02762936 Mon Sep 17 00:00:00 2001 From: Benoît Thébaudeau Date: Mon, 13 Aug 2012 22:50:53 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index e743796a09d..cf2a7b08667 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 66180892902..ff537b49a9c 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 ea05952eb5e..a40c99877c0 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; -- cgit v1.3.1