Skip to contentSkip to conversation

mtd: resync with Linux-3.7.1

PATCH Superseded Sergey Lapin 3 participants 11 messages Jan 14, 2013 – May 30, 2013

Subsystems (9)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

This patch is essentially an update of u-boot MTD subsystem to the state of Linux-3.7.1 with exclusion of some bits:

- the update is concentrated on NAND, no onenand or CFI/NOR/SPI flashes interfaces are updated EXCEPT for API changes.

- new large NAND chips support is there, though some updates have got in Linux-3.8.-rc1, (which will follow on top of this patch).

To produce this update I used tag v3.7.1 of linux-stable repository.

The update was made using application of relevant patches, with changes relevant to U-Boot-only stuff sticked together to keep bisectability. Then all changes were grouped together to this patch.

---

v2: recreated on v3.7.1
removed unimportant bits
fixed look of the patch
v1: original submission

 board/ait/cam_enc_4xx/cam_enc_4xx.c |   12 +-
 common/cmd_nand.c                   |   18 +-
 common/cmd_onenand.c                |   30 +-
 common/env_onenand.c                |    6 +-
 drivers/mtd/Makefile                |    4 +-
 drivers/mtd/cfi_mtd.c               |   12 +-
 drivers/mtd/mtdconcat.c             |   98 +--
 drivers/mtd/mtdcore.c               |  191 ++++
 drivers/mtd/mtdpart.c               |  158 ++--
 drivers/mtd/nand/atmel_nand.c       |   16 +-
 drivers/mtd/nand/davinci_nand.c     |    2 +-
 drivers/mtd/nand/diskonchip.c       |   12 +-
 drivers/mtd/nand/fsl_elbc_nand.c    |   16 +-
 drivers/mtd/nand/fsl_ifc_nand.c     |   16 +-
 drivers/mtd/nand/fsmc_nand.c        |    3 +-
 drivers/mtd/nand/mpc5121_nfc.c      |    2 +-
 drivers/mtd/nand/mxc_nand.c         |   18 +-
 drivers/mtd/nand/mxs_nand.c         |   31 +-
 drivers/mtd/nand/nand_base.c        | 1655 ++++++++++++++++++++---------------
 drivers/mtd/nand/nand_bbt.c         |  822 ++++++++---------
 drivers/mtd/nand/nand_ids.c         |   14 +-
 drivers/mtd/nand/nand_util.c        |   21 +-
 drivers/mtd/nand/omap_gpmc.c        |    2 +-
 drivers/mtd/nand/tegra_nand.c       |   26 +-
 drivers/mtd/nand/tegra_nand.h       |    2 +-
 drivers/mtd/onenand/onenand_base.c  |   82 +-
 drivers/mtd/onenand/onenand_bbt.c   |    6 +-
 drivers/mtd/ubi/build.c             |    2 +-
 drivers/mtd/ubi/eba.c               |    2 +-
 drivers/mtd/ubi/io.c                |   12 +-
 drivers/mtd/ubi/kapi.c              |    2 +-
 drivers/mtd/ubi/misc.c              |    2 +-
 drivers/mtd/ubi/vtbl.c              |    2 +-
 fs/yaffs2/yaffs_mtdif.c             |   18 +-
 fs/yaffs2/yaffs_mtdif2.c            |   14 +-
 include/linux/mtd/bbm.h             |   49 +-
 include/linux/mtd/mtd-abi.h         |  158 ----
 include/linux/mtd/mtd.h             |  203 +++--
 include/linux/mtd/nand.h            |  173 ++--
 include/linux/string.h              |    3 +
 include/mtd/mtd-abi.h               |  209 +++++
 include/nand.h                      |    8 +-
 lib/string.c                        |   59 ++
 43 files changed, 2333 insertions(+), 1858 deletions(-)
 delete mode 100644 include/linux/mtd/mtd-abi.h
 create mode 100644 include/mtd/mtd-abi.h
board/ait/cam_enc_4xx/cam_enc_4xx.c +7 -5
index 32b28f9..2a0c31c 100644
@@ -120,7 +120,7 @@ int board_eth_init(bd_t *bis)
 #ifdef CONFIG_NAND_DAVINCI
 static int
 davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
-				   uint8_t *buf, int page)
+				   uint8_t *buf, int oob_required, int page)
 {
 	struct nand_chip *this = mtd->priv;
 	int i, eccsize = chip->ecc.size;
@@ -167,8 +167,9 @@ davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 	return 0;
 }
 
