public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH] Towards DiskOnChip support as a NAND driver
@ 2004-06-16 14:19 Dan Brown
  2004-06-16 22:32 ` Thomas Gleixner
  0 siblings, 1 reply; 7+ messages in thread
From: Dan Brown @ 2004-06-16 14:19 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-mtd

[-- Attachment #1: Type: text/plain, Size: 2099 bytes --]

For review and testing, here is a patch which brings us a step closer to
proper support for DiskOnChip devices.  This is against the 20040615
snapshot.

This patch includes the following:

drivers/mtd/nand/diskonchip.c:
    - Fix pipeline problems for DOC2000 and Millenium/2000TSOP (only tested
on 2000TSOP)
    - Add bad block table (read-only) support for INFTL-based devices (only
2000TSOP for the moment)
    - Add hardware ECC support for DOC2000 and Millenium/2000TSOP (only
tested on 2000TSOP and needs more testing!)
    - Add auto-partitioning for INFTL-based devices (should be made
optional?)

drivers/mtd/nand/nand_base.c:
    - Add support for DiskOnChip hardware ECC
    - Fix a null-pointer ref that occurs if a NAND driver supplies a primary
but not a mirror BBT descriptor

include/linux/mtd/nand.h:
    - Add a return value to calculate_ecc.  This is used by nand_base to
skip the call to correct_data if we know there are no errors.  (This saves a
6-byte comparison-against-zero when using DOC.  Is it worth changing the API
for it?  You tell me.)

-----------------------------------------------------------

Please realize that this needs a lot more testing.  I still haven't gotten
JFFS2 to run properly with this (though I suspect that may reflect my
inexperience with JFFS2).  Also, the change to nand.h may break other nand
drivers (though the fix is trivial).

Things that aren't done yet:
    - BBT support for NFTL-based devices (coming soon!)
    - BBT updating (not important when using (I)NFTL filesystem, but matters
for JFFS2)
    - Auto-partitioning for NFTL-based devices?
    - DOC Millenium Plus support
    - Proper BBT handling for multi-floor INFTL devices (don't try it with
the current code!)
    - Modifying (I)NFTL to use the nand-based DiskOnChip driver
    - Modifying JFFS2 to use autooob layout?  (Not sure about this)
    - Modifying flash_eraseall to use autooob layout?  (Should work OK on
DOC by coincidence)
    - Adding the nand/diskonchip driver into the kernel build system instead
of the old one

    - More testing.

Enjoy!

    -Dan Brown

[-- Attachment #2: docnand.diff --]
[-- Type: application/octet-stream, Size: 16074 bytes --]

diff -u --recursive mtd-20040615/drivers/mtd/nand/diskonchip.c mtd/drivers/mtd/nand/diskonchip.c
--- mtd-20040615/drivers/mtd/nand/diskonchip.c	2004-03-27 18:00:08.000000000 -0500
+++ mtd/drivers/mtd/nand/diskonchip.c	2004-06-16 07:09:34.000000000 -0400
@@ -20,6 +20,8 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/doc2000.h>
 #include <linux/mtd/compatmac.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/inftl.h>
 
 struct doc_priv {
 	unsigned long virtadr;
@@ -31,6 +33,16 @@
 	int curchip;
 };
 
+static char inftl_bbt_pattern[] = "MSYS_BBT";
+
+static struct nand_bbt_descr inftl_bbt_descr = {
+        .options =NAND_BBT_LASTBLOCK | NAND_BBT_8BIT,
+        .offs =8,
+        .len = 8,
+        .maxblocks = 4,
+        .pattern = inftl_bbt_pattern
+};
+
 #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
 #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
 
@@ -110,10 +122,12 @@
 	unsigned long docptr = doc->virtadr;
 
 	ReadDOC(docptr, CDSNSlowIO);
+	DoC_Delay(doc, 2);
 	u_char ret = ReadDOC(docptr, 2k_CDSN_IO);
 	if (debug) printk("read_byte returns %02x\n", ret);
 	return ret;
 }
+
 static void doc2000_writebuf(struct mtd_info *mtd, 
 			     const u_char *buf, int len)
 {
@@ -180,7 +194,7 @@
 	return 0;
 }
 
-static uint16_t doc200x_ident_chip(struct mtd_info *mtd, int nr)
+static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = (void *)this->priv;
@@ -224,7 +238,7 @@
 	return ret;
 }
 
-static void doc2000_count_chips(struct mtd_info *mtd)
+static void __init doc2000_count_chips(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = (void *)this->priv;
@@ -276,11 +290,12 @@
 	struct doc_priv *doc = (void *)this->priv;
 	unsigned long docptr = doc->virtadr;
 
-	ReadDOC(docptr, CDSNSlowIO);
+	//ReadDOC(docptr, CDSNSlowIO);
 	/* 11.4.5 -- delay twice to allow extended length cycle */
 	DoC_Delay(doc, 2);
 	ReadDOC(docptr, ReadPipeInit);
-	return ReadDOC(docptr, Mil_CDSN_IO);
+	//return ReadDOC(docptr, Mil_CDSN_IO);
+	return ReadDOC(docptr, LastDataRead);
 }
 
 static void doc2001_writebuf(struct mtd_info *mtd, 
@@ -314,6 +329,7 @@
 	/* Terminate read pipeline */
 	buf[i] = ReadDOC(docptr, LastDataRead);
 }
+
 static int doc2001_verifybuf(struct mtd_info *mtd, 
 			     const u_char *buf, int len)
 {
@@ -425,30 +441,250 @@
 	return 0;
 }
 
-struct doc_priv mydoc = {
-	.physadr = 0xd4000,
+static int doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	struct nand_chip *this = mtd->priv;
+	struct doc_priv *doc = (void *)this->priv;
+	unsigned long docptr = doc->virtadr;
+
+	/* Prime the ECC engine */
+	WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+	if (mode == NAND_ECC_READ)
+		WriteDOC(DOC_ECC_EN, docptr, ECCConf);
+	else
+		WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+	return 0;
+}
+
+static int doc2000_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+				 unsigned char *ecc_code)
+{
+	struct nand_chip *this = mtd->priv;
+	struct doc_priv *doc = (void *)this->priv;
+	unsigned long docptr = doc->virtadr;
+	volatile char dummy;
+	int stat;
+	int i;
+	// DBB : check for NULL ecc_code here?
+
+	// DBB note: I'm using the presence of dat as a read/write indicator.  FIX ME!
+	if (dat) {
+		// DBB: this is assumed to be a read
+		// flush the pipeline:
+		dummy = ReadDOC(docptr, 2k_ECCStatus);
+		dummy = ReadDOC(docptr, 2k_ECCStatus);
+		dummy = ReadDOC(docptr, 2k_ECCStatus);
+		stat = dummy & 0x80;
+	} else {
+		// DBB: this is assumed to be a write
+		WriteDOC(doc->CDSNControl & ~CDSN_CTRL_FLASH_IO, docptr, CDSNControl);
+		WriteDOC(0, docptr, 2k_CDSN_IO);
+		WriteDOC(0, docptr, 2k_CDSN_IO);
+		WriteDOC(0, docptr, 2k_CDSN_IO);
+		WriteDOC(doc->CDSNControl, docptr, CDSNControl);
+		stat = 1;
+	}
+	if (stat) {
+		for (i = 0; i < 6; i++)
+			ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
+	} else {
+		/* On read, if there were no ECC errors, the syndrome is by
+		   definition zero.  We can skip actually reading it. */
+		memset(ecc_code, 0, 6);
+	}
+	WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+	return stat;
+}
+
+static int doc2001_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+				 unsigned char *ecc_code)
+{
+	struct nand_chip *this = mtd->priv;
+	struct doc_priv *doc = (void *)this->priv;
+	unsigned long docptr = doc->virtadr;
+	volatile char dummy;
+	int stat;
+	int i;
+	// DBB : check for NULL ecc_code here?
+
+	// DBB note: I'm using the presence of dat as a read/write indicator.  FIX ME!
+	if (dat) {
+		// DBB: this is assumed to be a read
+		// flush the pipeline:
+		dummy = ReadDOC(docptr, ECCConf);
+		dummy = ReadDOC(docptr, ECCConf);
+		dummy = ReadDOC(docptr, ECCConf);
+		stat = dummy & 0x80;
+	} else {
+		// DBB: this is assumed to be a write
+		WriteDOC(0, docptr, NOP);
+		WriteDOC(0, docptr, NOP);
+		WriteDOC(0, docptr, NOP);
+		stat = 1;
+	}
+	if (stat) {
+		for (i = 0; i < 6; i++)
+			ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
+	} else {
+		/* On read, if there were no ECC errors, the syndrome is by
+		   definition zero.  We can skip actually reading it. */
+		memset(ecc_code, 0, 6);
+	}
+	WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+	return stat;
+}
+
+static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+{
+	int ret = doc_decode_ecc(dat, calc_ecc);
+	printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
+	return ret;
+}
+		
+static struct doc_priv mydoc = {
+	.physadr = 0xd0000,
 	.curfloor = -1,
 	.curchip = -1,
 };
 
-u_char mydatabuf[528];
+//u_char mydatabuf[528];
 
-struct nand_chip mynand = {
+static struct nand_oobinfo doc200x_oobinfo = {
+        .useecc = MTD_NANDECC_AUTOPLACE,
+        .eccbytes = 6,
+        .eccpos = {0, 1, 2, 3, 4, 5},
+        .oobfree = { {8, 8} }
+};
+ 
+static struct nand_chip mynand = {
 	.priv = (void *)&mydoc,
 	.select_chip = doc200x_select_chip,
 	.hwcontrol = doc200x_hwcontrol,
 	.dev_ready = doc200x_dev_ready,
 	.waitfunc = doc200x_wait,
 	.block_bad = doc200x_block_bad,
-	.eccmode = NAND_ECC_SOFT,
-	.data_buf = mydatabuf,
+	.eccmode = NAND_ECC_DISKONCHIP,
+	//.data_buf = mydatabuf,
+	.options = NAND_USE_FLASH_BBT,
+	.autooob = &doc200x_oobinfo,
+	.correct_data = doc200x_correct_data,
+	.enable_hwecc = doc200x_enable_hwecc
 };
 
-struct mtd_info mymtd = {
+static struct mtd_info mymtd = {
 	.priv = (void *)&mynand,
 	.owner = THIS_MODULE,
 };
 
+/* This is a stripped-down copy of the code in inftlmount.c */
+static int __init inftl_partscan(struct mtd_info *mtd)
+{
+	u_char buf[SECTORSIZE];
+	struct INFTLMediaHeader *mh = (struct INFTLMediaHeader *) &buf;
+	int offs;
+	for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
+		int ret, retlen;
+                if ((ret = MTD_READ(mtd, offs, SECTORSIZE, &retlen, buf)))
+			continue;
+		if (retlen < sizeof(struct INFTLMediaHeader)) continue;
+//printk(KERN_ERR "Read %d bytes at %d, string is %s\n", retlen, offs, buf);
+		if (!memcmp(mh->bootRecordID, "BNAND", 6)) break;
+	}
+	if (offs >= mtd->size) {
+		printk(KERN_WARNING "INFTL Media Header not found.\n");
+		return 0;
+	}
+
+	mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
+	mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
+	mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
+	mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
+	mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
+	mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
+ 
+#ifdef CONFIG_MTD_DEBUG_VERBOSE
+	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
+	printk(KERN_ERR "Found INFTL Media Header at 0x%x:\n"
+			"    bootRecordID          = %s\n"
+			"    NoOfBootImageBlocks   = %d\n"
+			"    NoOfBinaryPartitions  = %d\n"
+			"    NoOfBDTLPartitions    = %d\n"
+			"    BlockMultiplerBits    = %d\n"
+			"    FormatFlgs            = %d\n"
+			"    OsakVersion           = 0x%x\n"
+			"    PercentUsed           = %d\n",
+		offs,
+		mh->bootRecordID, mh->NoOfBootImageBlocks,
+		mh->NoOfBinaryPartitions,
+		mh->NoOfBDTLPartitions,
+		mh->BlockMultiplierBits, mh->FormatFlags,
+		mh->OsakVersion, mh->PercentUsed);
+#endif
+
+	if (mh->BlockMultiplierBits != 0) {
+		printk(KERN_ERR "Currently only BlockMultiplierBits=0 is supported.\n");
+		return 0;
+	}
+
+	struct mtd_partition parts[6];
+	memset((char *) parts, 0, sizeof(parts));
+	int numparts = 0;
+	int lastblock = 0;
+
+	/* Scan the partitions */
+	int i;
+	struct INFTLPartition *ip;
+	for (i = 0; (i < 4); i++) {
+		ip = &(mh->Partitions[i]);
+		ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
+		ip->firstUnit = le32_to_cpu(ip->firstUnit);
+		ip->lastUnit = le32_to_cpu(ip->lastUnit);
+		ip->flags = le32_to_cpu(ip->flags);
+		ip->spareUnits = le32_to_cpu(ip->spareUnits);
+		ip->Reserved0 = le32_to_cpu(ip->Reserved0);
+
+#ifdef CONFIG_MTD_DEBUG_VERBOSE
+		if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
+		printk(	"    PARTITION[%d] ->\n"
+			"        virtualUnits    = %d\n"
+			"        firstUnit       = %d\n"
+			"        lastUnit        = %d\n"
+			"        flags	         = 0x%x\n"
+			"        spareUnits      = %d\n",
+			i, ip->virtualUnits, ip->firstUnit,
+			ip->lastUnit, ip->flags,
+			ip->spareUnits);
+#endif
+
+		if ((i == 0) && (ip->firstUnit > 0)) {
+			parts[0].name = "DiskOnChip IPL / Media Header partition";
+			parts[0].offset = 0;
+			parts[0].size = mtd->erasesize * ip->firstUnit;
+			numparts = 1;
+		}
+
+		if (ip->flags & INFTL_BINARY)
+			parts[numparts].name = "DiskOnChip BDK partition";
+		else
+			parts[numparts].name = "DiskOnChip BDTL partition";
+		parts[numparts].offset = mtd->erasesize * ip->firstUnit;
+		parts[numparts].size = mtd->erasesize * (1 + ip->lastUnit - ip->firstUnit);
+		numparts++;
+		if (ip->lastUnit > lastblock) lastblock = ip->lastUnit;
+		if (ip->flags & INFTL_LAST) break;
+	}
+	lastblock++;
+	if ((mtd->erasesize * lastblock) < mtd->size) {
+		parts[numparts].name = "DiskOnChip Remainder partition";
+		parts[numparts].offset = mtd->erasesize * lastblock;
+		parts[numparts].size = mtd->size - parts[numparts].offset;
+		numparts++;
+	}
+	add_mtd_partitions(mtd, parts, numparts);
+	return 1;
+}
+
+
 int __init init_nanddoc(void)
 {
 	mydoc.virtadr = (unsigned long)ioremap(mydoc.physadr, DOC_IOREMAP_LEN);
@@ -474,6 +710,9 @@
 		mynand.write_buf = doc2001_writebuf;
 		mynand.read_buf = doc2001_readbuf;
 		mynand.verify_buf = doc2001_verifybuf;
+                mynand.bbt_td = &inftl_bbt_descr;
+		mynand.calculate_ecc = doc2001_calculate_ecc;
+		//mynand.scan_bbt = nftl_scan_bbt;
 
 		ReadDOC(mydoc.virtadr, ChipID);
 		ReadDOC(mydoc.virtadr, ChipID);
@@ -499,11 +738,12 @@
 		mynand.write_buf = doc2000_writebuf;
 		mynand.read_buf = doc2000_readbuf;
 		mynand.verify_buf = doc2000_verifybuf;
+		mynand.calculate_ecc = doc2000_calculate_ecc;
 
 		doc2000_count_chips(&mymtd);
 		nrchips = 4 * mydoc.chips_per_floor;
 		name = "DiskOnChip 2000 (NFTL Model)";
-		mydoc.CDSNControl |= CDSN_CTRL_FLASH_IO;
+		mydoc.CDSNControl |= CDSN_CTRL_FLASH_IO|CDSN_CTRL_ECC_IO;
 
 		break;
 
@@ -516,12 +756,14 @@
 	}
 	mymtd.name = name;
 	add_mtd_device(&mymtd);
+	if (DoC_is_Millennium(&mydoc)) inftl_partscan(&mymtd);
 
 	return 0;
 }
 
 void __exit cleanup_nanddoc(void)
 {
+	del_mtd_partitions(&mymtd);
 	del_mtd_device(&mymtd);
 	iounmap((void *)mydoc.virtadr);
 }
diff -u --recursive mtd-20040615/drivers/mtd/nand/nand_base.c mtd/drivers/mtd/nand/nand_base.c
--- mtd-20040615/drivers/mtd/nand/nand_base.c	2004-06-07 18:00:15.000000000 -0400
+++ mtd/drivers/mtd/nand/nand_base.c	2004-06-16 07:37:48.000000000 -0400
@@ -830,6 +830,7 @@
 	case NAND_ECC_HW8_512:	
 		eccbytes += 2;
 	/* Hardware ecc 6 byte / 512 byte data */	
+	case NAND_ECC_DISKONCHIP:
 	case NAND_ECC_HW6_512:	
 		eccbytes += 3;
 	/* Hardware ecc 3 byte / 256 data */	
@@ -1013,6 +1014,7 @@
 	int	*oob_config, datidx;
 	int	blockcheck = (mtd->erasesize >> this->page_shift) - 1;
 	int	eccbytes = 3;
+	int	do_correct_data;
 
 
 	DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
@@ -1053,6 +1055,7 @@
 	ecc = this->eccsize;
 	switch (eccmode) {
 	case NAND_ECC_HW6_512: /* Hardware ECC 6 byte / 512 byte data  */
+	case NAND_ECC_DISKONCHIP:
 		eccbytes = 6;
 		break;						
 	case NAND_ECC_HW8_512: /* Hardware ECC 8 byte / 512 byte data  */
@@ -1096,6 +1099,8 @@
 			oob_data = &this->data_buf[end];
 
 		eccsteps = this->eccsteps;
+		do_correct_data = 1;
+		ecc_status = 0;
 		
 		switch (eccmode) {
 		case NAND_ECC_NONE: {	/* No ECC, Read in a page */
@@ -1125,13 +1130,29 @@
 			}
 			break;						
 
+		case NAND_ECC_DISKONCHIP:
+			/* On DOC, we have to read data + OOB-stored syndrome,
+			   then read the hw-computed syndrome, then the rest
+			   of the OOB data. */
+			this->enable_hwecc(mtd, NAND_ECC_READ);	
+			this->read_buf(mtd, data_poi, ecc);
+			this->read_buf(mtd, oob_data, eccbytes);
+			/* On DOC (at least), we have a ECC error register bit
+			   that allows us to skip the tedious process of reading
+			   the hw-computed syndrome, checking for and correcting
+			   errors, etc. */
+			do_correct_data = this->calculate_ecc(mtd, data_poi, ecc_calc);
+			break;
 		default:
 			printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
 			BUG();	
 		}
 
 		/* read oobdata */
-		this->read_buf(mtd, oob_data, mtd->oobsize);
+		if (eccmode == NAND_ECC_DISKONCHIP)
+			this->read_buf(mtd, oob_data + eccbytes, mtd->oobsize - eccbytes);
+		else
+			this->read_buf(mtd, oob_data, mtd->oobsize);
 		
 		/* Skip ECC, if not active */
 		if (eccmode == NAND_ECC_NONE)
@@ -1143,7 +1164,8 @@
 
 		/* correct data, if neccecary */
 		for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {
-			ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
+			if (do_correct_data)
+				ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
 			
 			/* Get next chunk of ecc bytes */
 			j += eccbytes;
@@ -2384,6 +2406,7 @@
 	case NAND_ECC_HW3_512: 
 	case NAND_ECC_HW6_512: 
 	case NAND_ECC_HW8_512: 
+	case NAND_ECC_DISKONCHIP:
 		if (mtd->oobblock == 256) {
 			printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
 			this->eccmode = NAND_ECC_SOFT;
diff -u --recursive mtd-20040615/drivers/mtd/nand/nand_bbt.c mtd/drivers/mtd/nand/nand_bbt.c
--- mtd-20040615/drivers/mtd/nand/nand_bbt.c	2004-06-04 18:00:12.000000000 -0400
+++ mtd/drivers/mtd/nand/nand_bbt.c	2004-06-16 07:40:34.000000000 -0400
@@ -794,7 +794,7 @@
 	
 	/* Prevent the bbt regions from erasing / writing */
 	mark_bbt_region (mtd, td);
-	mark_bbt_region (mtd, md);
+	if (md) mark_bbt_region (mtd, md);
 	
 	kfree (buf);
 	return res;
diff -u --recursive mtd-20040615/include/linux/mtd/nand.h mtd/include/linux/mtd/nand.h
--- mtd-20040615/include/linux/mtd/nand.h	2004-06-04 18:00:13.000000000 -0400
+++ mtd/include/linux/mtd/nand.h	2004-06-16 07:49:07.000000000 -0400
@@ -281,7 +281,7 @@
 	int  		(*dev_ready)(struct mtd_info *mtd);
 	void 		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
 	int 		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
-	void		(*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
+	int 		(*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
 	int 		(*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
 	void		(*enable_hwecc)(struct mtd_info *mtd, int mode);
 	void		(*erase_cmd)(struct mtd_info *mtd, int page);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Towards DiskOnChip support as a NAND driver
       [not found] <E1BacpZ-0008CJ-KT@canuck.infradead.org>
@ 2004-06-16 16:13 ` Slim
  2004-06-16 20:23   ` Dan Brown
  0 siblings, 1 reply; 7+ messages in thread
From: Slim @ 2004-06-16 16:13 UTC (permalink / raw)
  To: linux-mtd

I'd like to help test the driver for DOC 2000 dip, but I have a few
questions.  

>     - Add bad block table (read-only) support for INFTL-based devices
> (only
> 2000TSOP for the moment)

Is the doc2000 dip NFTL or INFTL?  With read only support, would I be
able to create a filesystem to read?

>     - Add hardware ECC support for DOC2000 and Millenium/2000TSOP
> (only
> tested on 2000TSOP and needs more testing!)

ECC - hardware error correction by the device?  Is this an optional
enable in the driver?

> Please realize that this needs a lot more testing.  I still haven't
> gotten
> JFFS2 to run properly with this 

Does it support other filesystems (ext2/3)? 

> Enjoy!

Thanks to everyone working on this.  I've needed a driver for doc2000
dip devices for a couple years now.

Slim



		
__________________________________
Do you Yahoo!?
Take Yahoo! Mail with you! Get it on your mobile phone.
http://mobile.yahoo.com/maildemo 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Towards DiskOnChip support as a NAND driver
  2004-06-16 16:13 ` Slim
