Skip to contentSkip to conversation

DiskOn Chip Millennium Plus 32MB + INFTL

DISCUSSION Jeff Kalikstein 6 participants 17 messages Jun 8, 2006 – Aug 30, 2006 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

I have a system with a DiskOnChip Millennium Plus and existing TrueFFS filesystem. In attempting to get this configuration working with Linux 2.6.16.20, I have tried both the "Self contained MTD device driver" and the MTD NAND based driver.

Running INFTL on the self-contained driver complains that "INFTL no longer supports the old DiskOnChip drivers loaded via docprobe.", and the MTD NAND based driver complains that "DiskOnChip Millennium Plus 32MB is not supported, ignoring.".

Is it possible to run INFTL on a DiskOnChip Millenium Plus 32MB? I found an old mailing list post from 2005 that suggested that there was a patch to support the mp32 to the MTD NAND based driver, so I was surprised to not see it in the latest linux 2.6 release.

#1 lore raw
Quoted 10 lines · Jeff Kalikstein

I have a system with a DiskOnChip Millennium Plus and existing TrueFFS filesystem. In attempting to get this configuration working with Linux 2.6.16.20, I have tried both the "Self contained MTD
device driver" and the MTD NAND based driver.

Running INFTL on the self-contained driver complains that "INFTL no longer supports the old DiskOnChip drivers loaded via docprobe.", and the MTD NAND based driver complains that "DiskOnChip Millennium Plus 32MB is not supported, ignoring.".

Quoted 4 lines

Is it possible to run INFTL on a DiskOnChip Millenium Plus 32MB? I found an old mailing list post from 2005 that suggested that there was a patch to support the mp32 to the MTD NAND based driver, so I was surprised to not see it in the latest linux 2.6 release.

Simply because nobody cared enough to put it in and test it proper. Patches welcome :)

tglx

#2 lore raw
In reply to Jeff Kalikstein
Quoted 2 lines · Jeff Kalikstein

and the MTD NAND based driver complains that "DiskOnChip Millennium Plus 32MB is not supported, ignoring.".

This is fixable. The 32MiB unit is just the same as the 16MiB unit except that it works in 16-bit mode instead of 8-bit mode, and by default does some bizarre interleaving of the data.

Just look for 'interleave' in drivers/mtd/devices/doc2001plus.c and see how many places there are where we treat the 16MiB and 32MiB units differently -- there aren't that many. Getting this to work in the NAND-based driver should be relatively simple.

Signature · 1 line
dwmw2
#3 lore raw

I have device with DiskOnChip Millennium Plus 64M "2x 32M", so I start making changes to nand based driver using the old one but I found the following problems:

1. The NAND layer use lookup table to set the size of the page, erase block .. etc, but this does work will 32/64M because of interleave.
2. When I set bus width to 16 in diskonchip level nand_scan return an error because that doesn't match with table.
3. Reading and writing has to be done in 16 bit otherwise you lose data, because MDOC+ 32/64M moves the pointer 2 bytes even if you read one byte.
4. I found that read_buff terminate the read each time, and because of that nand_read_ecc skip bytes when read across sections.
5. Layout of the data on the page is different form 16M, but I'm not sure if this is specific to INTFL.

I had look at the changes you guys made recently and I found that some of these change would fix some of the above problems but not all of them,.

My question will be would someboday be able to sumbit patch to you guys to fix the above problem.

Quoted 12 lines · David Woodhouse
Quoted 2 lines · Jeff Kalikstein

and the MTD NAND based driver complains that "DiskOnChip Millennium Plus 32MB is not supported, ignoring.".

This is fixable. The 32MiB unit is just the same as the 16MiB unit except that it works in 16-bit mode instead of 8-bit mode, and by default does some bizarre interleaving of the data.

Just look for 'interleave' in drivers/mtd/devices/doc2001plus.c and see how many places there are where we treat the 16MiB and 32MiB units differently -- there aren't that many. Getting this to work in the NAND-based driver should be relatively simple.

#4 lore raw
Quoted 6 lines · Husam

I have device with DiskOnChip Millennium Plus 64M "2x 32M", so I start making changes to nand based driver using the old one but I found the following problems:

1. The NAND layer use lookup table to set the size of the page, erase block .. etc, but this does work will 32/64M because of interleave.

I thought the 64MiB device was two separate 'floors' of 32MiB? So it's two chips of the same size... what exactly is the problem?

Quoted 2 lines

2. When I set bus width to 16 in diskonchip level nand_scan return an error because that doesn't match with table.

Doesn't match with which table? What chip ID is detected?

Quoted 2 lines