-static void davinci_std_write_page_syndrome(struct mtd_info *mtd,
-				    struct nand_chip *chip, const uint8_t *buf)
+static int davinci_std_write_page_syndrome(struct mtd_info *mtd,
+				    struct nand_chip *chip, const uint8_t *buf,
+				    int oob_required)
 {
 	unsigned char davinci_ecc_buf[NAND_MAX_OOBSIZE];
 	struct nand_chip *this = mtd->priv;
@@ -218,6 +219,7 @@ static void davinci_std_write_page_syndrome(struct mtd_info *mtd,
 	i = mtd->oobsize - (oob - chip->oob_poi);
 	if (i)
 		chip->write_buf(mtd, oob, i);
+	return 0;
 }
 
 static int davinci_std_write_oob_syndrome(struct mtd_info *mtd,
@@ -239,7 +241,7 @@ static int davinci_std_write_oob_syndrome(struct mtd_info *mtd,
 }
 
 static int davinci_std_read_oob_syndrome(struct mtd_info *mtd,
-	struct nand_chip *chip, int page, int sndcmd)
+	struct nand_chip *chip, int page)
 {
 	struct nand_chip *this = mtd->priv;
 	uint8_t *buf = chip->oob_poi;
@@ -249,7 +251,7 @@ static int davinci_std_read_oob_syndrome(struct mtd_info *mtd,
 
 	chip->read_buf(mtd, bufpoi, mtd->oobsize);
 
-	return 1;
+	return 0;
 }
 
 static void nand_dm365evm_select_chip(struct mtd_info *mtd, int chip)
common/cmd_nand.c +9 -9
index 1568594..c4ba0b3 100644
@@ -62,8 +62,8 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
 	ops.oobbuf = oobbuf;
 	ops.len = nand->writesize;
 	ops.ooblen = nand->oobsize;
-	ops.mode = MTD_OOB_RAW;
-	i = nand->read_oob(nand, addr, &ops);
+	ops.mode = MTD_OPS_RAW;
+	i = mtd_read_oob(nand, addr, &ops);
 	if (i < 0) {
 		printf("Error (%d) reading page %08lx\n", i, off);
 		free(datbuf);
@@ -407,13 +407,13 @@ static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
 			.oobbuf = ((u8 *)addr) + nand->writesize,
 			.len = nand->writesize,
 			.ooblen = nand->oobsize,
-			.mode = MTD_OOB_RAW
+			.mode = MTD_OPS_RAW
 		};
 
 		if (read)
-			ret = nand->read_oob(nand, off, &ops);
+			ret = mtd_read_oob(nand, off, &ops);
 		else
-			ret = nand->write_oob(nand, off, &ops);
+			ret = mtd_write_oob(nand, off, &ops);
 
 		if (ret) {
 			printf("%s: error at offset %llx, ret %d\n",
@@ -680,13 +680,13 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			mtd_oob_ops_t ops = {
 				.oobbuf = (u8 *)addr,
 				.ooblen = rwsize,
-				.mode = MTD_OOB_RAW
+				.mode = MTD_OPS_RAW
 			};
 
 			if (read)
-				ret = nand->read_oob(nand, off, &ops);
+				ret = mtd_read_oob(nand, off, &ops);
 			else
-				ret = nand->write_oob(nand, off, &ops);
+				ret = mtd_write_oob(nand, off, &ops);
 		} else if (raw) {
 			ret = raw_access(nand, addr, off, pagecount, read);
 		} else {
@@ -729,7 +729,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		while (argc > 0) {
 			addr = simple_strtoul(*argv, NULL, 16);
 
-			if (nand->block_markbad(nand, addr)) {
+			if (mtd_block_markbad(nand, addr)) {
 				printf("block 0x%08lx NOT marked "
 					"as bad! ERROR %d\n",
 					addr, ret);
common/cmd_onenand.c +15 -15
index a0d25e5..06cc140 100644
@@ -83,7 +83,7 @@ static int onenand_block_read(loff_t from, size_t len,
 		ops.len = blocksize;
 
 	while (blocks) {
-		ret = mtd->block_isbad(mtd, ofs);
+		ret = mtd_block_isbad(mtd, ofs);
 		if (ret) {
 			printk("Bad blocks %d at 0x%x\n",
 			       (u32)(ofs >> this->erase_shift), (u32)ofs);
@@ -97,7 +97,7 @@ static int onenand_block_read(loff_t from, size_t len,
 			ops.datbuf = buf;
 
 		ops.retlen = 0;
-		ret = mtd->read_oob(mtd, ofs, &ops);
+		ret = mtd_read_oob(mtd, ofs, &ops);
 		if (ret) {
 			printk("Read failed 0x%x, %d\n", (u32)ofs, ret);
 			ofs += blocksize;
@@ -118,7 +118,7 @@ static int onenand_write_oneblock_withoob(loff_t to, const u_char * buf,
 	struct mtd_oob_ops ops = {
 		.len = mtd->writesize,
 		.ooblen = mtd->oobsize,
-		.mode = MTD_OOB_AUTO,
+		.mode = MTD_OPS_AUTO_OOB,
 	};
 	int page, ret = 0;
 	for (page = 0; page < (mtd->erasesize / mtd->writesize); page ++) {
@@ -126,7 +126,7 @@ static int onenand_write_oneblock_withoob(loff_t to, const u_char * buf,
 		buf += mtd->writesize;
 		ops.oobbuf = (u_char *)buf;
 		buf += mtd->oobsize;
-		ret = mtd->write_oob(mtd, to, &ops);
+		ret = mtd_write_oob(mtd, to, &ops);
 		if (ret)
 			break;
 		to += mtd->writesize;
@@ -156,7 +156,7 @@ static int onenand_block_write(loff_t to, size_t len,
 	ofs = to;
 
 	while (blocks) {
-		ret = mtd->block_isbad(mtd, ofs);
+		ret = mtd_block_isbad(mtd, ofs);
 		if (ret) {
 			printk("Bad blocks %d at 0x%x\n",
 			       (u32)(ofs >> this->erase_shift), (u32)ofs);
@@ -165,7 +165,7 @@ static int onenand_block_write(loff_t to, size_t len,
 		}
 
 		if (!withoob)
-			ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf);
+			ret = mtd_write(mtd, ofs, blocksize, &_retlen, buf);
 		else
 			ret = onenand_write_oneblock_withoob(ofs, buf, &_retlen);
 		if (ret) {
@@ -195,7 +195,7 @@ static int onenand_block_erase(u32 start, u32 size, int force)
 	int blocksize = 1 << this->erase_shift;
 
 	for (ofs = start; ofs < (start + size); ofs += blocksize) {
-		ret = mtd->block_isbad(mtd, ofs);
+		ret = mtd_block_isbad(mtd, ofs);
 		if (ret && !force) {
 			printf("Skip erase bad block %d at 0x%x\n",
 			       (u32)(ofs >> this->erase_shift), (u32)ofs);
@@ -206,7 +206,7 @@ static int onenand_block_erase(u32 start, u32 size, int force)
 		instr.len = blocksize;
 		instr.priv = force;
 		instr.mtd = mtd;
-		ret = mtd->erase(mtd, &instr);
+		ret = mtd_erase(mtd, &instr);
 		if (ret) {
 			printf("erase failed block %d at 0x%x\n",
 			       (u32)(ofs >> this->erase_shift), (u32)ofs);
@@ -261,7 +261,7 @@ static int onenand_block_test(u32 start, u32 size)
 	while (blocks < end_block) {
 		printf("\rTesting block %d@0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs);
 
-		ret = mtd->block_isbad(mtd, ofs);
+		ret = mtd_block_isbad(mtd, ofs);
 		if (ret) {
 			printf("Skip erase bad block %d at 0x%x\n",
 			       (u32)(ofs >> this->erase_shift), (u32)ofs);
@@ -270,19 +270,19 @@ static int onenand_block_test(u32 start, u32 size)
 
 		instr.addr = ofs;
 		instr.len = blocksize;
-		ret = mtd->erase(mtd, &instr);
+		ret = mtd_erase(mtd, &instr);
 		if (ret) {
 			printk("Erase failed 0x%x, %d\n", (u32)ofs, ret);
 			goto next;
 		}
 
-		ret = mtd->write(mtd, ofs, blocksize, &retlen, buf);
+		ret = mtd_write(mtd, ofs, blocksize, &retlen, buf);
 		if (ret) {
 			printk("Write failed 0x%x, %d\n", (u32)ofs, ret);
 			goto next;
 		}
 
-		ret = mtd->read(mtd, ofs, blocksize, &retlen, verify_buf);
+		ret = mtd_read(mtd, ofs, blocksize, &retlen, verify_buf);
 		if (ret) {
 			printk("Read failed 0x%x, %d\n", (u32)ofs, ret);
 			goto next;
@@ -324,7 +324,7 @@ static int onenand_dump(struct mtd_info *mtd, ulong off, int only_oob)
 	ops.len = mtd->writesize;
 	ops.ooblen = mtd->oobsize;
 	ops.retlen = 0;
-	i = mtd->read_oob(mtd, addr, &ops);
+	i = mtd_read_oob(mtd, addr, &ops);
 	if (i < 0) {
 		printf("Error (%d) reading page %08lx\n", i, off);
 		free(datbuf);
@@ -373,7 +373,7 @@ static int do_onenand_bad(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar
 	/* Currently only one OneNAND device is supported */
 	printf("\nDevice %d bad blocks:\n", 0);
 	for (ofs = 0; ofs < mtd->size; ofs += mtd->erasesize) {
-		if (mtd->block_isbad(mtd, ofs))
+		if (mtd_block_isbad(mtd, ofs))
 			printf("  %08x\n", (u32)ofs);
 	}
 
@@ -530,7 +530,7 @@ static int do_onenand_markbad(cmd_tbl_t * cmdtp, int flag, int argc, char * cons
 	while (argc > 0) {
 		addr = simple_strtoul(*argv, NULL, 16);
 
-		if (mtd->block_markbad(mtd, addr)) {
+		if (mtd_block_markbad(mtd, addr)) {
 			printf("block 0x%08lx NOT marked "
 				"as bad! ERROR %d\n",
 				addr, ret);
common/env_onenand.c +3 -3
index faa903d..e8bde37 100644
@@ -68,7 +68,7 @@ void env_relocate_spec(void)
 	/* Check OneNAND exist */
 	if (mtd->writesize)
 		/* Ignore read fail */
-		mtd->read(mtd, env_addr, ONENAND_MAX_ENV_SIZE,
+		mtd_read(mtd, env_addr, ONENAND_MAX_ENV_SIZE,
 				&retlen, (u_char *)buf);
 	else
 		mtd->writesize = MAX_ONENAND_PAGESIZE;
@@ -113,12 +113,12 @@ int saveenv(void)
 #endif
 	instr.addr = env_addr;
 	instr.mtd = mtd;
-	if (mtd->erase(mtd, &instr)) {
+	if (mtd_erase(mtd, &instr)) {
 		printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
 		return 1;
 	}
 
-	if (mtd->write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
+	if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
 			(u_char *)&env_new)) {
 		printf("OneNAND: write failed at 0x%llx\n", instr.addr);
 		return 2;
drivers/mtd/Makefile +3 -1
index 543c845..99f39fc 100644
@@ -25,7 +25,9 @@ include $(TOPDIR)/config.mk
 
 LIB	:= $(obj)libmtd.o
 
-COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o
+ifneq (,$(findstring y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND)))
+COBJS-y += mtdcore.o
+endif
 COBJS-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
 COBJS-$(CONFIG_MTD_CONCAT) += mtdconcat.o
 COBJS-$(CONFIG_HAS_DATAFLASH) += at45.o
drivers/mtd/cfi_mtd.c +6 -6
index 8d74fa9..bbb71a1 100644
@@ -244,12 +244,12 @@ int cfi_mtd_init(void)
 		mtd->size		= fi->size;
 		mtd->writesize		= 1;
 
-		mtd->erase		= cfi_mtd_erase;
-		mtd->read		= cfi_mtd_read;
-		mtd->write		= cfi_mtd_write;
-		mtd->sync		= cfi_mtd_sync;
-		mtd->lock		= cfi_mtd_lock;
-		mtd->unlock		= cfi_mtd_unlock;
+		mtd->_erase		= cfi_mtd_erase;
+		mtd->_read		= cfi_mtd_read;
+		mtd->_write		= cfi_mtd_write;
+		mtd->_sync		= cfi_mtd_sync;
+		mtd->_lock		= cfi_mtd_lock;
+		mtd->_unlock		= cfi_mtd_unlock;
 		mtd->priv		= fi;
 
 		if (add_mtd_device(mtd))
drivers/mtd/mtdconcat.c +32 -66

240 lines not on this page · raw message

drivers/mtd/mtdcore.c +191 -0

200 lines not on this page · raw message

drivers/mtd/mtdpart.c +54 -104

284 lines not on this page · raw message

drivers/mtd/nand/atmel_nand.c +10 -6
index 994dd9f..b09e7b7 100644
@@ -489,7 +489,7 @@ normal_check:
 }
 
 static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
-	struct nand_chip *chip, uint8_t *buf, int page)
+	struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
 {
 	struct atmel_nand_host *host = chip->priv;
 	int eccsize = chip->ecc.size;
@@ -529,8 +529,9 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
 	return 0;
 }
 
-static void atmel_nand_pmecc_write_page(struct mtd_info *mtd,
-		struct nand_chip *chip, const uint8_t *buf)
+static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
+		struct nand_chip *chip, const uint8_t *buf,
+		int oob_required)
 {
 	struct atmel_nand_host *host = chip->priv;
 	uint32_t *eccpos = chip->ecc.layout->eccpos;
@@ -557,7 +558,7 @@ static void atmel_nand_pmecc_write_page(struct mtd_info *mtd,
 
 	if (!timeout) {
 		printk(KERN_ERR "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n");
-		return;
+		goto out;
 	}
 
 	for (i = 0; i < host->pmecc_sector_number; i++) {
@@ -570,6 +571,8 @@ static void atmel_nand_pmecc_write_page(struct mtd_info *mtd,
 		}
 	}
 	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+out:
+	return 0;
 }
 
 static void atmel_pmecc_core_init(struct mtd_info *mtd)
@@ -775,9 +778,10 @@ static int atmel_nand_calculate(struct mtd_info *mtd,
  * mtd:        mtd info structure
  * chip:       nand chip info structure
  * buf:        buffer to store read data
+ * oob_required:    caller expects OOB data read to chip->oob_poi
  */
-static int atmel_nand_read_page(struct mtd_info *mtd,
-		struct nand_chip *chip, uint8_t *buf, int page)
+static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+				uint8_t *buf, int oob_required, int page)
 {
 	int eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
drivers/mtd/nand/davinci_nand.c +1 -1
index e8506dd..04b24f3 100644
@@ -607,7 +607,7 @@ void davinci_nand_init(struct nand_chip *nand)
 {
 	nand->chip_delay  = 0;
 #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
-	nand->options	  |= NAND_USE_FLASH_BBT;
+	nand->bbt_options	  |= NAND_BBT_USE_FLASH;
 #endif
 #ifdef CONFIG_SYS_NAND_HW_ECC
 	nand->ecc.mode = NAND_ECC_HW;
drivers/mtd/nand/diskonchip.c +6 -6
index edf3a09..104d97f 100644
@@ -134,7 +134,7 @@ static struct rs_control *rs_decoder;
 
 /*
  * The HW decoder in the DoC ASIC's provides us a error syndrome,
- * which we must convert to a standard syndrom usable by the generic
+ * which we must convert to a standard syndrome usable by the generic
  * Reed-Solomon library code.
  *
  * Fabrice Bellard figured this out in the old docecc code. I added
@@ -154,7 +154,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 	ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2);
 	parity = ecc[1];
 
-	/* Initialize the syndrom buffer */
+	/* Initialize the syndrome buffer */
 	for (i = 0; i < NROOTS; i++)
 		s[i] = ds[0];
 	/*
@@ -1033,7 +1033,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
 		WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
 	else
 		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
-	if (no_ecc_failures && (ret == -EBADMSG)) {
+	if (no_ecc_failures && mtd_is_eccerr(ret)) {
 		printk(KERN_ERR "suppressing ECC failure\n");
 		ret = 0;
 	}
@@ -1073,7 +1073,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
 	size_t retlen;
 
 	for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
-		ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+		ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf);
 		if (retlen != mtd->writesize)
 			continue;
 		if (ret) {
@@ -1098,7 +1098,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
 	/* Only one mediaheader was found.  We want buf to contain a
 	   mediaheader on return, so we'll have to re-read the one we found. */
 	offs = doc->mh0_page << this->page_shift;
-	ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+	ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf);
 	if (retlen != mtd->writesize) {
 		/* Insanity.  Give up. */
 		printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
@@ -1658,7 +1658,7 @@ static int __init doc_probe(unsigned long physadr)
 	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
 	nand->ecc.size		= 512;
 	nand->ecc.bytes		= 6;
-	nand->options		= NAND_USE_FLASH_BBT;
+	nand->bbt_options	= NAND_BBT_USE_FLASH;
 
 	doc->physadr		= physadr;
 	doc->virtadr		= virtadr;
drivers/mtd/nand/fsl_elbc_nand.c +8 -8
index 834a8a6..65edbf5 100644
@@ -640,9 +640,8 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	return fsl_elbc_read_byte(mtd);
 }
 
-static int fsl_elbc_read_page(struct mtd_info *mtd,
-			      struct nand_chip *chip,
-			      uint8_t *buf, int page)
+static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+			      uint8_t *buf, int oob_required, int page)
 {
 	fsl_elbc_read_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -656,12 +655,13 @@ static int fsl_elbc_read_page(struct mtd_info *mtd,
 /* ECC will be calculated automatically, and errors will be detected in
  * waitfunc.
  */
-static void fsl_elbc_write_page(struct mtd_info *mtd,
-				struct nand_chip *chip,
-				const uint8_t *buf)
+static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+				const uint8_t *buf, int oob_required)
 {
 	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	return 0;
 }
 
 static struct fsl_elbc_ctrl *elbc_ctrl;
@@ -747,8 +747,8 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr)
 	nand->bbt_md = &bbt_mirror_descr;
 
   	/* set up nand options */
-	nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
-			NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE;
+	nand->options = NAND_NO_SUBPAGE_WRITE;
+	nand->bbt_options = NAND_BBT_USE_FLASH;
 
 	nand->controller = &elbc_ctrl->controller;
 	nand->priv = priv;
drivers/mtd/nand/fsl_ifc_nand.c +8 -8
index b13d8a9..5d47b40 100644
@@ -686,9 +686,8 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	return nand_fsr;
 }
 
-static int fsl_ifc_read_page(struct mtd_info *mtd,
-			      struct nand_chip *chip,
-			      uint8_t *buf, int page)
+static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+			     uint8_t *buf, int oob_required, int page)
 {
 	struct fsl_ifc_mtd *priv = chip->priv;
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
@@ -705,12 +704,13 @@ static int fsl_ifc_read_page(struct mtd_info *mtd,
 /* ECC will be calculated automatically, and errors will be detected in
  * waitfunc.
  */
-static void fsl_ifc_write_page(struct mtd_info *mtd,
-				struct nand_chip *chip,
-				const uint8_t *buf)
+static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+			       const uint8_t *buf, int oob_required)
 {
 	fsl_ifc_write_buf(mtd, buf, mtd->writesize);
 	fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	return 0;
 }
 
 static void fsl_ifc_ctrl_init(void)
@@ -852,8 +852,8 @@ int board_nand_init(struct nand_chip *nand)
 	nand->bbt_md = &bbt_mirror_descr;
 
 	/* set up nand options */
-	nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
-			NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE;
+	nand->options = NAND_NO_SUBPAGE_WRITE;
+	nand->bbt_options = NAND_BBT_USE_FLASH;
 
 	if (cspr & CSPR_PORT_SIZE_16) {
 		nand->read_byte = fsl_ifc_read_byte16;
drivers/mtd/nand/fsmc_nand.c +2 -1
index 7a61d88..48ca543 100644
@@ -341,6 +341,7 @@ void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	buffer to store read data
+ * @oob_required:	caller expects OOB data read to chip->oob_poi
  * @page:	page number to read
  *
  * This routine is needed for fsmc verison 8 as reading from NAND chip has to be
@@ -350,7 +351,7 @@ void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
  * max of 8 bits)
  */
 static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
-				 uint8_t *buf, int page)
+				 uint8_t *buf, int oob_required, int page)
 {
 	struct fsmc_eccplace *fsmc_eccpl;
 	int i, j, s, stat, eccsize = chip->ecc.size;
drivers/mtd/nand/mpc5121_nfc.c +1 -1
index e6b7a70..e53f341 100644
@@ -621,7 +621,7 @@ int board_nand_init(struct nand_chip *chip)
 	chip->write_buf = mpc5121_nfc_write_buf;
 	chip->verify_buf = mpc5121_nfc_verify_buf;
 	chip->select_chip = mpc5121_nfc_select_chip;
-	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
 	chip->ecc.mode = NAND_ECC_SOFT;
 
 	/* Reset NAND Flash controller */
drivers/mtd/nand/mxc_nand.c +12 -6
index d0ded48..c51a012 100644
@@ -380,7 +380,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 #ifdef MXC_NFC_V2_1
 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd,
 				      struct nand_chip *chip,
-				      int page, int sndcmd)
+				      int page)
 {
 	struct mxc_nand_host *host = chip->priv;
 	uint8_t *buf = chip->oob_poi;
@@ -434,6 +434,7 @@ static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd,
 static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd,
 					   struct nand_chip *chip,
 					   uint8_t *buf,
+					   int oob_required,
 					   int page)
 {
 	struct mxc_nand_host *host = chip->priv;
@@ -478,6 +479,7 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd,
 static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
 				       struct nand_chip *chip,
 				       uint8_t *buf,
+				       int oob_required,
 				       int page)
 {
 	struct mxc_nand_host *host = chip->priv;
@@ -567,9 +569,10 @@ static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
 	return status & NAND_STATUS_FAIL ? -EIO : 0;
 }
 
-static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
+static int mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
 					     struct nand_chip *chip,
-					     const uint8_t *buf)
+					     const uint8_t *buf,
+					     int oob_required)
 {
 	struct mxc_nand_host *host = chip->priv;
 	int eccsize = chip->ecc.size;
@@ -603,11 +606,13 @@ static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
 	size = mtd->oobsize - (oob - chip->oob_poi);
 	if (size)
 		chip->write_buf(mtd, oob, size);
+	return 0;
 }
 
-static void mxc_nand_write_page_syndrome(struct mtd_info *mtd,
+static int mxc_nand_write_page_syndrome(struct mtd_info *mtd,
 					 struct nand_chip *chip,
-					 const uint8_t *buf)
+					 const uint8_t *buf,
+					 int oob_required)
 {
 	struct mxc_nand_host *host = chip->priv;
 	int i, n, eccsize = chip->ecc.size;
@@ -646,6 +651,7 @@ static void mxc_nand_write_page_syndrome(struct mtd_info *mtd,
 	i = mtd->oobsize - (oob - chip->oob_poi);
 	if (i)
 		chip->write_buf(mtd, oob, i);
+	return 0;
 }
 
 static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
@@ -1172,7 +1178,7 @@ int board_nand_init(struct nand_chip *this)
 #endif
 
 #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
-	this->options |= NAND_USE_FLASH_BBT;
+	this->bbt_options |= NAND_BBT_USE_FLASH;
 	this->bbt_td = &bbt_main_descr;
 	this->bbt_md = &bbt_mirror_descr;
 #endif
drivers/mtd/nand/mxs_nand.c +17 -14
index e38e151..422519a 100644
@@ -546,7 +546,8 @@ static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
  * Read a page from NAND.
  */
 static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
-					uint8_t *buf, int page)
+					uint8_t *buf, int oob_required,
+					int page)
 {
 	struct mxs_nand_info *nand_info = nand->priv;
 	struct mxs_dma_desc *d;
@@ -691,8 +692,9 @@ rtn:
 /*
  * Write a page to NAND.
  */
-static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
-				struct nand_chip *nand, const uint8_t *buf)
+static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf,
+				int oob_required)
 {
 	struct mxs_nand_info *nand_info = nand->priv;
 	struct mxs_dma_desc *d;
@@ -748,6 +750,7 @@ static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
 
 rtn:
 	mxs_nand_return_dma_descs(nand_info);
+	return 0;
 }
 
 /*
@@ -763,7 +766,7 @@ static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
 	struct mxs_nand_info *nand_info = chip->priv;
 	int ret;
 
-	if (ops->mode == MTD_OOB_RAW)
+	if (ops->mode == MTD_OPS_RAW)
 		nand_info->raw_oob_mode = 1;
 	else
 		nand_info->raw_oob_mode = 0;
@@ -788,7 +791,7 @@ static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
 	struct mxs_nand_info *nand_info = chip->priv;
 	int ret;
 
-	if (ops->mode == MTD_OOB_RAW)
+	if (ops->mode == MTD_OPS_RAW)
 		nand_info->raw_oob_mode = 1;
 	else
 		nand_info->raw_oob_mode = 0;
@@ -997,19 +1000,19 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
 	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
 
 	/* Hook some operations at the MTD level. */
-	if (mtd->read_oob != mxs_nand_hook_read_oob) {
-		nand_info->hooked_read_oob = mtd->read_oob;
-		mtd->read_oob = mxs_nand_hook_read_oob;
+	if (mtd->_read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->_read_oob;
+		mtd->_read_oob = mxs_nand_hook_read_oob;
 	}
 
-	if (mtd->write_oob != mxs_nand_hook_write_oob) {
-		nand_info->hooked_write_oob = mtd->write_oob;
-		mtd->write_oob = mxs_nand_hook_write_oob;
+	if (mtd->_write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->_write_oob;
+		mtd->_write_oob = mxs_nand_hook_write_oob;
 	}
 
-	if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
-		nand_info->hooked_block_markbad = mtd->block_markbad;
-		mtd->block_markbad = mxs_nand_hook_block_markbad;
+	if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->_block_markbad;
+		mtd->_block_markbad = mxs_nand_hook_block_markbad;
 	}
 
 	/* We use the reference implementation for bad block management. */
drivers/mtd/nand/nand_base.c +925 -730

1,681 lines not on this page · raw message

drivers/mtd/nand/nand_bbt.c +386 -436

822 lines not on this page · raw message

drivers/mtd/nand/nand_ids.c +8 -6
index 3953549..f856778 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/nand/nand_util.c +11 -10
index 2ba0c5e..0c68384 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/nand/omap_gpmc.c +1 -1
index f1469d1..ccf9750 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/nand/tegra_nand.c +11 -15
index 4d94cc6..854fd21 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/nand/tegra_nand.h +1 -1
index 7e74be7..622b869 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/onenand/onenand_base.c +33 -49

82 lines not on this page · raw message

drivers/mtd/onenand/onenand_bbt.c +2 -4
index 9d5da54..0267c2c 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/ubi/build.c +1 -1
index d144ac2..0bd2938 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/ubi/eba.c +1 -1
index d523c94..d2d3c9c 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/ubi/io.c +6 -6
index 8423894..05de9ae 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/ubi/kapi.c +1 -1
index 423d479..e553188 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/ubi/misc.c +1 -1
index a6410bf..e8660d9 100644

Lines of this file are not shown. View the raw message.

drivers/mtd/ubi/vtbl.c +1 -1
index f679f06..29d2320 100644

Lines of this file are not shown. View the raw message.

fs/yaffs2/yaffs_mtdif.c +9 -9
index db49052..6fcba04 100644

Lines of this file are not shown. View the raw message.

fs/yaffs2/yaffs_mtdif2.c +7 -7
index 8135bcc..234cb70 100644

Lines of this file are not shown. View the raw message.

include/linux/mtd/bbm.h +35 -14

49 lines not on this page · raw message

include/linux/mtd/mtd-abi.h deleted +0 -158

158 lines not on this page · raw message

include/linux/mtd/mtd.h +128 -75

203 lines not on this page · raw message

include/linux/mtd/nand.h +105 -68

173 lines not on this page · raw message

include/linux/string.h +3 -0
index e9b134d..8e44855 100644

Lines of this file are not shown. View the raw message.

include/mtd/mtd-abi.h new file +209 -0

209 lines not on this page · raw message

include/nand.h +4 -4
index dded4e2..e61087a 100644

Lines of this file are not shown. View the raw message.

lib/string.c +59 -0

59 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.10.4

Part of the diff is not shown here. View the raw message.

#1 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

Quoted 11 lines · Sergey Lapin

This patch is essentially an update of u-boot MTD subsystem to the state of Linux-3.7.1 with exclusion of some bits:

- the update is concentrated on NAND, no onenand or CFI/NOR/SPI flashes interfaces are updated EXCEPT for API changes.

- new large NAND chips support is there, though some updates have got in Linux-3.8.-rc1, (which will follow on top of this patch).

To produce this update I used tag v3.7.1 of linux-stable repository.

Quoted 7 lines

The update was made using application of relevant patches, with changes relevant to U-Boot-only stuff sticked together to keep bisectability. Then all changes were grouped together to this patch.

---

Applying: mtd: resync with Linux-3.7.1 /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:4292: space before tab in indent.
chip->ecc.strength =
/home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:835: new blank line at EOF.
+ /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:6011: new blank line at EOF.
+ /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:7970: new blank line at EOF.
+
warning: 4 lines add whitespace errors.

Are these whitespace errors in Linux?

I tried booting on P2020RDB-PC_NAND, and got this:

Quoted 4 lines
L2:    512 KB already enabled, moving to 0xf8f80000
NAND:  BUG: failure at nand_base.c:3214/nand_scan_tail()!

BUG!
### ERROR ### Please RESET the board ###

It boots fine without this patch. nand_base.c:3214 is complaining about missing ecc.strength. You need to update existing U-Boot drivers for new
API so that nothing breaks. Ask maintainers of particular drivers for help if necessary.

You'll probably need to go through the various NAND patches between 3.0 and 3.7.1 looking for API changes, and make sure that they're all accounted for, beyond just making things build.

Quoted 17 lines
board/ait/cam_enc_4xx/cam_enc_4xx.c +1 -1
index 32b28f9..2a0c31c 100644
@@ -120,7 +120,7 @@ int board_eth_init(bd_t *bis)
 #ifdef CONFIG_NAND_DAVINCI
 static int
 davinci_std_read_page_syndrome(struct mtd_info *mtd, struct  
 nand_chip *chip,
-				   uint8_t *buf, int page)
+				   uint8_t *buf, int oob_required, int  
 page)
 {
board/ait/cam_enc_4xx/cam_enc_4xx.c +0 -0
 	struct nand_chip *this = mtd->priv;
 	int i, eccsize = chip->ecc.size;

board/ait/cam_enc_4xx/cam_enc_4xx.c davinci_std_read_page_syndrome(struct mtd_info · line 169

Quoted 3 lines
board/ait/cam_enc_4xx/cam_enc_4xx.c +0 -0
@@ -167,8 +167,9 @@ davinci_std_read_page_syndrome(struct mtd_info  
 *mtd, struct nand_chip *chip,
 	return 0;
 }

We really should not be having NAND driver code (stuff that interacts with the NAND API; not hardware setup) outside of drivers/mtd/nand.

drivers/mtd/Makefile include $(TOPDIR)/config.mk · line 31

Quoted 13 lines
drivers/mtd/Makefile +3 -1
index 543c845..99f39fc 100644
@@ -25,7 +25,9 @@ include $(TOPDIR)/config.mk
 
 LIB	:= $(obj)libmtd.o
 
-COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o
+ifneq (,$(findstring  
 y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND)))
+COBJS-y += mtdcore.o
+endif

Please just require users of CONFIG_CMD_NAND or CONFIG_CMD_ONENAND to also select CONFIG_MTD_DEVICE, if it's not going to be practical to do without it -- and remove the "#ifdef CONFIG_MTD_DEVICE" from nand.c.

Could you explain why it's no longer practical to have NAND by itself?

Quoted 6 lines
drivers/mtd/nand/diskonchip.c +0 -0
index edf3a09..104d97f 100644

drivers/mtd/nand/diskonchip.c static struct rs_control *rs_decoder; · line 140

Quoted 8 lines
drivers/mtd/nand/diskonchip.c +1 -1
@@ -134,7 +134,7 @@ static struct rs_control *rs_decoder;
 
 /*
  * The HW decoder in the DoC ASIC's provides us a error syndrome,
- * which we must convert to a standard syndrom usable by the generic
+ * which we must convert to a standard syndrome usable by the generic
  * Reed-Solomon library code.
  *
  * Fabrice Bellard figured this out in the old docecc code. I added

This file should just go away, as nobody has stepped up to fix and use it.

Quoted 5 lines

#ifdef CONFIG_MTD_DEBUG

drivers/mtd/nand/diskonchip.c +1 -0
+#define pr_debug(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
 #define MTDDEBUG(n, args...)				\
 	do {						\
 		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\

drivers/mtd/nand/diskonchip.c

Quoted 10 lines
drivers/mtd/nand/diskonchip.c +1 -0
 			printk(KERN_INFO args);		\
 	} while(0)
 #else /* CONFIG_MTD_DEBUG */
+#define pr_debug(args...)
 #define MTDDEBUG(n, args...)				\
 	do {						\
 		if (0)					\
 			printk(KERN_INFO args);		\
 	} while(0)
 #endif /* CONFIG_MTD_DEBUG */

If you define pr_debug() to be absolutely nothing, you won't catch errors
until CONFIG_MTD_DEBUG is actually turned on. That's why MTDDEBUG does the "if (0)" thing.

pr_debug() should not be defined in terms of CONFIG_MTD_DEBUG. What if this header gets included by some other part of U-Boot? What if some other part of U-Boot also wants pr_debug, but based on a different subsystem's CONFIG_FOO_DEBUG?

drivers/mtd/nand/diskonchip.c

Quoted 3 lines
drivers/mtd/nand/diskonchip.c +3 -0
+#define pr_info(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_warn(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_err(args...)		MTDDEBUG(MTD_DEBUG_LEVEL0, args)

These should be ordinary printf, not MTDDEBUG. Under normal (non-debug) circumstances MTDDEBUG is a no-op. We want to see errors and
warnings always.

Plus, these should be defined somewhere that isn't MTD-specific.

drivers/mtd/nand/diskonchip.c

Quoted 11 lines
drivers/mtd/nand/diskonchip.c +11 -0
+static inline int mtd_is_bitflip(int err) {
+	return err == -EUCLEAN;
+}
+
+static inline int mtd_is_eccerr(int err) {
+	return err == -EBADMSG;
+}
+
+static inline int mtd_is_bitflip_or_eccerr(int err) {
+	return mtd_is_bitflip(err) || mtd_is_eccerr(err);
+}

Sigh, Linux isn't following its own coding style.

Quoted 12 lines
include/mtd/mtd-abi.h new file +4 -0
new file mode 100644
index 0000000..d51c1ab
@@ -0,0 +1,209 @@
+/*
+ * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
+ *
+ * Portions of MTD ABI definition which are shared by kernel and  

user space
+ */

include/mtd/mtd-abi.h line 12

Quoted 7 lines
include/mtd/mtd-abi.h new file +7 -0
+
+#ifndef __MTD_ABI_H__
+#define __MTD_ABI_H__
+
+#if 1
+#include <linux/compat.h>
+#endif

Why "#if 1"?

-Scott

#2 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

Dear Scott,
thanks a lot for your review,
see below.

Quoted 35 lines · Scott Wood
Quoted 11 lines · Sergey Lapin

This patch is essentially an update of u-boot MTD subsystem to the state of Linux-3.7.1 with exclusion of some bits:

- the update is concentrated on NAND, no onenand or CFI/NOR/SPI flashes interfaces are updated EXCEPT for API changes.

- new large NAND chips support is there, though some updates have got in Linux-3.8.-rc1, (which will follow on top of this patch).

To produce this update I used tag v3.7.1 of linux-stable repository.

Quoted 7 lines

The update was made using application of relevant patches, with changes relevant to U-Boot-only stuff sticked together to keep bisectability. Then all changes were grouped together to this patch.

---

Applying: mtd: resync with Linux-3.7.1 /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:4292:
space before tab in indent.
chip->ecc.strength =
/home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:835: new blank line at EOF.
+ /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:6011:
new blank line at EOF.
+ /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:7970:
new blank line at EOF.
+
warning: 4 lines add whitespace errors.

Quoted 1 line

Are these whitespace errors in Linux?

Yeah, this thing wonders me why. I can fix these without too much hussle, should I?

Quoted 7 lines

I tried booting on P2020RDB-PC_NAND, and got this:

Quoted 4 lines
L2:    512 KB already enabled, moving to 0xf8f80000
NAND:  BUG: failure at nand_base.c:3214/nand_scan_tail()!

BUG!
### ERROR ### Please RESET the board ###

Can you debug this farther, as I don't have devices with hardware ECC NAND, and was unable to convince anyone for testing?
Or, better, direct access to some board for several days could be nice.

Quoted 6 lines

It boots fine without this patch. nand_base.c:3214 is complaining about missing ecc.strength. You need to update existing U-Boot drivers for new
API so that nothing breaks. Ask maintainers of particular drivers for help if necessary.

I updated all drivers I could test and tried to do that for all others, but it seems it won't work without testing.

Quoted 4 lines

You'll probably need to go through the various NAND patches between 3.0 and 3.7.1 looking for API changes, and make sure that they're all accounted for, beyond just making things build.

This is what I did most of time, shit happens.

Quoted 15 lines
Quoted 15 lines
board/ait/cam_enc_4xx/cam_enc_4xx.c +0 -0
index 32b28f9..2a0c31c 100644
@@ -120,7 +120,7 @@ int board_eth_init(bd_t *bis)
 #ifdef CONFIG_NAND_DAVINCI

static int
davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,

board/ait/cam_enc_4xx/cam_enc_4xx.c +1 -1
-				   uint8_t *buf, int page)
+				   uint8_t *buf, int oob_required, int page)
{
	struct nand_chip *this = mtd->priv;
Quoted 8 lines

board/ait/cam_enc_4xx/cam_enc_4xx.c davinci_std_read_page_syndrome(struct mtd_info · line 169

Quoted 5 lines
	int i, eccsize = chip->ecc.size;
board/ait/cam_enc_4xx/cam_enc_4xx.c +0 -0
@@ -167,8 +167,9 @@ davinci_std_read_page_syndrome(struct mtd_info
 *mtd, struct nand_chip *chip,
 	return 0;
 }

We really should not be having NAND driver code (stuff that interacts with the NAND API; not hardware setup) outside of drivers/mtd/nand.

This probably should be split.

Quoted 19 lines
Quoted 12 lines
drivers/mtd/Makefile +0 -0
index 543c845..99f39fc 100644
@@ -25,7 +25,9 @@ include $(TOPDIR)/config.mk
 

LIB := $(obj)libmtd.o

drivers/mtd/Makefile +1 -1
-COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o
+ifneq (,$(findstring

y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND)))

drivers/mtd/Makefile include $(TOPDIR)/config.mk · line 30

Quoted 2 lines
drivers/mtd/Makefile +2 -0
+COBJS-y += mtdcore.o
+endif

Please just require users of CONFIG_CMD_NAND or CONFIG_CMD_ONENAND to also select CONFIG_MTD_DEVICE, if it's not going to be practical to do without it -- and remove the "#ifdef CONFIG_MTD_DEVICE" from nand.c.

Quoted 1 line

Could you explain why it's no longer practical to have NAND by itself?

I have dilemma here:

New MTD API instead of calling mtd->foo(mtd...) uses mtd_foo(mtd...) functions. In Linux, these are defined in mtdcore.c

We can either move these functions from mtdcore.c somewhere (where?), or #ifndef unrelated parts from mtdcore.c

Quoted 54 lines
Quoted 7 lines
drivers/mtd/nand/diskonchip.c +0 -0
index edf3a09..104d97f 100644

drivers/mtd/nand/diskonchip.c static struct rs_control *rs_decoder; · line 140

Quoted 8 lines
drivers/mtd/nand/diskonchip.c +1 -1
@@ -134,7 +134,7 @@ static struct rs_control *rs_decoder;
 
 /*
 * The HW decoder in the DoC ASIC's provides us a error syndrome,
- * which we must convert to a standard syndrom usable by the generic
+ * which we must convert to a standard syndrome usable by the generic
 * Reed-Solomon library code.
 *
 * Fabrice Bellard figured this out in the old docecc code. I added

This file should just go away, as nobody has stepped up to fix and use it.

Quoted 14 lines

#ifdef CONFIG_MTD_DEBUG
+#define pr_debug(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args)

#define MTDDEBUG(n, args...)				\
	do {						\
		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\
			printk(KERN_INFO args);		\
	} while(0)
#else /* CONFIG_MTD_DEBUG */
+#define pr_debug(args...)
#define MTDDEBUG(n, args...)				\
	do {						\
		if (0)					\
			printk(KERN_INFO args);		\
	} while(0)
Quoted 1 line

#endif /* CONFIG_MTD_DEBUG */

If you define pr_debug() to be absolutely nothing, you won't catch errors
until CONFIG_MTD_DEBUG is actually turned on. That's why MTDDEBUG does the "if (0)" thing.

pr_debug() should not be defined in terms of CONFIG_MTD_DEBUG. What if this header gets included by some other part of U-Boot? What if some other part of U-Boot also wants pr_debug, but based on a different subsystem's CONFIG_FOO_DEBUG?

drivers/mtd/nand/diskonchip.c

Quoted 3 lines
drivers/mtd/nand/diskonchip.c +3 -0
+#define pr_info(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_warn(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_err(args...)		MTDDEBUG(MTD_DEBUG_LEVEL0, args)

These should be ordinary printf, not MTDDEBUG. Under normal (non-debug) circumstances MTDDEBUG is a no-op. We want to see errors and
warnings always.

Quoted 1 line

Plus, these should be defined somewhere that isn't MTD-specific.

So, should I add separate header?

Quoted 28 lines

drivers/mtd/nand/diskonchip.c

Quoted 12 lines
drivers/mtd/nand/diskonchip.c +11 -0
+static inline int mtd_is_bitflip(int err) {
+	return err == -EUCLEAN;
+}
+
+static inline int mtd_is_eccerr(int err) {
+	return err == -EBADMSG;
+}
+
+static inline int mtd_is_bitflip_or_eccerr(int err) {
+	return mtd_is_bitflip(err) || mtd_is_eccerr(err);
+}

Sigh, Linux isn't following its own coding style.

Quoted 13 lines
include/mtd/mtd-abi.h new file +4 -0
new file mode 100644
index 0000000..d51c1ab
@@ -0,0 +1,209 @@
+/*
+ * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
+ *
+ * Portions of MTD ABI definition which are shared by kernel and

user space
+ */
+

Quoted 8 lines

include/mtd/mtd-abi.h line 12

Quoted 6 lines
include/mtd/mtd-abi.h new file +6 -0
+#ifndef __MTD_ABI_H__
+#define __MTD_ABI_H__
+
+#if 1
+#include <linux/compat.h>
+#endif

Why "#if 1"?

Sorry, this is probably my conflict resolution issue, will fix.

So, what is next step?

Thanks a lot,
S.

#3 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

Quoted 42 lines · Sergey Lapin

Dear Scott,
thanks a lot for your review,
see below.

Quoted 9 lines · Scott Wood
Quoted 8 lines · Sergey Lapin

This patch is essentially an update of u-boot MTD subsystem to the state of Linux-3.7.1 with exclusion of some bits:

- the update is concentrated on NAND, no onenand or CFI/NOR/SPI flashes interfaces are updated EXCEPT for API changes.

- new large NAND chips support is there, though some updates have got in Linux-3.8.-rc1, (which will follow on top of this

patch).

Quoted 2 lines
Quoted 2 lines

To produce this update I used tag v3.7.1 of linux-stable

repository.

Quoted 24 lines
Quoted 8 lines

The update was made using application of relevant patches, with changes relevant to U-Boot-only stuff sticked together to keep bisectability. Then all changes were grouped together to this patch.

---

Applying: mtd: resync with Linux-3.7.1 /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:4292:
space before tab in indent.
chip->ecc.strength =
/home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:835: new blank line at EOF.
+ /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:6011:
new blank line at EOF.
+ /home/scott/fsl/git/u-boot/upstream/.git/rebase-apply/patch:7970:
new blank line at EOF.
+
warning: 4 lines add whitespace errors.

Quoted 3 lines
Quoted 1 line

Are these whitespace errors in Linux?

Yeah, this thing wonders me why. I can fix these without too much hussle, should I?

They don't appear to have come from the Linux sources, so yes, please fix them.

Quoted 5 lines
Quoted 1 line

You'll probably need to go through the various NAND patches between

3.0

Quoted 2 lines

and 3.7.1 looking for API changes, and make sure that they're all accounted for, beyond just making things build.

This is what I did most of time, shit happens.

OK... ecc.strength is going to need to be fixed on several drivers (pretty much everything that uses hardware ecc). When I fixed that, elbc worked.

Quoted 22 lines
Quoted 4 lines
Quoted 4 lines
board/ait/cam_enc_4xx/cam_enc_4xx.c +0 -1
index 32b28f9..2a0c31c 100644
--- a/board/ait/cam_enc_4xx/cam_enc_4xx.c
Quoted 8 lines

board/ait/cam_enc_4xx/cam_enc_4xx.c

Quoted 8 lines

+++ b/board/ait/cam_enc_4xx/cam_enc_4xx.c

board/ait/cam_enc_4xx/cam_enc_4xx.c +0 -0
@@ -120,7 +120,7 @@ int board_eth_init(bd_t *bis)
 #ifdef CONFIG_NAND_DAVINCI

static int
davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,

board/ait/cam_enc_4xx/cam_enc_4xx.c +1 -1
-				   uint8_t *buf, int page)
+				   uint8_t *buf, int oob_required, int  

page)

Quoted 9 lines

board/ait/cam_enc_4xx/cam_enc_4xx.c davinci_std_read_page_syndrome(struct mtd_info · line 169

Quoted 7 lines
{
	struct nand_chip *this = mtd->priv;
	int i, eccsize = chip->ecc.size;
board/ait/cam_enc_4xx/cam_enc_4xx.c +0 -0
@@ -167,8 +167,9 @@ davinci_std_read_page_syndrome(struct mtd_info
 *mtd, struct nand_chip *chip,
 	return 0;
 }

We really should not be having NAND driver code (stuff that

Quoted 3 lines

interacts

Quoted 1 line

with the NAND API; not hardware setup) outside of drivers/mtd/nand.

This probably should be split.

Yes, it's not a problem with this patch, just something that this patch made me notice (hence the CC to Heiko).

Quoted 23 lines
Quoted 8 lines
Quoted 8 lines
drivers/mtd/Makefile +0 -0
index 543c845..99f39fc 100644
@@ -25,7 +25,9 @@ include $(TOPDIR)/config.mk
 

LIB := $(obj)libmtd.o

Quoted 7 lines

drivers/mtd/Makefile include $(TOPDIR)/config.mk · line 30

Quoted 5 lines
drivers/mtd/Makefile +1 -1
-COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o
+ifneq (,$(findstring

y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND)))

drivers/mtd/Makefile +2 -0
+COBJS-y += mtdcore.o
+endif

Please just require users of CONFIG_CMD_NAND or CONFIG_CMD_ONENAND

to

Quoted 1 line

also select CONFIG_MTD_DEVICE, if it's not going to be practical to

do

Quoted 3 lines

without it -- and remove the "#ifdef CONFIG_MTD_DEVICE" from nand.c.

Could you explain why it's no longer practical to have NAND by

itself?

Quoted 8 lines

I have dilemma here:

New MTD API instead of calling mtd->foo(mtd...) uses mtd_foo(mtd...) functions. In Linux, these are defined in mtdcore.c

We can either move these functions from mtdcore.c somewhere (where?), or
#ifndef unrelated parts from mtdcore.c

I'd say move them to another file in drivers/mtd. mtdapi.c?

Quoted 11 lines
Quoted 10 lines

drivers/mtd/Makefile

Quoted 3 lines
drivers/mtd/Makefile +3 -0
+#define pr_info(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_warn(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_err(args...)		MTDDEBUG(MTD_DEBUG_LEVEL0, args)

These should be ordinary printf, not MTDDEBUG. Under normal (non-debug) circumstances MTDDEBUG is a no-op. We want to see errors and
warnings always.

Plus, these should be defined somewhere that isn't MTD-specific.

So, should I add separate header?

Put them in include/linux/compat.h

Quoted 1 line

So, what is next step?

Once ecc.strength and the other review issues are dealt with, it should be good to go in.

-Scott

#4 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

Dear Scott,

could you please test the following patch
on top of this big patch to see if ecc.strength
problem goes away? I can integrate it into big
one then.

#5 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

Hi, Sergey

Quoted 39 lines · Sergey Lapin

Dear Scott,

could you please test the following patch on top of this big patch to see if ecc.strength problem goes away? I can integrate it into big one then.

From dffea1f073c546ab88f37f219f66d9d1478d4cf1 Mon Sep 17 00:00:00 2001
From: Sergey Lapin <[email protected]>
Date: Thu, 17 Jan 2013 18:29:21 +0400
Subject: [PATCH] SQUASHME: mtd: nand: Add ecc.strength support to drivers

---
  drivers/mtd/nand/atmel_nand.c    |    1 +
  drivers/mtd/nand/bfin_nand.c     |    2 ++
  drivers/mtd/nand/davinci_nand.c  |    1 +
  drivers/mtd/nand/diskonchip.c    |    1 +
  drivers/mtd/nand/fsl_elbc_nand.c |    6 ++++++
  drivers/mtd/nand/fsl_ifc_nand.c  |    1 +
  drivers/mtd/nand/fsmc_nand.c     |    2 ++
  drivers/mtd/nand/jz4740_nand.c   |    5 +++++
  drivers/mtd/nand/mxc_nand.c      |    7 +++++++
  drivers/mtd/nand/mxs_nand.c      |    1 +
  drivers/mtd/nand/nand_base.c     |    1 +
  drivers/mtd/nand/ndfc.c          |    1 +
  drivers/mtd/nand/nomadik.c       |    1 +
  drivers/mtd/nand/omap_gpmc.c     |    1 +
  drivers/mtd/nand/s3c2410_nand.c  |    1 +
  drivers/mtd/nand/s3c64xx.c       |    1 +
  drivers/mtd/nand/tegra_nand.c    |    1 +
  17 files changed, 34 insertions(+)
drivers/mtd/nand/atmel_nand.c +0 -0
index b09e7b7..9cdf35b 100644

drivers/mtd/nand/atmel_nand.c static int atmel_pmecc_nand_init_params(struct nand_chip *nand, · line 712

Quoted 4 lines
drivers/mtd/nand/atmel_nand.c +1 -0
@@ -709,6 +709,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
 
  	nand->ecc.read_page = atmel_nand_pmecc_read_page;
  	nand->ecc.write_page = atmel_nand_pmecc_write_page;
+	nand->ecc.strength = 1;

For atmel nand, it should be:

+ nand->ecc.strength = cap;

Best Regards,
Josh Wu

Quoted 222 lines
drivers/mtd/nand/atmel_nand.c +0 -0
  	atmel_pmecc_core_init(mtd);
 
drivers/mtd/nand/bfin_nand.c +2 -0
index c7ddbb2..7e755e8 100644
@@ -374,9 +374,11 @@ int board_nand_init(struct nand_chip *chip)
  		if (!NAND_IS_512()) {
  			chip->ecc.bytes = 3;
  			chip->ecc.size = 256;
+			chip->ecc.strength = 1;
  		} else {
  			chip->ecc.bytes = 6;
  			chip->ecc.size = 512;
+			chip->ecc.strength = 2;
  		}
  		chip->ecc.mode = NAND_ECC_HW;
  		chip->ecc.calculate = bfin_nfc_calculate_ecc;
drivers/mtd/nand/davinci_nand.c +1 -0
index 04b24f3..9777878 100644
@@ -613,6 +613,7 @@ void davinci_nand_init(struct nand_chip *nand)
  	nand->ecc.mode = NAND_ECC_HW;
  	nand->ecc.size = 512;
  	nand->ecc.bytes = 3;
+	nand->ecc.strength = 4;
  	nand->ecc.calculate = nand_davinci_calculate_ecc;
  	nand->ecc.correct  = nand_davinci_correct_data;
  	nand->ecc.hwctl  = nand_davinci_enable_hwecc;
drivers/mtd/nand/diskonchip.c +1 -0
index 104d97f..4cd741e 100644
@@ -1658,6 +1658,7 @@ static int __init doc_probe(unsigned long physadr)
  	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
  	nand->ecc.size		= 512;
  	nand->ecc.bytes		= 6;
+	nand->ecc.strength	= 2;
  	nand->bbt_options	= NAND_BBT_USE_FLASH;
 
  	doc->physadr		= physadr;
drivers/mtd/nand/fsl_elbc_nand.c +6 -0
index 65edbf5..c3f350d 100644
@@ -781,6 +781,12 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr)
  		nand->ecc.size = 512;
  		nand->ecc.bytes = 3;
  		nand->ecc.steps = 1;
+		chip->ecc.strength = 1;
+		/*
+		 * FIXME: can hardware ecc correct 4 bitflips if page size is
+		 * 2k?  Then does hardware report number of corrections for this
+		 * case?  If so, ecc_stats reporting needs to be fixed as well.
+		 */
  	} else {
  		/* otherwise fall back to default software ECC */
  		nand->ecc.mode = NAND_ECC_SOFT;
drivers/mtd/nand/fsl_ifc_nand.c +1 -0
index 5d47b40..823a2eb 100644
@@ -871,6 +871,7 @@ int board_nand_init(struct nand_chip *nand)
  	/* Hardware generates ECC per 512 Bytes */
  	nand->ecc.size = 512;
  	nand->ecc.bytes = 8;
+	nand->ecc.strength = 1;
 
  	switch (csor & CSOR_NAND_PGS_MASK) {
  	case CSOR_NAND_PGS_512:
drivers/mtd/nand/fsmc_nand.c +2 -0
index 48ca543..fab2aeb 100644
@@ -453,6 +453,7 @@ int fsmc_nand_init(struct nand_chip *nand)
  	switch (fsmc_version) {
  	case FSMC_VER8:
  		nand->ecc.bytes = 13;
+		nand->ecc.strength = 8;
  		nand->ecc.correct = fsmc_bch8_correct_data;
  		nand->ecc.read_page = fsmc_read_page_hwecc;
  		if (mtd->writesize == 512)
@@ -467,6 +468,7 @@ int fsmc_nand_init(struct nand_chip *nand)
  		break;
  	default:
  		nand->ecc.bytes = 3;
+		nand->ecc.strength = 1;
  		nand->ecc.layout = &fsmc_ecc1_layout;
  		nand->ecc.correct = nand_correct_data;
  		break;
drivers/mtd/nand/jz4740_nand.c +5 -0
index 3ec34f3..3f64dc3 100644
@@ -253,6 +253,11 @@ int board_nand_init(struct nand_chip *nand)
  	nand->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
  	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
  	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength	= 2;
+	/*
+	 * FIXME: ecc_strength value of 2 bits per 512 bytes of data is a
+	 * conservative guess, given 9 ecc bytes and reed-solomon alg.
+	 */
  	nand->ecc.layout	= &qi_lb60_ecclayout_2gb;
  	nand->chip_delay	= 50;
  	nand->options		= NAND_USE_FLASH_BBT;
drivers/mtd/nand/mxc_nand.c +7 -0
index c51a012..df2f489 100644
@@ -1222,6 +1222,13 @@ int board_nand_init(struct nand_chip *this)
  		this->ecc.mode = NAND_ECC_HW;
  	}
 
+	if (this->ecc.mode == NAND_ECC_HW) {
+		if (is_mxc_nfc_1())
+			this->ecc.strength = 1;
+		else
+			this->ecc.strength = 4;
+	}
+
  	host->pagesize_2k = 0;
 
  	this->ecc.size = 512;
drivers/mtd/nand/mxs_nand.c +1 -0
index 422519a..d1f4986 100644
@@ -1166,6 +1166,7 @@ int board_nand_init(struct nand_chip *nand)
  	nand->ecc.mode		= NAND_ECC_HW;
  	nand->ecc.bytes		= 9;
  	nand->ecc.size		= 512;
+	nand->ecc.strength	= 8;
 
  	return 0;
 
drivers/mtd/nand/nand_base.c +1 -0
index 3ad7783..a2df8ee 100644
@@ -3233,6 +3233,7 @@ int nand_scan_tail(struct mtd_info *mtd)
  		if (!chip->ecc.size)
  			chip->ecc.size = 256;
  		chip->ecc.bytes = 3;
+		chip->ecc.strength = 1;
  		break;
 
  	case NAND_ECC_SOFT_BCH:
drivers/mtd/nand/ndfc.c +1 -0
index 6ebbb5e..b7a837b 100644
@@ -216,6 +216,7 @@ int board_nand_init(struct nand_chip *nand)
  	nand->ecc.mode = NAND_ECC_HW;
  	nand->ecc.size = 256;
  	nand->ecc.bytes = 3;
+	nand->ecc.strength = 1;
  	nand->select_chip = ndfc_select_chip;
 
  #ifdef CONFIG_SYS_NDFC_16BIT
drivers/mtd/nand/nomadik.c +1 -0
index b76f4cb..dc8e513 100644
@@ -212,6 +212,7 @@ int board_nand_init(struct nand_chip *chip)
  	chip->ecc.mode = NAND_ECC_HW;
  	chip->ecc.bytes = 3;
  	chip->ecc.size = 512;
+	chip->ecc.strength = 1;
  	chip->ecc.layout = &nomadik_ecc_layout;
  	chip->ecc.calculate = nomadik_ecc_calculate;
  	chip->ecc.hwctl = nomadik_ecc_hwctl;
drivers/mtd/nand/omap_gpmc.c +1 -0
index ccf9750..728dfdc 100644
@@ -274,6 +274,7 @@ void omap_nand_switch_ecc(int32_t hardware)
  		nand->ecc.layout = &hw_nand_oob;
  		nand->ecc.size = 512;
  		nand->ecc.bytes = 3;
+		nand->ecc.strength = 1;
  		nand->ecc.hwctl = omap_enable_hwecc;
  		nand->ecc.correct = omap_correct_data;
  		nand->ecc.calculate = omap_calculate_ecc;
drivers/mtd/nand/s3c2410_nand.c +1 -0
index e1a459b..43d8213 100644
@@ -173,6 +173,7 @@ int board_nand_init(struct nand_chip *nand)
  	nand->ecc.mode = NAND_ECC_HW;
  	nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
  	nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength = 1;
  #else
  	nand->ecc.mode = NAND_ECC_SOFT;
  #endif
drivers/mtd/nand/s3c64xx.c +1 -0
index 87f0341..8c4a737 100644
@@ -285,6 +285,7 @@ int board_nand_init(struct nand_chip *nand)
  	nand->ecc.mode		= NAND_ECC_HW;
  	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
  	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength	= 1;
  #else
  	nand->ecc.mode		= NAND_ECC_SOFT;
  #endif /* ! CONFIG_SYS_S3C_NAND_HWECC */
drivers/mtd/nand/tegra_nand.c +1 -0
index 854fd21..6afbec6 100644
@@ -1014,6 +1014,7 @@ int tegra_nand_init(struct nand_chip *nand, int devnum)
  	nand->ecc.write_page_raw = nand_write_page_raw;
  	nand->ecc.read_oob = nand_read_oob;
  	nand->ecc.write_oob = nand_write_oob;
+	nand->ecc.strength = 1;
  	nand->select_chip = nand_select_chip;
  	nand->dev_ready  = nand_dev_ready;
  	nand->priv = &nand_ctrl;
#6 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

Hi, Josh

Quoted 13 lines

drivers/mtd/nand/atmel_nand.c static int atmel_pmecc_nand_init_params(struct nand_chip *nand, · line 711

Quoted 8 lines
drivers/mtd/nand/atmel_nand.c +1 -0
index b09e7b7..9cdf35b 100644
@@ -709,6 +709,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
 	nand->ecc.read_page = atmel_nand_pmecc_read_page;
 	nand->ecc.write_page = atmel_nand_pmecc_write_page;
+	nand->ecc.strength = 1;

For atmel nand, it should be:

(quoted diff) +1 -0
+	nand->ecc.strength = cap;
Quoted 2 lines

Best Regards,
Josh Wu

Thanks, changed.

#7 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

In reply to Sergey Lapin

Dear Scott,

Quoted 9 lines

could you please test the following patch on top of this big patch to see if ecc.strength problem goes away? I can integrate it into big one then.

Quoted 1 line

From dffea1f073c546ab88f37f219f66d9d1478d4cf1 Mon Sep 17 00:00:00 2001

From: Sergey Lapin <[email protected]>
Date: Thu, 17 Jan 2013 18:29:21 +0400
Subject: [PATCH] SQUASHME: mtd: nand: Add ecc.strength support to drivers

Updated the patch according to Josh's request:

#8 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

Quoted 6 lines · Sergey Lapin
drivers/mtd/nand/bfin_nand.c +0 -0
index c7ddbb2..7e755e8 100644

drivers/mtd/nand/bfin_nand.c int board_nand_init(struct nand_chip *chip) · line 382

Quoted 9 lines
drivers/mtd/nand/bfin_nand.c +2 -0
@@ -374,9 +374,11 @@ int board_nand_init(struct nand_chip *chip)
 		if (!NAND_IS_512()) {
 			chip->ecc.bytes = 3;
 			chip->ecc.size = 256;
+			chip->ecc.strength = 1;
 		} else {
 			chip->ecc.bytes = 6;
 			chip->ecc.size = 512;
+			chip->ecc.strength = 2;
 		}

Hmm, I'm not sure that ecc.strength should be set to 2 here, if it's really two separate 256-byte regions each of which can correct 1 bit. 2 bit correction can only be done under certain circumstances (i.e. the errors are not in the same half).

Linux does the same thing you've done, but that was also a "fix all the drivers" patch, so I'd like the input of someone familiar with the hardware. CCing Mike Frysinger. Maybe the driver should be reporting an ECC block size of 256 bytes? Or at least internally return the number of bitflips from the half that had more bitflips.

Quoted 8 lines
drivers/mtd/nand/bfin_nand.c +0 -0
 		chip->ecc.mode = NAND_ECC_HW;
 		chip->ecc.calculate = bfin_nfc_calculate_ecc;
drivers/mtd/nand/davinci_nand.c +0 -0
index 04b24f3..9777878 100644

drivers/mtd/nand/davinci_nand.c void davinci_nand_init(struct nand_chip *nand) · line 619

Quoted 7 lines
drivers/mtd/nand/davinci_nand.c +1 -0
@@ -613,6 +613,7 @@ void davinci_nand_init(struct nand_chip *nand)
 	nand->ecc.mode = NAND_ECC_HW;
 	nand->ecc.size = 512;
 	nand->ecc.bytes = 3;
+	nand->ecc.strength = 4;
 	nand->ecc.calculate = nand_davinci_calculate_ecc;
 	nand->ecc.correct  = nand_davinci_correct_data;
 	nand->ecc.hwctl  = nand_davinci_enable_hwecc;

This is in the 1-bit ECC #ifdef, so ecc.strength should be 1, and later in CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST in should be set to 4.

Quoted 32 lines
drivers/mtd/nand/diskonchip.c +1 -0
index 104d97f..4cd741e 100644
@@ -1658,6 +1658,7 @@ static int __init doc_probe(unsigned long  
 physadr)
 	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
 	nand->ecc.size		= 512;
 	nand->ecc.bytes		= 6;
+	nand->ecc.strength	= 2;
 	nand->bbt_options	= NAND_BBT_USE_FLASH;
 
drivers/mtd/nand/diskonchip.c +0 -0
 	doc->physadr		= physadr;
drivers/mtd/nand/fsl_elbc_nand.c +3 -0
index 65edbf5..c3f350d 100644
@@ -781,6 +781,12 @@ static int fsl_elbc_chip_init(int devnum, u8  
 *addr)
 		nand->ecc.size = 512;
 		nand->ecc.bytes = 3;
 		nand->ecc.steps = 1;
+		chip->ecc.strength = 1;
+		/*
+		 * FIXME: can hardware ecc correct 4 bitflips if page  

size is

drivers/mtd/nand/fsl_elbc_nand.c +1 -0
+		 * 2k?  Then does hardware report number of corrections  

for this

drivers/mtd/nand/fsl_elbc_nand.c +1 -0
+		 * case?  If so, ecc_stats reporting needs to be fixed  

as well.

drivers/mtd/nand/fsl_elbc_nand.c

Quoted 1 line
drivers/mtd/nand/fsl_elbc_nand.c +1 -0
+		 */

It can correct 1 bitflip per 512 bytes. This is a similar situation to blackfin (as far as I can tell), except that we report the actual hardware ECC block size, so ecc.strength = 1 is clearly correct.

As for ecc_stats, read_page() is supposed to return the number of bitflips from the ECC block with the most bitflips (see the generic read_page implementations). This change was made to fsl_elbc_nand.c in Linux. Note that all of the conversions of read_page() functions to simply return zero seem to be incorrect, and should be returning max_bitflips.

drivers/mtd/nand/fsl_ifc_nand.c int board_nand_init(struct nand_chip *nand) · line 877

Quoted 13 lines
drivers/mtd/nand/fsl_ifc_nand.c +1 -0
index 5d47b40..823a2eb 100644
@@ -871,6 +871,7 @@ int board_nand_init(struct nand_chip *nand)
 	/* Hardware generates ECC per 512 Bytes */
 	nand->ecc.size = 512;
 	nand->ecc.bytes = 8;
+	nand->ecc.strength = 1;
 
 	switch (csor & CSOR_NAND_PGS_MASK) {
 	case CSOR_NAND_PGS_512:

IFC has ECC strength of 4 or 8 depending on ECC mode. It also needs max_bitflips handling in read_page().

Quoted 13 lines
drivers/mtd/nand/jz4740_nand.c +3 -0
index 3ec34f3..3f64dc3 100644
@@ -253,6 +253,11 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
 	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
 	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength	= 2;
+	/*
+	 * FIXME: ecc_strength value of 2 bits per 512 bytes of data is  

a

drivers/mtd/nand/jz4740_nand.c

Quoted 5 lines
drivers/mtd/nand/jz4740_nand.c +2 -0
+	 * conservative guess, given 9 ecc bytes and reed-solomon alg.
+	 */
 	nand->ecc.layout	= &qi_lb60_ecclayout_2gb;
 	nand->chip_delay	= 50;
 	nand->options		= NAND_USE_FLASH_BBT;

The Linux driver sets ecc.strength to 4, though that may have been after Linux 3.7.

Quoted 13 lines
drivers/mtd/nand/tegra_nand.c +1 -0
index 854fd21..6afbec6 100644
@@ -1014,6 +1014,7 @@ int tegra_nand_init(struct nand_chip *nand, int  
 devnum)
 	nand->ecc.write_page_raw = nand_write_page_raw;
 	nand->ecc.read_oob = nand_read_oob;
 	nand->ecc.write_oob = nand_write_oob;
+	nand->ecc.strength = 1;
 	nand->select_chip = nand_select_chip;
 	nand->dev_ready  = nand_dev_ready;
Quoted 1 line

nand->priv = &nand_ctrl;

Jim, does ecc.strength = 1 look correct for Tegra? It has more ECC bytes than I'd expect for 1-bit correction (does "4 symbol correct ECC" mean "4-bit correctable ECC"?).

-Scott

#9 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

In reply to Scott Wood

Dear Scott,

Quoted 7 lines

I tried booting on P2020RDB-PC_NAND, and got this:

Quoted 4 lines
L2:    512 KB already enabled, moving to 0xf8f80000
NAND:  BUG: failure at nand_base.c:3214/nand_scan_tail()!

BUG!
### ERROR ### Please RESET the board ###

Quoted 5 lines

It boots fine without this patch. nand_base.c:3214 is complaining about missing ecc.strength. You need to update existing U-Boot drivers for new
API so that nothing breaks. Ask maintainers of particular drivers for help if necessary.

Found the culprit. Will resubmit shortly.

#10 lore raw

PATCH v2 1/1 mtd: resync with Linux-3.7.1

In reply to Sergey Lapin
Quoted 16 lines · Sergey Lapin

This patch is essentially an update of u-boot MTD subsystem to the state of Linux-3.7.1 with exclusion of some bits:

- the update is concentrated on NAND, no onenand or CFI/NOR/SPI flashes interfaces are updated EXCEPT for API changes.

- new large NAND chips support is there, though some updates have got in Linux-3.8.-rc1, (which will follow on top of this patch).

To produce this update I used tag v3.7.1 of linux-stable repository.

The update was made using application of relevant patches, with changes relevant to U-Boot-only stuff sticked together to keep bisectability. Then all changes were grouped together to this patch.

Quoted 7 lines

---
v2: recreated on v3.7.1
removed unimportant bits
fixed look of the patch
v1: original submission

Applied to u-boot-nand-flash, with the ecc strength patch merged, and some fixes based mainly on my earlier comments, and to fix build breakage.

Here's the diff of what I applied from this patch:

drivers/mtd/nand/atmel_nand.c +1 -0
index b09e7b7..3bfbaf8 100644
@@ -709,6 +709,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
 
 	nand->ecc.read_page = atmel_nand_pmecc_read_page;
 	nand->ecc.write_page = atmel_nand_pmecc_write_page;
+	nand->ecc.strength = cap;
 
 	atmel_pmecc_core_init(mtd);
 
drivers/mtd/nand/bfin_nand.c +2 -0
index c7ddbb2..7e755e8 100644
@@ -374,9 +374,11 @@ int board_nand_init(struct nand_chip *chip)
 		if (!NAND_IS_512()) {
 			chip->ecc.bytes = 3;
 			chip->ecc.size = 256;
+			chip->ecc.strength = 1;
 		} else {
 			chip->ecc.bytes = 6;
 			chip->ecc.size = 512;
+			chip->ecc.strength = 2;
 		}
 		chip->ecc.mode = NAND_ECC_HW;
 		chip->ecc.calculate = bfin_nfc_calculate_ecc;
drivers/mtd/nand/davinci_nand.c +2 -0
index 04b24f3..90f5985 100644
@@ -613,6 +613,7 @@ void davinci_nand_init(struct nand_chip *nand)
 	nand->ecc.mode = NAND_ECC_HW;
 	nand->ecc.size = 512;
 	nand->ecc.bytes = 3;
+	nand->ecc.strength = 1;
 	nand->ecc.calculate = nand_davinci_calculate_ecc;
 	nand->ecc.correct  = nand_davinci_correct_data;
 	nand->ecc.hwctl  = nand_davinci_enable_hwecc;
@@ -623,6 +624,7 @@ void davinci_nand_init(struct nand_chip *nand)
 	nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
 	nand->ecc.size = 512;
 	nand->ecc.bytes = 10;
+	nand->ecc.strength = 4;
 	nand->ecc.calculate = nand_davinci_4bit_calculate_ecc;
 	nand->ecc.correct = nand_davinci_4bit_correct_data;
 	nand->ecc.hwctl = nand_davinci_4bit_enable_hwecc;
drivers/mtd/nand/diskonchip.c +1 -0
index 104d97f..4cd741e 100644
@@ -1658,6 +1658,7 @@ static int __init doc_probe(unsigned long physadr)
 	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
 	nand->ecc.size		= 512;
 	nand->ecc.bytes		= 6;
+	nand->ecc.strength	= 2;
 	nand->bbt_options	= NAND_BBT_USE_FLASH;
 
 	doc->physadr		= physadr;
drivers/mtd/nand/fsl_elbc_nand.c +1 -0
index 28e6d35..0fa776a 100644
@@ -769,6 +769,7 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr)
 		nand->ecc.size = 512;
 		nand->ecc.bytes = 3;
 		nand->ecc.steps = 1;
+		nand->ecc.strength = 1;
 	} else {
 		/* otherwise fall back to default software ECC */
 		nand->ecc.mode = NAND_ECC_SOFT;
drivers/mtd/nand/fsl_ifc_nand.c +4 -0
index 68c1c83..439822c 100644
@@ -890,11 +890,13 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
 			bbt_mirror_descr.offs = 0;
 		}
 
+		nand->ecc.strength = 4;
 		priv->bufnum_mask = 15;
 		break;
 
 	case CSOR_NAND_PGS_2K:
 		layout = &oob_2048_ecc4;
+		nand->ecc.strength = 4;
 		priv->bufnum_mask = 3;
 		break;
 
@@ -902,8 +904,10 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
 		if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
 		    CSOR_NAND_ECC_MODE_4) {
 			layout = &oob_4096_ecc4;
+			nand->ecc.strength = 4;
 		} else {
 			layout = &oob_4096_ecc8;
+			nand->ecc.strength = 8;
 			nand->ecc.bytes = 16;
 		}
 
drivers/mtd/nand/fsmc_nand.c +2 -0
index 48ca543..fab2aeb 100644
@@ -453,6 +453,7 @@ int fsmc_nand_init(struct nand_chip *nand)
 	switch (fsmc_version) {
 	case FSMC_VER8:
 		nand->ecc.bytes = 13;
+		nand->ecc.strength = 8;
 		nand->ecc.correct = fsmc_bch8_correct_data;
 		nand->ecc.read_page = fsmc_read_page_hwecc;
 		if (mtd->writesize == 512)
@@ -467,6 +468,7 @@ int fsmc_nand_init(struct nand_chip *nand)
 		break;
 	default:
 		nand->ecc.bytes = 3;
+		nand->ecc.strength = 1;
 		nand->ecc.layout = &fsmc_ecc1_layout;
 		nand->ecc.correct = nand_correct_data;
 		break;
drivers/mtd/nand/jz4740_nand.c +1 -0
index 3ec34f3..a691fbc 100644
@@ -253,6 +253,7 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
 	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
 	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength	= 4;
 	nand->ecc.layout	= &qi_lb60_ecclayout_2gb;
 	nand->chip_delay	= 50;
 	nand->options		= NAND_USE_FLASH_BBT;
drivers/mtd/nand/mxc_nand.c +7 -0
index 633d0a7..ac435f2 100644
@@ -1242,6 +1242,13 @@ int board_nand_init(struct nand_chip *this)
 		this->ecc.mode = NAND_ECC_HW;
 	}
 
+	if (this->ecc.mode == NAND_ECC_HW) {
+		if (is_mxc_nfc_1())
+			this->ecc.strength = 1;
+		else
+			this->ecc.strength = 4;
+	}
+
 	host->pagesize_2k = 0;
 
 	this->ecc.size = 512;
drivers/mtd/nand/mxs_nand.c +2 -1
index 422519a..7ba48c1 100644
@@ -869,7 +869,7 @@ static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
  * what to do.
  */
 static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
-				int page, int cmd)
+				int page)
 {
 	struct mxs_nand_info *nand_info = nand->priv;
 
@@ -1166,6 +1166,7 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.mode		= NAND_ECC_HW;
 	nand->ecc.bytes		= 9;
 	nand->ecc.size		= 512;
+	nand->ecc.strength	= 8;
 
 	return 0;
 
drivers/mtd/nand/nand_base.c +1 -0
index 748eef9..9e05cef 100644
@@ -3233,6 +3233,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 		if (!chip->ecc.size)
 			chip->ecc.size = 256;
 		chip->ecc.bytes = 3;
+		chip->ecc.strength = 1;
 		break;
 
 	case NAND_ECC_SOFT_BCH:
drivers/mtd/nand/nand_util.c +1 -1
index e2bf633..d81972c 100644
@@ -616,7 +616,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 				ops.datbuf = p_buffer;
 				ops.oobbuf = ops.datbuf + pagesize;
 
-				rval = nand->write_oob(nand, offset, &ops);
+				rval = mtd_write_oob(nand, offset, &ops);
 				if (rval != 0)
 					break;
 
drivers/mtd/nand/ndfc.c +1 -0
index 213d2c9..94b9033 100644
@@ -216,6 +216,7 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.mode = NAND_ECC_HW;
 	nand->ecc.size = 256;
 	nand->ecc.bytes = 3;
+	nand->ecc.strength = 1;
 	nand->select_chip = ndfc_select_chip;
 
 #ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
drivers/mtd/nand/nomadik.c +1 -0
index b76f4cb..dc8e513 100644
@@ -212,6 +212,7 @@ int board_nand_init(struct nand_chip *chip)
 	chip->ecc.mode = NAND_ECC_HW;
 	chip->ecc.bytes = 3;
 	chip->ecc.size = 512;
+	chip->ecc.strength = 1;
 	chip->ecc.layout = &nomadik_ecc_layout;
 	chip->ecc.calculate = nomadik_ecc_calculate;
 	chip->ecc.hwctl = nomadik_ecc_hwctl;
drivers/mtd/nand/omap_gpmc.c +3 -1
index e45dacb..d5f3248 100644
@@ -590,11 +590,12 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	buffer to store read data
+ * @oob_required: caller expects OOB data read to chip->oob_poi
  * @page:	page number to read
  *
  */
 static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
-				uint8_t *buf, int page)
+				uint8_t *buf, int oob_required, int page)
 {
 	int i, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
@@ -804,6 +805,7 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 	nand->ecc.hwctl = NULL;
 	nand->ecc.correct = NULL;
 	nand->ecc.calculate = NULL;
+	nand->ecc.strength = eccstrength;
 
 	/* Setup the ecc configurations again */
 	if (hardware) {
drivers/mtd/nand/s3c2410_nand.c +1 -0
index e1a459b..43d8213 100644
@@ -173,6 +173,7 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.mode = NAND_ECC_HW;
 	nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
 	nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength = 1;
 #else
 	nand->ecc.mode = NAND_ECC_SOFT;
 #endif
drivers/mtd/nand/tegra_nand.c +1 -0
index 854fd21..6afbec6 100644
@@ -1014,6 +1014,7 @@ int tegra_nand_init(struct nand_chip *nand, int devnum)
 	nand->ecc.write_page_raw = nand_write_page_raw;
 	nand->ecc.read_oob = nand_read_oob;
 	nand->ecc.write_oob = nand_write_oob;
+	nand->ecc.strength = 1;
 	nand->select_chip = nand_select_chip;
 	nand->dev_ready  = nand_dev_ready;
 	nand->priv = &nand_ctrl;