@ 2004-06-16 20:23   ` Dan Brown
  2004-06-16 21:47     ` Thomas Gleixner
  0 siblings, 1 reply; 7+ messages in thread
From: Dan Brown @ 2004-06-16 20:23 UTC (permalink / raw)
  To: Slim, linux-mtd

A few answers:

> Is the doc2000 dip NFTL or INFTL?  With read only support, would I be
> able to create a filesystem to read?

Some are NFTL, some are INFTL.  The INFTL variant is sometimes also known as
DiskOnChip 2000 TSOP.  From the pdf file that comes with the DOS-based DOC
utilities (hint hint):

[Inverse NAND Flash Translation Layer] M-Systems' latest flash management
algorithm, used by the TrueFFS driver for the following devices:
- DiskOnChip Millennium Plus

- Mobile DiskOnChip Plus

- DiskOnChip 2000 DIP (high), 384Mbytes and higher.

- DiskOnChip 2000 DIP (low), 192Mbytes and higher.

As for read-only support, its only the bad-block table itself that's
read-only, not the device itself.  Sorry, I should have been clearer in my
message.  If more blocks go bad at runtime, the information won't be
recorded to flash, and you'll forget about these additional bad blocks at
poweroff (which is bad).  Unless you're using INFTL filesystem, which has
its own markers for post-sale bad blocks.  Except INFTL doesn't work with
this driver yet. :(

The ability to update the BBT is something I plan to add soon, since I need
it. :)

