From 5e856fa8bec49b86e680626be772dd6b6aa3e5df Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 14 Apr 2015 08:59:00 -0600 Subject: [PATCH 01/13] nand: fix buffer alignment in new verification feature On systems with caches enabled, NAND I/O may need to flush/invalidate the cache during read/write operations. For this to work correctly, all buffers must be cache-aligned. Fix nand_verify*() to allocate aligned buffers. This prevents cache alignment warnings from being spewed when using U-Boot to write an updated version of itself to flash on NVIDIA Tegra Seaboard (after perturbation of stack/data layout in current u-boot-dm/next branch). I have validatd (executed) nand_verify(), but I don't think I've executed nand_verify_page_oob(); testing of that would be useful. Cc: Peter Tyser Cc: Heiko Schocher Cc: Scott Wood Fixes: 59b5a2ad83df ("nand: Add verification functions") Signed-off-by: Stephen Warren Reviewed-by: Simon Glass Acked-by: Scott Wood --- drivers/mtd/nand/nand_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 12dd26a33f..ee2c24df3b 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -483,7 +483,7 @@ int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, loff_t ofs) memcpy(&vops, ops, sizeof(vops)); - vops.datbuf = malloc(verlen); + vops.datbuf = memalign(ARCH_DMA_MINALIGN, verlen); if (!vops.datbuf) return -ENOMEM; @@ -520,7 +520,7 @@ int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf) int rval = 0; size_t verofs; size_t verlen = nand->writesize; - uint8_t *verbuf = malloc(verlen); + uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen); if (!verbuf) return -ENOMEM; From 6b8583b0adac6c8119d2fc6fd4f03ed8373b5d42 Mon Sep 17 00:00:00 2001 From: Raghav Dogra Date: Wed, 20 May 2015 14:54:58 +0530 Subject: [PATCH 02/13] nand/elbc: Memory leak fix Freeing allocated memory to priv before returning from the function Signed-off-by: Raghav Dogra [scottwood: removed unnecessary cast] Signed-off-by: Scott Wood --- drivers/mtd/nand/fsl_elbc_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index e85832d319..b3a0edbf14 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -679,6 +679,7 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr) if (priv->bank >= MAX_BANKS) { printf("fsl_elbc_nand: address did not match any " "chip selects\n"); + kfree(priv); return -ENODEV; } From bd38da1a558ea31f2dee4a14a972333b68bfa0ee Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 15 Apr 2015 09:27:21 +0200 Subject: [PATCH 03/13] mtd:mxs:nand calculate ecc strength dynamically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calculate ecc strength according oobsize, but not hardcoded which is not aligned with kernel driver Signed-off-by: Peng Fan Signed-off-by: Ye.Li Reviewed-by: Marek Vasut Signed-off-by: Jörg Krause --- drivers/mtd/nand/mxs_nand.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 2d2b938633..fc5cf586c5 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -146,26 +146,20 @@ static uint32_t mxs_nand_aux_status_offset(void) static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size, uint32_t page_oob_size) { - if (page_data_size == 2048) { - if (page_oob_size == 64) - return 8; + int ecc_strength; - if (page_oob_size == 112) - return 14; - } + /* + * Determine the ECC layout with the formula: + * ECC bits per chunk = (total page spare data bits) / + * (bits per ECC level) / (chunks per page) + * where: + * total page spare data bits = + * (page oob size - meta data size) * (bits per byte) + */ + ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8) + / (13 * mxs_nand_ecc_chunk_cnt(page_data_size)); - if (page_data_size == 4096) { - if (page_oob_size == 128) - return 8; - - if (page_oob_size == 218) - return 16; - - if (page_oob_size == 224) - return 16; - } - - return 0; + return round_down(ecc_strength, 2); } static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size, From 1fbdb706106a6ad135f87d29bb8dfe09ff995950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Krause?= Date: Wed, 15 Apr 2015 09:27:22 +0200 Subject: [PATCH 04/13] mtd: nand: mxs: Replace magic number for bits per ECC level with macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörg Krause Reviewed-by: Marek Vasut --- drivers/mtd/nand/mxs_nand.c | 7 ++++--- tools/mxsboot.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index fc5cf586c5..9c144a21e1 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -36,7 +36,7 @@ #define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 0 #endif #define MXS_NAND_METADATA_SIZE 10 - +#define MXS_NAND_BITS_PER_ECC_LEVEL 13 #define MXS_NAND_COMMAND_BUFFER_SIZE 32 #define MXS_NAND_BCH_TIMEOUT 10000 @@ -135,7 +135,7 @@ static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size) static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength) { - return ecc_strength * 13; + return ecc_strength * MXS_NAND_BITS_PER_ECC_LEVEL; } static uint32_t mxs_nand_aux_status_offset(void) @@ -157,7 +157,8 @@ static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size, * (page oob size - meta data size) * (bits per byte) */ ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8) - / (13 * mxs_nand_ecc_chunk_cnt(page_data_size)); + / (MXS_NAND_BITS_PER_ECC_LEVEL * + mxs_nand_ecc_chunk_cnt(page_data_size)); return round_down(ecc_strength, 2); } diff --git a/tools/mxsboot.c b/tools/mxsboot.c index 6d48cfb3e4..08219b34e8 100644 --- a/tools/mxsboot.c +++ b/tools/mxsboot.c @@ -48,6 +48,7 @@ static uint32_t sd_sector = 2048; #define MXS_NAND_DMA_DESCRIPTOR_COUNT 4 #define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512 #define MXS_NAND_METADATA_SIZE 10 +#define MXS_NAND_BITS_PER_ECC_LEVEL 13 #define MXS_NAND_COMMAND_BUFFER_SIZE 32 struct mx28_nand_fcb { @@ -127,7 +128,7 @@ struct mx28_sd_config_block { static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength) { - return ecc_strength * 13; + return ecc_strength * MXS_NAND_BITS_PER_ECC_LEVEL; } static inline uint32_t mx28_nand_get_ecc_strength(uint32_t page_data_size, From 6121560d7714d6d8e41ce1687a1388a1a8fea4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Krause?= Date: Wed, 15 Apr 2015 09:27:23 +0200 Subject: [PATCH 05/13] tools: mxsboot: Calculate ECC strength dynamically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calculating the ECC strength dynamically to be aligned with the mxs NAND driver and the Linux Kernel. Signed-off-by: Jörg Krause Reviewed-by: Marek Vasut --- tools/mxsboot.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/tools/mxsboot.c b/tools/mxsboot.c index 08219b34e8..185b327920 100644 --- a/tools/mxsboot.c +++ b/tools/mxsboot.c @@ -14,6 +14,10 @@ #include "compiler.h" +/* Taken from */ +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + /* * Default BCB layout. * @@ -126,6 +130,11 @@ struct mx28_sd_config_block { struct mx28_sd_drive_info drv_info[1]; }; +static inline uint32_t mx28_nand_ecc_chunk_cnt(uint32_t page_data_size) +{ + return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; +} + static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength) { return ecc_strength * MXS_NAND_BITS_PER_ECC_LEVEL; @@ -134,21 +143,21 @@ static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength) static inline uint32_t mx28_nand_get_ecc_strength(uint32_t page_data_size, uint32_t page_oob_size) { - if (page_data_size == 2048) - return 8; + int ecc_strength; - if (page_data_size == 4096) { - if (page_oob_size == 128) - return 8; + /* + * Determine the ECC layout with the formula: + * ECC bits per chunk = (total page spare data bits) / + * (bits per ECC level) / (chunks per page) + * where: + * total page spare data bits = + * (page oob size - meta data size) * (bits per byte) + */ + ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8) + / (MXS_NAND_BITS_PER_ECC_LEVEL * + mx28_nand_ecc_chunk_cnt(page_data_size)); - if (page_oob_size == 218) - return 16; - - if (page_oob_size == 224) - return 16; - } - - return 0; + return round_down(ecc_strength, 2); } static inline uint32_t mx28_nand_get_mark_offset(uint32_t page_data_size, From f55bc296a88c0a9d71ad363b89b54975d2aab14f Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:06 +0200 Subject: [PATCH 06/13] mtd: vf610_nfc: remove caching of page in buffer To improve performance we remember the current page in the buffer and avoid reading it twice. This implicit page cache increases complexity while does not increase performance in real world cases. This patch removes that feature. Acked-by: Bill Pringlemeir Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index d98dd28800..fa0bb9dcaf 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -147,7 +147,6 @@ struct vf610_nfc { uint column; int spareonly; int page_sz; - int page; /* Status and ID are in alternate locations. */ int alt_buf; #define ALT_BUF_ID 1 @@ -347,7 +346,6 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, switch (command) { case NAND_CMD_PAGEPROG: - nfc->page = -1; vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN, command, PROGRAM_PAGE_CMD_CODE); @@ -367,10 +365,6 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_SEQIN: /* Pre-read for partial writes. */ case NAND_CMD_READ0: column = 0; - /* Already read? */ - if (nfc->page == page) - return; - nfc->page = page; vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, NAND_CMD_READSTART, READ_PAGE_CMD_CODE); @@ -378,7 +372,6 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, break; case NAND_CMD_ERASE1: - nfc->page = -1; vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_commands(nfc->regs, command, NAND_CMD_ERASE2, ERASE_CMD_CODE); @@ -532,10 +525,8 @@ static inline int vf610_nfc_correct_data(struct mtd_info *mtd, u_char *dat) flip = count_written_bits(dat, nfc->chip.ecc.size, ecc_count); /* ECC failed. */ - if (flip > ecc_count) { - nfc->page = -1; + if (flip > ecc_count) return -1; - } /* Erased page. */ memset(dat, 0xff, nfc->chip.ecc.size); From 6fcfd1e890ff752224f3266a11dec6e1b5624cb4 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:07 +0200 Subject: [PATCH 07/13] mtd: vf610_nfc: remove read on SEQIN Since we do not support sub-page writes anyway, reading the page back to the controller on SEQIN command is not required. Remove the page read on SEQIN. However, the column/page values relevant to the SEQIN command, hence set the column/row address on SEQIN command. Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index fa0bb9dcaf..66b335d008 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -345,24 +345,26 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, nfc->alt_buf = 0; switch (command) { + case NAND_CMD_SEQIN: + /* Use valid column/page from preread... */ + vf610_nfc_addr_cycle(mtd, column, page); + /* + * SEQIN => data => PAGEPROG sequence is done by the controller + * hence we do not need to issue the command here... + */ + return; case NAND_CMD_PAGEPROG: vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN, command, PROGRAM_PAGE_CMD_CODE); - vf610_nfc_addr_cycle(mtd, column, page); break; case NAND_CMD_RESET: vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_command(nfc->regs, command, RESET_CMD_CODE); break; - /* - * NFC does not support sub-page reads and writes, - * so emulate them using full page transfers. - */ case NAND_CMD_READOOB: nfc->spareonly = 1; - case NAND_CMD_SEQIN: /* Pre-read for partial writes. */ case NAND_CMD_READ0: column = 0; vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); From d111bf99a81feacd3876010984a28575964ff0dc Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:08 +0200 Subject: [PATCH 08/13] mtd: vf610_nfc: allow bitflips in an empty page Allow bit flips in a empty page up to half of the recoverable bits (strength / 2). Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 66b335d008..16485f5713 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -527,7 +527,7 @@ static inline int vf610_nfc_correct_data(struct mtd_info *mtd, u_char *dat) flip = count_written_bits(dat, nfc->chip.ecc.size, ecc_count); /* ECC failed. */ - if (flip > ecc_count) + if (flip > ecc_count && flip > (nfc->chip.ecc.strength / 2)) return -1; /* Erased page. */ From 5dec286b8233f658764497b10d455ba447167816 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:09 +0200 Subject: [PATCH 09/13] mtd: vf610_nfc: implement OOB only read Implement read of OOB area only. When using column and sector size properties, only parts of the page can be read. However, this works only when hardware ECC is disabled, otherwise the ECC engine would ruin the data in the buffer. To allow OOB only reads, three points had to be addressed: - Set ECC mode per command. - Handle NAND_CMD_READOOB seperate. Make sure column and sector size is correctly set up, while disabling ECC. - Now, the OOB data end up at the beginning of the buffer. Remove the special handling of OOB (spareonly). Especially bad block scans benefit from this change. On a 512MiB SLC NAND device, the bad block scan took 1.5s less than before. Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 103 ++++++++++++++--------------------- 1 file changed, 42 insertions(+), 61 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 16485f5713..5d72b4a020 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -145,8 +145,6 @@ struct vf610_nfc { struct nand_chip chip; void __iomem *regs; uint column; - int spareonly; - int page_sz; /* Status and ID are in alternate locations. */ int alt_buf; #define ALT_BUF_ID 1 @@ -319,8 +317,8 @@ static void vf610_nfc_addr_cycle(struct mtd_info *mtd, int column, int page) { if (column != -1) { struct vf610_nfc *nfc = mtd_to_nfc(mtd); - if (nfc->chip.options | NAND_BUSWIDTH_16) - column = column/2; + if (nfc->chip.options & NAND_BUSWIDTH_16) + column = column / 2; vf610_nfc_set_field(mtd, NFC_COL_ADDR, COL_ADDR_MASK, COL_ADDR_SHIFT, column); } @@ -329,6 +327,13 @@ static void vf610_nfc_addr_cycle(struct mtd_info *mtd, int column, int page) ROW_ADDR_SHIFT, page); } +static inline void vf610_nfc_ecc_mode(struct mtd_info *mtd, int ecc_mode) +{ + vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, + CONFIG_ECC_MODE_MASK, + CONFIG_ECC_MODE_SHIFT, ecc_mode); +} + static inline void vf610_nfc_transfer_size(void __iomem *regbase, int size) { __raw_writel(size, regbase + NFC_SECTOR_SIZE); @@ -339,10 +344,10 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, int column, int page) { struct vf610_nfc *nfc = mtd_to_nfc(mtd); + int page_sz = nfc->chip.options & NAND_BUSWIDTH_16 ? 1 : 0; - nfc->column = max(column, 0); - nfc->spareonly = 0; - nfc->alt_buf = 0; + nfc->column = max(column, 0); + nfc->alt_buf = 0; switch (command) { case NAND_CMD_SEQIN: @@ -354,23 +359,36 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, */ return; case NAND_CMD_PAGEPROG: - vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); + page_sz += mtd->writesize + mtd->oobsize; + vf610_nfc_transfer_size(nfc->regs, page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN, command, PROGRAM_PAGE_CMD_CODE); + vf610_nfc_ecc_mode(mtd, ECC_45_BYTE); break; case NAND_CMD_RESET: vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_command(nfc->regs, command, RESET_CMD_CODE); break; + case NAND_CMD_READOOB: - nfc->spareonly = 1; - case NAND_CMD_READ0: - column = 0; - vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); + page_sz += mtd->oobsize; + column = mtd->writesize; + vf610_nfc_transfer_size(nfc->regs, page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, NAND_CMD_READSTART, READ_PAGE_CMD_CODE); vf610_nfc_addr_cycle(mtd, column, page); + vf610_nfc_ecc_mode(mtd, ECC_BYPASS); + break; + + case NAND_CMD_READ0: + page_sz += mtd->writesize + mtd->oobsize; + column = 0; + vf610_nfc_transfer_size(nfc->regs, page_sz); + vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, + NAND_CMD_READSTART, READ_PAGE_CMD_CODE); + vf610_nfc_addr_cycle(mtd, column, page); + vf610_nfc_ecc_mode(mtd, ECC_45_BYTE); break; case NAND_CMD_ERASE1: @@ -399,46 +417,25 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, vf610_nfc_done(mtd); } -static inline void vf610_nfc_read_spare(struct mtd_info *mtd, void *buf, - int len) -{ - struct vf610_nfc *nfc = mtd_to_nfc(mtd); - - len = min(mtd->oobsize, (uint)len); - if (len > 0) - vf610_nfc_memcpy(buf, nfc->regs + mtd->writesize, len); -} - /* Read data from NFC buffers */ static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) { struct vf610_nfc *nfc = mtd_to_nfc(mtd); uint c = nfc->column; - uint l; - /* Handle main area */ - if (!nfc->spareonly) { - l = min((uint)len, mtd->writesize - c); - nfc->column += l; - - if (!nfc->alt_buf) - vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, - l); - else - if (nfc->alt_buf & ALT_BUF_ID) - *buf = vf610_nfc_get_id(mtd, c); - else - *buf = vf610_nfc_get_status(mtd); - - buf += l; - len -= l; + switch (nfc->alt_buf) { + case ALT_BUF_ID: + *buf = vf610_nfc_get_id(mtd, c); + break; + case ALT_BUF_STAT: + *buf = vf610_nfc_get_status(mtd); + break; + default: + vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); + break; } - /* Handle spare area access */ - if (len) { - nfc->column += len; - vf610_nfc_read_spare(mtd, buf, len); - } + nfc->column += len; } /* Write data to NFC buffers */ @@ -629,17 +626,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) if (cfg.flash_bbt) chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_CREATE; - /* Default to software ECC until flash ID. */ - vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, - CONFIG_ECC_MODE_MASK, - CONFIG_ECC_MODE_SHIFT, ECC_BYPASS); - chip->bbt_td = &bbt_main_descr; chip->bbt_md = &bbt_mirror_descr; - nfc->page_sz = PAGE_2K + OOB_64; - nfc->page_sz += cfg.width == 16 ? 1 : 0; - /* Set configuration register. */ vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_ADDR_AUTO_INCR_BIT); vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_BUFNO_AUTO_INCR_BIT); @@ -667,15 +656,12 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) chip->ecc.mode = NAND_ECC_SOFT; /* default */ - nfc->page_sz = mtd->writesize + mtd->oobsize; - /* Single buffer only, max 256 OOB minus ECC status */ - if (nfc->page_sz > PAGE_2K + 256 - 8) { + if (mtd->writesize + mtd->oobsize > PAGE_2K + 256 - 8) { dev_err(nfc->dev, "Unsupported flash size\n"); err = -ENXIO; goto error; } - nfc->page_sz += cfg.width == 16 ? 1 : 0; if (cfg.hardware_ecc) { if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) { @@ -696,11 +682,6 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) chip->ecc.size = PAGE_2K; chip->ecc.strength = 24; - /* set ECC mode to 45 bytes OOB with 24 bits correction */ - vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, - CONFIG_ECC_MODE_MASK, - CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE); - /* Enable ECC_STATUS */ vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_ECC_SRAM_REQ_BIT); } From 84d656a2836021c3707172707245ba3d87bd54c8 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:10 +0200 Subject: [PATCH 10/13] mtd: vf610_nfc: use in-band bad block table Use in-band bad block table (NAND_BBT_NO_OOB) which allows to use the full OOB for hardare ECC purposes. Since there is no ECC correction on the OOB it is also safer to use in-band area to store the bad block table marker. Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 5d72b4a020..05cbdf3e69 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -155,29 +155,6 @@ struct vf610_nfc { #define mtd_to_nfc(_mtd) \ (struct vf610_nfc *)((struct nand_chip *)_mtd->priv)->priv -static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; -static u8 mirror_pattern[] = {'1', 't', 'b', 'B' }; - -static struct nand_bbt_descr bbt_main_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | - NAND_BBT_2BIT | NAND_BBT_VERSION, - .offs = 11, - .len = 4, - .veroffs = 15, - .maxblocks = 4, - .pattern = bbt_pattern, -}; - -static struct nand_bbt_descr bbt_mirror_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | - NAND_BBT_2BIT | NAND_BBT_VERSION, - .offs = 11, - .len = 4, - .veroffs = 15, - .maxblocks = 4, - .pattern = mirror_pattern, -}; - static struct nand_ecclayout vf610_nfc_ecc45 = { .eccbytes = 45, .eccpos = {19, 20, 21, 22, 23, @@ -624,10 +601,8 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) /* Bad block options. */ if (cfg.flash_bbt) - chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_CREATE; - - chip->bbt_td = &bbt_main_descr; - chip->bbt_md = &bbt_mirror_descr; + chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB | + NAND_BBT_CREATE; /* Set configuration register. */ vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_ADDR_AUTO_INCR_BIT); From 5519194d4f6ba3c1aeea2f07f444cc936913560a Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:11 +0200 Subject: [PATCH 11/13] mtd: vf610_nfc: add Freescale NFC controller configs to Kconfig This commit allows users to enable/disable the Freescale NFC controller found in systems like Vybrid (VF610), MPC5125, MCF54418 or Kinetis K70 via Kconfig with more detailed help docs. Signed-off-by: Stefan Agner Acked-by: Stefano Babic [scottwood: updated vf610twr_nand_defconfig] Signed-off-by: Scott Wood --- configs/colibri_vf_defconfig | 2 ++ configs/vf610twr_defconfig | 2 ++ configs/vf610twr_nand_defconfig | 2 ++ doc/README.nand | 18 ------------------ drivers/mtd/nand/Kconfig | 30 ++++++++++++++++++++++++++++++ include/configs/colibri_vf.h | 2 -- include/configs/vf610twr.h | 3 --- 7 files changed, 36 insertions(+), 23 deletions(-) diff --git a/configs/colibri_vf_defconfig b/configs/colibri_vf_defconfig index 0df337c7a4..3b1f66aa76 100644 --- a/configs/colibri_vf_defconfig +++ b/configs/colibri_vf_defconfig @@ -1,3 +1,5 @@ CONFIG_ARM=y CONFIG_TARGET_COLIBRI_VF=y CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/toradex/colibri_vf/imximage.cfg,ENV_IS_IN_NAND,IMX_NAND" +CONFIG_NAND_VF610_NFC=y +CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES=y diff --git a/configs/vf610twr_defconfig b/configs/vf610twr_defconfig index 3a71740559..85c7c3d101 100644 --- a/configs/vf610twr_defconfig +++ b/configs/vf610twr_defconfig @@ -1,3 +1,5 @@ CONFIG_ARM=y CONFIG_TARGET_VF610TWR=y CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/vf610twr/imximage.cfg,ENV_IS_IN_MMC" +CONFIG_NAND_VF610_NFC=y +CONFIG_SYS_NAND_BUSWIDTH_16BIT=y diff --git a/configs/vf610twr_nand_defconfig b/configs/vf610twr_nand_defconfig index e22704ac99..ebc915c48b 100644 --- a/configs/vf610twr_nand_defconfig +++ b/configs/vf610twr_nand_defconfig @@ -1,3 +1,5 @@ CONFIG_ARM=y CONFIG_TARGET_VF610TWR=y CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/vf610twr/imximage.cfg,ENV_IS_IN_NAND" +CONFIG_NAND_VF610_NFC=y +CONFIG_SYS_NAND_BUSWIDTH_16BIT=y diff --git a/doc/README.nand b/doc/README.nand index 46d7edd179..0ff56331d5 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -188,24 +188,6 @@ Configuration Options: This is used by SoC platforms which do not have built-in ELM hardware engine required for BCH ECC correction. - CONFIG_SYS_NAND_BUSWIDTH_16BIT - Indicates that NAND device has 16-bit wide data-bus. In absence of this - config, bus-width of NAND device is assumed to be either 8-bit and later - determined by reading ONFI params. - Above config is useful when NAND device's bus-width information cannot - be determined from on-chip ONFI params, like in following scenarios: - - SPL boot does not support reading of ONFI parameters. This is done to - keep SPL code foot-print small. - - In current U-Boot flow using nand_init(), driver initialization - happens in board_nand_init() which is called before any device probe - (nand_scan_ident + nand_scan_tail), thus device's ONFI parameters are - not available while configuring controller. So a static CONFIG_NAND_xx - is needed to know the device's bus-width in advance. - Some drivers using above config are: - drivers/mtd/nand/mxc_nand.c - drivers/mtd/nand/ndfc.c - drivers/mtd/nand/omap_gpmc.c - Platform specific options ========================= diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 72825c3e2e..0a9e96f60a 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -32,6 +32,36 @@ config NAND_DENALI_SPARE_AREA_SKIP_BYTES of OOB area before last ECC sector data starts. This is potentially used to preserve the bad block marker in the OOB area. +config NAND_VF610_NFC + bool "Support for Freescale NFC for VF610/MPC5125" + select SYS_NAND_SELF_INIT + help + Enables support for NAND Flash Controller on some Freescale + processors like the VF610, MPC5125, MCF54418 or Kinetis K70. + The driver supports a maximum 2k page size. The driver + currently does not support hardware ECC. + +comment "Generic NAND options" + +# Enhance depends when converting drivers to Kconfig which use this config +# option (mxc_nand, ndfc, omap_gpmc). +config SYS_NAND_BUSWIDTH_16BIT + bool "Use 16-bit NAND interface" + depends on NAND_VF610_NFC + help + Indicates that NAND device has 16-bit wide data-bus. In absence of this + config, bus-width of NAND device is assumed to be either 8-bit and later + determined by reading ONFI params. + Above config is useful when NAND device's bus-width information cannot + be determined from on-chip ONFI params, like in following scenarios: + - SPL boot does not support reading of ONFI parameters. This is done to + keep SPL code foot-print small. + - In current U-Boot flow using nand_init(), driver initialization + happens in board_nand_init() which is called before any device probe + (nand_scan_ident + nand_scan_tail), thus device's ONFI parameters are + not available while configuring controller. So a static CONFIG_NAND_xx + is needed to know the device's bus-width in advance. + if SPL config SPL_NAND_DENALI diff --git a/include/configs/colibri_vf.h b/include/configs/colibri_vf.h index 414600ac43..b3c73bbb96 100644 --- a/include/configs/colibri_vf.h +++ b/include/configs/colibri_vf.h @@ -50,8 +50,6 @@ /* NAND support */ #define CONFIG_CMD_NAND -#define CONFIG_NAND_VF610_NFC -#define CONFIG_SYS_NAND_SELF_INIT #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR diff --git a/include/configs/vf610twr.h b/include/configs/vf610twr.h index 05bc7d0d9e..621aa13484 100644 --- a/include/configs/vf610twr.h +++ b/include/configs/vf610twr.h @@ -50,10 +50,7 @@ #define CONFIG_CMD_NAND_TRIMFFS #ifdef CONFIG_CMD_NAND -#define CONFIG_NAND_VF610_NFC -#define CONFIG_SYS_NAND_SELF_INIT #define CONFIG_USE_ARCH_MEMCPY -#define CONFIG_SYS_NAND_BUSWIDTH_16BIT #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR From 080a71e8e9fe917ba82bdde2251eb0d4dd68cb5c Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:12 +0200 Subject: [PATCH 12/13] mtd: vf610_nfc: add 32-error correction option for HW ECC Add option to choose between current 24-error correction and 32-error correction through Kconfig. 32-error correction allow to use NAND chips which require up to 8-bit error correction per 512 byte (when using 2K pages). Signed-off-by: Stefan Agner --- drivers/mtd/nand/Kconfig | 15 ++++++++++++++ drivers/mtd/nand/vf610_nfc.c | 40 +++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 0a9e96f60a..3024357de7 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -41,6 +41,21 @@ config NAND_VF610_NFC The driver supports a maximum 2k page size. The driver currently does not support hardware ECC. +choice + prompt "Hardware ECC strength" + depends on NAND_VF610_NFC + default SYS_NAND_VF610_NFC_45_ECC_BYTES + help + Select the ECC strength used in the hardware BCH ECC block. + +config SYS_NAND_VF610_NFC_45_ECC_BYTES + bool "24-error correction (45 ECC bytes)" + +config SYS_NAND_VF610_NFC_60_ECC_BYTES + bool "32-error correction (60 ECC bytes)" + +endchoice + comment "Generic NAND options" # Enhance depends when converting drivers to Kconfig which use this config diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 05cbdf3e69..2c02ff5996 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -71,6 +71,7 @@ /* NFC ECC mode define */ #define ECC_BYPASS 0 #define ECC_45_BYTE 6 +#define ECC_60_BYTE 7 /*** Register Mask and bit definitions */ @@ -155,7 +156,10 @@ struct vf610_nfc { #define mtd_to_nfc(_mtd) \ (struct vf610_nfc *)((struct nand_chip *)_mtd->priv)->priv -static struct nand_ecclayout vf610_nfc_ecc45 = { +#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES) +#define ECC_HW_MODE ECC_45_BYTE + +static struct nand_ecclayout vf610_nfc_ecc = { .eccbytes = 45, .eccpos = {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, @@ -167,6 +171,24 @@ static struct nand_ecclayout vf610_nfc_ecc45 = { {.offset = 8, .length = 11} } }; +#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES) +#define ECC_HW_MODE ECC_60_BYTE + +static struct nand_ecclayout vf610_nfc_ecc = { + .eccbytes = 60, + .eccpos = { 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63 }, + .oobfree = { + {.offset = 2, + .length = 2} } +}; +#endif static inline u32 vf610_nfc_read(struct mtd_info *mtd, uint reg) { @@ -340,7 +362,7 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, vf610_nfc_transfer_size(nfc->regs, page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN, command, PROGRAM_PAGE_CMD_CODE); - vf610_nfc_ecc_mode(mtd, ECC_45_BYTE); + vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); break; case NAND_CMD_RESET: @@ -365,7 +387,7 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, NAND_CMD_READSTART, READ_PAGE_CMD_CODE); vf610_nfc_addr_cycle(mtd, column, page); - vf610_nfc_ecc_mode(mtd, ECC_45_BYTE); + vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); break; case NAND_CMD_ERASE1: @@ -645,7 +667,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) goto error; } - chip->ecc.layout = &vf610_nfc_ecc45; + /* Current HW ECC layouts only use 64 bytes of OOB */ + if (mtd->oobsize > 64) + mtd->oobsize = 64; /* propagate ecc.layout to mtd_info */ mtd->ecclayout = chip->ecc.layout; @@ -653,9 +677,15 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) chip->ecc.write_page = vf610_nfc_write_page; chip->ecc.mode = NAND_ECC_HW; - chip->ecc.bytes = 45; chip->ecc.size = PAGE_2K; + chip->ecc.layout = &vf610_nfc_ecc; +#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES) chip->ecc.strength = 24; + chip->ecc.bytes = 45; +#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES) + chip->ecc.strength = 32; + chip->ecc.bytes = 60; +#endif /* Enable ECC_STATUS */ vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_ECC_SRAM_REQ_BIT); From 8fca2d8cb84fb039bb41061f5f5fd9f31cd596c9 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 May 2015 19:07:13 +0200 Subject: [PATCH 13/13] mtd: vf610_nfc: enable ONFI detection This changes enable ONFI detection. The Read ID command now allows one address byte which is needed for ONFI detection. To read the ONFI parameter page, the NAND_CMD_PARAM need to be supported. The CMD code enables one command and one address byte along with reading data from flash using R/B#, as specified by ONFI. Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 67 ++++++++++++++++++++++++++---------- include/configs/colibri_vf.h | 1 + include/configs/vf610twr.h | 1 + 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 2c02ff5996..5c11ac94aa 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -62,6 +62,7 @@ * Briefly these are bitmasks of controller cycles. */ #define READ_PAGE_CMD_CODE 0x7EE0 +#define READ_ONFI_PARAM_CMD_CODE 0x4860 #define PROGRAM_PAGE_CMD_CODE 0x7FC0 #define ERASE_CMD_CODE 0x4EC0 #define READ_ID_CMD_CODE 0x4804 @@ -150,6 +151,7 @@ struct vf610_nfc { int alt_buf; #define ALT_BUF_ID 1 #define ALT_BUF_STAT 2 +#define ALT_BUF_ONFI 3 struct clk *clk; }; @@ -390,6 +392,16 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); break; + case NAND_CMD_PARAM: + nfc->alt_buf = ALT_BUF_ONFI; + vf610_nfc_transfer_size(nfc->regs, 768); + vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM, + READ_ONFI_PARAM_CMD_CODE); + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, + ROW_ADDR_SHIFT, column); + vf610_nfc_ecc_mode(mtd, ECC_BYPASS); + break; + case NAND_CMD_ERASE1: vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_commands(nfc->regs, command, @@ -399,8 +411,11 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_READID: nfc->alt_buf = ALT_BUF_ID; + nfc->column = 0; vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE); + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, + ROW_ADDR_SHIFT, column); break; case NAND_CMD_STATUS: @@ -422,17 +437,11 @@ static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) struct vf610_nfc *nfc = mtd_to_nfc(mtd); uint c = nfc->column; - switch (nfc->alt_buf) { - case ALT_BUF_ID: - *buf = vf610_nfc_get_id(mtd, c); - break; - case ALT_BUF_STAT: - *buf = vf610_nfc_get_status(mtd); - break; - default: - vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); - break; - } + /* Alternate buffers are only supported through read_byte */ + if (nfc->alt_buf) + return; + + vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); nfc->column += len; } @@ -453,8 +462,29 @@ static void vf610_nfc_write_buf(struct mtd_info *mtd, const u_char *buf, /* Read byte from NFC buffers */ static u8 vf610_nfc_read_byte(struct mtd_info *mtd) { + struct vf610_nfc *nfc = mtd_to_nfc(mtd); u8 tmp; - vf610_nfc_read_buf(mtd, &tmp, sizeof(tmp)); + uint c = nfc->column; + + switch (nfc->alt_buf) { + case ALT_BUF_ID: + tmp = vf610_nfc_get_id(mtd, c); + break; + case ALT_BUF_STAT: + tmp = vf610_nfc_get_status(mtd); + break; + case ALT_BUF_ONFI: +#ifdef __LITTLE_ENDIAN + /* Reverse byte since the controller uses big endianness */ + c = nfc->column ^ 0x3; + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); + break; +#endif + default: + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); + break; + } + nfc->column++; return tmp; } @@ -602,13 +632,11 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) mtd->priv = chip; chip->priv = nfc; - if (cfg.width == 16) { + if (cfg.width == 16) chip->options |= NAND_BUSWIDTH_16; - vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); - } else { - chip->options &= ~NAND_BUSWIDTH_16; - vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); - } + + /* Use 8-bit mode during initialization */ + vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); /* Disable subpage writes as we do not provide ecc->hwctl */ chip->options |= NAND_NO_SUBPAGE_WRITE; @@ -651,6 +679,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) goto error; } + if (cfg.width == 16) + vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); + chip->ecc.mode = NAND_ECC_SOFT; /* default */ /* Single buffer only, max 256 OOB minus ECC status */ diff --git a/include/configs/colibri_vf.h b/include/configs/colibri_vf.h index b3c73bbb96..804291dfaa 100644 --- a/include/configs/colibri_vf.h +++ b/include/configs/colibri_vf.h @@ -50,6 +50,7 @@ /* NAND support */ #define CONFIG_CMD_NAND +#define CONFIG_SYS_NAND_ONFI_DETECTION #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR diff --git a/include/configs/vf610twr.h b/include/configs/vf610twr.h index 621aa13484..aa310411bf 100644 --- a/include/configs/vf610twr.h +++ b/include/configs/vf610twr.h @@ -48,6 +48,7 @@ /* NAND support */ #define CONFIG_CMD_NAND #define CONFIG_CMD_NAND_TRIMFFS +#define CONFIG_SYS_NAND_ONFI_DETECTION #ifdef CONFIG_CMD_NAND #define CONFIG_USE_ARCH_MEMCPY