3. Reading and writing has to be done in 16 bit otherwise you lose data, because MDOC+ 32/64M moves the pointer 2 bytes even if you read one byte.

That's OK though, isn't it? Writing has to be done in chunks much larger than that anyway, and for ECC reasons so does reading.

Quoted 2 lines

4. I found that read_buff terminate the read each time, and because of that nand_read_ecc skip bytes when read across sections.

I think the new code probably fixed this, didn't it? If not, we can make sure it does.

Quoted 2 lines

5. Layout of the data on the page is different form 16M, but I'm not sure if this is specific to INTFL.

I _think_ it's specific to INFTL -- it's weird, though. I don't actually know why M-Systems did that interleaving. There are guys from M-Systems on the list though -- perhaps they can enlighten us?

Quoted 2 lines

I had look at the changes you guys made recently and I found that some of these change would fix some of the above problems but not all of them,.

Now is a good time to get the remaining issues fixed. I'd very much like to have the 32MiB and 64MiB DiskOnChip Millennium Plus devices working.

Signature · 1 line
dwmw2
#5 lore raw
Quoted 11 lines · you
Quoted 6 lines · Husam

I have device with DiskOnChip Millennium Plus 64M "2x 32M", so I start making changes to nand based driver using the old one but I found the following problems:

1. The NAND layer use lookup table to set the size of the page, erase block .. etc, but this does work will 32/64M because of interleave.

I thought the 64MiB device was two separate 'floors' of 32MiB? So it's two chips of the same size... what exactly is the problem?

Yes thats correct but the 32MiB consist of two "NAND 16MiB, 8-bit" Chip, providing 16 bit access using interleave, and that double size the page "Page = 1024 + 32 OOB".

But does NAND layer need to be abee to handle Multi floor device?

Quoted 5 lines
Quoted 2 lines

2. When I set bus width to 16 in diskonchip level nand_scan return an error because that doesn't match with table.

Doesn't match with which table? What chip ID is detected?

Yes the ID exist on the table "mfr = 0x98 (Toshiba) , id = 0x75" which match the id I get from trueffs driver for wince, so I would expect "NAND 16MiB, 8-bit". However as I said before the driver should double the size of the page because of interleave.

Quoted 11 lines
Quoted 2 lines

3. Reading and writing has to be done in 16 bit otherwise you lose data, because MDOC+ 32/64M moves the pointer 2 bytes even if you read one byte.

That's OK though, isn't it? Writing has to be done in chunks much larger than that anyway, and for ECC reasons so does reading.

Quoted 2 lines

4. I found that read_buff terminate the read each time, and because of that nand_read_ecc skip bytes when read across sections.

I think the new code probably fixed this, didn't it? If not, we can make sure it does.

No you are still terminating the read at the end of read_buf function, you wold need to

1. Send READ command
2. Read date "e.g. 512 bytes"
3. Read ECC 6 bytes
4. terminate read stream

My be diskonchip layer should implement read_page !!!

Quoted 8 lines
Quoted 3 lines

5. Layout of the data on the page is different form 16M, but I'm not sure if this is specific to INTFL.

I _think_ it's specific to INFTL -- it's weird, though. I don't actually know why M-Systems did that interleaving. There are guys from M-Systems on the list though -- perhaps they can enlighten us?

But would be able to use the same layout with jffs?

Quoted 5 lines
Quoted 2 lines

I had look at the changes you guys made recently and I found that some of these change would fix some of the above problems but not all of them,.

Now is a good time to get the remaining issues fixed. I'd very much like to have the 32MiB and 64MiB DiskOnChip Millennium Plus devices working.

Thats good ... because from what I see 64MiB is not even supported by INTFL layer, in 64MiB each device has separate boot records but information for some of the partitions into the two boot records.

e.g

Partition 1

DISK 1

PARTITION[1] ->

        virtualUnits    = 1184
        firstUnit       = 17
        lastUnit        = 0 				====> Disk 2
        flags           = 0x4000000d
        spareUnits      = 2
        Reserved0       = 16
        Reserved1       = 0

Disk 2

PARTITION[1] ->

        virtualUnits    = 1184
        firstUnit       = 0					===> in Disk 1
        lastUnit        = 1224
        flags           = 0x4000000d
        spareUnits      = 2
        Reserved0       = 0
        Reserved1       = 0
#6 lore raw
Quoted 5 lines · Husam

Yes thats correct but the 32MiB consist of two "NAND 16MiB, 8-bit" Chip, providing 16 bit access using interleave, and that double size the page "Page = 1024 + 32 OOB".

But does NAND layer need to be abee to handle Multi floor device?