You should be able to create a filesystem, but as I mentioned I haven't
gotten JFFS2 to work for me, yet.

> ECC - hardware error correction by the device?  Is this an optional
> enable in the driver?

Yes, the DOC has an ASIC that does ECC computation (for actual error
correction, software assitance is required).  It's not optional, though it
could be made so....  Why would you want to turn it off?

> Does it support other filesystems (ext2/3)?

Once the (I)NFTL code works with this driver, you can put filesystems like
ext2/3 over (I)NFTL.  For reasons why you might not want to, read up on
JFFS2.

> Thanks to everyone working on this.  I've needed a driver for doc2000
> dip devices for a couple years now.

Yeah, me too, but until now I kept hoping David would do it in his copious
spare time :)

    -Dan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Towards DiskOnChip support as a NAND driver
  2004-06-16 20:23   ` Dan Brown
@ 2004-06-16 21:47     ` Thomas Gleixner
  0 siblings, 0 replies; 7+ messages in thread
From: Thomas Gleixner @ 2004-06-16 21:47 UTC (permalink / raw)
  To: Dan Brown, Slim, linux-mtd

On Wednesday 16 June 2004 22:23, Dan Brown wrote:
> > ECC - hardware error correction by the device?  Is this an optional
> > enable in the driver?
>
> Yes, the DOC has an ASIC that does ECC computation (for actual error
> correction, software assitance is required).  It's not optional, though it
> could be made so....  Why would you want to turn it off?

