DiskOn Chip Millennium Plus 32MB + INFTL
Husam
husamsenussi at gmail.com
Mon Jun 19 20:31:53 EDT 2006
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
On Tuesday 13 June 2006 21:59, Thomas Gleixner wrote:
> On Tue, 2006-06-13 at 21:20 +0100, Husam wrote:
> > On Tuesday 13 June 2006 20:56, David Woodhouse wrote:
> > > On Tue, 2006-06-13 at 20:42 +0100, Husam wrote:
> > > > 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
More information about the linux-mtd
mailing list