Hm, no -- it's two separate device, isn't it? So don't we just have to probe them separately and then perhaps use something like mtdconcat?

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

2. When I set bus width to 16 in diskonchip level nand_scan return an error because that doesn't match with table.

Doesn't match with which table? What chip ID is detected?

Yes the ID exist on the table "mfr = 0x98 (Toshiba) , id = 0x75" which match the id I get from trueffs driver for wince, so I would expect "NAND 16MiB, 8-bit". However as I said before the driver should double the size of the page because of interleave.

Hm, is it actually two 8-bit chips, rather than a single 16-bit chip?

In that case, we might have to do a bit more to make it work.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

4. I found that read_buff terminate the read each time, and because of that nand_read_ecc skip bytes when read across sections.

I think the new code probably fixed this, didn't it? If not, we can make sure it does.

No you are still terminating the read at the end of read_buf function, you wold need to

Quoted 6 lines

1. Send READ command
2. Read date "e.g. 512 bytes"
3. Read ECC 6 bytes
4. terminate read stream

My be diskonchip layer should implement read_page !!!

Yeah, I think that's probably a sane plan.

Quoted 9 lines
Quoted 8 lines
Quoted 3 lines

5. Layout of the data on the page is different form 16M, but I'm not sure if this is specific to INTFL.

I _think_ it's specific to INFTL -- it's weird, though. I don't actually know why M-Systems did that interleaving. There are guys from M-Systems on the list though -- perhaps they can enlighten us?

But would be able to use the same layout with jffs?

I see no reason why not.

Quoted 6 lines
Quoted 2 lines

Now is a good time to get the remaining issues fixed. I'd very much like to have the 32MiB and 64MiB DiskOnChip Millennium Plus devices working.

Thats good ... because from what I see 64MiB is not even supported by INTFL layer, in 64MiB each device has separate boot records but information for some of the partitions into the two boot records.

Hm, OK -- we'll need to work on that too.

Let's forget INFTL for now -- can we work on getting basic read/write operations on the 32MiB unit working first? We can do 64MiB next, then INFTL (for 32MiB and then 64MiB).

Signature · 1 line
dwmw2
#7 lore raw
Quoted 10 lines · you
Quoted 5 lines · Husam

Yes thats correct but the 32MiB consist of two "NAND 16MiB, 8-bit" Chip, providing 16 bit access using interleave, and that double size the page "Page = 1024 + 32 OOB".

But does NAND layer need to be abee to handle Multi floor device?

Hm, no -- it's two separate device, isn't it? So don't we just have to probe them separately and then perhaps use something like mtdconcat?

OK ... I guess that would cleaner way and makes the interface more compatible. I haven't seen mtdconcat yet.

Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines

2. When I set bus width to 16 in diskonchip level nand_scan return an error because that doesn't match with table.

Doesn't match with which table? What chip ID is detected?

Quoted 9 lines
Quoted 4 lines

Yes the ID exist on the table "mfr = 0x98 (Toshiba) , id = 0x75" which match the id I get from trueffs driver for wince, so I would expect "NAND 16MiB, 8-bit". However as I said before the driver should double the size of the page because of interleave.

Hm, is it actually two 8-bit chips, rather than a single 16-bit chip?

In that case, we might have to do a bit more to make it work.

Yes it's not single 16-bit, could we add anther flag to NAND say "NAND_INTERLEAVE" .. or maybe pass number  of chips from device layer to NAND layer.

All we need to do I guess is to pass the right information so the NAND layer can calculate the right size for page and to block.

Quoted 37 lines
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

4. I found that read_buff terminate the read each time, and because of that nand_read_ecc skip bytes when read across sections.

I think the new code probably fixed this, didn't it? If not, we can make sure it does.

No  you are still terminating the read at the end of read_buf function, you wold need to

Quoted 6 lines

1. Send READ command
2. Read date "e.g. 512 bytes"
3. Read ECC 6 bytes
4. terminate read stream

My be diskonchip layer should implement read_page !!!

Yeah, I think that's probably a sane plan.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

5. Layout of the data on the page is different form 16M, but I'm not sure if this is specific  to INTFL.

I _think_ it's specific to INFTL -- it's weird, though. I don't actually know why M-Systems did that interleaving. There are guys from M-Systems on the list though -- perhaps they can enlighten us?

But would be able to use the same layout with jffs?

I see no reason why not.

Quoted 7 lines
Quoted 3 lines

Now is a good time to get the remaining issues fixed. I'd very much like to have the 32MiB and 64MiB DiskOnChip Millennium Plus devices working.

Thats good ... because from what I see 64MiB is not even supported by INTFL layer, in 64MiB each device has separate boot records but information for some of the partitions into the two boot records.