It has two advantages over software ECC.

1. The software ECC is a Hamming code which can correct 1 bit errors and 
detect 2 bit errors. The HW ECC on DOC devices is a Reed Solomon Encoder / 
Decoder which allows to correct and detect more errors

2. In general a HW based ECC generator is a lot faster than the software 
version as it gets you rid of a ugly loop through all the data bytes on each 
read / write.

A small drawback is the error correction for reed solomon, as it is more  
complex and slower than for hamming codes. This is not too bad as error 
correction usually starts to happen when the device wears out, but then the 
hamming code which we use in soft ecc can be rather unsufficient. 
The speed improvement on write and read is really worth to use hw ecc if its 
thers

-- 
Thomas
_____________________________________________________________________
From slash dot org
"When customers are visiting, engineers are not allowed to wear ties. 
That way the customer can tell who is the engineer and who is the 
salesman (and therefore whom to believe.). Ties cut off blood flow 
to the brain, making it easier for the salesmen to do their jobs." 
_____________________________________________________________________
linutronix - competence in embedded & realtime linux
http://www.linutronix.de
mail: tglx@linutronix.de

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Towards DiskOnChip support as a NAND driver
  2004-06-16 14:19 [PATCH] Towards DiskOnChip support as a NAND driver Dan Brown
@ 2004-06-16 22:32 ` Thomas Gleixner
  2004-06-16 22:46   ` David Woodhouse
  0 siblings, 1 reply; 7+ messages in thread
