It looks like we're getting there :)
This patch (against the stock openwrt-svn) combines the ideas from David
and Claudio (with some fixes in the byte ordering) into something that
can write a bootable kernel image to the flash.
However, the resulting kernel cannot read the pre-2.6.17 yaffs format
because of the different blockStatus encoding.
While I can get two-way compatibility by also including the block status
byte in an oob_free range and handling it at the yaffs level, I don't
know if it doing that is a good idea.
What do you think?
Andrea
diff -Nur linux-2.6.19.2-base/drivers/mtd/nand/rbmipsnand.c linux-2.6.19.2/drivers/mtd/nand/rbmipsnand.c
--- linux-2.6.19.2-base/drivers/mtd/nand/rbmipsnand.c 2007-05-14 22:02:21.000000000 +0200
+++ linux-2.6.19.2/drivers/mtd/nand/rbmipsnand.c 2007-05-15 00:04:46.000000000 +0200
@@ -67,6 +67,12 @@
static struct mtd_info rmtd;
static struct nand_chip rnand;
+static struct nand_ecclayout rb_ecclayout = {
+ .eccbytes = 6,
+ .eccpos = { 8, 9, 10, 13, 14, 15 },
+ .oobfree = { { 0, 5 } , { 6, 2 }, { 11, 2 } }
+};
+
static unsigned init_ok = 0;
unsigned get_rbnand_block_size(void) {
@@ -93,6 +99,7 @@
return -ENXIO;
}
rnand.ecc.mode = NAND_ECC_SOFT;
+ rnand.ecc.layout = &rb_ecclayout;
rnand.chip_delay = 25;
rnand.options |= NAND_NO_AUTOINCR;
rmtd.priv = &rnand;
diff -Nur linux-2.6.19.2-base/fs/yaffs2/yaffs_mtdif.c linux-2.6.19.2/fs/yaffs2/yaffs_mtdif.c
--- linux-2.6.19.2-base/fs/yaffs2/yaffs_mtdif.c 2007-05-14 21:51:13.000000000 +0200
+++ linux-2.6.19.2/fs/yaffs2/yaffs_mtdif.c 2007-05-15 01:49:20.000000000 +0200
@@ -45,12 +45,12 @@
oob[1] = spare->tagByte1;
oob[2] = spare->tagByte2;
oob[3] = spare->tagByte3;
- oob[4] = spare->tagByte4;
- oob[5] = spare->tagByte5 & 0x3f;
- oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80;
- oob[5] |= spare->pageStatus == 0 ? 0: 0x40;
- oob[6] = spare->tagByte6;
- oob[7] = spare->tagByte7;
+ oob[4] = spare->pageStatus;
+ oob[5] = spare->tagByte4;
+ oob[6] = spare->tagByte5 & 0x3f;
+ oob[6] |= spare->blockStatus == 'Y' ? 0: 0x80;
+ oob[7] = spare->tagByte6;
+ oob[8] = spare->tagByte7;
}
static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob)
@@ -60,13 +60,13 @@
spare->tagByte1 = oob[1];
spare->tagByte2 = oob[2];
spare->tagByte3 = oob[3];
- spare->tagByte4 = oob[4];
- spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f;
- spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y';
- spare->pageStatus = oob[5] & 0x40 ? 0xff : 0;
+ spare->pageStatus = oob[4];
+ spare->tagByte4 = oob[5];
+ spare->tagByte5 = oob[6] == 0xff ? 0xff : oob[6] & 0x3f;
+ spare->blockStatus = oob[6] & 0x80 ? 0xff : 'Y';
spare->ecc1[0] = spare->ecc1[1] = spare->ecc1[2] = 0xff;
- spare->tagByte6 = oob[6];
- spare->tagByte7 = oob[7];
+ spare->tagByte6 = oob[7];
+ spare->tagByte7 = oob[8];
spare->ecc2[0] = spare->ecc2[1] = spare->ecc2[2] = 0xff;
nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */
@@ -85,7 +85,7 @@
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
- __u8 spareAsBytes[8]; /* OOB */
+ __u8 spareAsBytes[9]; /* OOB */
if (data && !spare)
retval = mtd->write(mtd, addr, dev->nDataBytesPerChunk,
@@ -94,7 +94,7 @@
if (dev->useNANDECC) {
translate_spare2oob(spare, spareAsBytes);
ops.mode = MTD_OOB_AUTO;
- ops.ooblen = 8; /* temp hack */
+ ops.ooblen = 9; /* temp hack */
} else {
ops.mode = MTD_OOB_RAW;
ops.ooblen = YAFFS_BYTES_PER_SPARE;
@@ -149,7 +149,7 @@
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
- __u8 spareAsBytes[8]; /* OOB */
+ __u8 spareAsBytes[9]; /* OOB */
if (data && !spare)
retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
@@ -157,7 +157,7 @@
else if (spare) {
if (dev->useNANDECC) {
ops.mode = MTD_OOB_AUTO;
- ops.ooblen = 8; /* temp hack */
+ ops.ooblen = 9; /* temp hack */
} else {
ops.mode = MTD_OOB_RAW;
ops.ooblen = YAFFS_BYTES_PER_SPARE;