Quoted 5 lines

Hm, OK -- we'll need to work on that too.

Let's forget INFTL for now -- can we work on getting basic read/write operations on the 32MiB unit working first? We can do 64MiB next, then INFTL (for 32MiB and then 64MiB).

I guess that would be the right way to go ... I'm looking at the code for my device bootloader and so far I manage to get alots of info about the MDOC+

#8 lore raw
Quoted 6 lines · Husam

Yes it's not single 16-bit, could we add anther flag to NAND say "NAND_INTERLEAVE" .. or maybe pass number of chips from device layer to NAND layer.

All we need to do I guess is to pass the right information so the NAND layer can calculate the right size for page and to block.

Can we do this by providing our own command function?

Signature · 1 line
dwmw2
#9 lore raw
Quoted 9 lines · David Woodhouse
Quoted 6 lines · Husam

Yes it's not single 16-bit, could we add anther flag to NAND say "NAND_INTERLEAVE" .. or maybe pass number of chips from device layer to NAND layer.

All we need to do I guess is to pass the right information so the NAND layer can calculate the right size for page and to block.

Can we do this by providing our own command function?

I guess we can ... but I thought the scan function is not replaceable

#10 lore raw
Quoted 11 lines · Husam
Quoted 9 lines · David Woodhouse
Quoted 6 lines · Husam

Yes it's not single 16-bit, could we add anther flag to NAND say "NAND_INTERLEAVE" .. or maybe pass number of chips from device layer to NAND layer.

All we need to do I guess is to pass the right information so the NAND layer can calculate the right size for page and to block.

Can we do this by providing our own command function?

I guess we can ... but I thought the scan function is not replaceable

We can add this to scan. Its not intrusive.

tglx

#11 lore raw

Hi,

I did small changes to get read to work on MDoC, and manage to do that ...

I still have one problem when I use nanddump OOB area seams to have the wrong data, where the actual page is correct "I have dump of the same page using anther tool".

I had look at the read_oob function and it looks like it's only using read_buf,which mean the read will never get terminated.

below is sample of the data I read from block 4 where the boot loader exist.

readbuf of 512 bytes: 03fe ea00 0000 0000 0000 0000 0000 0000 readbuf of 6 bytes: 3e51 c3da 6106
readbuf of 4 bytes: 5555 5555
readbuf of 512 bytes: 0000 0000 0000 0000 0000 0000 0000 0000 readbuf of 6 bytes: 005b 05c8 0891
readbuf of 14 bytes: 4357 3045 3030 3030 ffff ffff ffff

but nanddump shows the wrong data in OOB part

readbuf of 32 bytes: ffff ffff 0000 0000 0000 0000 0000 005b

Anyway I have attached patch with changes I made so far .. may someone wants to have look.

Thanks
Husam

Quoted 10 lines · Thomas Gleixner
Quoted 9 lines · Husam
Quoted 8 lines · David Woodhouse
Quoted 6 lines · Husam

Yes it's not single 16-bit, could we add anther flag to NAND say "NAND_INTERLEAVE" .. or maybe pass number of chips from device layer to NAND layer.

All we need to do I guess is to pass the right information so the NAND layer can calculate the right size for page and to block.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Can we do this by providing our own command function?

I guess we can ... but I thought the scan function is not replaceable

We can add this to scan. Its not intrusive.

tglx

nand_base.c renamed from home/husam/mtd-2.6/drivers/mtd/nand/nand_base.c +7 -3
@@ -2044,6 +2044,10 @@
 {
 	struct nand_flash_dev *type = NULL;
 	int i, dev_id, maf_idx;
+	int interleave;
+
+	/* Check in inerleave used */
+    interleave = (chip->options & NAND_INTERLEAVE)? 1: 0;
 
 	/* Select the device */
 	chip->select_chip(mtd, 0);
@@ -2094,10 +2098,10 @@
 		/*
 		 * Old devices have chip data hardcoded in the device id table
 		 */
-		mtd->erasesize = type->erasesize;
-		mtd->writesize = type->pagesize;
+		mtd->erasesize = type->erasesize << interleave;
+		mtd->writesize = type->pagesize << interleave;
 		mtd->oobsize = mtd->writesize / 32;
-		busw = type->options & NAND_BUSWIDTH_16;
+		busw = interleave? NAND_BUSWIDTH_16: nand_flash_ids[i].options & NAND_BUSWIDTH_16;
 	}
 
 	/* Try to identify manufacturer */
diskonchip.c renamed from home/husam/mtd-2.6/drivers/mtd/nand/diskonchip.c +152 -1

189 lines not on this page · raw message