From: Thomas Gleixner @ 2004-06-16 22:32 UTC (permalink / raw)
  To: Dan Brown; +Cc: David Woodhouse, linux-mtd

On Wednesday 16 June 2004 16:19, Dan Brown wrote:
> Please realize that this needs a lot more testing.  I still haven't gotten
> JFFS2 to run properly with this (though I suspect that may reflect my
> inexperience with JFFS2).  Also, the change to nand.h may break other nand
> drivers (though the fix is trivial).

The nand.h change is fixed in nand_ecc.c

>     - Modifying JFFS2 to use autooob layout?  (Not sure about this)
>     - Modifying flash_eraseall to use autooob layout?  (Should work OK on
> DOC by coincidence)

Yes, flash_eraseall works by coincidence, but I will look into this.

>     - Adding the nand/diskonchip driver into the kernel build system
> instead of the old one

Can you make it optional to use or should we break the code in 
drivers/mtd/devices to enforce the development on Dan's code in 
drivers/mtd/nand ? 

dwmw2 ??

IMHO the current DOC code in drivers/mtd/devices has too many todo's which 
inhibit proper usage. 

They are partly related to the bad block management. The bad block management 
support in the generic nand driver is able to support all types of bad block 
tables found on DOC devices. 

We fixed the HW ecc problems in nand_base.c today. 

It should be not too hard to adjust (I)NFTL to work on the new driver.

Some specialities of the DOC variants which are already working in the old 
drivers should be easily copyied to the new one as Dan has already done for 
his chip.

Another point is the error correction code. I have a generic reed solomon 
library nearly finished which is then usable for all kind of reed solomon 
based hw ecc generators. I don't want to make the old drivers use it and I 
dont wan't to have duplicate code around.

-- 
Thomas
_____________________________________________________________________
From slash dot org
"When customers are visiting, engineers are not allowed to wear ties. 
That way the customer can tell who is the engineer and who is the 
salesman (and therefore whom to believe.). Ties cut off blood flow 
to the brain, making it easier for the salesmen to do their jobs." 
_____________________________________________________________________
linutronix - competence in embedded & realtime linux
http://www.linutronix.de
mail: tglx@linutronix.de

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Towards DiskOnChip support as a NAND driver
  2004-06-16 22:32 ` Thomas Gleixner
@ 2004-06-16 22:46   ` David Woodhouse
  2004-06-16 22:50     ` Thomas Gleixner
  0 siblings, 1 reply; 7+ messages in thread
From: David Woodhouse @ 2004-06-16 22:46 UTC (permalink / raw)
  To: tglx; +Cc: Dan Brown, linux-mtd

On Thu, 2004-06-17 at 00:32 +0200, Thomas Gleixner wrote:
> Can you make it optional to use or should we break the code in 
> drivers/mtd/devices to enforce the development on Dan's code in 
> drivers/mtd/nand ? 
> 
> dwmw2 ??
> 
> IMHO the current DOC code in drivers/mtd/devices has too many todo's which 
> inhibit proper usage. 

It's not so bad on the original DiskOnChip 2000 and Millennium devices.
I'd rather keep it an option for now, at least till the todo list for
the new nand-based driver is reduced. We need to get the HW ECC working
on the driver, and fix up NFTL to work with it. We also need to fix up
the probing to work properly -- currently my hack just had the address
hard-coded.

-- 
dwmw2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Towards DiskOnChip support as a NAND driver
  2004-06-16 22:46   ` David Woodhouse