../../include/linux/mtd/nand.h renamed from home/husam/mtd-2.6/include/linux/mtd/nand.h +7 -0
@@ -490,6 +490,13 @@
 /* Search good / bad pattern on the first and the second page */
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
 
+/* Interleave architecture allows 16bits internal access
+ * instead of 8bit internal access to arrauy of daul NAND flash,
+ * which means array of two 8bit NAND flash will be seen as one
+ * large 16bit NAND flash.
+ */
+#define NAND_INTERLEAVE     0x00100000
+
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
 
../../include/linux/mtd/doc2000.h renamed from home/husam/mtd-2.6/include/linux/mtd/doc2000.h +7 -1
@@ -73,6 +73,7 @@
 #define DoC_Mplus_Toggle		0x1046
 #define DoC_Mplus_DownloadStatus	0x1074
 #define DoC_Mplus_CtrlConfirm		0x1076
+#define DoC_Mplus_NprotectionStatus   0x1078
 #define DoC_Mplus_Power			0x1fff
 
 /* How to access the device?
@@ -80,7 +81,7 @@
  * On PPC, it's mmap'd and 16-bit wide.
  * Others use readb/writeb
  */
-#if defined(__arm__)
+#if defined(__arm__) && !defined(CONFIG_MACH_OMAP_H6300)
 #define ReadDOC_(adr, reg)      ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2))))
 #define WriteDOC_(d, adr, reg)  do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
 #define DOC_IOREMAP_LEN 0x8000
@@ -91,6 +92,8 @@
 #else
 #define ReadDOC_(adr, reg)      readb((void __iomem *)(adr) + (reg))
 #define WriteDOC_(d, adr, reg)  writeb(d, (void __iomem *)(adr) + (reg))
+#define ReadWDOC_(adr, reg)      readw((void __iomem *)(adr) + (reg))
+#define WriteWDOC_(d, adr, reg)  writew(d, (void __iomem *)(adr) + (reg))
 #define DOC_IOREMAP_LEN 0x2000
 
 #endif
@@ -103,6 +106,9 @@
 #define ReadDOC(adr, reg)      ReadDOC_(adr,DoC_##reg)
 #define WriteDOC(d, adr, reg)  WriteDOC_(d,adr,DoC_##reg)
 
+#define ReadWDOC(adr, reg)      ReadWDOC_(adr,DoC_##reg)
+#define WriteWDOC(d, adr, reg)  WriteWDOC_(d,adr,DoC_##reg)
+
 #define DOC_MODE_RESET 		0
 #define DOC_MODE_NORMAL 	1
 #define DOC_MODE_RESERVED1 	2
#12 lore raw
In reply to Thomas Gleixner

Today 01:21:54

Hi,

I did small changes to get read to work on MDoC, and manage to do that ...

I still have one problem when I use nanddump OOB area seams to have the wrong data, where the actual page is correct "I have dump of  the same page using anther tool".

I had look at the read_oob function and it looks like it's only using read_buf,which mean the read will never get terminated.

below is sample of the data I read from block 4 where the boot loader exist.

readbuf of 512 bytes: 03fe ea00 0000 0000 0000 0000 0000 0000 readbuf of 6 bytes: 3e51 c3da 6106
readbuf of 4 bytes: 5555 5555
readbuf of 512 bytes: 0000 0000 0000 0000 0000 0000 0000 0000 readbuf of 6 bytes: 005b 05c8 0891
readbuf of 14 bytes: 4357 3045 3030 3030 ffff ffff ffff

but nanddump shows the wrong data in OOB part

readbuf of 32 bytes: ffff ffff 0000 0000 0000 0000 0000 005b

Anyway I have included patch with changes I made so far .. may someone wants to have look.

Thanks
Husam

--- /home/husam/mtd-2.6/drivers/mtd/nand/nand_base.c 2006-06-17
22:55:33.000000000 +0100
+++ nand_base.c 2006-06-18 20:32:40.000000000 +0100
@@ -2044,6 +2044,10 @@
{
struct nand_flash_dev *type = NULL;
int i, dev_id, maf_idx;
+ int interleave;
+
+ /* Check in inerleave used */
+ interleave = (chip->options & NAND_INTERLEAVE)? 1: 0;

/* Select the device */
chip->select_chip(mtd, 0);
@@ -2094,10 +2098,10 @@
/*
* Old devices have chip data hardcoded in the device id table */
- mtd->erasesize = type->erasesize;
- mtd->writesize = type->pagesize;
+ mtd->erasesize = type->erasesize << interleave;
+ mtd->writesize = type->pagesize << interleave;
mtd->oobsize = mtd->writesize / 32;
- busw = type->options & NAND_BUSWIDTH_16;
+ busw = interleave? NAND_BUSWIDTH_16: nand_flash_ids[i].options &
NAND_BUSWIDTH_16;
}

/* Try to identify manufacturer */
--- /home/husam/mtd-2.6/drivers/mtd/nand/diskonchip.c 2006-06-17
22:55:33.000000000 +0100
+++ diskonchip.c 2006-06-19 01:27:06.000000000 +0100
@@ -61,6 +61,8 @@
0xff000000,
#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
0xff000000,
+#elif defined(CONFIG_MACH_OMAP_H6300)
+ 0x00000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations
defined
#endif
@@ -114,6 +116,9 @@
static int show_firmware_partition = 0; module_param(show_firmware_partition, int, 0);

+static int floor = 0;
+module_param(floor, int, 0);
+
#ifdef MTD_NAND_DISKONCHIP_BBTWRITE
static int inftl_bbt_write = 1;
#else
@@ -1483,6 +1488,146 @@
}
}

+/************************************************************************/
+/*********************** MDoC+ 32MiB interface ************************/
+static void mdocplus32_select_chip(struct mtd_info *mtd, int chip) +{

+    struct nand_chip *this = mtd->priv;
+    struct doc_priv *doc = this->priv;
+    void __iomem *docptr = doc->virtadr;

+
+ if (debug)
+ printk("select chip (%d)\n", chip);
+
+ if (chip == -1) {

+        /* Disable flash internally */
+        WriteDOC(0, docptr, Mplus_FlashSelect);
+        return;

+ }
+
+ /* Select teh device */
+ WriteDOC(doc->curfloor, docptr, Mplus_DeviceSelect);
+

+    /* Assert ChipEnable and deassert WriteProtect */
+    WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
+    this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);

+}
+
+static void mdocplus32_readbuf(struct mtd_info *mtd,
+ u_char *buf, int len)
+{

+    struct nand_chip *this = mtd->priv;
+    struct doc_priv *doc = this->priv;
+    void __iomem *docptr = doc->virtadr;
+    int i;
+    uint16_t *buff  = (uint16_t *) buf;
+    int      size   = len >> 1;
+    int      loc    = DoC_Mil_CDSN_IO;

+
+ if (debug)printk("readbuf of %d bytes: ", len);
+ for (i=0; i < size; i++, loc += 2) {
+ buff[i] = ReadWDOC_(docptr ,loc);
+ if (debug && i < 8)
+ printk("%04x ", buff[i]);
+ }
+ if (debug) printk("\n");
+}
+
+static void mdocplus32_writebuf(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{

+    struct nand_chip *this = mtd->priv;
+    struct doc_priv *doc = this->priv;
+    void __iomem *docptr = doc->virtadr;
+    int i;
+    uint16_t *buff  = (uint16_t *) buf;
+    int      size   = len >> 1;
+    int      loc    = DoC_Mil_CDSN_IO;

+
+ if (debug)printk("writebuf of %d bytes: ", len);
+ for (i=0; i < size; i++, loc += 2) {
+ WriteWDOC_(buff[i], docptr ,loc);
+ if (debug && i < 8)
+ printk("%02x ", buf[i]);
+ }
+ if (debug) printk("\n");
+}
+
+static int mdocplus32_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf)
+{
+ struct nand_chip *this = mtd->priv;

+    struct doc_priv *doc = this->priv;
+    void __iomem *docptr = doc->virtadr;
+    uint8_t *p = buf;
+    uint8_t *oob = chip->oob_poi;

+ int stat;
+
+ ReadWDOC(docptr, Mplus_ReadPipeInit);
+ ReadWDOC(docptr, Mplus_ReadPipeInit);
+
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, 512);
+
+ chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
+ chip->read_buf(mtd, oob, 6);
+ stat = chip->ecc.correct(mtd, p, oob, NULL);
+
+ if (stat == -1)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+
+ oob += 6;
+ chip->read_buf(mtd, oob, 4);
+ oob += 4;
+
+ p += 512;
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, 512);
+
+ chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
+ chip->read_buf(mtd, oob, 6);
+ stat = chip->ecc.correct(mtd, p, oob, NULL);
+
+ if (stat == -1)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+ oob += 6;
+
+ chip->read_buf(mtd, oob, 14);
+ oob += 14;
+ *((uint16_t *) oob) = ReadWDOC_(docptr,DoC_Mplus_LastDataRead);
+
+ return 0;
+}
+
+static inline int __init mdocplus32_init(struct mtd_info *mtd) +{
+ struct nand_chip *this = mtd->priv;
+ struct doc_priv *doc = this->priv;
+

+    this->read_byte   	= doc2001plus_read_byte;
+    this->write_buf   	= mdocplus32_writebuf;
+    this->read_buf 	  	= mdocplus32_readbuf;
+    this->verify_buf  	= doc2001plus_verifybuf;
+    this->scan_bbt 	  	= inftl_scan_bbt;
+    this->cmd_ctrl 	  	= NULL;
+    this->select_chip 	= mdocplus32_select_chip;
+    this->cmdfunc 	  	= doc2001plus_command;
+    this->ecc.hwctl   	= doc2001plus_enable_hwecc;

+ this->ecc.read_page = mdocplus32_read_page;
+ this->options |= (NAND_INTERLEAVE | NAND_BUSWIDTH_16);
+
+ doc->curfloor = floor;
+ doc->chips_per_floor = 1;
+ mtd->name = "DiskOnChip Millennium Plus";
+
+ return 1;
+} +/*******************************************************************/ +
static inline int __init doc2001plus_init(struct mtd_info *mtd) {
struct nand_chip *this = mtd->priv;
@@ -1569,6 +1714,9 @@
WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); mdelay(1);

+ /* Select the device */
+ WriteDOC(floor, virtadr, Mplus_DeviceSelect);
+
ChipID = ReadDOC(virtadr, ChipID);

switch (ChipID) {
@@ -1576,7 +1724,8 @@
reg = DoC_Mplus_Toggle; break;
case DOC_ChipID_DocMilPlus32:
- printk(KERN_ERR "DiskOnChip Millennium Plus 32MB is not supported,
ignoring.\n");
+ reg = DoC_Mplus_Toggle;
+ break;
default:
ret = -ENODEV;
goto notfound;
@@ -1680,6 +1829,8 @@
numchips = doc2000_init(mtd);
else if (ChipID == DOC_ChipID_DocMilPlus16)
numchips = doc2001plus_init(mtd);
+ else if (ChipID == DOC_ChipID_DocMilPlus32)
+ numchips = mdocplus32_init(mtd);
else
numchips = doc2001_init(mtd);

--- /home/husam/mtd-2.6/include/linux/mtd/nand.h 2006-06-17 22:56:05.000000000
+0100
+++ ../../../include/linux/mtd/nand.h 2006-06-18 18:57:01.000000000 +0100
@@ -490,6 +490,13 @@
/* Search good / bad pattern on the first and the second page */
#define NAND_BBT_SCAN2NDPAGE 0x00004000

+/* Interleave architecture allows 16bits internal access
+ * instead of 8bit internal access to arrauy of daul NAND flash,
+ * which means array of two 8bit NAND flash will be seen as one
+ * large 16bit NAND flash.
+ */
+#define NAND_INTERLEAVE 0x00100000
+
/* The maximum number of blocks to scan for a bbt */
#define NAND_BBT_SCAN_MAXBLOCKS 4

--- /home/husam/mtd-2.6/include/linux/mtd/doc2000.h 2006-06-17
22:56:05.000000000 +0100
+++ ../../../include/linux/mtd/doc2000.h 2006-06-18 22:34:33.000000000 +0100
@@ -73,6 +73,7 @@
#define DoC_Mplus_Toggle 0x1046
#define DoC_Mplus_DownloadStatus 0x1074
#define DoC_Mplus_CtrlConfirm 0x1076
+#define DoC_Mplus_NprotectionStatus 0x1078
#define DoC_Mplus_Power 0x1fff

/* How to access the device?
@@ -80,7 +81,7 @@
* On PPC, it's mmap'd and 16-bit wide.
* Others use readb/writeb
*/
-#if defined(__arm__)
+#if defined(__arm__) && !defined(CONFIG_MACH_OMAP_H6300)
#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)
(((unsigned long)adr)+((reg)<<2))))
#define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned
long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
#define DOC_IOREMAP_LEN 0x8000
@@ -91,6 +92,8 @@
#else
#define ReadDOC_(adr, reg) readb((void __iomem *)(adr) + (reg))
#define WriteDOC_(d, adr, reg) writeb(d, (void __iomem *)(adr) + (reg))
+#define ReadWDOC_(adr, reg) readw((void __iomem *)(adr) + (reg))
+#define WriteWDOC_(d, adr, reg) writew(d, (void __iomem *)(adr) + (reg))
#define DOC_IOREMAP_LEN 0x2000

#endif
@@ -103,6 +106,9 @@
#define ReadDOC(adr, reg) ReadDOC_(adr,DoC_##reg)
#define WriteDOC(d, adr, reg) WriteDOC_(d,adr,DoC_##reg)

+#define ReadWDOC(adr, reg) ReadWDOC_(adr,DoC_##reg)
+#define WriteWDOC(d, adr, reg) WriteWDOC_(d,adr,DoC_##reg) +
#define DOC_MODE_RESET 0
#define DOC_MODE_NORMAL 1
#define DOC_MODE_RESERVED1 2

Quoted 17 lines · Thomas Gleixner
Quoted 6 lines · Husam
Quoted 5 lines · David Woodhouse
Quoted 4 lines · Husam

Yes it's not single 16-bit, could we add anther flag to NAND say "NAND_INTERLEAVE" .. or maybe pass number of chips from device layer to NAND layer.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

All we need to do I guess is to pass the right information so the NAND layer can calculate the right size for page and to block.

Can we do this by providing our own command function?

I guess we can ... but I thought the scan function is not replaceable

We can add this to scan. Its not intrusive.

tglx

#13 lore raw
In reply to David Woodhouse

Hi,

I have manage to get the driver work with 32MiB, so now I need to see if I can get it to work with 64 MiB.

Quoted 66 lines · David Woodhouse
Quoted 5 lines · Husam

Yes thats correct but the 32MiB consist of two "NAND 16MiB, 8-bit" Chip, providing 16 bit access using interleave, and that double size the page "Page = 1024 + 32 OOB".

But does NAND layer need to be abee to handle Multi floor device?

Hm, no -- it's two separate device, isn't it? So don't we just have to probe them separately and then perhaps use something like mtdconcat?

Quoted 9 lines
Quoted 4 lines
Quoted 2 lines

2. When I set bus width to 16 in diskonchip level nand_scan return an error because that doesn't match with table.

Doesn't match with which table? What chip ID is detected?

Yes the ID exist on the table "mfr = 0x98 (Toshiba) , id = 0x75" which match the id I get from trueffs driver for wince, so I would expect "NAND 16MiB, 8-bit". However as I said before the driver should double the size of the page because of interleave.

Hm, is it actually two 8-bit chips, rather than a single 16-bit chip?

In that case, we might have to do a bit more to make it work.

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

4. I found that read_buff terminate the read each time, and because of that nand_read_ecc skip bytes when read across sections.

I think the new code probably fixed this, didn't it? If not, we can make sure it does.

No you are still terminating the read at the end of read_buf function, you wold need to

Quoted 6 lines

1. Send READ command
2. Read date "e.g. 512 bytes"
3. Read ECC 6 bytes
4. terminate read stream

My be diskonchip layer should implement read_page !!!

Yeah, I think that's probably a sane plan.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

5. Layout of the data on the page is different form 16M, but I'm not sure if this is specific to INTFL.

I _think_ it's specific to INFTL -- it's weird, though. I don't actually know why M-Systems did that interleaving. There are guys from M-Systems on the list though -- perhaps they can enlighten us?

But would be able to use the same layout with jffs?

I see no reason why not.

Quoted 7 lines
Quoted 3 lines

Now is a good time to get the remaining issues fixed. I'd very much like to have the 32MiB and 64MiB DiskOnChip Millennium Plus devices working.

Thats good ... because from what I see 64MiB is not even supported by INTFL layer, in 64MiB each device has separate boot records but information for some of the partitions into the two boot records.

Hm, OK -- we'll need to work on that too.

Let's forget INFTL for now -- can we work on getting basic read/write operations on the 32MiB unit working first? We can do 64MiB next, then INFTL (for 32MiB and then 64MiB).

#14 lore raw
Quoted 2 lines · Husam

I have manage to get the driver work with 32MiB, so now I need to see if I can get it to work with 64 MiB.

Great work; thanks.

Signature · 1 line
dwmw2
#15 lore raw
In reply to Husam
Quoted 2 lines · Husam

I have manage to get the driver work with 32MiB, so now I need to see if I can get it to work with 64 MiB.

Hello,

Did you manage to get the driver to work with all Diskonchip Millennium Plus devices? Can you please send your latest patch.

Signature · 2 lines
Best regards,
Kalev Lember
#16 lore raw

Am Tuesday 29 August 2006 14:20 schrieb Kalev Lember:

Quoted 9 lines
Quoted 2 lines · Husam

I have manage to get the driver work with 32MiB, so now I need to see if I can get it to work with 64 MiB.

Hello,

Did you manage to get the driver to work with all Diskonchip Millennium Plus devices?
Can you please send your latest patch.

Hello Kalev,

I didn't get it to work. The device had another "normal" flash chip. A bigger flash was used and so the Diskonchip option was removed.

Best reagrds,

Rüdiger