@ 2004-06-16 22:50     ` Thomas Gleixner
  0 siblings, 0 replies; 7+ messages in thread
From: Thomas Gleixner @ 2004-06-16 22:50 UTC (permalink / raw)
  To: David Woodhouse; +Cc: Dan Brown, linux-mtd

On Thursday 17 June 2004 00:46, David Woodhouse wrote:
> On Thu, 2004-06-17 at 00:32 +0200, Thomas Gleixner wrote:
> > Can you make it optional to use or should we break the code in
> > drivers/mtd/devices to enforce the development on Dan's code in
> > drivers/mtd/nand ?
> >
> > dwmw2 ??
> >
> > IMHO the current DOC code in drivers/mtd/devices has too many todo's
> > which inhibit proper usage.
>
> It's not so bad on the original DiskOnChip 2000 and Millennium devices.
> I'd rather keep it an option for now, at least till the todo list for
> the new nand-based driver is reduced. We need to get the HW ECC working
> on the driver, and fix up NFTL to work with it. We also need to fix up
> the probing to work properly -- currently my hack just had the address
> hard-coded.

My main concern was to wake up those, who asked for DOC support / improvements 
recently and point them to the new code and make clear that the code in 
drivers/mtd/devices is a subject to be removed in the near future. 
So, if they need proper DOC support they can provide testing and hacking 
capacities. This should get us along quite fast if enough interest is there. 

-- 
Thomas
_____________________________________________________________________
From slash dot org
"When customers are visiting, engineers are not allowed to wear ties. 
That way the customer can tell who is the engineer and who is the 
salesman (and therefore whom to believe.). Ties cut off blood flow 
to the brain, making it easier for the salesmen to do their jobs." 
_____________________________________________________________________
linutronix - competence in embedded & realtime linux
http://www.linutronix.de
mail: tglx@linutronix.de

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-06-16 22:56 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-06-16 14:19 [PATCH] Towards DiskOnChip support as a NAND driver Dan Brown
2004-06-16 22:32 ` Thomas Gleixner
2004-06-16 22:46   ` David Woodhouse
2004-06-16 22:50     ` Thomas Gleixner
     [not found] <E1BacpZ-0008CJ-KT@canuck.infradead.org>
2004-06-16 16:13 ` Slim
2004-06-16 20:23   ` Dan Brown
2004-06-16 21:47     ` Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox