From dmitry.torokhov at gmail.com  Tue Jun  1 01:05:39 2010
From: dmitry.torokhov at gmail.com (Dmitry Torokhov)
Date: Mon, 31 May 2010 22:05:39 -0700
Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL)
In-Reply-To: <1275342512.24079.1559.camel@rex>
References: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de>
	<20100531190911.GC30712@core.coreip.homeip.net>
	<1275342512.24079.1559.camel@rex>
Message-ID: <20100601050538.GA7391@core.coreip.homeip.net>

On Mon, May 31, 2010 at 10:48:32PM +0100, Richard Purdie wrote:
> On Mon, 2010-05-31 at 12:09 -0700, Dmitry Torokhov wrote:
> > On Mon, May 31, 2010 at 02:55:48PM +0200, Wolfram Sang wrote:
> > > I2C-drivers can use the clientdata-pointer to point to private data. As I2C
> > > devices are not really unregistered, but merely detached from their driver, it
> > > used to be the drivers obligation to clear this pointer during remove() or a
> > > failed probe(). As a couple of drivers forgot to do this, it was agreed that it
> > > was cleaner if the i2c-core does this clearance when appropriate, as there is
> > > no guarantee for the lifetime of the clientdata-pointer after remove() anyhow.
> > > This feature was added to the core with commit
> > > e4a7b9b04de15f6b63da5ccdd373ffa3057a3681 to fix the faulty drivers.
> > > 
> > > As there is no need anymore to clear the clientdata-pointer, remove all current
> > > occurrences in the drivers to simplify the code and prevent confusion.
> > > 
> > > Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
> > > Cc: Jean Delvare <khali at linux-fr.org>
> > > ---
> > > 
> > > Some more notes:
> > > 
> > > I waited for rc1 as I knew there were some drivers/patches coming along which
> > > needed to be processed, too.
> > > 
> > > I'd suggest that this goes via the i2c-tree, so we get rid of all occurences at
> > > once.
> > > 
> > 
> > Frankly I'd prefer taking input stuff through my tree with the goal of
> > .36 merge window just to minimize potential merge issues. This is a
> > simple cleanup patch that has no dependencies, so there is little gain
> > from doing it all in one go.
> 
> How about asking Linus to take this one now, then its done and we can
> all move on rather than queuing up problems for the next merge window?
> 

That should work.

Acked-by: Dmitry Torokhov <dtor at mail.ru>

> Acked-by: Richard Purdie <rpurdie at linux.intel.com>
> 

-- 
Dmitry


From muehlfelder at enertex.de  Tue Jun  1 03:28:17 2010
From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=)
Date: Tue, 1 Jun 2010 09:28:17 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <AANLkTindexX7RcLC_2YLonXLrNQe011Lz-XjT0AnbtpD@mail.gmail.com>
References: <201005311503.42629.muehlfelder@enertex.de>
	<AANLkTindexX7RcLC_2YLonXLrNQe011Lz-XjT0AnbtpD@mail.gmail.com>
Message-ID: <201006010928.17637.muehlfelder@enertex.de>

Am Monday 31 May 2010 21:59:56 schrieb Vitaly Wool:
> > Do I have to use a newer kernel version?
>
> Better do so :)

After checking the Linux ChangeLogs at http://kernelnewbies.org/Linux26Changes 
I did not find any changes related to JFFS2 summary option, so I don't think 
a newer kernel is needed ;-)


From Ladislav.Michl at seznam.cz  Tue Jun  1 06:05:19 2010
From: Ladislav.Michl at seznam.cz (Ladislav Michl)
Date: Tue, 1 Jun 2010 12:05:19 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <201006010928.17637.muehlfelder@enertex.de>
References: <201005311503.42629.muehlfelder@enertex.de>
	<AANLkTindexX7RcLC_2YLonXLrNQe011Lz-XjT0AnbtpD@mail.gmail.com>
	<201006010928.17637.muehlfelder@enertex.de>
Message-ID: <20100601100519.GA4085@localhost.localdomain>

On Tue, Jun 01, 2010 at 09:28:17AM +0200, Thorsten M?hlfelder wrote:
> After checking the Linux ChangeLogs at http://kernelnewbies.org/Linux26Changes 
> I did not find any changes related to JFFS2 summary option, so I don't think 
> a newer kernel is needed ;-)

Above summary is meant to list user and kernel developer visible changes only.
You may want to check real changelog: http://git.infradead.org/mtd-2.6.git

	l.


From jy0922.shim at samsung.com  Tue Jun  1 04:17:35 2010
From: jy0922.shim at samsung.com (Joonyoung Shim)
Date: Tue, 01 Jun 2010 17:17:35 +0900
Subject: [PATCH 1/2] mtd: OneNAND: Add runtime badblock check feature
Message-ID: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>

From: Kyungmin Park <kyungmin.park at samsung.com>

This patch is to support runtime badblock checking. This supports only
OneNAND currently. The OneNAND badblock checking when boots occurs boot
time delay. We can reduce boot time because can detect badblock at
runtime.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 drivers/mtd/Kconfig                |    6 +++
 drivers/mtd/mtdpart.c              |    3 +
 drivers/mtd/onenand/onenand_base.c |   14 +++---
 drivers/mtd/onenand/onenand_bbt.c  |   79 ++++++++++++++++++++++++++++++++++-
 include/linux/mtd/onenand.h        |    1 +
 5 files changed, 93 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index f8210bf..2584928 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -328,6 +328,12 @@ config MTD_OOPS
 	  To use, add console=ttyMTDx to the kernel command line,
 	  where x is the MTD device number to use.
 
+config MTD_RUNTIME_BADBLOCK_CHECK
+	bool "Runtime badblock check support"
+	depends on MTD_ONENAND
+	help
+	  This enables check badblocks at access time.
+
 source "drivers/mtd/chips/Kconfig"
 
 source "drivers/mtd/maps/Kconfig"
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index b8043a9..f11d944 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -485,6 +485,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 	}
 
 	slave->mtd.ecclayout = master->ecclayout;
+
+#ifndef CONFIG_MTD_RUNTIME_BADBLOCK_CHECK
 	if (master->block_isbad) {
 		uint64_t offs = 0;
 
@@ -495,6 +497,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 			offs += slave->mtd.erasesize;
 		}
 	}
+#endif
 
 out_register:
 	/* register our partition */
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index fc91c4a..93597ff 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1536,6 +1536,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 	int ret = 0, readcmd;
 	size_t len = ops->ooblen;
 	u_char *buf = ops->oobbuf;
+	int update = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %zi\n",
 		__func__, (unsigned int) from, len);
@@ -1550,13 +1551,15 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 		return ONENAND_BBT_READ_FATAL_ERROR;
 	}
 
-	/* Grab the lock and see if the device is available */
-	onenand_get_device(mtd, FL_READING);
-
 	column = from & (mtd->oobsize - 1);
 
 	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
+	if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+		readcmd = ONENAND_CMD_READ;
+		update = 1;
+	}
+
 	while (read < len) {
 		cond_resched();
 
@@ -1565,7 +1568,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 
 		this->command(mtd, readcmd, from, mtd->oobsize);
 
-		onenand_update_bufferram(mtd, from, 0);
+		onenand_update_bufferram(mtd, from, update);
 
 		ret = this->bbt_wait(mtd, FL_READING);
 		if (unlikely(ret))
@@ -1589,9 +1592,6 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 		}
 	}
 
-	/* Deselect and wake up anyone waiting on the device */
-	onenand_release_device(mtd);
-
 	ops->oobretlen = read;
 	return ret;
 }
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index a91fcac..802cf20 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -3,11 +3,17 @@
  *
  *  Bad Block Table support for the OneNAND driver
  *
- *  Copyright(c) 2005 Samsung Electronics
+ *  Copyright(c) 2005-2010 Samsung Electronics
  *  Kyungmin Park <kyungmin.park at samsung.com>
  *
  *  Derived from nand_bbt.c
  *
+ *  Legend in badblock table:
+ *     0x00	Normal
+ *     0x01	RESERVED
+ *     0x02	Used for runtime badblock check
+ *     0x03	Bad block (initial or runtime)
+ *
  *  TODO:
  *    Split BBT core and chip specific BBT.
  */
@@ -17,6 +23,16 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
+#define BBT_NORMAL_BITS			0x00
+#define BBT_RUNTIME_BADBLOCK_BITS	0x02
+#define BBT_BADBLOCK_BITS		0x03
+
+#ifdef CONFIG_MTD_RUNTIME_BADBLOCK_CHECK
+#define BBT_SCAN_PAGE			1
+#else
+#define BBT_SCAN_PAGE			2
+#endif
+
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
  * @param buf		the buffer to search
@@ -44,6 +60,52 @@ static int check_short_pattern(uint8_t *buf, int len, int paglen, struct nand_bb
 }
 
 /**
+ * read_page_oob - [GENERIC] Read oob for runtime badblock check
+ * @param mtd          MTD device structure
+ * @param from         the length of buffer to search
+ * @param buf          temporary buffer
+ *
+ * Read page oob at runtime badblock check
+ */
+static int read_page_oob(struct mtd_info *mtd, loff_t from, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct bbm_info *bbm = this->bbm;
+	struct nand_bbt_descr *bd = bbm->badblock_pattern;
+	struct mtd_oob_ops ops;
+	int ret, scanlen, block, j, res;
+
+	scanlen = 0;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooblen = 32;
+	ops.oobbuf = buf;
+	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
+	/* Get block number * 2 */
+	block = (int) ((from >> this->erase_shift) << 1);
+
+	/* Set normal block first */
+	res = BBT_NORMAL_BITS;
+	bbm->bbt[block >> 3] &= ~(0x3 << (block & 0x6));
+	bbm->bbt[block >> 3] |= res << (block & 0x6);
+
+	for (j = 0; j < BBT_SCAN_PAGE; j++) {
+		ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
+		if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
+			res = BBT_BADBLOCK_BITS;
+			bbm->bbt[block >> 3] |= res << (block & 0x6);
+			printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
+					block >> 1, (unsigned int) from);
+			mtd->ecc_stats.badblocks++;
+			break;
+		}
+	}
+
+	return res;
+}
+
+/**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
  * @param mtd		MTD device structure
  * @param buf		temporary buffer
@@ -67,7 +129,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 
 	printk(KERN_INFO "Scanning device for bad blocks\n");
 
-	len = 2;
+	len = BBT_SCAN_PAGE;
 
 	/* We need only read few bytes from the OOB area */
 	scanlen = ooblen = 0;
@@ -99,7 +161,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 				return -EIO;
 
 			if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
-				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
+				bbm->bbt[i >> 3] |= BBT_BADBLOCK_BITS << (i & 0x6);
 				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
 					i >> 1, (unsigned int) from);
 				mtd->ecc_stats.badblocks++;
@@ -152,6 +214,11 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 	block = (int) (onenand_block(this, offs) << 1);
 	res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
+	if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+		if (res == BBT_RUNTIME_BADBLOCK_BITS)
+			res = read_page_oob(mtd, offs, this->page_buf);
+	}
+
 	DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
 		(unsigned int) offs, block >> 1, res);
 
@@ -201,6 +268,12 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	if (!bbm->isbad_bbt)
 		bbm->isbad_bbt = onenand_isbad_bbt;
 
+	if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+		printk(KERN_INFO "Scanning device for bad blocks (skipped)\n");
+		memset(bbm->bbt, 0xAA, len);
+		return 0;
+	}
+
 	/* Scan the device to build a memory based bad block table */
 	if ((ret = onenand_memory_bbt(mtd, bd))) {
 		printk(KERN_ERR "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n");
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 57c3bb4..059b5f7 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -181,6 +181,7 @@ struct onenand_chip {
 #define ONENAND_HAS_2PLANE		(0x0004)
 #define ONENAND_HAS_4KB_PAGE		(0x0008)
 #define ONENAND_SKIP_UNLOCK_CHECK	(0x0100)
+#define ONENAND_RUNTIME_BADBLOCK_CHECK	(0x0200)
 #define ONENAND_PAGEBUF_ALLOC		(0x1000)
 #define ONENAND_OOBBUF_ALLOC		(0x2000)
 
-- 
1.7.0.4



From jy0922.shim at samsung.com  Tue Jun  1 04:17:36 2010
From: jy0922.shim at samsung.com (Joonyoung Shim)
Date: Tue, 01 Jun 2010 17:17:36 +0900
Subject: [PATCH 2/2] mtd: OneNAND: Support runtime badblock check of Samsung
	Soc OneNAND
In-Reply-To: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>
References: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>
Message-ID: <1275380256-15315-2-git-send-email-jy0922.shim@samsung.com>

From: Kyungmin Park <kyungmin.park at samsung.com>

This patch is to support runtime badblock check to Samsung Soc OneNAND
driver.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 drivers/mtd/onenand/samsung.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index fa4b743..c2bbeae 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -837,8 +837,12 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	/* Set onenand_chip also */
 	this->base = onenand->base;
 
-	/* Use runtime badblock check */
+	/* Skip unlock all check */
 	this->options |= ONENAND_SKIP_UNLOCK_CHECK;
+#ifdef CONFIG_MTD_RUNTIME_BADBLOCK_CHECK
+	/* Use runtime badblock check */
+	this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK;
+#endif
 
 	if (onenand->type != TYPE_S5PC110) {
 		r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-- 
1.7.0.4



From dwmw2 at infradead.org  Tue Jun  1 05:15:15 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Tue, 01 Jun 2010 10:15:15 +0100
Subject: How stable is jffs2 summarize option?
In-Reply-To: <201005311503.42629.muehlfelder@enertex.de>
References: <201005311503.42629.muehlfelder@enertex.de>
Message-ID: <1275383715.25797.14.camel@macbook.infradead.org>

On Mon, 2010-05-31 at 15:03 +0200, Thorsten M?hlfelder wrote:
> to reduce boot time of a device I want to use the jffs2 summarize option on my 
> root file system. Currently 'm using Linux 2.6.24 on that specific device and 
> the summarize option is marked as "experimental", so I wonder if it is stable 
> enough for a productive system?
> Are there any well known devices that use this option, too?
> Do I have to use a newer kernel version?

There are other reasons why you should update from 2.6.24 if you're
using JFFS2, but I don't think the summary code has changed much since
then. The only reason it was still marked as 'experimental' is because I
wanted to optimise the on-medium format.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From muehlfelder at enertex.de  Tue Jun  1 05:26:23 2010
From: muehlfelder at enertex.de (Thorsten =?utf-8?q?M=C3=BChlfelder?=)
Date: Tue, 1 Jun 2010 11:26:23 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <1275383715.25797.14.camel@macbook.infradead.org>
References: <201005311503.42629.muehlfelder@enertex.de>
	<1275383715.25797.14.camel@macbook.infradead.org>
Message-ID: <201006011126.23862.muehlfelder@enertex.de>

Am Tuesday 01 June 2010 11:15:15 schrieb David Woodhouse:
> On Mon, 2010-05-31 at 15:03 +0200, Thorsten M?hlfelder wrote:
> > to reduce boot time of a device I want to use the jffs2 summarize option
> > on my root file system. Currently 'm using Linux 2.6.24 on that specific
> > device and the summarize option is marked as "experimental", so I wonder
> > if it is stable enough for a productive system?
> > Are there any well known devices that use this option, too?
> > Do I have to use a newer kernel version?
>
> There are other reasons why you should update from 2.6.24 if you're
> using JFFS2, but I don't think the summary code has changed much since
> then. The only reason it was still marked as 'experimental' is because I
> wanted to optimise the on-medium format.

Hi,

and what do you think about switching to yaffs2? I know it is developed 
elsewhere, but it seems to be a good alternative to jffs2+summary and 
probably switching is easier than to ubifs.

Best regards
Thorsten


From dwmw2 at infradead.org  Tue Jun  1 05:33:08 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Tue, 01 Jun 2010 10:33:08 +0100
Subject: How stable is jffs2 summarize option?
In-Reply-To: <201006011126.23862.muehlfelder@enertex.de>
References: <201005311503.42629.muehlfelder@enertex.de>
	<1275383715.25797.14.camel@macbook.infradead.org>
	<201006011126.23862.muehlfelder@enertex.de>
Message-ID: <1275384788.25797.17.camel@macbook.infradead.org>

On Tue, 2010-06-01 at 11:26 +0200, Thorsten M?hlfelder wrote:
> and what do you think about switching to yaffs2? I know it is developed 
> elsewhere, but it seems to be a good alternative to jffs2+summary and 
> probably switching is easier than to ubifs. 

Why would you think that switching to something that isn't part of the
Linux kernel would be easier than switching to ubifs? That seems... odd.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From vitalywool at gmail.com  Tue Jun  1 05:47:27 2010
From: vitalywool at gmail.com (Vitaly Wool)
Date: Tue, 1 Jun 2010 11:47:27 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <201006011126.23862.muehlfelder@enertex.de>
References: <201005311503.42629.muehlfelder@enertex.de>
	<1275383715.25797.14.camel@macbook.infradead.org>
	<201006011126.23862.muehlfelder@enertex.de>
Message-ID: <AANLkTik7JCuxgYe623F0CaR2OAA2f3Wohvp5btP_7y7c@mail.gmail.com>

Hi Thorsten,

2010/6/1 Thorsten M?hlfelder <muehlfelder at enertex.de>:

> and what do you think about switching to yaffs2? I know it is developed
> elsewhere, but it seems to be a good alternative to jffs2+summary and
> probably switching is easier than to ubifs.

Can you please share your reasons why you're considering switching first? :)

~Vitaly


From joakim.tjernlund at transmode.se  Tue Jun  1 05:50:06 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Tue, 1 Jun 2010 11:50:06 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <1275384788.25797.17.camel@macbook.infradead.org>
References: <201005311503.42629.muehlfelder@enertex.de>	<1275383715.25797.14.camel@macbook.infradead.org>
	<201006011126.23862.muehlfelder@enertex.de>
	<1275384788.25797.17.camel@macbook.infradead.org>
Message-ID: <OF6BA924CE.75C9F3A4-ONC1257735.0035A313-C1257735.00360683@transmode.se>

>
> On Tue, 2010-06-01 at 11:26 +0200, Thorsten M?hlfelder wrote:
> > and what do you think about switching to yaffs2? I know it is developed
> > elsewhere, but it seems to be a good alternative to jffs2+summary and
> > probably switching is easier than to ubifs.
>
> Why would you think that switching to something that isn't part of the
> Linux kernel would be easier than switching to ubifs? That seems... odd.

Yes, if ubifs doesn't fit, perhaps have a look at the recently added
logfs?

    Jocke

BTW, I once tried JFFS2 summary and it didn't make much of a difference for us.



From w.sang at pengutronix.de  Tue Jun  1 05:55:12 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Tue, 1 Jun 2010 11:55:12 +0200
Subject: Do we remove from jedec_probe.c?
In-Reply-To: <20100526175320.GD24167@pengutronix.de>
References: <20100526175320.GD24167@pengutronix.de>
Message-ID: <20100601095512.GC16143@pengutronix.de>

On Wed, May 26, 2010 at 07:53:20PM +0200, Wolfram Sang wrote:
> Hi,
> 
> now that Guillaume introduced cfi-support for some SST-flashes, I wonder if
> those can be removed from jedec_probe.c? Or should they stay for
> backward-compatibility?

Ping?

> 
> Proposed patch would look like this:
> 
> diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
> index d72a5fb..37fdff3 100644
> --- a/drivers/mtd/chips/jedec_probe.c
> +++ b/drivers/mtd/chips/jedec_probe.c
> @@ -146,8 +146,6 @@
>  #define SST29LE512	0x003d
>  #define SST39LF800	0x2781
>  #define SST39LF160	0x2782
> -#define SST39VF1601	0x234b
> -#define SST39VF3201	0x235b
>  #define SST39WF1601	0x274b
>  #define SST39WF1602	0x274a
>  #define SST39LF512	0x00D4
> @@ -1500,19 +1498,6 @@ static const struct amd_flash_info jedec_table[] = {
>  			ERASEINFO(0x1000,256)
>  		}
>  	}, {
> -		.mfr_id		= CFI_MFR_SST,     /* should be CFI */
> -		.dev_id		= SST39VF1601,
> -		.name		= "SST 39VF1601",
> -		.devtypes	= CFI_DEVICETYPE_X16,
> -		.uaddr		= MTD_UADDR_0xAAAA_0x5555,
> -		.dev_size	= SIZE_2MiB,
> -		.cmd_set	= P_ID_AMD_STD,
> -		.nr_regions	= 2,
> -		.regions	= {
> -			ERASEINFO(0x1000,256),
> -			ERASEINFO(0x1000,256)
> -		}
> -	}, {
>  		/* CFI is broken: reports AMD_STD, but needs custom uaddr */
>  		.mfr_id		= CFI_MFR_SST,
>  		.dev_id		= SST39WF1601,
> @@ -1541,21 +1526,6 @@ static const struct amd_flash_info jedec_table[] = {
>  			ERASEINFO(0x1000,256)
>  		}
>  	}, {
> -		.mfr_id		= CFI_MFR_SST,     /* should be CFI */
> -		.dev_id		= SST39VF3201,
> -		.name		= "SST 39VF3201",
> -		.devtypes	= CFI_DEVICETYPE_X16,
> -		.uaddr		= MTD_UADDR_0xAAAA_0x5555,
> -		.dev_size	= SIZE_4MiB,
> -		.cmd_set	= P_ID_AMD_STD,
> -		.nr_regions	= 4,
> -		.regions	= {
> -			ERASEINFO(0x1000,256),
> -			ERASEINFO(0x1000,256),
> -			ERASEINFO(0x1000,256),
> -			ERASEINFO(0x1000,256)
> -		}
> -	}, {
>  		.mfr_id		= CFI_MFR_SST,
>  		.dev_id		= SST36VF3203,
>  		.name		= "SST 36VF3203",
> 
> -- 
> Pengutronix e.K.                           | Wolfram Sang                |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |



> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/


-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20100601/aa4877f3/attachment.sig>

From muehlfelder at enertex.de  Tue Jun  1 06:03:00 2010
From: muehlfelder at enertex.de (Thorsten =?utf-8?q?M=C3=BChlfelder?=)
Date: Tue, 1 Jun 2010 12:03:00 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <1275384788.25797.17.camel@macbook.infradead.org>
References: <201005311503.42629.muehlfelder@enertex.de>
	<201006011126.23862.muehlfelder@enertex.de>
	<1275384788.25797.17.camel@macbook.infradead.org>
Message-ID: <201006011203.00664.muehlfelder@enertex.de>

Am Tuesday 01 June 2010 11:33:08 schrieb David Woodhouse:
> On Tue, 2010-06-01 at 11:26 +0200, Thorsten M?hlfelder wrote:
> > and what do you think about switching to yaffs2? I know it is developed
> > elsewhere, but it seems to be a good alternative to jffs2+summary and
> > probably switching is easier than to ubifs.
>
> Why would you think that switching to something that isn't part of the
> Linux kernel would be easier than switching to ubifs? That seems... odd.

Because getting yaffs2 source and patching the kernel only was 2 commands and 
no single additional tool is needed. Just boot from USB stick and run:
flash_eraseall /dev/mtd1
mount -t yaffs2 /dev/mtdblock1 /mnt/device-root
tar xvf root-filesystem.tar -C /mnt/device-root

;-)


From muehlfelder at enertex.de  Tue Jun  1 06:07:41 2010
From: muehlfelder at enertex.de (Thorsten =?iso-8859-15?q?M=FChlfelder?=)
Date: Tue, 1 Jun 2010 12:07:41 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <OF6BA924CE.75C9F3A4-ONC1257735.0035A313-C1257735.00360683@transmode.se>
References: <201005311503.42629.muehlfelder@enertex.de>
	<1275384788.25797.17.camel@macbook.infradead.org>
	<OF6BA924CE.75C9F3A4-ONC1257735.0035A313-C1257735.00360683@transmode.se>
Message-ID: <201006011207.41709.muehlfelder@enertex.de>

Am Tuesday 01 June 2010 11:50:06 schrieb Joakim Tjernlund:
> > On Tue, 2010-06-01 at 11:26 +0200, Thorsten M?hlfelder wrote:
> > > and what do you think about switching to yaffs2? I know it is developed
> > > elsewhere, but it seems to be a good alternative to jffs2+summary and
> > > probably switching is easier than to ubifs.
> >
> > Why would you think that switching to something that isn't part of the
> > Linux kernel would be easier than switching to ubifs? That seems... odd.
>
> Yes, if ubifs doesn't fit, perhaps have a look at the recently added
> logfs?
>
>     Jocke
>
> BTW, I once tried JFFS2 summary and it didn't make much of a difference for
> us.

JFFS2 summary has reduced the mount time of my 500 MB root partition from 
around 50 seconds to 10 seconds.

yaffs2 has a mount time of ~3 seconds and it seems it has faster read access 
because whole boot time is reduced by ~30 seconds (compared to jffs2 
summary).

I did not try ubifs yet.

AFAIK LogFS is still experimental?


From muehlfelder at enertex.de  Tue Jun  1 06:13:50 2010
From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=)
Date: Tue, 1 Jun 2010 12:13:50 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <AANLkTik7JCuxgYe623F0CaR2OAA2f3Wohvp5btP_7y7c@mail.gmail.com>
References: <201005311503.42629.muehlfelder@enertex.de>
	<201006011126.23862.muehlfelder@enertex.de>
	<AANLkTik7JCuxgYe623F0CaR2OAA2f3Wohvp5btP_7y7c@mail.gmail.com>
Message-ID: <201006011213.50278.muehlfelder@enertex.de>

Am Tuesday 01 June 2010 11:47:27 schrieb Vitaly Wool:
> Hi Thorsten,
>
> 2010/6/1 Thorsten M?hlfelder <muehlfelder at enertex.de>:
> > and what do you think about switching to yaffs2? I know it is developed
> > elsewhere, but it seems to be a good alternative to jffs2+summary and
> > probably switching is easier than to ubifs.
>
> Can you please share your reasons why you're considering switching first?
> :)
>

Hi Vitaly,
1. We've used JFFS2 without summary until now, but now I have to reduce the 
boot time to the minimum possible. So first idea was the summary option, 
because other than slow mount times JFFS2 has worked OK. But if I do a major 
change now, why not switch to a more modern FS which will fasten boot up even 
more? ;-)

Additional requirements:
Sometimes it's written to the root FS and the device must be aware of power 
failures during write. I guess all the mentioned FS can handle this quite 
well.

Greetings
Thorsten


From glecerf at gmail.com  Tue Jun  1 06:13:41 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 1 Jun 2010 12:13:41 +0200
Subject: Do we remove from jedec_probe.c?
In-Reply-To: <20100601095512.GC16143@pengutronix.de>
References: <20100526175320.GD24167@pengutronix.de>
	<20100601095512.GC16143@pengutronix.de>
Message-ID: <AANLkTinas78bDYXGg8eoLFgB0zSL6BCF10IZtQpEtjHZ@mail.gmail.com>

2010/6/1 Wolfram Sang <w.sang at pengutronix.de>:
> On Wed, May 26, 2010 at 07:53:20PM +0200, Wolfram Sang wrote:
>> Hi,
>>
>> now that Guillaume introduced cfi-support for some SST-flashes, I wonder if
>> those can be removed from jedec_probe.c? Or should they stay for
>> backward-compatibility?

May I add that SST39VF3201 (0x235b) jedec detection does not work, the
chip being mis-detected as SST49LF080A (0x005B).
This is because of this changeset [1] that checks for 8bit devices
before 16bits.

This may be the case for others chips whom IDs lower bits overlap.

[1] http://git.infradead.org/mtd-2.6.git/commitdiff/6170b43401a3230756ff76287ee07db0d75eddde
-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From dwmw2 at infradead.org  Tue Jun  1 06:38:57 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Tue, 01 Jun 2010 11:38:57 +0100
Subject: How stable is jffs2 summarize option?
In-Reply-To: <OF6BA924CE.75C9F3A4-ONC1257735.0035A313-C1257735.00360683@transmode.se>
References: <201005311503.42629.muehlfelder@enertex.de>
	<1275383715.25797.14.camel@macbook.infradead.org>
	<201006011126.23862.muehlfelder@enertex.de>
	<1275384788.25797.17.camel@macbook.infradead.org>
	<OF6BA924CE.75C9F3A4-ONC1257735.0035A313-C1257735.00360683@transmode.se>
Message-ID: <1275388737.25797.89.camel@macbook.infradead.org>

On Tue, 2010-06-01 at 11:50 +0200, Joakim Tjernlund wrote:
> >
> > On Tue, 2010-06-01 at 11:26 +0200, Thorsten M?hlfelder wrote:
> > > and what do you think about switching to yaffs2? I know it is developed
> > > elsewhere, but it seems to be a good alternative to jffs2+summary and
> > > probably switching is easier than to ubifs.
> >
> > Why would you think that switching to something that isn't part of the
> > Linux kernel would be easier than switching to ubifs? That seems... odd.
> 
> Yes, if ubifs doesn't fit, perhaps have a look at the recently added
> logfs?
> 
>     Jocke
> 
> BTW, I once tried JFFS2 summary and it didn't make much of a difference for us.

Did you use 'sumtool' after creating your images? For reasons which are
now lost in the mists of time, that support wasn't just added directly
to mkfs.jffs2.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From joakim.tjernlund at transmode.se  Tue Jun  1 07:39:25 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Tue, 1 Jun 2010 13:39:25 +0200
Subject: How stable is jffs2 summarize option?
In-Reply-To: <1275388737.25797.89.camel@macbook.infradead.org>
References: <201005311503.42629.muehlfelder@enertex.de>	
	<1275383715.25797.14.camel@macbook.infradead.org>
	<201006011126.23862.muehlfelder@enertex.de>	
	<1275384788.25797.17.camel@macbook.infradead.org>
	<OF6BA924CE.75C9F3A4-ONC1257735.0035A313-C1257735.00360683@transmode.se>
	<1275388737.25797.89.camel@macbook.infradead.org>
Message-ID: <OF1EBB9E60.E5975679-ONC1257735.003FC2D1-C1257735.004008A6@transmode.se>

David Woodhouse <dwmw2 at infradead.org> wrote on 2010/06/01 12:38:57:
>
> On Tue, 2010-06-01 at 11:50 +0200, Joakim Tjernlund wrote:
> > >
> > > On Tue, 2010-06-01 at 11:26 +0200, Thorsten M?hlfelder wrote:
> > > > and what do you think about switching to yaffs2? I know it is developed
> > > > elsewhere, but it seems to be a good alternative to jffs2+summary and
> > > > probably switching is easier than to ubifs.
> > >
> > > Why would you think that switching to something that isn't part of the
> > > Linux kernel would be easier than switching to ubifs? That seems... odd.
> >
> > Yes, if ubifs doesn't fit, perhaps have a look at the recently added
> > logfs?
> >
> >     Jocke
> >
> > BTW, I once tried JFFS2 summary and it didn't make much of a difference for us.
>
> Did you use 'sumtool' after creating your images? For reasons which are
> now lost in the mists of time, that support wasn't just added directly
> to mkfs.jffs2.

This was some years ago but I cannot recall using 'sumtool'. Also
our NOR FS is between 128 and 64 MB so perhaps it is too small to benefit
from summary?



From khali at linux-fr.org  Tue Jun  1 09:53:10 2010
From: khali at linux-fr.org (Jean Delvare)
Date: Tue, 1 Jun 2010 15:53:10 +0200
Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL)
In-Reply-To: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de>
References: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de>
Message-ID: <20100601155310.3781fce6@hyperion.delvare>

On Mon, 31 May 2010 14:55:48 +0200, Wolfram Sang wrote:
> I2C-drivers can use the clientdata-pointer to point to private data. As I2C
> devices are not really unregistered, but merely detached from their driver, it
> used to be the drivers obligation to clear this pointer during remove() or a
> failed probe(). As a couple of drivers forgot to do this, it was agreed that it
> was cleaner if the i2c-core does this clearance when appropriate, as there is
> no guarantee for the lifetime of the clientdata-pointer after remove() anyhow.
> This feature was added to the core with commit
> e4a7b9b04de15f6b63da5ccdd373ffa3057a3681 to fix the faulty drivers.
> 
> As there is no need anymore to clear the clientdata-pointer, remove all current
> occurrences in the drivers to simplify the code and prevent confusion.
> 
> Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
> Cc: Jean Delvare <khali at linux-fr.org>
> (...)

Applied, thanks. Will go to Linus in the next few days.

-- 
Jean Delvare


From julia at diku.dk  Tue Jun  1 10:34:20 2010
From: julia at diku.dk (Julia Lawall)
Date: Tue, 1 Jun 2010 16:34:20 +0200 (CEST)
Subject: [PATCH 1/4] drivers/mtd/maps: introduce missing kfree
Message-ID: <Pine.LNX.4.64.1006011625510.12546@ask.diku.dk>

From: Julia Lawall <julia at diku.dk>

Error handling code following a kmalloc should free the allocated data.

The semantic match that finds the problem is as follows:
(http://www.emn.fr/x-info/coccinelle/)

// <smpl>
@r exists@
local idexpression x;
statement S;
expression E;
identifier f,f1,l;
position p1,p2;
expression *ptr != NULL;
@@

x at p1 = \(kmalloc\|kzalloc\|kcalloc\)(...);
...
if (x == NULL) S
<... when != x
     when != if (...) { <+...x...+> }
(
x->f1 = E
|
 (x->f1 == NULL || ...)
|
 f(...,x->f1,...)
)
...>
(
 return \(0\|<+...x...+>\|ptr\);
|
 return at p2 ...;
)

@script:python@
p1 << r.p1;
p2 << r.p2;
@@

print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line)
// </smpl>

Signed-off-by: Julia Lawall <julia at diku.dk>
---
 drivers/mtd/maps/physmap_of.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index ba124ba..6ac5f9f 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -353,7 +353,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
 				   &info->parts, 0);
 	if (err < 0) {
 		of_free_probes(part_probe_types);
-		return err;
+		goto err_out;
 	}
 	of_free_probes(part_probe_types);
 
@@ -361,14 +361,14 @@ static int __devinit of_flash_probe(struct of_device *dev,
 	if (err == 0) {
 		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
 		if (err < 0)
-			return err;
+			goto err_out;
 	}
 #endif
 
 	if (err == 0) {
 		err = parse_obsolete_partitions(dev, info, dp);
 		if (err < 0)
-			return err;
+			goto err_out;
 	}
 
 	if (err > 0)


From matthieu.castet at parrot.com  Wed Jun  2 05:22:46 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Wed, 2 Jun 2010 11:22:46 +0200
Subject: ubi question
Message-ID: <4C0622E6.7070203@parrot.com>

Hi,

I have some question about ubi implementation.
I have read most of the "drivers/mtd/ubi/ubi-media.h" documentation.

The doc is not very clear about the case when data_size is set for
dynamic volume. From my understanding it is set in case copy_flag is set 
and the value is the logical eraseblock size.

When a block with copy_flag set, when we append data (and make the crc 
invalid), do we make sure that all previous version of this logical 
eraseblock are removed from flash ?

Why layout volume isn't a static volume with one eraseblock and update 
done with atomic leb update (copy flag) ?
This would have :
- make the crc ckeck done by generic code (static volume one)
- make the handling of update by generic code
- avoid to having to handle dynamic volume in minimalist implementation 
(bootloader)
Do I miss something ?


Matthieu


From dedekind1 at gmail.com  Wed Jun  2 07:10:48 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 02 Jun 2010 14:10:48 +0300
Subject: ubi question
In-Reply-To: <4C0622E6.7070203@parrot.com>
References: <4C0622E6.7070203@parrot.com>
Message-ID: <1275477048.27484.18.camel@localhost>

On Wed, 2010-06-02 at 11:22 +0200, Matthieu CASTET wrote:
> Hi,
> 
> I have some question about ubi implementation.
> I have read most of the "drivers/mtd/ubi/ubi-media.h" documentation.
> 
> The doc is not very clear about the case when data_size is set for
> dynamic volume.

Please, when you get the understanding, submit a patch which amends the
comments.

>  From my understanding it is set in case copy_flag is set 
> and the value is the logical eraseblock size.

Yeah, copy_flag tells that this VID header was written by UBI when some
other PEB was copied.

And yes, data_size and data_crc flags are valid when the copy_flag is 1.

IOW:

1. copy_flag says this PEB was created by copying, and that data_size
and data_crc fields are valid for this PEB
2. data_crc contains CRC32 of the first data_size bytes of this PEB.

> When a block with copy_flag set, when we append data (and make the crc 
> invalid),

When we append data, we do not make CRC invalid. CRC was calculated for
the first data_size bytes in this PEB. And it stays valid forever.

The only reason we have this data_crc/data_size fields is to tolerate
power cuts. When sacnning later, and encountering 2 PEB which belong to
the same volume/LEB, we pick the copy if the CRC is valid.

>  do we make sure that all previous version of this logical 
> eraseblock are removed from flash ?

No, this is not required. We just append data. In case of power cut we
will pick the newer PEB because it has larger seq_num, and we'll check
CRC and it'll match.

> Why layout volume isn't a static volume with one eraseblock and update 
> done with atomic leb update (copy flag) ?

Atomic LEB change was introduce later, after first UBI implementation
has been finished. We introduce the atomic LEB change to satisfy UBIFS
needs. You can spot event that the comments in ubi-media.h mention only
wear-levelling copying, but not the atomic LEB change case - simply
because they were not updated.

If you happen to send a patch which clarifies the comments, feel free to
update them and mention the atomic LEB change stuff as well.

> This would have :
> - make the crc ckeck done by generic code (static volume one)
> - make the handling of update by generic code
> - avoid to having to handle dynamic volume in minimalist implementation 
> (bootloader)
> Do I miss something ?

Yeah, probably, but it is too late now :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From maximlevitsky at gmail.com  Wed Jun  2 09:01:44 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Wed,  2 Jun 2010 16:01:44 +0300
Subject: Few fixes for my driver + minor fix in mtd's Kconfig
Message-ID: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>


Hi,

These patches finally fix few dma related problems in my r852 driver.
Last patch unrelated to my driver, fixes display in xconfig, 
as it would otherwise put whole nand submenu under 'mtd' directly.
I don't think there is functional change.

Best regards,
	Maxim Levitsky




From maximlevitsky at gmail.com  Wed Jun  2 09:01:45 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Wed,  2 Jun 2010 16:01:45 +0300
Subject: [PATCH 1/4] r852: register IRQ as last step
In-Reply-To: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
References: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1275483708-11929-2-git-send-email-maximlevitsky@gmail.com>

From: Maxim Levitsky <maximlevitsky at gmail.com>

Otherwise, if it fires right away, it might access
uninitialized spinlock

Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/nand/r852.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 78a4232..20a654a 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -940,18 +940,19 @@ int  r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 
 	r852_dma_test(dev);
 
+	dev->irq = pci_dev->irq;
+	spin_lock_init(&dev->irqlock);
+
+	dev->card_detected = 0;
+	r852_card_update_present(dev);
+
 	/*register irq handler*/
 	error = -ENODEV;
 	if (request_irq(pci_dev->irq, &r852_irq, IRQF_SHARED,
 			  DRV_NAME, dev))
 		goto error10;
 
-	dev->irq = pci_dev->irq;
-	spin_lock_init(&dev->irqlock);
-
 	/* kick initial present test */
-	dev->card_detected = 0;
-	r852_card_update_present(dev);
 	queue_delayed_work(dev->card_workqueue,
 		&dev->card_detect_work, 0);
 
-- 
1.7.0.4



From maximlevitsky at gmail.com  Wed Jun  2 09:01:46 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Wed,  2 Jun 2010 16:01:46 +0300
Subject: [PATCH 2/4] r852: Fixes in case of DMA timeout
In-Reply-To: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
References: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1275483708-11929-3-git-send-email-maximlevitsky@gmail.com>

* Don't call complete on dma completion
* do a INIT_COMPLETE before using it each time
* Report DMA read error via ecc 'correct'

I finally managed to make my system do suspend to ram propertly, and I see that
if card was inserted during suspend (while system was off), I get dma timeouts
on resume. Simple card reinsert solves the issue.
This patch solves a crash that would happen otherwise

Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/nand/r852.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 20a654a..3f219e6 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -150,7 +150,6 @@ static void r852_dma_done(struct r852_device *dev, int error)
 	if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer)
 		pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN,
 			dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-	complete(&dev->dma_done);
 }
 
 /*
@@ -182,6 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read)
 	/* Set dma direction */
 	dev->dma_dir = do_read;
 	dev->dma_stage = 1;
+	INIT_COMPLETION(dev->dma_done);
 
 	dbg_verbose("doing dma %s ", do_read ? "read" : "write");
 
@@ -494,6 +494,11 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
 	if (dev->card_unstable)
 		return 0;
 
+	if (dev->dma_error) {
+		dev->dma_error = 0;
+		return -1;
+	}
+
 	r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS);
 	ecc_reg = r852_read_reg_dword(dev, R852_DATALINE);
 	r852_write_reg(dev, R852_CTL, dev->ctlreg);
@@ -796,6 +801,7 @@ static irqreturn_t r852_irq(int irq, void *data)
 		if (dma_status & R852_DMA_IRQ_ERROR) {
 			dbg("recieved dma error IRQ");
 			r852_dma_done(dev, -EIO);
+			complete(&dev->dma_done);
 			goto out;
 		}
 
@@ -825,8 +831,10 @@ static irqreturn_t r852_irq(int irq, void *data)
 			r852_dma_enable(dev);
 
 		/* Operation done */
-		if (dev->dma_stage == 3)
+		if (dev->dma_stage == 3) {
 			r852_dma_done(dev, 0);
+			complete(&dev->dma_done);
+		}
 		goto out;
 	}
 
@@ -1082,7 +1090,7 @@ int r852_resume(struct device *device)
 			dev->card_detected ? "added" : "removed");
 
 		queue_delayed_work(dev->card_workqueue,
-		&dev->card_detect_work, 1000);
+		&dev->card_detect_work, msecs_to_jiffies(1000));
 		return 0;
 	}
 
-- 
1.7.0.4



From maximlevitsky at gmail.com  Wed Jun  2 09:01:47 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Wed,  2 Jun 2010 16:01:47 +0300
Subject: [PATCH 3/4] r852: update card detect early.
In-Reply-To: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
References: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1275483708-11929-4-git-send-email-maximlevitsky@gmail.com>

This turns out to be the reason for DMA timeouts on resume,
if card was inserted while system was suspended

Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/nand/r852.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 3f219e6..bcfc851 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -712,6 +712,7 @@ void r852_card_detect_work(struct work_struct *work)
 		container_of(work, struct r852_device, card_detect_work.work);
 
 	r852_card_update_present(dev);
+	r852_update_card_detect(dev);
 	dev->card_unstable = 0;
 
 	/* False alarm */
@@ -727,7 +728,6 @@ void r852_card_detect_work(struct work_struct *work)
 	else
 		r852_unregister_nand_device(dev);
 exit:
-	/* Update detection logic */
 	r852_update_card_detect(dev);
 }
 
-- 
1.7.0.4



From maximlevitsky at gmail.com  Wed Jun  2 09:01:48 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Wed,  2 Jun 2010 16:01:48 +0300
Subject: [PATCH 4/4] MTD: Fix NAND submenu
In-Reply-To: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
References: <1275483708-11929-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1275483708-11929-5-git-send-email-maximlevitsky@gmail.com>

Move all nand options under 'if MTD_NAND'
otherwise xconfig output is broken.


Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/nand/Kconfig |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 98a04b3..5927239 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -8,6 +8,8 @@ menuconfig MTD_NAND
 	  devices. For further information see
 	  <http://www.linux-mtd.infradead.org/doc/nand.html>.
 
+if MTD_NAND
+
 config MTD_NAND_ECC
 	tristate
 
@@ -19,7 +21,7 @@ config MTD_NAND_ECC_SMC
 	  Software ECC according to the Smart Media Specification.
 	  The original Linux implementation had byte 0 and 1 swapped.
 
-if MTD_NAND
+
 
 config MTD_NAND_VERIFY_WRITE
 	bool "Verify NAND page writes"
-- 
1.7.0.4



From maximlevitsky at gmail.com  Wed Jun  2 11:22:48 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Wed,  2 Jun 2010 18:22:48 +0300
Subject: [PATCH V2] MTD: Fix NAND submenu
Message-ID: <1275492168-4584-1-git-send-email-maximlevitsky@gmail.com>

Move MTD_NAND_ECC and MTD_NAND_ECC_SMC above NAND memuconfig, to unbreak
display in xconfig.
This shouldn't change any depedencies

Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/nand/Kconfig |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 98a04b3..ffc3720 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,13 +1,3 @@
-menuconfig MTD_NAND
-	tristate "NAND Device Support"
-	depends on MTD
-	select MTD_NAND_IDS
-	select MTD_NAND_ECC
-	help
-	  This enables support for accessing all type of NAND flash
-	  devices. For further information see
-	  <http://www.linux-mtd.infradead.org/doc/nand.html>.
-
 config MTD_NAND_ECC
 	tristate
 
@@ -19,6 +9,17 @@ config MTD_NAND_ECC_SMC
 	  Software ECC according to the Smart Media Specification.
 	  The original Linux implementation had byte 0 and 1 swapped.
 
+
+menuconfig MTD_NAND
+	tristate "NAND Device Support"
+	depends on MTD
+	select MTD_NAND_IDS
+	select MTD_NAND_ECC
+	help
+	  This enables support for accessing all type of NAND flash
+	  devices. For further information see
+	  <http://www.linux-mtd.infradead.org/doc/nand.html>.
+
 if MTD_NAND
 
 config MTD_NAND_VERIFY_WRITE
-- 
1.7.0.4



From lars at metafoo.de  Wed Jun  2 15:12:23 2010
From: lars at metafoo.de (Lars-Peter Clausen)
Date: Wed,  2 Jun 2010 21:12:23 +0200
Subject: [RFC][PATCH 17/26] MTD: Nand: Add JZ4740 NAND driver
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
Message-ID: <1275505950-17334-1-git-send-email-lars@metafoo.de>

This patch adds support for the NAND controller on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars at metafoo.de>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: linux-mtd at lists.infradead.org
---
 drivers/mtd/nand/Kconfig        |    6 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/jz4740_nand.c  |  442 +++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/jz4740_nand.h |   34 +++
 4 files changed, 483 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/jz4740_nand.c
 create mode 100644 include/linux/mtd/jz4740_nand.h

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 98a04b3..5e03939 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -525,4 +525,10 @@ config MTD_NAND_NUC900
 	  This enables the driver for the NAND Flash on evaluation board based
 	  on w90p910 / NUC9xx.
 
+config MTD_NAND_JZ4740
+	tristate "Support for JZ4740 SoC NAND controller"
+	depends on MACH_JZ4740
+	help
+		Enables support for NAND Flash on JZ4740 SoC based boards.
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index e8ab884..ac83dcd 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -46,5 +46,6 @@ obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
+obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
new file mode 100644
index 0000000..fee3123
--- /dev/null
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -0,0 +1,442 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars at metafoo.de>
+ *	JZ4740 SoC NAND controller driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/gpio.h>
+
+#define JZ_REG_NAND_CTRL	0x50
+#define JZ_REG_NAND_ECC_CTRL	0x100
+#define JZ_REG_NAND_DATA	0x104
+#define JZ_REG_NAND_PAR0	0x108
+#define JZ_REG_NAND_PAR1	0x10C
+#define JZ_REG_NAND_PAR2	0x110
+#define JZ_REG_NAND_IRQ_STAT	0x114
+#define JZ_REG_NAND_IRQ_CTRL	0x118
+#define JZ_REG_NAND_ERR(x)	(0x11C + (x << 2))
+
+#define JZ_NAND_ECC_CTRL_PAR_READY	BIT(4)
+#define JZ_NAND_ECC_CTRL_ENCODING	BIT(3)
+#define JZ_NAND_ECC_CTRL_RS		BIT(2)
+#define JZ_NAND_ECC_CTRL_RESET		BIT(1)
+#define JZ_NAND_ECC_CTRL_ENABLE		BIT(0)
+
+#define JZ_NAND_STATUS_ERR_COUNT	(BIT(31) | BIT(30) | BIT(29))
+#define JZ_NAND_STATUS_PAD_FINISH	BIT(4)
+#define JZ_NAND_STATUS_DEC_FINISH	BIT(3)
+#define JZ_NAND_STATUS_ENC_FINISH	BIT(2)
+#define JZ_NAND_STATUS_UNCOR_ERROR	BIT(1)
+#define JZ_NAND_STATUS_ERROR		BIT(0)
+
+#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT(x << 1)
+#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT((x << 1) + 1)
+
+#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
+#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
+#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
+
+struct jz_nand {
+	struct mtd_info mtd;
+	struct nand_chip chip;
+	void __iomem *base;
+	struct resource *mem;
+
+	struct jz_nand_platform_data *pdata;
+	bool is_reading;
+};
+
+static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
+{
+	return container_of(mtd, struct jz_nand, mtd);
+}
+
+static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	struct nand_chip *chip = mtd->priv;
+	uint32_t reg;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
+		if (ctrl & NAND_ALE)
+			chip->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
+		else if (ctrl & NAND_CLE)
+			chip->IO_ADDR_W = JZ_NAND_CMD_ADDR;
+		else
+			chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+		reg = readl(nand->base + JZ_REG_NAND_CTRL);
+		if (ctrl & NAND_NCE)
+			reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
+		else
+			reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
+		writel(reg, nand->base + JZ_REG_NAND_CTRL);
+	}
+	if (dat != NAND_CMD_NONE)
+		writeb(dat, chip->IO_ADDR_W);
+}
+
+static int jz_nand_dev_ready(struct mtd_info *mtd)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	return gpio_get_value_cansleep(nand->pdata->busy_gpio);
+}
+
+static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	uint32_t reg;
+
+
+	writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	reg |= JZ_NAND_ECC_CTRL_RESET;
+	reg |= JZ_NAND_ECC_CTRL_ENABLE;
+	reg |= JZ_NAND_ECC_CTRL_RS;
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
+		nand->is_reading = true;
+		break;
+	case NAND_ECC_WRITE:
+		reg |= JZ_NAND_ECC_CTRL_ENCODING;
+		nand->is_reading = false;
+		break;
+	default:
+		break;
+	}
+
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+}
+
+
+static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat,
+	uint8_t *ecc_code)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	uint32_t reg, status;
+	int i;
+	static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4,
+						0x8b, 0xff, 0xb7, 0x6f};
+
+	if (nand->is_reading)
+		return 0;
+
+	do {
+		status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+	} while (!(status & JZ_NAND_STATUS_ENC_FINISH));
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	for (i = 0; i < 9; ++i)
+		ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i);
+
+	/* If the written data is completly 0xff, we also want to write 0xff as
+	 * ecc, otherwise we will get in trouble when doing subpage writes. */
+	if (memcmp(ecc_code, empty_block_ecc, 9) == 0)
+		memset(ecc_code, 0xff, 9);
+
+	return 0;
+}
+
+/*#define printkd printk*/
+#define printkd(...)
+
+static void correct_data(uint8_t *dat, int index, int mask)
+{
+	int offset = index & 0x7;
+	uint16_t data;
+	printkd("correct: ");
+
+	index += (index >> 3);
+
+	data = dat[index];
+	data |= dat[index+1] << 8;
+
+	printkd("0x%x -> ", data);
+
+	mask ^= (data >> offset) & 0x1ff;
+	data &= ~(0x1ff << offset);
+	data |= (mask << offset);
+
+	printkd("0x%x\n", data);
+
+	dat[index] = data & 0xff;
+	dat[index+1] = (data >> 8) & 0xff;
+}
+
+static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
+	uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	int i, error_count, index;
+	uint32_t reg, status, error;
+	uint32_t t;
+
+	t = read_ecc[0];
+
+	if (t == 0xff) {
+		for (i = 1; i < 9; ++i)
+			t &= read_ecc[i];
+
+		t &= dat[0];
+		t &= dat[nand->chip.ecc.size / 2];
+		t &= dat[nand->chip.ecc.size - 1];
+
+		if (t == 0xff) {
+			for (i = 1; i < nand->chip.ecc.size - 1; ++i)
+				t &= dat[i];
+			if (t == 0xff)
+				return 0;
+		}
+	}
+
+	for (i = 0; i < 9; ++i)
+		writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg |= JZ_NAND_ECC_CTRL_PAR_READY;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	do {
+		status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+	} while (!(status & JZ_NAND_STATUS_DEC_FINISH));
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	if (status & JZ_NAND_STATUS_ERROR) {
+		if (status & JZ_NAND_STATUS_UNCOR_ERROR) {
+			printkd("uncorrectable ecc:");
+			for (i = 0; i < 9; ++i)
+				printkd(" 0x%x", read_ecc[i]);
+			printkd("\n");
+			printkd("uncorrectable data:");
+			for (i = 0; i < 32; ++i)
+				printkd(" 0x%x", dat[i]);
+			printkd("\n");
+			return -1;
+		}
+
+		error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
+
+		printkd("error_count: %d %x\n", error_count, status);
+
+		for (i = 0; i < error_count; ++i) {
+			error = readl(nand->base + JZ_REG_NAND_ERR(i));
+			index = ((error >> 16) & 0x1ff) - 1;
+			if (index >= 0 && index < 512)
+				correct_data(dat, index, error & 0x1ff);
+		}
+
+		return error_count;
+	}
+
+	return 0;
+}
+
+
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+static const char *part_probes[] = {"cmdline", NULL};
+#endif
+
+static int __devinit jz_nand_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jz_nand *nand;
+	struct nand_chip *chip;
+	struct mtd_info *mtd;
+	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *partition_info;
+	int num_partitions = 0;
+#endif
+
+	nand = kzalloc(sizeof(*nand), GFP_KERNEL);
+	if (!nand) {
+		dev_err(&pdev->dev, "Failed to allocate device structure.\n");
+		return -ENOMEM;
+	}
+
+	nand->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!nand->mem) {
+		dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
+		ret = -ENOENT;
+		goto err_free;
+	}
+
+	nand->mem = request_mem_region(nand->mem->start,
+					resource_size(nand->mem), pdev->name);
+
+	if (!nand->mem) {
+		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	nand->base = ioremap(nand->mem->start, resource_size(nand->mem));
+
+	if (!nand->base) {
+		dev_err(&pdev->dev, "Failed to ioremap mmio memory region\n");
+		ret = -EBUSY;
+		goto err_release_mem;
+	}
+
+	if (pdata && gpio_is_valid(pdata->busy_gpio)) {
+		ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to request busy gpio %d: %d\n",
+				pdata->busy_gpio, ret);
+			goto err_iounmap;
+		}
+	}
+
+	mtd		= &nand->mtd;
+	chip		= &nand->chip;
+	mtd->priv	= chip;
+	mtd->owner	= THIS_MODULE;
+	mtd->name	= "jz4740-nand";
+
+	chip->ecc.hwctl		= jz_nand_hwctl;
+	chip->ecc.calculate	= jz_nand_calculate_ecc_rs;
+	chip->ecc.correct	= jz_nand_correct_ecc_rs;
+	chip->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
+	chip->ecc.size		= 512;
+	chip->ecc.bytes		= 9;
+	if (pdata)
+		chip->ecc.layout = pdata->ecc_layout;
+
+	chip->chip_delay = 50;
+	chip->cmd_ctrl = jz_nand_cmd_ctrl;
+
+	if (pdata && gpio_is_valid(pdata->busy_gpio))
+		chip->dev_ready = jz_nand_dev_ready;
+
+	chip->IO_ADDR_R = JZ_NAND_DATA_ADDR;
+	chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+	nand->pdata = pdata;
+	platform_set_drvdata(pdev, nand);
+
+	ret = nand_scan_ident(mtd, 1, NULL);
+	if (ret) {
+		dev_err(&pdev->dev,  "Failed to scan nand\n");
+		goto err_gpio_free;
+	}
+
+	if (pdata && pdata->ident_callback) {
+		pdata->ident_callback(pdev, chip, &pdata->partitions,
+					&pdata->num_partitions);
+	}
+
+	ret = nand_scan_tail(mtd);
+	if (ret) {
+		dev_err(&pdev->dev,  "Failed to scan nand\n");
+		goto err_gpio_free;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+	num_partitions = parse_mtd_partitions(mtd, part_probes,
+						&partition_info, 0);
+#endif
+	if (num_partitions <= 0 && pdata) {
+		num_partitions = pdata->num_partitions;
+		partition_info = pdata->partitions;
+	}
+
+	if (num_partitions > 0)
+		ret = add_mtd_partitions(mtd, partition_info, num_partitions);
+	else
+#endif
+	ret = add_mtd_device(mtd);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add mtd device\n");
+		goto err_nand_release;
+	}
+
+	dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
+
+	return 0;
+err_nand_release:
+	nand_release(&nand->mtd);
+err_gpio_free:
+	platform_set_drvdata(pdev, NULL);
+	gpio_free(pdata->busy_gpio);
+err_iounmap:
+	iounmap(nand->base);
+err_release_mem:
+	release_mem_region(nand->mem->start, resource_size(nand->mem));
+err_free:
+	kfree(nand);
+	return ret;
+}
+
+static void __devexit jz_nand_remove(struct platform_device *pdev)
+{
+	struct jz_nand *nand = platform_get_drvdata(pdev);
+
+	nand_release(&nand->mtd);
+
+	iounmap(nand->base);
+
+	release_mem_region(nand->mem->start, resource_size(nand->mem));
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(nand);
+}
+
+struct platform_driver jz_nand_driver = {
+	.probe = jz_nand_probe,
+	.remove = __devexit_p(jz_nand_probe),
+	.driver = {
+		.name = "jz4740-nand",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init jz_nand_init(void)
+{
+	return platform_driver_register(&jz_nand_driver);
+}
+module_init(jz_nand_init);
+
+static void __exit jz_nand_exit(void)
+{
+	platform_driver_unregister(&jz_nand_driver);
+}
+module_exit(jz_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars at metafoo.de>");
+MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC");
+MODULE_ALIAS("platform:jz4740-nand");
diff --git a/include/linux/mtd/jz4740_nand.h b/include/linux/mtd/jz4740_nand.h
new file mode 100644
index 0000000..379f9b6
--- /dev/null
+++ b/include/linux/mtd/jz4740_nand.h
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars at metafoo.de>
+ *  JZ4740 SoC NAND controller driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __JZ_NAND_H__
+#define __JZ_NAND_H__
+
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+struct jz_nand_platform_data {
+	int			num_partitions;
+	struct mtd_partition	*partitions;
+
+	struct nand_ecclayout	*ecc_layout;
+
+	unsigned int busy_gpio;
+
+	void (*ident_callback)(struct platform_device *, struct nand_chip *,
+				struct mtd_partition **, int *num_partitions);
+};
+
+#endif
-- 
1.5.6.5



From agust at denx.de  Wed Jun  2 20:37:17 2010
From: agust at denx.de (Anatolij Gustschin)
Date: Thu,  3 Jun 2010 02:37:17 +0200
Subject: [PATCH] of/mtd: nand: fix build breakage in drivers
Message-ID: <1275525437-364-1-git-send-email-agust@denx.de>

Fixes build errors in drivers caused by the OF device_node
pointer being moved into struct device

Signed-off-by: Anatolij Gustschin <agust at denx.de>
---
 drivers/mtd/nand/fsl_upm.c       |   17 +++++++++--------
 drivers/mtd/nand/socrates_nand.c |    4 ++--
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 00aea6f..1312eda 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -232,7 +232,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
 	if (!fun)
 		return -ENOMEM;
 
-	ret = of_address_to_resource(ofdev->node, 0, &io_res);
+	ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res);
 	if (ret) {
 		dev_err(&ofdev->dev, "can't get IO base\n");
 		goto err1;
@@ -244,7 +244,8 @@ static int __devinit fun_probe(struct of_device *ofdev,
 		goto err1;
 	}
 
-	prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size);
+	prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset",
+			       &size);
 	if (!prop || size != sizeof(uint32_t)) {
 		dev_err(&ofdev->dev, "can't get UPM address offset\n");
 		ret = -EINVAL;
@@ -252,7 +253,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
 	}
 	fun->upm_addr_offset = *prop;
 
-	prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size);
+	prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size);
 	if (!prop || size != sizeof(uint32_t)) {
 		dev_err(&ofdev->dev, "can't get UPM command offset\n");
 		ret = -EINVAL;
@@ -260,7 +261,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
 	}
 	fun->upm_cmd_offset = *prop;
 
-	prop = of_get_property(ofdev->node,
+	prop = of_get_property(ofdev->dev.of_node,
 			       "fsl,upm-addr-line-cs-offsets", &size);
 	if (prop && (size / sizeof(uint32_t)) > 0) {
 		fun->mchip_count = size / sizeof(uint32_t);
@@ -276,7 +277,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
 
 	for (i = 0; i < fun->mchip_count; i++) {
 		fun->rnb_gpio[i] = -1;
-		rnb_gpio = of_get_gpio(ofdev->node, i);
+		rnb_gpio = of_get_gpio(ofdev->dev.of_node, i);
 		if (rnb_gpio >= 0) {
 			ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev));
 			if (ret) {
@@ -292,13 +293,13 @@ static int __devinit fun_probe(struct of_device *ofdev,
 		}
 	}
 
-	prop = of_get_property(ofdev->node, "chip-delay", NULL);
+	prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
 	if (prop)
 		fun->chip_delay = *prop;
 	else
 		fun->chip_delay = 50;
 
-	prop = of_get_property(ofdev->node, "fsl,upm-wait-flags", &size);
+	prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
 	if (prop && size == sizeof(uint32_t))
 		fun->wait_flags = *prop;
 	else
@@ -315,7 +316,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
 	fun->dev = &ofdev->dev;
 	fun->last_ctrl = NAND_CLE;
 
-	ret = fun_chip_init(fun, ofdev->node, &io_res);
+	ret = fun_chip_init(fun, ofdev->dev.of_node, &io_res);
 	if (ret)
 		goto err2;
 
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 884852d..cc728b1 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -183,7 +183,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
 		return -ENOMEM;
 	}
 
-	host->io_base = of_iomap(ofdev->node, 0);
+	host->io_base = of_iomap(ofdev->dev.of_node, 0);
 	if (host->io_base == NULL) {
 		printk(KERN_ERR "socrates_nand: ioremap failed\n");
 		kfree(host);
@@ -244,7 +244,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
 #ifdef CONFIG_MTD_OF_PARTS
 	if (num_partitions == 0) {
 		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-							 ofdev->node,
+							 ofdev->dev.of_node,
 							 &partitions);
 		if (num_partitions < 0) {
 			res = num_partitions;
-- 
1.7.0.4



From akshayts at yahoo.co.in  Thu Jun  3 04:08:28 2010
From: akshayts at yahoo.co.in (akshay st)
Date: Thu, 3 Jun 2010 01:08:28 -0700 (PDT)
Subject: UBIFS and mkfs.ubifs Security Extended attribute support patch
	available?
Message-ID: <439695.63477.qm@web94901.mail.in2.yahoo.com>

Hi Artem,
Sending message again, because i had to send in plain text.
I was looking for a patch to support Security extended attribute
support for UBIFS in kernel and mkfs.ubifs. Also i dont understand
what security extended attribute to write in mkfs.ubifs. Can u give me
some insight, or if there is some link which tells the same.
If there is no patch available i was looking to implement it. Can u please advise me.

Warm Regards,
Akshay





From barnes.leo at gmail.com  Thu Jun  3 10:02:15 2010
From: barnes.leo at gmail.com (Leo Barnes)
Date: Thu, 3 Jun 2010 16:02:15 +0200
Subject: CRC error when mounting UBIFS
Message-ID: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>

Hello!

I am trying to create and mount an UBIFS partition and get the
following error when trying to mount it:
<7>[  397.117065] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 490:0
<7>[  397.117218] UBIFS DBG (pid 438): ubifs_scan: look at LEB 490:0
(126976 bytes left)
<7>[  397.117401] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  397.117614] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 490 at offset 0
<3>[  397.119598] UBIFS error (pid 438): check_lpt_crc: invalid crc in
LPT node: crc 0 calc 90d1

This is what I have done:
1. I have compiled the kernel (2.6.32, msm-android) with paranoid UBI
checks, UBIFS debug level 3 and with UBIFS extra checks.
2. I have erased the partition with 'flash_eraseall /dev/mtd4' (I
wanted a completely clean partition so I know the fault is not with
ubiformat)
3. I have attached the partition with 'ubiattach /dev/ubi_ctrl -m 4'
4. I have created a ubi volume with 'ubivolume /dev/ubi0 -N ubivol -m'

These steps work flawlessly, but when I then try to mount the volume
with 'mount -t ubifs ubi0!ubivol /ubivol', I get the error message
shown above.

Any ideas on how to fix it? When I disable the UBIFS extra checks, I
can mount the volume, but it gets corrupted after a while. I find it
odd that I get CRC errors since the ubi-volume and the ubifs
filesystem is created by the kernel.

See below for more extensive kernel logs.
Best regards,
//Leo

'ubiattach /dev/ubi_ctrl -m 4':
UBI device number 0, total 756 LEBs (95993856 bytes, 91.5 MiB),
available 745 LEBs (94597120 bytes, 90.2 MiB), LEB size 126976 bytes
(124.0 KiB)

dmesg for 'ubiattach /dev/ubi_ctrl -m 4':
----------------------------------------
<5>[  189.954956] UBI: attaching mtd4 to ubi0
<7>[  189.955322] UBI DBG (pid 417): io_init: min_io_size      2048
<7>[  189.955932] UBI DBG (pid 417): io_init: hdrs_min_io_size 2048
<7>[  189.956268] UBI DBG (pid 417): io_init: ec_hdr_alsize    2048
<7>[  189.956878] UBI DBG (pid 417): io_init: vid_hdr_alsize   2048
<7>[  189.957244] UBI DBG (pid 417): io_init: vid_hdr_offset   2048
<7>[  189.957855] UBI DBG (pid 417): io_init: vid_hdr_aloffset 2048
<7>[  189.958190] UBI DBG (pid 417): io_init: vid_hdr_shift    0
<7>[  189.958831] UBI DBG (pid 417): io_init: leb_start        4096
<7>[  189.959167] UBI DBG (pid 417): io_init: max_erroneous    76
<5>[  189.961547] UBI: physical eraseblock size:   131072 bytes (128 KiB)
<5>[  189.961914] UBI: logical eraseblock size:    126976 bytes
<5>[  189.962860] UBI: smallest flash I/O unit:    2048
<5>[  189.963195] UBI: VID header offset:          2048 (aligned 2048)
<5>[  189.964111] UBI: data offset:                4096
<7>[  190.764221] UBI DBG (pid 417): ubi_scan: scanning is finished
<5>[  190.764556] UBI: empty MTD device detected
<5>[  190.888336] UBI: create volume table (copy #1)
<5>[  190.957275] UBI: create volume table (copy #2)
<5>[  191.038269] UBI: attached mtd4 to ubi0
<5>[  191.038604] UBI: MTD device name:            "cache"
<5>[  191.038940] UBI: MTD device size:            95 MiB
<5>[  191.039550] UBI: number of good PEBs:        756
<5>[  191.040466] UBI: number of bad PEBs:         4
<5>[  191.041076] UBI: max. allowed volumes:       128
<5>[  191.041412] UBI: wear-leveling threshold:    4096
<5>[  191.041748] UBI: number of internal volumes: 1
<5>[  191.042358] UBI: number of user volumes:     0
<5>[  191.042694] UBI: available PEBs:             745
<5>[  191.043334] UBI: total number of reserved PEBs: 11
<5>[  191.043670] UBI: number of PEBs reserved for bad PEB handling: 7
<5>[  191.044281] UBI: max/mean erase counter: 0/0
<5>[  191.044616] UBI: image sequence number: 0
<5>[  191.044952] UBI: background thread "ubi_bgt0d" started, PID 418
----------------------------------------

'ubivolume /dev/ubi0 -N ubivol -m':
Set volume size to 94597120
Volume ID 0, size 745 LEBs (94597120 bytes, 90.2 MiB), LEB size 126976
bytes (124.0 KiB), dynamic, name "ubivol", alignment 1

dmesg for 'ubivolume /dev/ubi0 -N ubivol -m':
----------------------------------------
nothing
----------------------------------------

'mount -t ubifs ubi0!ubivol /ubivol':
mount: mounting ubi0!ubivol on ubivol failed: Invalid argument

dmesg for 'mount -t ubifs ubi0!ubivol /ubivol':
----------------------------------------
<7>[  395.754272] UBIFS DBG (pid 438): ubifs_get_sb: name ubi0!ubivol,
flags 0x8000
<7>[  395.754669] UBIFS DBG (pid 438): ubifs_get_sb: opened ubi0_0
<7>[  395.759246] UBIFS DBG (pid 438): set_ltab: LEB 7 free 126976
dirty 0 to 122880 213
<7>[  395.814483] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: space_bits 14
<7>[  395.814849] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: lpt_lnum_bits 2
<7>[  395.815460] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: lpt_offs_bits 17
<7>[  395.815826] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: lpt_spc_bits 17
<7>[  395.816436] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: pcnt_bits 8
<7>[  395.817077] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: lnum_bits 10
<7>[  395.817413] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: pnode_sz 17
<7>[  395.818023] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: nnode_sz 12
<7>[  395.818359] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: ltab_sz 11
<7>[  395.819000] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: lsave_sz 323
<7>[  395.819335] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: lsave_cnt 256
<7>[  395.820037] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: lpt_hght 4
<7>[  395.820373] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: big_lpt 0
<7>[  395.820983] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: LPT root
is at 7:3860
<7>[  395.821624] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: LPT head
is at 7:4096
<7>[  395.821960] UBIFS DBG (pid 438): ubifs_create_dflt_lpt: LPT ltab
is at 7:3872
<7>[  395.822692] UBIFS DBG (pid 438): create_default_filesystem: LEB
Properties Tree created (LEBs 7-8)
<7>[  395.823547] UBIFS DBG (pid 438): ubifs_write_node: LEB 0:0,
superblock node, length 4096 (aligned 4096)
<7>[  395.879119] UBIFS DBG (pid 438): create_default_filesystem:
default superblock created at LEB 0:0
<7>[  395.879577] UBIFS DBG (pid 438): ubifs_write_node: LEB 1:0,
master node, length 512 (aligned 2048)
<7>[  395.932678] UBIFS DBG (pid 438): ubifs_write_node: LEB 2:0,
master node, length 512 (aligned 2048)
<7>[  395.985870] UBIFS DBG (pid 438): create_default_filesystem:
default master node created at LEB 1:0
<7>[  395.986572] UBIFS DBG (pid 438): ubifs_write_node: LEB 11:0,
indexing node, length 48 (aligned 2048)
<7>[  396.039764] UBIFS DBG (pid 438): create_default_filesystem:
default root indexing node created LEB 11:0
<7>[  396.040222] UBIFS DBG (pid 438): ubifs_write_node: LEB 12:0,
inode node, length 160 (aligned 2048)
<7>[  396.093170] UBIFS DBG (pid 438): create_default_filesystem: root
inode created at LEB 12:0
<7>[  396.093902] UBIFS DBG (pid 438): ubifs_write_node: LEB 3:0,
commit start node, length 32 (aligned 2048)
<5>[  396.147125] UBIFS: default file-system created
<7>[  396.147613] UBIFS DBG (pid 438): ubifs_read_node: LEB 0:0,
superblock node, length 4096
<7>[  396.150421] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 1:0
<7>[  396.150878] UBIFS DBG (pid 439): ubifs_bg_thread: background
thread "ubifs_bgt0_0" started, PID 439
<7>[  396.195709] UBIFS DBG (pid 438): ubifs_scan: look at LEB 1:0
(126976 bytes left)
<7>[  396.196350] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning master node
<7>[  396.196746] UBIFS DBG (pid 438): ubifs_scan: look at LEB 1:512
(126464 bytes left)
<7>[  396.197357] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning padding node
<7>[  396.197998] UBIFS DBG (pid 438): ubifs_scan_a_node: 1508 bytes
padded, offset now 2048
<7>[  396.198364] UBIFS DBG (pid 438): ubifs_scan: look at LEB 1:2048
(124928 bytes left)
<7>[  396.198974] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.199615] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 1 at offset 2048
<7>[  396.201324] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 2:0
<7>[  396.246887] UBIFS DBG (pid 438): ubifs_scan: look at LEB 2:0
(126976 bytes left)
<7>[  396.247283] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning master node
<7>[  396.247985] UBIFS DBG (pid 438): ubifs_scan: look at LEB 2:512
(126464 bytes left)
<7>[  396.248657] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning padding node
<7>[  396.249023] UBIFS DBG (pid 438): ubifs_scan_a_node: 1508 bytes
padded, offset now 2048
<7>[  396.249725] UBIFS DBG (pid 438): ubifs_scan: look at LEB 2:2048
(124928 bytes left)
<7>[  396.251129] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.251495] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 2 at offset 2048
<7>[  396.253448] UBIFS DBG (pid 438): ubifs_read_node: LEB 11:0,
indexing node, length 48
<7>[  396.254638] UBIFS DBG (pid 438): ubifs_write_node: LEB 1:2048,
master node, length 512 (aligned 2048)
<7>[  396.257598] UBIFS DBG (pid 438): ubifs_write_node: LEB 2:2048,
master node, length 512 (aligned 2048)
<7>[  396.263519] UBIFS DBG (pid 438): lpt_init_rd: space_bits 14
<7>[  396.264160] UBIFS DBG (pid 438): lpt_init_rd: lpt_lnum_bits 2
<7>[  396.264526] UBIFS DBG (pid 438): lpt_init_rd: lpt_offs_bits 17
<7>[  396.265136] UBIFS DBG (pid 438): lpt_init_rd: lpt_spc_bits 17
<7>[  396.265502] UBIFS DBG (pid 438): lpt_init_rd: pcnt_bits 8
<7>[  396.266113] UBIFS DBG (pid 438): lpt_init_rd: lnum_bits 10
<7>[  396.266448] UBIFS DBG (pid 438): lpt_init_rd: pnode_sz 17
<7>[  396.267059] UBIFS DBG (pid 438): lpt_init_rd: nnode_sz 12
<7>[  396.267395] UBIFS DBG (pid 438): lpt_init_rd: ltab_sz 11
<7>[  396.268005] UBIFS DBG (pid 438): lpt_init_rd: lsave_sz 323
<7>[  396.268341] UBIFS DBG (pid 438): lpt_init_rd: lsave_cnt 256
<7>[  396.268951] UBIFS DBG (pid 438): lpt_init_rd: lpt_hght 4
<7>[  396.269287] UBIFS DBG (pid 438): lpt_init_rd: big_lpt 0
<7>[  396.269958] UBIFS DBG (pid 438): lpt_init_rd: LPT root is at 7:3860
<7>[  396.270324] UBIFS DBG (pid 438): lpt_init_rd: LPT head is at 7:4096
<7>[  396.270935] UBIFS DBG (pid 438): lpt_init_rd: LPT ltab is at 7:3872
<7>[  396.271514] UBIFS DBG (pid 438): ubifs_read_node: LEB 11:0,
indexing node, length 48
<7>[  396.273803] UBIFS DBG (pid 438): read_znode: LEB 11:0, level 0, 1 branch
<7>[  396.275024] UBIFS DBG (pid 438): ubifs_add_lpt_dirt: LEB 7 add 12 to 213
<7>[  396.275421] UBIFS DBG (pid 438): ubifs_add_lpt_dirt: LEB 7 add 11 to 225
<7>[  396.276550] UBIFS DBG (pid 438): ubifs_add_lpt_dirt: LEB 7 add 12 to 236
<7>[  396.277374] UBIFS DBG (pid 438): ubifs_add_lpt_dirt: LEB 7 add 12 to 248
<7>[  396.278533] UBIFS DBG (pid 438): ubifs_add_lpt_dirt: LEB 7 add 12 to 260
<7>[  396.279724] UBIFS DBG (pid 438): ubifs_lpt_lookup: LEB 11, free
124928, dirty 2000, flags 34
<7>[  396.280090] UBIFS DBG (pid 438): ubifs_lpt_lookup: LEB 12, free
124928, dirty 1888, flags 3
<7>[  396.280731] UBIFS DBG (pid 438): ubifs_add_lpt_dirt: LEB 7 add 17 to 272
<7>[  396.281372] UBIFS DBG (pid 438): ubifs_lpt_lookup_dirty: LEB 11,
free 124928, dirty 2000, flags 34
<7>[  396.281738] UBIFS DBG (pid 438): ubifs_change_lp: LEB 11, free
-2147483647, dirty -2147483647, flags 50
<7>[  396.282379] UBIFS DBG (pid 438): ubifs_lpt_lookup_dirty: LEB 11,
free 124928, dirty 2000, flags 34
<7>[  396.283172] UBIFS DBG (pid 438): ubifs_replay_journal: start
replaying the journal
<7>[  396.283813] UBIFS DBG (pid 438): replay_log_leb: replay log LEB 3:0
<7>[  396.284149] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 3:0
<7>[  396.330383] UBIFS DBG (pid 438): ubifs_scan: look at LEB 3:0
(126976 bytes left)
<7>[  396.330749] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning
commit start node
<7>[  396.331390] UBIFS DBG (pid 438): ubifs_scan: look at LEB 3:32
(126944 bytes left)
<7>[  396.332031] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning padding node
<7>[  396.332366] UBIFS DBG (pid 438): ubifs_scan_a_node: 1988 bytes
padded, offset now 2048
<7>[  396.333007] UBIFS DBG (pid 438): ubifs_scan: look at LEB 3:2048
(124928 bytes left)
<7>[  396.333618] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.333953] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 3 at offset 2048
<7>[  396.335845] UBIFS DBG (pid 438): replay_log_leb: commit start sqnum 7
<7>[  396.336486] UBIFS DBG (pid 438): replay_log_leb: replay log LEB 4:0
<7>[  396.336822] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 4:0
<7>[  396.337615] UBIFS DBG (pid 438): ubifs_scan: look at LEB 4:0
(126976 bytes left)
<7>[  396.337982] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.338592] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 4 at offset 0
<7>[  396.340118] UBIFS DBG (pid 438): ubifs_replay_journal: finished,
log head LEB 3:2048, max_sqnum 7, highest_inum 64
<7>[  396.341064] UBIFS DBG (pid 438): ubifs_lpt_lookup_dirty: LEB 13,
free 126976, dirty 0, flags 4
<7>[  396.341705] UBIFS DBG (pid 438): ubifs_change_lp: LEB 13, free
126976, dirty 0, flags 20
<7>[  396.342346] UBIFS DBG (pid 438): ubifs_lpt_lookup_dirty: LEB 13,
free 126976, dirty 0, flags 4
<7>[  396.343048] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 11:0
<7>[  396.388977] UBIFS DBG (pid 438): ubifs_scan: look at LEB 11:0
(126976 bytes left)
<7>[  396.389617] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning indexing node
<7>[  396.390075] UBIFS DBG (pid 438): ubifs_scan: look at LEB 11:48
(126928 bytes left)
<7>[  396.391265] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning padding node
<7>[  396.391906] UBIFS DBG (pid 438): ubifs_scan_a_node: 1972 bytes
padded, offset now 2048
<7>[  396.392242] UBIFS DBG (pid 438): ubifs_scan: look at LEB 11:2048
(124928 bytes left)
<7>[  396.392883] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.393493] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 11 at offset 2048
<7>[  396.395141] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 12:0
<7>[  396.440399] UBIFS DBG (pid 438): ubifs_scan: look at LEB 12:0
(126976 bytes left)
<7>[  396.441101] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning inode node
<7>[  396.441467] UBIFS DBG (pid 438): ubifs_scan: look at LEB 12:160
(126816 bytes left)
<7>[  396.442108] UBIFS DBG (pid 438): ubifs_scan_a_node: scanning padding node
<7>[  396.442443] UBIFS DBG (pid 438): ubifs_scan_a_node: 1860 bytes
padded, offset now 2048
<7>[  396.443084] UBIFS DBG (pid 438): ubifs_scan: look at LEB 12:2048
(124928 bytes left)
<7>[  396.443695] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.444061] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 12 at offset 2048
<7>[  396.445922] UBIFS DBG (pid 438): ubifs_lookup_level0: search key
(1, inode)
<7>[  396.446563] UBIFS DBG (pid 438): ubifs_lookup_level0: found 1, lvl 0, n 0
<7>[  396.446929] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 13:0
<7>[  396.447723] UBIFS DBG (pid 438): ubifs_scan: look at LEB 13:0
(126976 bytes left)
<7>[  396.448089] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.448699] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 13 at offset 0
<7>[  396.450469] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 14:0
<7>[  396.451019] UBIFS DBG (pid 438): ubifs_scan: look at LEB 14:0
(126976 bytes left)
<7>[  396.453002] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  396.453369] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 14 at offset 0
........ and so on ............
<7>[  397.117065] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 490:0
<7>[  397.117218] UBIFS DBG (pid 438): ubifs_scan: look at LEB 490:0
(126976 bytes left)
<7>[  397.117401] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
<7>[  397.117614] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
LEB 490 at offset 0
<3>[  397.119598] UBIFS error (pid 438): check_lpt_crc: invalid crc in
LPT node: crc 0 calc 90d1
<4>[  397.119903] [<c0028990>] (unwind_backtrace+0x0/0xd8) from
[<c0155be4>] (check_lpt_crc+0x8c/0xa4)
<4>[  397.120117] [<c0155be4>] (check_lpt_crc+0x8c/0xa4) from
[<c0155d04>] (unpack_pnode+0x108/0x110)
<4>[  397.120300] [<c0155d04>] (unpack_pnode+0x108/0x110) from
[<c0155ed4>] (scan_get_pnode+0x1c8/0x28c)
<4>[  397.120422] [<c0155ed4>] (scan_get_pnode+0x1c8/0x28c) from
[<c01567d8>] (ubifs_lpt_scan_nolock+0x45c/0x49c)
<4>[  397.120635] [<c01567d8>] (ubifs_lpt_scan_nolock+0x45c/0x49c)
from [<c015936c>] (dbg_check_lprops+0xa0/0x2d4)
<4>[  397.120849] [<c015936c>] (dbg_check_lprops+0xa0/0x2d4) from
[<c013a140>] (ubifs_fill_super+0xcf8/0x1dfc)
<4>[  397.121063] [<c013a140>] (ubifs_fill_super+0xcf8/0x1dfc) from
[<c013b52c>] (ubifs_get_sb+0x2e8/0x35c)
<4>[  397.121276] [<c013b52c>] (ubifs_get_sb+0x2e8/0x35c) from
[<c00b774c>] (vfs_kern_mount+0x4c/0xd0)
<4>[  397.121490] [<c00b774c>] (vfs_kern_mount+0x4c/0xd0) from
[<c00b7814>] (do_kern_mount+0x34/0xd8)
<4>[  397.121612] [<c00b7814>] (do_kern_mount+0x34/0xd8) from
[<c00cf4e8>] (do_mount+0x73c/0x7b8)
<4>[  397.121826] [<c00cf4e8>] (do_mount+0x73c/0x7b8) from
[<c00cf5e8>] (sys_mount+0x84/0xc4)
<4>[  397.122009] [<c00cf5e8>] (sys_mount+0x84/0xc4) from [<c0023f00>]
(ret_fast_syscall+0x0/0x2c)
<7>[  397.122833] UBIFS DBG (pid 439): ubifs_bg_thread: background
thread "ubifs_bgt0_0" stops
----------------------------------------


From matthieu.castet at parrot.com  Thu Jun  3 10:14:27 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Thu, 3 Jun 2010 16:14:27 +0200
Subject: [PATCH] ubi : generate random image_seq when attaching empty MTD
	device
Message-ID: <4C07B8C3.7080304@parrot.com>

generate random image_seq when attaching empty MTD device (kernel do the 
ubi formating).

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ubi.diff
Type: text/x-diff
Size: 706 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20100603/c8872fac/attachment.bin>

From dedekind1 at gmail.com  Thu Jun  3 10:25:18 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 03 Jun 2010 17:25:18 +0300
Subject: CRC error when mounting UBIFS
In-Reply-To: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
Message-ID: <1275575118.9729.2.camel@localhost.localdomain>

On Thu, 2010-06-03 at 16:02 +0200, Leo Barnes wrote:
> Hello!
> 
> I am trying to create and mount an UBIFS partition and get the
> following error when trying to mount it:
> <7>[  397.117065] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 490:0
> <7>[  397.117218] UBIFS DBG (pid 438): ubifs_scan: look at LEB 490:0
> (126976 bytes left)
> <7>[  397.117401] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
> <7>[  397.117614] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
> LEB 490 at offset 0
> <3>[  397.119598] UBIFS error (pid 438): check_lpt_crc: invalid crc in
> LPT node: crc 0 calc 90d1

Most of the time errors like this are because of problems in the driver
level, e.g., when the driver does not handle small or unaligned length
reads. Did you validate your MTD driver with MTD tests?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  3 10:25:56 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 03 Jun 2010 17:25:56 +0300
Subject: [PATCH] ubi : generate random image_seq when attaching empty
	MTD device
In-Reply-To: <4C07B8C3.7080304@parrot.com>
References: <4C07B8C3.7080304@parrot.com>
Message-ID: <1275575156.9729.3.camel@localhost.localdomain>

On Thu, 2010-06-03 at 16:14 +0200, Matthieu CASTET wrote:
> generate random image_seq when attaching empty MTD device (kernel do the 
> ubi formating).
> 
> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>

Looks OK, I'll push it to the UBI tree as soon as I have time - very
busy right now, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  3 10:28:49 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 03 Jun 2010 17:28:49 +0300
Subject: UBIFS and mkfs.ubifs Security Extended attribute support patch
	available?
In-Reply-To: <439695.63477.qm@web94901.mail.in2.yahoo.com>
References: <439695.63477.qm@web94901.mail.in2.yahoo.com>
Message-ID: <1275575329.9729.4.camel@localhost.localdomain>

On Thu, 2010-06-03 at 01:08 -0700, akshay st wrote:
> Hi Artem,
> Sending message again, because i had to send in plain text.
> I was looking for a patch to support Security extended attribute
> support for UBIFS in kernel and mkfs.ubifs. Also i dont understand
> what security extended attribute to write in mkfs.ubifs. Can u give me
> some insight, or if there is some link which tells the same.
> If there is no patch available i was looking to implement it. Can u please advise me.

I guess you should read this discussion:

http://lists.infradead.org/pipermail/linux-mtd/2009-February/024488.html

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From c-d.hailfinger.devel.2006 at gmx.net  Thu Jun  3 10:44:00 2010
From: c-d.hailfinger.devel.2006 at gmx.net (Carl-Daniel Hailfinger)
Date: Thu, 03 Jun 2010 16:44:00 +0200
Subject: Do we remove from jedec_probe.c?
In-Reply-To: <20100526175320.GD24167@pengutronix.de>
References: <20100526175320.GD24167@pengutronix.de>
Message-ID: <4C07BFB0.2060107@gmx.net>

Hi,

On 26.05.2010 19:53, Wolfram Sang wrote:
> now that Guillaume introduced cfi-support for some SST-flashes, I wonder if
> those can be removed from jedec_probe.c? Or should they stay for
> backward-compatibility?
>   

The userspace flashrom utility is getting support for those big SST NOR
flashes soon, so depending on whether you want these chips to host a
file system, flashrom may be an option.

Regards,
Carl-Daniel

-- 
http://www.hailfinger.org/



From barnes.leo at gmail.com  Thu Jun  3 11:14:00 2010
From: barnes.leo at gmail.com (Leo Barnes)
Date: Thu, 3 Jun 2010 17:14:00 +0200
Subject: CRC error when mounting UBIFS
In-Reply-To: <1275575118.9729.2.camel@localhost.localdomain>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
Message-ID: <AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>

Hmm, ok. I would have thought the paranoid UBI checks would be able to
find driver related problems. I have however now tried creating and
mounting ubi/ubifs through nandsim on the device, so ubifs seems to be
working well.

I have tried mtd_readtest on the driver which fails when I allow
OOB-reads. Since the driver handles ECC in hardware and I dont need to
read the OOB-data for the sake of UBI/UBIFS, this should be no
problem. When removing the oob-reads from the test, it works
perfectly.

You are probably right that what fails is unaligned/short reads, since
this is exactly the functionality that I had to add to the driver.
Does any of the mtd-tests test these kinds of reads? Might be a good
addition if not.

Will perform some more debugging. Thanks for very fast replies!
//Leo


On Thu, Jun 3, 2010 at 4:25 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Thu, 2010-06-03 at 16:02 +0200, Leo Barnes wrote:
>> Hello!
>>
>> I am trying to create and mount an UBIFS partition and get the
>> following error when trying to mount it:
>> <7>[ ?397.117065] UBIFS DBG (pid 438): ubifs_start_scan: scan LEB 490:0
>> <7>[ ?397.117218] UBIFS DBG (pid 438): ubifs_scan: look at LEB 490:0
>> (126976 bytes left)
>> <7>[ ?397.117401] UBIFS DBG (pid 438): ubifs_scan_a_node: hit empty space
>> <7>[ ?397.117614] UBIFS DBG (pid 438): ubifs_end_scan: stop scanning
>> LEB 490 at offset 0
>> <3>[ ?397.119598] UBIFS error (pid 438): check_lpt_crc: invalid crc in
>> LPT node: crc 0 calc 90d1
>
> Most of the time errors like this are because of problems in the driver
> level, e.g., when the driver does not handle small or unaligned length
> reads. Did you validate your MTD driver with MTD tests?
>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>


From dedekind1 at gmail.com  Thu Jun  3 11:32:07 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 03 Jun 2010 18:32:07 +0300
Subject: CRC error when mounting UBIFS
In-Reply-To: <AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
	<AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
Message-ID: <1275579127.9729.6.camel@localhost.localdomain>

On Thu, 2010-06-03 at 17:14 +0200, Leo Barnes wrote:
> Hmm, ok. I would have thought the paranoid UBI checks would be able to
> find driver related problems. I have however now tried creating and
> mounting ubi/ubifs through nandsim on the device, so ubifs seems to be
> working well.

Well, with extra self-checks, UBI reads all it writes and verifies, but
since all writes are aligned, all UBI reads are aligned too.

> I have tried mtd_readtest on the driver which fails when I allow
> OOB-reads. Since the driver handles ECC in hardware and I dont need to
> read the OOB-data for the sake of UBI/UBIFS, this should be no
> problem. When removing the oob-reads from the test, it works
> perfectly.
> 
> You are probably right that what fails is unaligned/short reads, since
> this is exactly the functionality that I had to add to the driver.
> Does any of the mtd-tests test these kinds of reads? Might be a good
> addition if not.

I do not remember, you'd need to look into the test. And of course
patches are welcome.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  3 11:41:06 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 03 Jun 2010 18:41:06 +0300
Subject: CRC error when mounting UBIFS
In-Reply-To: <AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
	<AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
Message-ID: <1275579666.9729.8.camel@localhost.localdomain>

On Thu, 2010-06-03 at 17:14 +0200, Leo Barnes wrote:
> Hmm, ok. I would have thought the paranoid UBI checks would be able to
> find driver related problems. I have however now tried creating and
> mounting ubi/ubifs through nandsim on the device, so ubifs seems to be
> working well.
> 
> I have tried mtd_readtest on the driver which fails when I allow
> OOB-reads. Since the driver handles ECC in hardware and I dont need to
> read the OOB-data for the sake of UBI/UBIFS, this should be no
> problem. When removing the oob-reads from the test, it works
> perfectly.
> 
> You are probably right that what fails is unaligned/short reads, since
> this is exactly the functionality that I had to add to the driver.
> Does any of the mtd-tests test these kinds of reads? Might be a good
> addition if not.

Note, the ltp reads in UBI may be even from odd addresses - check that
your drive handles this properly.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Fri Jun  4 01:15:00 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Fri, 04 Jun 2010 08:15:00 +0300
Subject: UBIFS and mkfs.ubifs Security Extended attribute support patch
	available?
In-Reply-To: <934572.90077.qm@web94913.mail.in2.yahoo.com>
References: <934572.90077.qm@web94913.mail.in2.yahoo.com>
Message-ID: <1275628500.25847.4.camel@localhost>

On Thu, 2010-06-03 at 17:32 +0200, ext akshay st wrote:
> Hi Artem
>  I understand now that it is not completely supported,I also
>  wanted to know is there anything to be done in mkfs.ubifs
>  for security xattr. 

I do not know, you need to look at the sources and try.

> I feel I can just add
>  securityinitinode() while creating a new inode in Linux
>  kernel?

Probably, I do not have time to look at this now, but if you submit me
tested patches, I'll happily accept them.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From s-ghorai at ti.com  Fri Jun  4 03:40:03 2010
From: s-ghorai at ti.com (Sukumar Ghorai)
Date: Fri,  4 Jun 2010 13:10:03 +0530
Subject: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
In-Reply-To: <1275637205-489-1-git-send-email-s-ghorai@ti.com>
References: <Sukumar Ghorai <s-ghorai@ti.com>
	<1275637205-489-1-git-send-email-s-ghorai@ti.com>
Message-ID: <1275637205-489-2-git-send-email-s-ghorai@ti.com>

few functions added in gpmc module and to be used by other drivers like NAND.
E.g.: - ioctl function
      - ecc functions

Signed-off-by: Sukumar Ghorai <s-ghorai at ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |  219 ++++++++++++++++++++++++++++++--
 arch/arm/plat-omap/include/plat/gpmc.h |   33 +++++-
 drivers/mtd/nand/omap2.c               |    4 +-
 3 files changed, 239 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..48b5af0
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -46,8 +46,9 @@
 #define GPMC_ECC_CONFIG		0x1f4
 #define GPMC_ECC_CONTROL	0x1f8
 #define GPMC_ECC_SIZE_CONFIG	0x1fc
+#define GPMC_ECC1_RESULT        0x200
 
-#define GPMC_CS0		0x60
+#define GPMC_CS0_BASE		0x60
 #define GPMC_CS_SIZE		0x30
 
 #define GPMC_MEM_START		0x00000000
@@ -92,7 +93,8 @@ struct omap3_gpmc_regs {
 static struct resource	gpmc_mem_root;
 static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned		gpmc_cs_map;
+static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
+static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
 
 static void __iomem *gpmc_base;
 
@@ -108,11 +110,27 @@ static u32 gpmc_read_reg(int idx)
 	return __raw_readl(gpmc_base + idx);
 }
 
+static void gpmc_cs_write_byte(int cs, int idx, u8 val)
+{
+	void __iomem *reg_addr;
+
+	reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+	__raw_writeb(val, reg_addr);
+}
+
+static u8 gpmc_cs_read_byte(int cs, int idx)
+{
+	void __iomem *reg_addr;
+
+	reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+	return __raw_readb(reg_addr);
+}
+
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+	reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
 	__raw_writel(val, reg_addr);
 }
 
@@ -120,7 +138,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+	reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
 	return __raw_readl(reg_addr);
 }
 
@@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
 EXPORT_SYMBOL(gpmc_cs_free);
 
 /**
+ * gpmc_hwcontrol - hardware specific access (read/ write) control
+ * @cs: chip select number
+ * @cmd: command type
+ * @write: 1 for write; 0 for read
+ * @wval: value to write
+ * @rval: read pointer
+ */
+int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
+{
+	u32 regval = 0;
+
+	if (!write && !rval)
+		return -EINVAL;
+
+	switch (cmd) {
+	case GPMC_STATUS_BUFFER:
+		regval = gpmc_read_reg(GPMC_STATUS);
+		/* 1 : buffer is available to write */
+		*rval = regval & GPMC_STATUS_BUFF_EMPTY;
+		break;
+
+	case GPMC_GET_SET_IRQ_STATUS:
+		if (write)
+			gpmc_write_reg(GPMC_IRQSTATUS, wval);
+		else
+			*rval = gpmc_read_reg(GPMC_IRQSTATUS);
+		break;
+
+	case GPMC_PREFETCH_FIFO_CNT:
+		regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+		*rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
+		break;
+
+	case GPMC_PREFETCH_COUNT:
+		regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+		*rval = GPMC_PREFETCH_STATUS_COUNT(regval);
+		break;
+
+	case GPMC_CONFIG_WP:
+		regval = gpmc_read_reg(GPMC_CONFIG);
+		if (wval)
+			regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
+		else
+			regval |= GPMC_CONFIG_WRITEPROTECT;  /* WP is OFF */
+		gpmc_write_reg(GPMC_CONFIG, regval);
+		break;
+
+	case GPMC_CONFIG_RDY_BSY:
+		regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+		regval |= WR_RD_PIN_MONITORING;
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+		break;
+
+	case GPMC_CONFIG_DEV_SIZE:
+		regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+		regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+		break;
+
+	case GPMC_CONFIG_DEV_TYPE:
+		regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+		regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+		if (wval == GPMC_DEVICETYPE_NOR)
+			regval |= GPMC_CONFIG1_MUXADDDATA;
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+		break;
+
+	case GPMC_NAND_COMMAND:
+		gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
+		break;
+
+	case GPMC_NAND_ADDRESS:
+		gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
+		break;
+
+	case GPMC_NAND_DATA:
+		if (write)
+			gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
+		else
+			*rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
+		break;
+
+	default:
+		printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(gpmc_hwcontrol);
+
+/**
  * gpmc_prefetch_enable - configures and starts prefetch transfer
- * @cs: nand cs (chip select) number
+ * @cs: cs (chip select) number
  * @dma_mode: dma mode enable (1) or disable (0)
  * @u32_count: number of bytes to be transferred
  * @is_write: prefetch read(0) or write post(1) mode
@@ -428,7 +538,6 @@ EXPORT_SYMBOL(gpmc_cs_free);
 int gpmc_prefetch_enable(int cs, int dma_mode,
 				unsigned int u32_count, int is_write)
 {
-	uint32_t prefetch_config1;
 
 	if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
 		/* Set the amount of bytes to be prefetched */
@@ -437,17 +546,17 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
 		/* Set dma/mpu mode, the prefetch read / post write and
 		 * enable the engine. Set which cs is has requested for.
 		 */
-		prefetch_config1 = ((cs << CS_NUM_SHIFT) |
+		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
 					PREFETCH_FIFOTHRESHOLD |
 					ENABLE_PREFETCH |
 					(dma_mode << DMA_MPU_MODE) |
-					(0x1 & is_write));
-		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
+					(0x1 & is_write)));
+
+		/*  Start the prefetch engine */
+		gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
 	} else {
 		return -EBUSY;
 	}
-	/*  Start the prefetch engine */
-	gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
 
 	return 0;
 }
@@ -456,13 +565,22 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
 /**
  * gpmc_prefetch_reset - disables and stops the prefetch engine
  */
-void gpmc_prefetch_reset(void)
+int gpmc_prefetch_reset(int cs)
 {
+	u32 config1;
+
+	/* check if the same module/cs is trying to reset */
+	config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
+	if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs)
+		return -EINVAL;
+
 	/* Stop the PFPW engine */
 	gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
 
 	/* Reset/disable the PFPW engine */
 	gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
+
+	return 0;
 }
 EXPORT_SYMBOL(gpmc_prefetch_reset);
 
@@ -615,3 +733,80 @@ void omap3_gpmc_restore_context(void)
 	}
 }
 #endif /* CONFIG_ARCH_OMAP3 */
+
+/**
+ * gpmc_enable_hwecc - enable hardware ecc functionality
+ * @cs: chip select number
+ * @mode: read/write mode
+ * @dev_width: device bus width(1 for x16, 0 for x8)
+ * @ecc_size: bytes for which ECC will be generated
+ */
+int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
+{
+	unsigned int val;
+
+	/* check if ecc module is in used */
+	if (gpmc_ecc_used != -EINVAL)
+		return -EINVAL;
+
+	gpmc_ecc_used = cs;
+
+	/* clear ecc and enable bits */
+	val = ((0x00000001<<8) | 0x00000001);
+	gpmc_write_reg(GPMC_ECC_CONTROL, val);
+
+	/* program ecc and result sizes */
+	val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
+	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
+
+	switch (mode) {
+	case GPMC_ECC_READ:
+		gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+		break;
+	case GPMC_ECC_READSYN:
+		 gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
+		break;
+	case GPMC_ECC_WRITE:
+		gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+		break;
+	default:
+		printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
+		break;
+	}
+
+	/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+	val = (dev_width << 7) | (cs << 1) | (0x1);
+	gpmc_write_reg(GPMC_ECC_CONFIG, val);
+	return 0;
+}
+
+/**
+ * gpmc_calculate_ecc - generate non-inverted ecc bytes
+ * @cs: chip select number
+ * @dat: data pointer over which ecc is computed
+ * @ecc_code: ecc code buffer
+ *
+ * Using non-inverted ECC is considered ugly since writing a blank
+ * page (padding) will clear the ECC bytes. This is not a problem as long
+ * no one is trying to write data on the seemingly unused page. Reading
+ * an erased page will produce an ECC mismatch between generated and read
+ * ECC bytes that has to be dealt with separately.
+ */
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
+{
+	unsigned int val = 0x0;
+
+	if (gpmc_ecc_used != cs)
+		return -EINVAL;
+
+	/* read ecc result */
+	val = gpmc_read_reg(GPMC_ECC1_RESULT);
+	*ecc_code++ = val;          /* P128e, ..., P1e */
+	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
+	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+	gpmc_ecc_used = -EINVAL;
+	return 0;
+}
+
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..8a1e9d9
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -27,8 +27,24 @@
 
 #define GPMC_CONFIG		0x50
 #define GPMC_STATUS		0x54
-#define GPMC_CS0_BASE		0x60
-#define GPMC_CS_SIZE		0x30
+
+/* Control Commands */
+#define GPMC_CONFIG_WP		0x00000001
+#define GPMC_CONFIG_RDY_BSY	0x00000002
+#define GPMC_CONFIG_DEV_SIZE	0x00000003
+#define GPMC_CONFIG_DEV_TYPE	0x00000004
+#define GPMC_NAND_COMMAND	0x00000005
+#define GPMC_NAND_ADDRESS	0x00000006
+#define GPMC_NAND_DATA		0x00000007
+#define GPMC_STATUS_BUFFER	0x00000008 /* 1: buffer is available to write */
+#define GPMC_PREFETCH_FIFO_CNT	0x00000009 /* bytes available in FIFO for r/w */
+#define GPMC_PREFETCH_COUNT	0x0000000A /* remaining bytes to be read/write*/
+#define GPMC_GET_SET_IRQ_STATUS	0x0000000B
+
+/* ECC commands */
+#define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN	2 /* Reset before syndrom is read back */
 
 #define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
 #define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
@@ -56,6 +72,14 @@
 #define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
 #define GPMC_CONFIG7_CSVALID		(1 << 6)
 
+#define GPMC_DEVICETYPE_NOR		0
+#define GPMC_DEVICETYPE_NAND		2
+#define GPMC_CONFIG_WRITEPROTECT	0x00000010
+#define GPMC_STATUS_BUFF_EMPTY		0x00000001
+#define WR_RD_PIN_MONITORING		0x00600000
+#define GPMC_PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
+#define GPMC_PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
+
 /*
  * Note that all values in this struct are in nanoseconds, while
  * the register values are in gpmc_fck cycles.
@@ -108,10 +132,13 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);
 extern int gpmc_cs_reserved(int cs);
 extern int gpmc_prefetch_enable(int cs, int dma_mode,
 					unsigned int u32_count, int is_write);
-extern void gpmc_prefetch_reset(void);
+extern int gpmc_prefetch_reset(int cs);
 extern int gpmc_prefetch_status(void);
 extern void omap3_gpmc_save_context(void);
 extern void omap3_gpmc_restore_context(void);
 extern void gpmc_init(void);
+extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval);
 
+int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size);
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
 #endif
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ee87325..ec8eb31
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -319,7 +319,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 		} while (len);
 
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset();
+		gpmc_prefetch_reset(info->gpmc_cs);
 	}
 }
 
@@ -363,7 +363,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		}
 
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset();
+		gpmc_prefetch_reset(info->gpmc_cs);
 	}
 }
 


From s-ghorai at ti.com  Fri Jun  4 03:40:04 2010
From: s-ghorai at ti.com (Sukumar Ghorai)
Date: Fri,  4 Jun 2010 13:10:04 +0530
Subject: [PATCH v5 2/3] omap3 nand: cleanup virtual address usages
In-Reply-To: <1275637205-489-2-git-send-email-s-ghorai@ti.com>
References: <Sukumar Ghorai <s-ghorai@ti.com>
	<1275637205-489-1-git-send-email-s-ghorai@ti.com>
	<1275637205-489-2-git-send-email-s-ghorai@ti.com>
Message-ID: <1275637205-489-3-git-send-email-s-ghorai@ti.com>

This patch removes direct reference of gpmc address from generic nand platform code.
Nand platform code now uses wrapper functions which are implemented in gpmc module. 

Signed-off-by: Sukumar Ghorai <s-ghorai at ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c        |   39 ++----
 arch/arm/mach-omap2/gpmc.c             |    9 --
 arch/arm/plat-omap/include/plat/gpmc.h |    5 -
 arch/arm/plat-omap/include/plat/nand.h |    6 +-
 drivers/mtd/nand/omap2.c               |  225 +++++++++-----------------------
 5 files changed, 77 insertions(+), 207 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index e57fb29..80f5d94
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -19,8 +19,6 @@
 #include <plat/board.h>
 #include <plat/gpmc.h>
 
-#define WR_RD_PIN_MONITORING	0x00600000
-
 static struct omap_nand_platform_data *gpmc_nand_data;
 
 static struct resource gpmc_nand_resource = {
@@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void)
 	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
 
 	/* Configure GPMC */
-	gpmc_cs_write_reg(gpmc_nand_data->cs, GPMC_CS_CONFIG1,
-			GPMC_CONFIG1_DEVICESIZE(gpmc_nand_data->devsize) |
-			GPMC_CONFIG1_DEVICETYPE_NAND);
-
+	gpmc_hwcontrol(gpmc_nand_data->cs,
+			GPMC_CONFIG_DEV_SIZE, 1, gpmc_nand_data->devsize, NULL);
+	gpmc_hwcontrol(gpmc_nand_data->cs,
+			GPMC_CONFIG_DEV_TYPE, 1, GPMC_DEVICETYPE_NAND, NULL);
 	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
 	if (err)
 		return err;
@@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void)
 	return 0;
 }
 
-static int gpmc_nand_setup(void)
-{
-	struct device *dev = &gpmc_nand_device.dev;
-
-	/* Set timings in GPMC */
-	if (omap2_nand_gpmc_retime() < 0) {
-		dev_err(dev, "Unable to set gpmc timings\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
 {
-	unsigned int val;
 	int err	= 0;
 	struct device *dev = &gpmc_nand_device.dev;
 
 	gpmc_nand_data = _nand_data;
-	gpmc_nand_data->nand_setup = gpmc_nand_setup;
+	gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime;
 	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
 
 	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -112,19 +96,17 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
 		return err;
 	}
 
-	err = gpmc_nand_setup();
+	 /* Set timings in GPMC */
+	err = omap2_nand_gpmc_retime();
 	if (err < 0) {
-		dev_err(dev, "NAND platform setup failed: %d\n", err);
+		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
 		return err;
 	}
 
 	/* Enable RD PIN Monitoring Reg */
 	if (gpmc_nand_data->dev_ready) {
-		val  = gpmc_cs_read_reg(gpmc_nand_data->cs,
-						 GPMC_CS_CONFIG1);
-		val |= WR_RD_PIN_MONITORING;
-		gpmc_cs_write_reg(gpmc_nand_data->cs,
-						GPMC_CS_CONFIG1, val);
+		gpmc_hwcontrol(gpmc_nand_data->cs,
+					GPMC_CONFIG_RDY_BSY, 1, 1, NULL);
 	}
 
 	err = platform_device_register(&gpmc_nand_device);
@@ -140,3 +122,4 @@ out_free_cs:
 
 	return err;
 }
+
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 48b5af0..91e1526 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -584,15 +584,6 @@ int gpmc_prefetch_reset(int cs)
 }
 EXPORT_SYMBOL(gpmc_prefetch_reset);
 
-/**
- * gpmc_prefetch_status - reads prefetch status of engine
- */
-int  gpmc_prefetch_status(void)
-{
-	return gpmc_read_reg(GPMC_PREFETCH_STATUS);
-}
-EXPORT_SYMBOL(gpmc_prefetch_status);
-
 static void __init gpmc_mem_init(void)
 {
 	int cs;
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 8a1e9d9..ccbc530
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,9 +25,6 @@
 #define GPMC_CS_NAND_ADDRESS	0x20
 #define GPMC_CS_NAND_DATA	0x24
 
-#define GPMC_CONFIG		0x50
-#define GPMC_STATUS		0x54
-
 /* Control Commands */
 #define GPMC_CONFIG_WP		0x00000001
 #define GPMC_CONFIG_RDY_BSY	0x00000002
@@ -63,7 +60,6 @@
 #define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
 #define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
 #define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_DEVICETYPE_NAND    GPMC_CONFIG1_DEVICETYPE(2)
 #define GPMC_CONFIG1_MUXADDDATA         (1 << 9)
 #define GPMC_CONFIG1_TIME_PARA_GRAN     (1 << 4)
 #define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
@@ -133,7 +129,6 @@ extern int gpmc_cs_reserved(int cs);
 extern int gpmc_prefetch_enable(int cs, int dma_mode,
 					unsigned int u32_count, int is_write);
 extern int gpmc_prefetch_reset(int cs);
-extern int gpmc_prefetch_status(void);
 extern void omap3_gpmc_save_context(void);
 extern void omap3_gpmc_restore_context(void);
 extern void gpmc_init(void);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index f8efd54..6562cd0
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -21,13 +21,11 @@ struct omap_nand_platform_data {
 	int			(*dev_ready)(struct omap_nand_platform_data *);
 	int			dma_channel;
 	unsigned long		phys_base;
-	void __iomem		*gpmc_cs_baseaddr;
-	void __iomem		*gpmc_baseaddr;
 	int			devsize;
 };
 
-/* size (4 KiB) for IO mapping */
-#define	NAND_IO_SIZE	SZ_4K
+/* minimum size for IO mapping */
+#define	NAND_IO_SIZE	4
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 extern int gpmc_nand_init(struct omap_nand_platform_data *d);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ec8eb31..f9fa3cb
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -7,6 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#define CONFIG_MTD_NAND_OMAP_HWECC
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
@@ -23,20 +24,8 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 
-#define GPMC_IRQ_STATUS		0x18
-#define GPMC_ECC_CONFIG		0x1F4
-#define GPMC_ECC_CONTROL	0x1F8
-#define GPMC_ECC_SIZE_CONFIG	0x1FC
-#define GPMC_ECC1_RESULT	0x200
-
 #define	DRIVER_NAME	"omap2-nand"
 
-#define	NAND_WP_OFF	0
-#define NAND_WP_BIT	0x00000010
-
-#define	GPMC_BUF_FULL	0x00000001
-#define	GPMC_BUF_EMPTY	0x00000000
-
 #define NAND_Ecc_P1e		(1 << 0)
 #define NAND_Ecc_P2e		(1 << 1)
 #define NAND_Ecc_P4e		(1 << 2)
@@ -139,34 +128,11 @@ struct omap_nand_info {
 
 	int				gpmc_cs;
 	unsigned long			phys_base;
-	void __iomem			*gpmc_cs_baseaddr;
-	void __iomem			*gpmc_baseaddr;
-	void __iomem			*nand_pref_fifo_add;
 	struct completion		comp;
 	int				dma_ch;
 };
 
 /**
- * omap_nand_wp - This function enable or disable the Write Protect feature
- * @mtd: MTD device structure
- * @mode: WP ON/OFF
- */
-static void omap_nand_wp(struct mtd_info *mtd, int mode)
-{
-	struct omap_nand_info *info = container_of(mtd,
-						struct omap_nand_info, mtd);
-
-	unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
-
-	if (mode)
-		config &= ~(NAND_WP_BIT);	/* WP is ON */
-	else
-		config |= (NAND_WP_BIT);	/* WP is OFF */
-
-	__raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
-}
-
-/**
  * omap_hwcontrol - hardware specific access to control-lines
  * @mtd: MTD device structure
  * @cmd: command to device
@@ -181,31 +147,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
 	struct omap_nand_info *info = container_of(mtd,
 					struct omap_nand_info, mtd);
-	switch (ctrl) {
-	case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
-		info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
-						GPMC_CS_NAND_COMMAND;
-		info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
-						GPMC_CS_NAND_DATA;
-		break;
-
-	case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
-		info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
-						GPMC_CS_NAND_ADDRESS;
-		info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
-						GPMC_CS_NAND_DATA;
-		break;
-
-	case NAND_CTRL_CHANGE | NAND_NCE:
-		info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
-						GPMC_CS_NAND_DATA;
-		info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
-						GPMC_CS_NAND_DATA;
-		break;
-	}
 
-	if (cmd != NAND_CMD_NONE)
-		__raw_writeb(cmd, info->nand.IO_ADDR_W);
+	if (cmd != NAND_CMD_NONE) {
+		if (ctrl & NAND_CLE)
+			gpmc_hwcontrol(info->gpmc_cs,
+					GPMC_NAND_COMMAND, 1, cmd, NULL);
+
+		else if (ctrl & NAND_ALE)
+			gpmc_hwcontrol(info->gpmc_cs,
+					GPMC_NAND_ADDRESS, 1, cmd, NULL);
+
+		else /* NAND_NCE */
+			gpmc_hwcontrol(info->gpmc_cs,
+					GPMC_NAND_DATA, 1, cmd, NULL);
+	}
 }
 
 /**
@@ -232,11 +187,15 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
 	struct omap_nand_info *info = container_of(mtd,
 						struct omap_nand_info, mtd);
 	u_char *p = (u_char *)buf;
+	u32	status = 0;
 
 	while (len--) {
 		iowrite8(*p++, info->nand.IO_ADDR_W);
-		while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
-						GPMC_STATUS) & GPMC_BUF_FULL));
+		/* wait until buffer is available for write */
+		do {
+			gpmc_hwcontrol(info->gpmc_cs,
+					GPMC_STATUS_BUFFER, 0, 0, &status);
+		} while (!status);
 	}
 }
 
@@ -264,16 +223,17 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
 	struct omap_nand_info *info = container_of(mtd,
 						struct omap_nand_info, mtd);
 	u16 *p = (u16 *) buf;
-
+	u32	status = 0;
 	/* FIXME try bursts of writesw() or DMA ... */
 	len >>= 1;
 
 	while (len--) {
 		iowrite16(*p++, info->nand.IO_ADDR_W);
-
-		while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
-						GPMC_STATUS) & GPMC_BUF_FULL))
-			;
+		/* wait until buffer is available for write */
+		do {
+			gpmc_hwcontrol(info->gpmc_cs,
+					GPMC_STATUS_BUFFER, 0, 0, &status);
+		} while (!status);
 	}
 }
 
@@ -287,7 +247,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 {
 	struct omap_nand_info *info = container_of(mtd,
 						struct omap_nand_info, mtd);
-	uint32_t pfpw_status = 0, r_count = 0;
+	uint32_t r_count = 0;
 	int ret = 0;
 	u32 *p = (u32 *)buf;
 
@@ -310,14 +270,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 		else
 			omap_read_buf8(mtd, buf, len);
 	} else {
+		p = (u32 *) buf;
 		do {
-			pfpw_status = gpmc_prefetch_status();
-			r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
-			ioread32_rep(info->nand_pref_fifo_add, p, r_count);
+			gpmc_hwcontrol(info->gpmc_cs,
+				GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count);
+			r_count = r_count >> 2;
+			ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
 			p += r_count;
 			len -= r_count << 2;
 		} while (len);
-
 		/* disable and stop the PFPW engine */
 		gpmc_prefetch_reset(info->gpmc_cs);
 	}
@@ -334,13 +295,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 {
 	struct omap_nand_info *info = container_of(mtd,
 						struct omap_nand_info, mtd);
-	uint32_t pfpw_status = 0, w_count = 0;
+	uint32_t pref_count = 0, w_count = 0;
 	int i = 0, ret = 0;
-	u16 *p = (u16 *) buf;
+	u16 *p;
 
 	/* take care of subpage writes */
 	if (len % 2 != 0) {
-		writeb(*buf, info->nand.IO_ADDR_R);
+		writeb(*buf, info->nand.IO_ADDR_W);
 		p = (u16 *)(buf + 1);
 		len--;
 	}
@@ -354,14 +315,19 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		else
 			omap_write_buf8(mtd, buf, len);
 	} else {
-		pfpw_status = gpmc_prefetch_status();
-		while (pfpw_status & 0x3FFF) {
-			w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
+		p = (u16 *) buf;
+		while (len) {
+			gpmc_hwcontrol(info->gpmc_cs,
+					GPMC_PREFETCH_FIFO_CNT, 0, 0, &w_count);
+			w_count = w_count >> 1;
 			for (i = 0; (i < w_count) && len; i++, len -= 2)
-				iowrite16(*p++, info->nand_pref_fifo_add);
-			pfpw_status = gpmc_prefetch_status();
+				iowrite16(*p++, info->nand.IO_ADDR_W);
 		}
-
+		/* wait for data to flushed-out before reset the prefetch */
+		do {
+			gpmc_hwcontrol(info->gpmc_cs,
+				GPMC_PREFETCH_COUNT, 0, 0, &pref_count);
+		} while (pref_count);
 		/* disable and stop the PFPW engine */
 		gpmc_prefetch_reset(info->gpmc_cs);
 	}
@@ -451,8 +417,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	/* setup and start DMA using dma_addr */
 	wait_for_completion(&info->comp);
 
-	while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
-		;
+	do {
+		gpmc_hwcontrol(info->gpmc_cs,
+				GPMC_PREFETCH_COUNT, 0, 0, &prefetch_status);
+	} while (prefetch_status);
 	/* disable and stop the PFPW engine */
 	gpmc_prefetch_reset();
 
@@ -530,29 +498,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
 }
 
 #ifdef CONFIG_MTD_NAND_OMAP_HWECC
-/**
- * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
- * @mtd: MTD device structure
- */
-static void omap_hwecc_init(struct mtd_info *mtd)
-{
-	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
-							mtd);
-	struct nand_chip *chip = mtd->priv;
-	unsigned long val = 0x0;
-
-	/* Read from ECC Control Register */
-	val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-	/* Clear all ECC | Enable Reg1 */
-	val = ((0x00000001<<8) | 0x00000001);
-	__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-
-	/* Read from ECC Size Config Register */
-	val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
-	/* ECCSIZE1=512 | Select eccResultsize[0-3] */
-	val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
-	__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
-}
 
 /**
  * gen_true_ecc - This function will generate true ECC value
@@ -755,19 +700,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
-	unsigned long val = 0x0;
-	unsigned long reg;
-
-	/* Start Reading from HW ECC1_Result = 0x200 */
-	reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
-	val = __raw_readl(reg);
-	*ecc_code++ = val;          /* P128e, ..., P1e */
-	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
-	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
-	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
-	reg += 4;
-
-	return 0;
+	return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
 }
 
 /**
@@ -781,32 +714,10 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 							mtd);
 	struct nand_chip *chip = mtd->priv;
 	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
-	unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
-
-	switch (mode) {
-	case NAND_ECC_READ:
-		__raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-		/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
-		val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
-		break;
-	case NAND_ECC_READSYN:
-		 __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-		/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
-		val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
-		break;
-	case NAND_ECC_WRITE:
-		__raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-		/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
-		val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
-		break;
-	default:
-		DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
-					mode);
-		break;
-	}
 
-	__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
 }
+
 #endif
 
 /**
@@ -834,14 +745,10 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	else
 		timeo += (HZ * 20) / 1000;
 
-	this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
-						GPMC_CS_NAND_COMMAND;
-	this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
-
-	__raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
-
+	gpmc_hwcontrol(info->gpmc_cs,
+			GPMC_NAND_COMMAND, 1,  (NAND_CMD_STATUS & 0xFF), NULL);
 	while (time_before(jiffies, timeo)) {
-		status = __raw_readb(this->IO_ADDR_R);
+		gpmc_hwcontrol(info->gpmc_cs, GPMC_NAND_DATA, 0,  0, &status);
 		if (status & NAND_STATUS_READY)
 			break;
 		cond_resched();
@@ -855,22 +762,24 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
  */
 static int omap_dev_ready(struct mtd_info *mtd)
 {
+	unsigned int val = 0;
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
-	unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
 
+	gpmc_hwcontrol(info->gpmc_cs, GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
 	if ((val & 0x100) == 0x100) {
 		/* Clear IRQ Interrupt */
 		val |= 0x100;
 		val &= ~(0x0);
-		__raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+		gpmc_hwcontrol(info->gpmc_cs,
+			GPMC_GET_SET_IRQ_STATUS, 1, val, NULL);
 	} else {
 		unsigned int cnt = 0;
 		while (cnt++ < 0x1FF) {
 			if  ((val & 0x100) == 0x100)
 				return 0;
-			val = __raw_readl(info->gpmc_baseaddr +
-							GPMC_IRQ_STATUS);
+			gpmc_hwcontrol(info->gpmc_cs,
+				GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
 		}
 	}
 
@@ -901,8 +810,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
-	info->gpmc_baseaddr	= pdata->gpmc_baseaddr;
-	info->gpmc_cs_baseaddr	= pdata->gpmc_cs_baseaddr;
 	info->phys_base		= pdata->phys_base;
 
 	info->mtd.priv		= &info->nand;
@@ -913,7 +820,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
 	/* NAND write protect off */
-	omap_nand_wp(&info->mtd, NAND_WP_OFF);
+	gpmc_hwcontrol(info->gpmc_cs, GPMC_CONFIG_WP, 1, 0, NULL);
 
 	if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
 				pdev->dev.driver->name)) {
@@ -948,8 +855,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	}
 
 	if (use_prefetch) {
-		/* copy the virtual address of nand base for fifo access */
-		info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
 
 		info->nand.read_buf   = omap_read_buf_pref;
 		info->nand.write_buf  = omap_write_buf_pref;
@@ -989,8 +894,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->nand.ecc.correct		= omap_correct_data;
 	info->nand.ecc.mode		= NAND_ECC_HW;
 
-	/* init HW ECC */
-	omap_hwecc_init(&info->mtd);
 #else
 	info->nand.ecc.mode = NAND_ECC_SOFT;
 #endif
@@ -1040,7 +943,7 @@ static int omap_nand_remove(struct platform_device *pdev)
 
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
-	iounmap(info->nand_pref_fifo_add);
+	iounmap(info->nand.IO_ADDR_R);
 	kfree(&info->mtd);
 	return 0;
 }


From s-ghorai at ti.com  Fri Jun  4 03:40:05 2010
From: s-ghorai at ti.com (Sukumar Ghorai)
Date: Fri,  4 Jun 2010 13:10:05 +0530
Subject: [PATCH v5 3/3] omap3 nand: fix issue in board file to detect nand
In-Reply-To: <1275637205-489-3-git-send-email-s-ghorai@ti.com>
References: <Sukumar Ghorai <s-ghorai@ti.com>
	<1275637205-489-1-git-send-email-s-ghorai@ti.com>
	<1275637205-489-2-git-send-email-s-ghorai@ti.com>
	<1275637205-489-3-git-send-email-s-ghorai@ti.com>
Message-ID: <1275637205-489-4-git-send-email-s-ghorai@ti.com>

Board file modified for not to provide gpmc phys_base address to nand driver.
The gpmc_nand_init funciton is now used to detect the nand and required to
adopt _prob function as in nand/omap2.c

Signed-off-by: Sukumar Ghorai <s-ghorai at ti.com>
---
 arch/arm/mach-omap2/board-cm-t35.c         |   20 +-------------------
 arch/arm/mach-omap2/board-devkit8000.c     |   25 +------------------------
 arch/arm/mach-omap2/board-omap3beagle.c    |   24 +-----------------------
 arch/arm/mach-omap2/board-omap3touchbook.c |   25 +------------------------
 arch/arm/mach-omap2/board-overo.c          |   24 +-----------------------
 arch/arm/mach-omap2/board-sdp-flash.c      |    5 -----
 6 files changed, 5 insertions(+), 118 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index bc4c3f8..4870da2
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -61,8 +61,6 @@
 #define SB_T35_SMSC911X_GPIO	65
 
 #define NAND_BLOCK_SIZE		SZ_128K
-#define GPMC_CS0_BASE		0x60
-#define GPMC_CS0_BASE_ADDR	(OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE)
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <linux/smsc911x.h>
@@ -223,28 +221,12 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
 	.nr_parts		= ARRAY_SIZE(cm_t35_nand_partitions),
 	.dma_channel		= -1,	/* disable DMA in OMAP NAND driver */
 	.cs			= 0,
-	.gpmc_cs_baseaddr	= (void __iomem *)GPMC_CS0_BASE_ADDR,
-	.gpmc_baseaddr		= (void __iomem *)OMAP34XX_GPMC_VIRT,
 
 };
 
-static struct resource cm_t35_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device cm_t35_nand_device = {
-	.name		= "omap2-nand",
-	.id		= -1,
-	.num_resources	= 1,
-	.resource	= &cm_t35_nand_resource,
-	.dev		= {
-		.platform_data	= &cm_t35_nand_data,
-	},
-};
-
 static void __init cm_t35_init_nand(void)
 {
-	if (platform_device_register(&cm_t35_nand_device) < 0)
+	if (gpmc_nand_init(&cm_t35_nand_data) < 0)
 		pr_err("CM-T35: Unable to register NAND device\n");
 }
 #else
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 922b746..364511a
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,9 +58,6 @@
 #include "mux.h"
 #include "hsmmc.h"
 
-#define GPMC_CS0_BASE  0x60
-#define GPMC_CS_SIZE   0x30
-
 #define NAND_BLOCK_SIZE		SZ_128K
 
 #define OMAP_DM9000_GPIO_IRQ	25
@@ -104,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
 	.dma_channel	= -1,		/* disable DMA in OMAP NAND driver */
 };
 
-static struct resource devkit8000_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device devkit8000_nand_device = {
-	.name		= "omap2-nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &devkit8000_nand_data,
-	},
-	.num_resources	= 1,
-	.resource	= &devkit8000_nand_resource,
-};
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -581,8 +564,6 @@ static void __init devkit8000_flash_init(void)
 	u8 cs = 0;
 	u8 nandcs = GPMC_CS_NUM + 1;
 
-	u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
 	/* find out the chip-select on which NAND exists */
 	while (cs < GPMC_CS_NUM) {
 		u32 ret = 0;
@@ -604,13 +585,9 @@ static void __init devkit8000_flash_init(void)
 
 	if (nandcs < GPMC_CS_NUM) {
 		devkit8000_nand_data.cs = nandcs;
-		devkit8000_nand_data.gpmc_cs_baseaddr = (void *)
-			(gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
-		devkit8000_nand_data.gpmc_baseaddr = (void *)
-			(gpmc_base_add);
 
 		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (platform_device_register(&devkit8000_nand_device) < 0)
+		if (gpmc_nand_init(&devkit8000_nand_data) < 0)
 			printk(KERN_ERR "Unable to register NAND device\n");
 	}
 }
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 0ab0c26..befb5e3
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -48,9 +48,6 @@
 #include "mux.h"
 #include "hsmmc.h"
 
-#define GPMC_CS0_BASE  0x60
-#define GPMC_CS_SIZE   0x30
-
 #define NAND_BLOCK_SIZE		SZ_128K
 
 static struct mtd_partition omap3beagle_nand_partitions[] = {
@@ -93,20 +90,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = {
 	.dev_ready	= NULL,
 };
 
-static struct resource omap3beagle_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device omap3beagle_nand_device = {
-	.name		= "omap2-nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &omap3beagle_nand_data,
-	},
-	.num_resources	= 1,
-	.resource	= &omap3beagle_nand_resource,
-};
-
 /* DSS */
 
 static int beagle_enable_dvi(struct omap_dss_device *dssdev)
@@ -424,8 +407,6 @@ static void __init omap3beagle_flash_init(void)
 	u8 cs = 0;
 	u8 nandcs = GPMC_CS_NUM + 1;
 
-	u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
 	/* find out the chip-select on which NAND exists */
 	while (cs < GPMC_CS_NUM) {
 		u32 ret = 0;
@@ -447,12 +428,9 @@ static void __init omap3beagle_flash_init(void)
 
 	if (nandcs < GPMC_CS_NUM) {
 		omap3beagle_nand_data.cs = nandcs;
-		omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
-			(gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
-		omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
 
 		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (platform_device_register(&omap3beagle_nand_device) < 0)
+		if (gpmc_nand_init(&omap3beagle_nand_data) < 0)
 			printk(KERN_ERR "Unable to register NAND device\n");
 	}
 }
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index f05b867..bf8089f
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -54,9 +54,6 @@
 
 #include <asm/setup.h>
 
-#define GPMC_CS0_BASE  0x60
-#define GPMC_CS_SIZE   0x30
-
 #define NAND_BLOCK_SIZE		SZ_128K
 
 #define OMAP3_AC_GPIO		136
@@ -106,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
 	.dev_ready	= NULL,
 };
 
-static struct resource omap3touchbook_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device omap3touchbook_nand_device = {
-	.name		= "omap2-nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &omap3touchbook_nand_data,
-	},
-	.num_resources	= 1,
-	.resource	= &omap3touchbook_nand_resource,
-};
-
 #include "sdram-micron-mt46h32m32lf-6.h"
 
 static struct omap2_hsmmc_info mmc[] = {
@@ -458,8 +441,6 @@ static void __init omap3touchbook_flash_init(void)
 	u8 cs = 0;
 	u8 nandcs = GPMC_CS_NUM + 1;
 
-	u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
 	/* find out the chip-select on which NAND exists */
 	while (cs < GPMC_CS_NUM) {
 		u32 ret = 0;
@@ -481,13 +462,9 @@ static void __init omap3touchbook_flash_init(void)
 
 	if (nandcs < GPMC_CS_NUM) {
 		omap3touchbook_nand_data.cs = nandcs;
-		omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *)
-			(gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
-		omap3touchbook_nand_data.gpmc_baseaddr =
-						(void *) (gpmc_base_add);
 
 		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (platform_device_register(&omap3touchbook_nand_device) < 0)
+		if (gpmc_nand_init(&omap3touchbook_nand_data) < 0)
 			printk(KERN_ERR "Unable to register NAND device\n");
 	}
 }
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index d05ced5..9c51936
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -58,8 +58,6 @@
 #define OVERO_GPIO_USBH_NRESET	183
 
 #define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE  0x60
-#define GPMC_CS_SIZE   0x30
 
 #define OVERO_SMSC911X_CS      5
 #define OVERO_SMSC911X_GPIO    176
@@ -269,28 +267,11 @@ static struct omap_nand_platform_data overo_nand_data = {
 	.dma_channel = -1,	/* disable DMA in OMAP NAND driver */
 };
 
-static struct resource overo_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device overo_nand_device = {
-	.name		= "omap2-nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &overo_nand_data,
-	},
-	.num_resources	= 1,
-	.resource	= &overo_nand_resource,
-};
-
-
 static void __init overo_flash_init(void)
 {
 	u8 cs = 0;
 	u8 nandcs = GPMC_CS_NUM + 1;
 
-	u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
 	/* find out the chip-select on which NAND exists */
 	while (cs < GPMC_CS_NUM) {
 		u32 ret = 0;
@@ -312,12 +293,9 @@ static void __init overo_flash_init(void)
 
 	if (nandcs < GPMC_CS_NUM) {
 		overo_nand_data.cs = nandcs;
-		overo_nand_data.gpmc_cs_baseaddr = (void *)
-			(gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
-		overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
 
 		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (platform_device_register(&overo_nand_device) < 0)
+		if (gpmc_nand_init(&overo_nand_data) < 0)
 			printk(KERN_ERR "Unable to register NAND device\n");
 	}
 }
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
old mode 100644
new mode 100755
index 2d02632..2638c83
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -162,11 +162,6 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
 	sdp_nand_data.parts		= sdp_nand_parts.parts;
 	sdp_nand_data.nr_parts		= sdp_nand_parts.nr_parts;
 
-	sdp_nand_data.gpmc_cs_baseaddr	= (void *)(OMAP34XX_GPMC_VIRT +
-							GPMC_CS0_BASE +
-							cs * GPMC_CS_SIZE);
-	sdp_nand_data.gpmc_baseaddr	 = (void *) (OMAP34XX_GPMC_VIRT);
-
 	gpmc_nand_init(&sdp_nand_data);
 }
 #else


From s-ghorai at ti.com  Fri Jun  4 03:40:02 2010
From: s-ghorai at ti.com (Sukumar Ghorai)
Date: Fri,  4 Jun 2010 13:10:02 +0530
Subject: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
In-Reply-To: <Sukumar Ghorai <s-ghorai@ti.com>
References: <Sukumar Ghorai <s-ghorai@ti.com>
Message-ID: <1275637205-489-1-git-send-email-s-ghorai@ti.com>

   The following set of patches applies on top of for-next branch.
	http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
   Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board

   And these are the patches required to address the following input -
     1. The NAND driver needs to stop tinkering with the GPMC registers
	The omap General Purpose Memory Controller (GPMC) registers are omap
        specific, and not driver specific. Tinkering with these registers can
        cause issues with the other devices on the GPMC.

     2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
	Passing hardcoded GPMC virtual addressess is sure way to mess up things.
        This should all become unnecessary once the NAND drivers stops messing
        with the GPMC registers directly.
     Discussion: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg27630.html

   Changes in this series -
		Unused function removed.
		
  Functions related to ecc and prefetch engine are optimized.
  v4: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg29458.html

  Few functionality was missing  like - There should be some locking as only
   one chipselect can use the ECC or prefetch engine at a time. If you have
   NAND in two chipselects, bad things would happen.
  v3: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28715.html

  Additionally, it was needed to implement more functions for the platform
  init code to use.
  v2: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28467.html
	
  v1: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28164.html


Sukumar Ghorai (3):
	omap3 gpmc: functionality enhancement
	omap3 nand: cleanup virtual address usages
	omap3 nand: fix issue in board file to detect nand
 arch/arm/mach-omap2/board-cm-t35.c         |   20 +---
 arch/arm/mach-omap2/board-devkit8000.c     |   25 +---
 arch/arm/mach-omap2/board-omap3beagle.c    |   24 +---
 arch/arm/mach-omap2/board-omap3touchbook.c |   25 +---
 arch/arm/mach-omap2/board-overo.c          |   24 +---
 arch/arm/mach-omap2/board-sdp-flash.c      |    5 -
 arch/arm/mach-omap2/gpmc-nand.c            |   39 ++----
 arch/arm/mach-omap2/gpmc.c                 |  228 +++++++++++++++++++++++++---
 arch/arm/plat-omap/include/plat/gpmc.h     |   36 ++++-
 arch/arm/plat-omap/include/plat/nand.h     |    6 +-
 drivers/mtd/nand/omap2.c                   |  229 ++++++++--------------------
 11 files changed, 320 insertions(+), 341 deletions(-)



From barnes.leo at gmail.com  Fri Jun  4 12:18:26 2010
From: barnes.leo at gmail.com (Leo Barnes)
Date: Fri, 4 Jun 2010 18:18:26 +0200
Subject: CRC error when mounting UBIFS
In-Reply-To: <1275579127.9729.6.camel@localhost.localdomain>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
	<AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
	<1275579127.9729.6.camel@localhost.localdomain>
Message-ID: <AANLkTinzLo7e5sHOn7sFKRAZNZHWoi3TMMG-FslG-CVv@mail.gmail.com>

You were completely right that the errors were driver related. I
created a test that tested page-aligned/unaligned reads of different
lengths and then managed to spot the error in the driver. I will send
in the test once I have cleaned up the code a bit. Might be useful for
someone else.

A new question:
Background:
The driver in use in the device does all communication with the
NAND-chipset/controller via DMA. Some of the problems I had with the
driver was that UBI in some cases sends vmalloc'd buffers to the
mtd-driver for reading and writing which failed spectacularly (it
might have been kmalloc'd buffers that were not allocated with
GFP_DMA, I'm unsure if DMA would succeed in this case). Since I dont
know exactly how UBI manages it's memory buffers, my question might be
impossible to implement efficiently.

Question:
Would it be possible to make all buffers that are sent to mtd->read()
DMA-friendly?

Best regards,
//Leo

On Thu, Jun 3, 2010 at 5:32 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Thu, 2010-06-03 at 17:14 +0200, Leo Barnes wrote:
>> Hmm, ok. I would have thought the paranoid UBI checks would be able to
>> find driver related problems. I have however now tried creating and
>> mounting ubi/ubifs through nandsim on the device, so ubifs seems to be
>> working well.
>
> Well, with extra self-checks, UBI reads all it writes and verifies, but
> since all writes are aligned, all UBI reads are aligned too.
>
>> I have tried mtd_readtest on the driver which fails when I allow
>> OOB-reads. Since the driver handles ECC in hardware and I dont need to
>> read the OOB-data for the sake of UBI/UBIFS, this should be no
>> problem. When removing the oob-reads from the test, it works
>> perfectly.
>>
>> You are probably right that what fails is unaligned/short reads, since
>> this is exactly the functionality that I had to add to the driver.
>> Does any of the mtd-tests test these kinds of reads? Might be a good
>> addition if not.
>
> I do not remember, you'd need to look into the test. And of course
> patches are welcome.
>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>


From dedekind1 at gmail.com  Fri Jun  4 13:03:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 04 Jun 2010 20:03:15 +0300
Subject: CRC error when mounting UBIFS
In-Reply-To: <AANLkTinzLo7e5sHOn7sFKRAZNZHWoi3TMMG-FslG-CVv@mail.gmail.com>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
	<AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
	<1275579127.9729.6.camel@localhost.localdomain>
	<AANLkTinzLo7e5sHOn7sFKRAZNZHWoi3TMMG-FslG-CVv@mail.gmail.com>
Message-ID: <1275670996.9729.19.camel@localhost.localdomain>

On Fri, 2010-06-04 at 18:18 +0200, Leo Barnes wrote:
> You were completely right that the errors were driver related. I
> created a test that tested page-aligned/unaligned reads of different
> lengths and then managed to spot the error in the driver. I will send
> in the test once I have cleaned up the code a bit. Might be useful for
> someone else.

Could you please patch mtd_readtest and send the patch?

> A new question:
> Background:
> The driver in use in the device does all communication with the
> NAND-chipset/controller via DMA. Some of the problems I had with the
> driver was that UBI in some cases sends vmalloc'd buffers to the
> mtd-driver for reading and writing which failed spectacularly (it
> might have been kmalloc'd buffers that were not allocated with
> GFP_DMA, I'm unsure if DMA would succeed in this case). Since I dont
> know exactly how UBI manages it's memory buffers, my question might be
> impossible to implement efficiently.

Yes, both UBI and UBIFS use vmalloc() buffers when they manage whole
eraseblocks - e.g., in UBIFS garbage collector when scanning the
journal, or in UBI when moving eraseblocks for wear-leveling purposes.
The reason is that eraseblocks may be large (e.g., 256 KiB), and
kmalloc() that much of contiguous physical memory is prone to fail.

The way to fix this is to make UBI/UBIFS use arrays of pages instead. Or
array of 2, 4, 8, etc pages, or it may be flexible and contain a field
which describes the allocation order. And then UBI/UBIFS code should be
amended correspondingly.

This will need some effort, but I think a skilled engineer would do this
relatively quickly. We are not actively working on UBI/UBIFS now, so we
will unlikely implement this, but I'd be happy to help someone else to
do this.

Many people ask about small features like security xattrs, or NFS
support, or DMA friendliness, but it is strange that people want ready
solutions instead of investing a bit of time and just implementing this.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From barnes.leo at gmail.com  Fri Jun  4 13:35:27 2010
From: barnes.leo at gmail.com (Leo Barnes)
Date: Fri, 4 Jun 2010 19:35:27 +0200
Subject: CRC error when mounting UBIFS
In-Reply-To: <1275670996.9729.19.camel@localhost.localdomain>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
	<AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
	<1275579127.9729.6.camel@localhost.localdomain>
	<AANLkTinzLo7e5sHOn7sFKRAZNZHWoi3TMMG-FslG-CVv@mail.gmail.com>
	<1275670996.9729.19.camel@localhost.localdomain>
Message-ID: <AANLkTimUrdHmrf5hblunbpI3J24A6tMQj1tIIXbSQoIy@mail.gmail.com>

> The way to fix this is to make UBI/UBIFS use arrays of pages instead. Or
> array of 2, 4, 8, etc pages, or it may be flexible and contain a field
> which describes the allocation order. And then UBI/UBIFS code should be
> amended correspondingly.
>
> This will need some effort, but I think a skilled engineer would do this
> relatively quickly. We are not actively working on UBI/UBIFS now, so we
> will unlikely implement this, but I'd be happy to help someone else to
> do this.
>
> Many people ask about small features like security xattrs, or NFS
> support, or DMA friendliness, but it is strange that people want ready
> solutions instead of investing a bit of time and just implementing this.

Sounds good, I might take a crack at it, I have been looking for some
way to contribute to the linux kernel.

Have I understood the UBI code correctly in that only the
ubi->peb_buf1, ubi->peb_buf2 and ubi->dbg_peb_buf are ever sent to the
mtd->read/write functions? Currently at home and dont really have
anything to test code in.

Does UBIFS ever access the mtd-layer directly?

Best regards,
//Leo


From dedekind1 at gmail.com  Fri Jun  4 14:01:53 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 04 Jun 2010 21:01:53 +0300
Subject: CRC error when mounting UBIFS
In-Reply-To: <AANLkTimUrdHmrf5hblunbpI3J24A6tMQj1tIIXbSQoIy@mail.gmail.com>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
	<AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
	<1275579127.9729.6.camel@localhost.localdomain>
	<AANLkTinzLo7e5sHOn7sFKRAZNZHWoi3TMMG-FslG-CVv@mail.gmail.com>
	<1275670996.9729.19.camel@localhost.localdomain>
	<AANLkTimUrdHmrf5hblunbpI3J24A6tMQj1tIIXbSQoIy@mail.gmail.com>
Message-ID: <1275674513.9729.22.camel@localhost.localdomain>

On Fri, 2010-06-04 at 19:35 +0200, Leo Barnes wrote:
> > The way to fix this is to make UBI/UBIFS use arrays of pages instead. Or
> > array of 2, 4, 8, etc pages, or it may be flexible and contain a field
> > which describes the allocation order. And then UBI/UBIFS code should be
> > amended correspondingly.
> >
> > This will need some effort, but I think a skilled engineer would do this
> > relatively quickly. We are not actively working on UBI/UBIFS now, so we
> > will unlikely implement this, but I'd be happy to help someone else to
> > do this.
> >
> > Many people ask about small features like security xattrs, or NFS
> > support, or DMA friendliness, but it is strange that people want ready
> > solutions instead of investing a bit of time and just implementing this.
> 
> Sounds good, I might take a crack at it, I have been looking for some
> way to contribute to the linux kernel.
> 
> Have I understood the UBI code correctly in that only the
> ubi->peb_buf1, ubi->peb_buf2 and ubi->dbg_peb_buf are ever sent to the
> mtd->read/write functions? Currently at home and dont really have
> anything to test code in.

Yes, AFAIR. If you really will try to do this, let's discuss the
strategy.

> Does UBIFS ever access the mtd-layer directly?

No. In UBIFS getting rid of vmalloc will be more difficult because it'll
need to modify algorithms like GC which walks uses the buffers.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From mcuos.com at gmail.com  Sat Jun  5 02:40:30 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 05 Jun 2010 14:40:30 +0800
Subject: [PATCH 1/3] MTD/pxa: patch for error return value method of
	pxa2xx-flash.c
Message-ID: <4C09F15E.9020408@gmail.com>

This patch is to re-implement the 'pxa2xx-flash.c' error return value method
of probe() and remove() function,the old return way can arouse the 'info' memory
leak risk.

Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>

---
 drivers/mtd/maps/pxa2xx-flash.c |   47 ++++++++++++++++++++++++++++----------
 1 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index dd90880..1d2583f 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -60,12 +60,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
 	int ret = 0;

 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
+	if (!res) {
+		ret = -ENODEV;
+		goto fail0;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		ret = -EBUSY;
+		goto fail0;
+	}

 	info = kzalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
+	if (!info) {
+		ret = -ENOMEM;
+		goto fail1;
+	}

 	info->map.name = (char *) flash->name;
 	info->map.bankwidth = flash->width;
@@ -78,13 +87,17 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
 	if (!info->map.virt) {
 		printk(KERN_WARNING "Failed to ioremap %s\n",
 		       info->map.name);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail2;
 	}
 	info->map.cached =
 		ioremap_cached(info->map.phys, info->map.size);
-	if (!info->map.cached)
+	if (!info->map.cached) {
 		printk(KERN_WARNING "Failed to ioremap cached %s\n",
 		       info->map.name);
+		ret = -ENOMEM;
+		goto fail3;
+	}
 	info->map.inval_cache = pxa2xx_map_inval_cache;
 	simple_map_init(&info->map);

@@ -97,10 +110,8 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
 	info->mtd = do_map_probe(flash->map_name, &info->map);

 	if (!info->mtd) {
-		iounmap((void *)info->map.virt);
-		if (info->map.cached)
-			iounmap(info->map.cached);
-		return -EIO;
+		ret = -EIO;
+		goto fail4;
 	}
 	info->mtd->owner = THIS_MODULE;

@@ -124,13 +135,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)

 	platform_set_drvdata(pdev, info);
 	return 0;
+
+fail4:	iounmap(info->map.cached);
+fail3:	iounmap(info->map.virt);
+fail2:	kfree(info);
+fail1:	release_mem_region(res->start, resource_size(res));
+fail0:
+	return ret;
 }

 static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
 {
 	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
+	struct resource *res;

-	platform_set_drvdata(dev, NULL);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

 #ifdef CONFIG_MTD_PARTITIONS
 	if (info->nr_parts)
@@ -141,10 +160,12 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)

 	map_destroy(info->mtd);
 	iounmap(info->map.virt);
-	if (info->map.cached)
-		iounmap(info->map.cached);
+	iounmap(info->map.cached);
 	kfree(info->parts);
 	kfree(info);
+	release_mem_region(res->start, resource_size(res));
+	platform_set_drvdata(dev, NULL);
+
 	return 0;
 }

-- 
1.6.3.3


From mcuos.com at gmail.com  Sat Jun  5 02:44:46 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 05 Jun 2010 14:44:46 +0800
Subject: [PATCH 2/3] MTD/pxa: use __devinit for pxa2xx_flash_probe
Message-ID: <4C09F25E.8090908@gmail.com>

This patch is to use the '__devinit' for pxa2xx_flash_probe.


Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>
---
 drivers/mtd/maps/pxa2xx-flash.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 1d2583f..43f8bb8 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -51,7 +51,7 @@ struct pxa2xx_flash_info {
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };


-static int __init pxa2xx_flash_probe(struct platform_device *pdev)
+static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
-- 
1.6.3.3


From mcuos.com at gmail.com  Sat Jun  5 02:48:57 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 05 Jun 2010 14:48:57 +0800
Subject: [PATCH 3/3] MTD/pxa: use resource_size(res) for pxa2xx-flash
Message-ID: <4C09F359.1000100@gmail.com>

The size calculation is end - start + 1. But,sometimes, the '1' can
be forgotten carelessly, witch will have potential risk, so use resource_size
should be good habit.

Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>

---
 drivers/mtd/maps/pxa2xx-flash.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 43f8bb8..6ed9a2d 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -79,7 +79,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	info->map.name = (char *) flash->name;
 	info->map.bankwidth = flash->width;
 	info->map.phys = res->start;
-	info->map.size = res->end - res->start + 1;
+	info->map.size = resource_size(res);
 	info->parts = flash->parts;
 	info->nr_parts = flash->nr_parts;

-- 
1.6.3.3


From eric.y.miao at gmail.com  Sat Jun  5 03:14:21 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Sat, 5 Jun 2010 15:14:21 +0800
Subject: [PATCH 1/3] MTD/pxa: patch for error return value method of 
	pxa2xx-flash.c
In-Reply-To: <4C09F15E.9020408@gmail.com>
References: <4C09F15E.9020408@gmail.com>
Message-ID: <AANLkTinLfGD-x-861sFK9r2zW5aEZvyXIB4PFKJl8NDZ@mail.gmail.com>

2010/6/5 Wan ZongShun <mcuos.com at gmail.com>:
> This patch is to re-implement the 'pxa2xx-flash.c' error return value method
> of probe() and remove() function,the old return way can arouse the 'info' memory
> leak risk.
>
> Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>
>
> ---
> ?drivers/mtd/maps/pxa2xx-flash.c | ? 47 ++++++++++++++++++++++++++++----------
> ?1 files changed, 34 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
> index dd90880..1d2583f 100644
> --- a/drivers/mtd/maps/pxa2xx-flash.c
> +++ b/drivers/mtd/maps/pxa2xx-flash.c
> @@ -60,12 +60,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
> ? ? ? ?int ret = 0;
>
> ? ? ? ?res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> - ? ? ? if (!res)
> - ? ? ? ? ? ? ? return -ENODEV;
> + ? ? ? if (!res) {
> + ? ? ? ? ? ? ? ret = -ENODEV;
> + ? ? ? ? ? ? ? goto fail0;
> + ? ? ? }

Can just return -ENODEV, why bother goto here?

> +
> + ? ? ? if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
> + ? ? ? ? ? ? ? ret = -EBUSY;
> + ? ? ? ? ? ? ? goto fail0;
> + ? ? ? }
>

Same here, nothing to release, can just return -EBUSY here. Provided I
always doubt the necessity of request_mem_region() here since the resource
should have been claimed when the platform device is registered, this is
possibly going to claim a sub-region of that resource. But that's another
story.

> ? ? ? ?info = kzalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
> - ? ? ? if (!info)
> - ? ? ? ? ? ? ? return -ENOMEM;
> + ? ? ? if (!info) {
> + ? ? ? ? ? ? ? ret = -ENOMEM;
> + ? ? ? ? ? ? ? goto fail1;
> + ? ? ? }
>
> ? ? ? ?info->map.name = (char *) flash->name;
> ? ? ? ?info->map.bankwidth = flash->width;
> @@ -78,13 +87,17 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
> ? ? ? ?if (!info->map.virt) {
> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap %s\n",
> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
> - ? ? ? ? ? ? ? return -ENOMEM;
> + ? ? ? ? ? ? ? ret = -ENOMEM;
> + ? ? ? ? ? ? ? goto fail2;
> ? ? ? ?}
> ? ? ? ?info->map.cached =
> ? ? ? ? ? ? ? ?ioremap_cached(info->map.phys, info->map.size);
> - ? ? ? if (!info->map.cached)
> + ? ? ? if (!info->map.cached) {
> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap cached %s\n",
> ? ? ? ? ? ? ? ? ? ? ? info->map.name);


This might not be an error at all, it's a warning. The cached mapping is
for performance reason on some platforms, it should be working all right
without it.

> + ? ? ? ? ? ? ? ret = -ENOMEM;
> + ? ? ? ? ? ? ? goto fail3;
> + ? ? ? }
> ? ? ? ?info->map.inval_cache = pxa2xx_map_inval_cache;
> ? ? ? ?simple_map_init(&info->map);
>
> @@ -97,10 +110,8 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
> ? ? ? ?info->mtd = do_map_probe(flash->map_name, &info->map);
>
> ? ? ? ?if (!info->mtd) {
> - ? ? ? ? ? ? ? iounmap((void *)info->map.virt);
> - ? ? ? ? ? ? ? if (info->map.cached)
> - ? ? ? ? ? ? ? ? ? ? ? iounmap(info->map.cached);
> - ? ? ? ? ? ? ? return -EIO;
> + ? ? ? ? ? ? ? ret = -EIO;

See above.

> + ? ? ? ? ? ? ? goto fail4;
> ? ? ? ?}
> ? ? ? ?info->mtd->owner = THIS_MODULE;
>
> @@ -124,13 +135,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>
> ? ? ? ?platform_set_drvdata(pdev, info);
> ? ? ? ?return 0;
> +
> +fail4: iounmap(info->map.cached);
> +fail3: iounmap(info->map.virt);
> +fail2: kfree(info);
> +fail1: release_mem_region(res->start, resource_size(res));
> +fail0:
> + ? ? ? return ret;
> ?}
>
> ?static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
> ?{
> ? ? ? ?struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
> + ? ? ? struct resource *res;
>
> - ? ? ? platform_set_drvdata(dev, NULL);

What's wrong with the above statement? And normally there is some benefit
of setting drive data to be NULL, as the driver data could be used concurrently
during removal (i.e. an interrupt handler if the IRQ is not already disabled).
Though relying on this behavior to safely remove a device is _not_ by anyway
recommended.

> + ? ? ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>
> ?#ifdef CONFIG_MTD_PARTITIONS
> ? ? ? ?if (info->nr_parts)
> @@ -141,10 +160,12 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
>
> ? ? ? ?map_destroy(info->mtd);
> ? ? ? ?iounmap(info->map.virt);
> - ? ? ? if (info->map.cached)
> - ? ? ? ? ? ? ? iounmap(info->map.cached);
> + ? ? ? iounmap(info->map.cached);

See above, the map.cached is supposed to be optional and can only
be removed if it's mapped, no force here.

> ? ? ? ?kfree(info->parts);
> ? ? ? ?kfree(info);
> + ? ? ? release_mem_region(res->start, resource_size(res));
> + ? ? ? platform_set_drvdata(dev, NULL);
> +
> ? ? ? ?return 0;
> ?}
>
> --
> 1.6.3.3
>


From eric.y.miao at gmail.com  Sat Jun  5 03:14:55 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Sat, 5 Jun 2010 15:14:55 +0800
Subject: [PATCH 2/3] MTD/pxa: use __devinit for pxa2xx_flash_probe
In-Reply-To: <4C09F25E.8090908@gmail.com>
References: <4C09F25E.8090908@gmail.com>
Message-ID: <AANLkTillJtAYn653DamU7_u3fmKt7rKGJtwfCHPPUVUF@mail.gmail.com>

2010/6/5 Wan ZongShun <mcuos.com at gmail.com>:
> This patch is to use the '__devinit' for pxa2xx_flash_probe.
>
>
> Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>

Acked.

> ---
> ?drivers/mtd/maps/pxa2xx-flash.c | ? ?2 +-
> ?1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
> index 1d2583f..43f8bb8 100644
> --- a/drivers/mtd/maps/pxa2xx-flash.c
> +++ b/drivers/mtd/maps/pxa2xx-flash.c
> @@ -51,7 +51,7 @@ struct pxa2xx_flash_info {
> ?static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
>
>
> -static int __init pxa2xx_flash_probe(struct platform_device *pdev)
> +static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
> ?{
> ? ? ? ?struct flash_platform_data *flash = pdev->dev.platform_data;
> ? ? ? ?struct pxa2xx_flash_info *info;
> --
> 1.6.3.3
>


From eric.y.miao at gmail.com  Sat Jun  5 03:15:12 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Sat, 5 Jun 2010 15:15:12 +0800
Subject: [PATCH 3/3] MTD/pxa: use resource_size(res) for pxa2xx-flash
In-Reply-To: <4C09F359.1000100@gmail.com>
References: <4C09F359.1000100@gmail.com>
Message-ID: <AANLkTilaptn-GhkoNC-CWLNP4XsTY7v-QCAypsF_BeKo@mail.gmail.com>

2010/6/5 Wan ZongShun <mcuos.com at gmail.com>:
> The size calculation is end - start + 1. But,sometimes, the '1' can
> be forgotten carelessly, witch will have potential risk, so use resource_size
> should be good habit.
>
> Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>

Acked.

>
> ---
> ?drivers/mtd/maps/pxa2xx-flash.c | ? ?2 +-
> ?1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
> index 43f8bb8..6ed9a2d 100644
> --- a/drivers/mtd/maps/pxa2xx-flash.c
> +++ b/drivers/mtd/maps/pxa2xx-flash.c
> @@ -79,7 +79,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
> ? ? ? ?info->map.name = (char *) flash->name;
> ? ? ? ?info->map.bankwidth = flash->width;
> ? ? ? ?info->map.phys = res->start;
> - ? ? ? info->map.size = res->end - res->start + 1;
> + ? ? ? info->map.size = resource_size(res);
> ? ? ? ?info->parts = flash->parts;
> ? ? ? ?info->nr_parts = flash->nr_parts;
>
> --
> 1.6.3.3
>


From mcuos.com at gmail.com  Sat Jun  5 03:38:10 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 5 Jun 2010 15:38:10 +0800
Subject: [PATCH 1/3] MTD/pxa: patch for error return value method of 
	pxa2xx-flash.c
In-Reply-To: <AANLkTinLfGD-x-861sFK9r2zW5aEZvyXIB4PFKJl8NDZ@mail.gmail.com>
References: <4C09F15E.9020408@gmail.com>
	<AANLkTinLfGD-x-861sFK9r2zW5aEZvyXIB4PFKJl8NDZ@mail.gmail.com>
Message-ID: <AANLkTikJiPjl3LKVqgqtlK2YEePXDf7K6EdOlUE4uzBb@mail.gmail.com>

Hi Eric,

Thanks for your review.

2010/6/5 Eric Miao <eric.y.miao at gmail.com>:
> 2010/6/5 Wan ZongShun <mcuos.com at gmail.com>:
>> This patch is to re-implement the 'pxa2xx-flash.c' error return value method
>> of probe() and remove() function,the old return way can arouse the 'info' memory
>> leak risk.
>>
>> Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>
>>
>> ---
>> ?drivers/mtd/maps/pxa2xx-flash.c | ? 47 ++++++++++++++++++++++++++++----------
>> ?1 files changed, 34 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
>> index dd90880..1d2583f 100644
>> --- a/drivers/mtd/maps/pxa2xx-flash.c
>> +++ b/drivers/mtd/maps/pxa2xx-flash.c
>> @@ -60,12 +60,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>> ? ? ? ?int ret = 0;
>>
>> ? ? ? ?res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> - ? ? ? if (!res)
>> - ? ? ? ? ? ? ? return -ENODEV;
>> + ? ? ? if (!res) {
>> + ? ? ? ? ? ? ? ret = -ENODEV;
>> + ? ? ? ? ? ? ? goto fail0;
>> + ? ? ? }
>
> Can just return -ENODEV, why bother goto here?
>
>> +
>> + ? ? ? if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
>> + ? ? ? ? ? ? ? ret = -EBUSY;
>> + ? ? ? ? ? ? ? goto fail0;
>> + ? ? ? }
>>
>
> Same here, nothing to release, can just return -EBUSY here. Provided I
> always doubt the necessity of request_mem_region() here since the resource
> should have been claimed when the platform device is registered, this is
> possibly going to claim a sub-region of that resource. But that's another
> story.

I agree with you.
So, keep it be there or remove it?

Could Keeping it make a more compatibility code?


>
>> ? ? ? ?info = kzalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
>> - ? ? ? if (!info)
>> - ? ? ? ? ? ? ? return -ENOMEM;
>> + ? ? ? if (!info) {
>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>> + ? ? ? ? ? ? ? goto fail1;
>> + ? ? ? }
>>
>> ? ? ? ?info->map.name = (char *) flash->name;
>> ? ? ? ?info->map.bankwidth = flash->width;
>> @@ -78,13 +87,17 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>> ? ? ? ?if (!info->map.virt) {
>> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap %s\n",
>> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
>> - ? ? ? ? ? ? ? return -ENOMEM;
>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>> + ? ? ? ? ? ? ? goto fail2;
>> ? ? ? ?}
>> ? ? ? ?info->map.cached =
>> ? ? ? ? ? ? ? ?ioremap_cached(info->map.phys, info->map.size);
>> - ? ? ? if (!info->map.cached)
>> + ? ? ? if (!info->map.cached) {
>> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap cached %s\n",
>> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
>
>
> This might not be an error at all, it's a warning. The cached mapping is
> for performance reason on some platforms, it should be working all right
> without it.

Thanks, I just have a doubt regarding this condition judement, so
thanks for your comments.

>
>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>> + ? ? ? ? ? ? ? goto fail3;
>> + ? ? ? }
>> ? ? ? ?info->map.inval_cache = pxa2xx_map_inval_cache;
>> ? ? ? ?simple_map_init(&info->map);
>>
>> @@ -97,10 +110,8 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>> ? ? ? ?info->mtd = do_map_probe(flash->map_name, &info->map);
>>
>> ? ? ? ?if (!info->mtd) {
>> - ? ? ? ? ? ? ? iounmap((void *)info->map.virt);
>> - ? ? ? ? ? ? ? if (info->map.cached)
>> - ? ? ? ? ? ? ? ? ? ? ? iounmap(info->map.cached);
>> - ? ? ? ? ? ? ? return -EIO;
>> + ? ? ? ? ? ? ? ret = -EIO;
>
> See above.
>
>> + ? ? ? ? ? ? ? goto fail4;
>> ? ? ? ?}
>> ? ? ? ?info->mtd->owner = THIS_MODULE;
>>
>> @@ -124,13 +135,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>
>> ? ? ? ?platform_set_drvdata(pdev, info);
>> ? ? ? ?return 0;
>> +
>> +fail4: iounmap(info->map.cached);
>> +fail3: iounmap(info->map.virt);
>> +fail2: kfree(info);
>> +fail1: release_mem_region(res->start, resource_size(res));
>> +fail0:
>> + ? ? ? return ret;
>> ?}
>>
>> ?static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
>> ?{
>> ? ? ? ?struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
>> + ? ? ? struct resource *res;
>>
>> - ? ? ? platform_set_drvdata(dev, NULL);
>
> What's wrong with the above statement? And normally there is some benefit
> of setting drive data to be NULL, as the driver data could be used concurrently
> during removal (i.e. an interrupt handler if the IRQ is not already disabled).
> Though relying on this behavior to safely remove a device is _not_ by anyway
> recommended.

I got it,so, setting the drive data to be NULL should be as early as possible.

>
>> + ? ? ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>
>> ?#ifdef CONFIG_MTD_PARTITIONS
>> ? ? ? ?if (info->nr_parts)
>> @@ -141,10 +160,12 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
>>
>> ? ? ? ?map_destroy(info->mtd);
>> ? ? ? ?iounmap(info->map.virt);
>> - ? ? ? if (info->map.cached)
>> - ? ? ? ? ? ? ? iounmap(info->map.cached);
>> + ? ? ? iounmap(info->map.cached);
>
> See above, the map.cached is supposed to be optional and can only
> be removed if it's mapped, no force here.
>
>> ? ? ? ?kfree(info->parts);
>> ? ? ? ?kfree(info);
>> + ? ? ? release_mem_region(res->start, resource_size(res));
>> + ? ? ? platform_set_drvdata(dev, NULL);
>> +
>> ? ? ? ?return 0;
>> ?}
>>
>> --
>> 1.6.3.3
>>
>



-- 
*linux-arm-kernel mailing list
mail addr:linux-arm-kernel at lists.infradead.org
you can subscribe by:
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

* linux-arm-NUC900 mailing list
mail addr:NUC900 at googlegroups.com
main web: https://groups.google.com/group/NUC900
you can subscribe it by sending me mail:
mcuos.com at gmail.com


From mcuos.com at gmail.com  Sat Jun  5 03:53:25 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 5 Jun 2010 15:53:25 +0800
Subject: [PATCH 1/3] MTD/pxa: patch for error return value method of 
	pxa2xx-flash.c
In-Reply-To: <AANLkTikJiPjl3LKVqgqtlK2YEePXDf7K6EdOlUE4uzBb@mail.gmail.com>
References: <4C09F15E.9020408@gmail.com>
	<AANLkTinLfGD-x-861sFK9r2zW5aEZvyXIB4PFKJl8NDZ@mail.gmail.com>
	<AANLkTikJiPjl3LKVqgqtlK2YEePXDf7K6EdOlUE4uzBb@mail.gmail.com>
Message-ID: <AANLkTilydl5oKETCC69C_QY6xJa3mIXve097JU6qevfp@mail.gmail.com>

Hi Eric,

This following piece of code:

	if (!info->map.virt) {
		printk(KERN_WARNING "Failed to ioremap %s\n",
		       info->map.name);
		ret = -ENOMEM;
		goto fail2;
	}

Shouldn't  the 'KERN_ERR' in stead of the 'KERN_WARNING '?
Because the  'info->map.virt == NULL' can arouse the serious crash.

2010/6/5 Wan ZongShun <mcuos.com at gmail.com>:
> Hi Eric,
>
> Thanks for your review.
>
> 2010/6/5 Eric Miao <eric.y.miao at gmail.com>:
>> 2010/6/5 Wan ZongShun <mcuos.com at gmail.com>:
>>> This patch is to re-implement the 'pxa2xx-flash.c' error return value method
>>> of probe() and remove() function,the old return way can arouse the 'info' memory
>>> leak risk.
>>>
>>> Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>
>>>
>>> ---
>>> ?drivers/mtd/maps/pxa2xx-flash.c | ? 47 ++++++++++++++++++++++++++++----------
>>> ?1 files changed, 34 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
>>> index dd90880..1d2583f 100644
>>> --- a/drivers/mtd/maps/pxa2xx-flash.c
>>> +++ b/drivers/mtd/maps/pxa2xx-flash.c
>>> @@ -60,12 +60,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>> ? ? ? ?int ret = 0;
>>>
>>> ? ? ? ?res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> - ? ? ? if (!res)
>>> - ? ? ? ? ? ? ? return -ENODEV;
>>> + ? ? ? if (!res) {
>>> + ? ? ? ? ? ? ? ret = -ENODEV;
>>> + ? ? ? ? ? ? ? goto fail0;
>>> + ? ? ? }
>>
>> Can just return -ENODEV, why bother goto here?
>>
>>> +
>>> + ? ? ? if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
>>> + ? ? ? ? ? ? ? ret = -EBUSY;
>>> + ? ? ? ? ? ? ? goto fail0;
>>> + ? ? ? }
>>>
>>
>> Same here, nothing to release, can just return -EBUSY here. Provided I
>> always doubt the necessity of request_mem_region() here since the resource
>> should have been claimed when the platform device is registered, this is
>> possibly going to claim a sub-region of that resource. But that's another
>> story.
>
> I agree with you.
> So, keep it be there or remove it?
>
> Could Keeping it make a more compatibility code?
>
>
>>
>>> ? ? ? ?info = kzalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
>>> - ? ? ? if (!info)
>>> - ? ? ? ? ? ? ? return -ENOMEM;
>>> + ? ? ? if (!info) {
>>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>>> + ? ? ? ? ? ? ? goto fail1;
>>> + ? ? ? }
>>>
>>> ? ? ? ?info->map.name = (char *) flash->name;
>>> ? ? ? ?info->map.bankwidth = flash->width;
>>> @@ -78,13 +87,17 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>> ? ? ? ?if (!info->map.virt) {
>>> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap %s\n",
>>> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
>>> - ? ? ? ? ? ? ? return -ENOMEM;
>>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>>> + ? ? ? ? ? ? ? goto fail2;
>>> ? ? ? ?}
>>> ? ? ? ?info->map.cached =
>>> ? ? ? ? ? ? ? ?ioremap_cached(info->map.phys, info->map.size);
>>> - ? ? ? if (!info->map.cached)
>>> + ? ? ? if (!info->map.cached) {
>>> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap cached %s\n",
>>> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
>>
>>
>> This might not be an error at all, it's a warning. The cached mapping is
>> for performance reason on some platforms, it should be working all right
>> without it.
>
> Thanks, I just have a doubt regarding this condition judement, so
> thanks for your comments.
>
>>
>>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>>> + ? ? ? ? ? ? ? goto fail3;
>>> + ? ? ? }
>>> ? ? ? ?info->map.inval_cache = pxa2xx_map_inval_cache;
>>> ? ? ? ?simple_map_init(&info->map);
>>>
>>> @@ -97,10 +110,8 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>> ? ? ? ?info->mtd = do_map_probe(flash->map_name, &info->map);
>>>
>>> ? ? ? ?if (!info->mtd) {
>>> - ? ? ? ? ? ? ? iounmap((void *)info->map.virt);
>>> - ? ? ? ? ? ? ? if (info->map.cached)
>>> - ? ? ? ? ? ? ? ? ? ? ? iounmap(info->map.cached);
>>> - ? ? ? ? ? ? ? return -EIO;
>>> + ? ? ? ? ? ? ? ret = -EIO;
>>
>> See above.
>>
>>> + ? ? ? ? ? ? ? goto fail4;
>>> ? ? ? ?}
>>> ? ? ? ?info->mtd->owner = THIS_MODULE;
>>>
>>> @@ -124,13 +135,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>>
>>> ? ? ? ?platform_set_drvdata(pdev, info);
>>> ? ? ? ?return 0;
>>> +
>>> +fail4: iounmap(info->map.cached);
>>> +fail3: iounmap(info->map.virt);
>>> +fail2: kfree(info);
>>> +fail1: release_mem_region(res->start, resource_size(res));
>>> +fail0:
>>> + ? ? ? return ret;
>>> ?}
>>>
>>> ?static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
>>> ?{
>>> ? ? ? ?struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
>>> + ? ? ? struct resource *res;
>>>
>>> - ? ? ? platform_set_drvdata(dev, NULL);
>>
>> What's wrong with the above statement? And normally there is some benefit
>> of setting drive data to be NULL, as the driver data could be used concurrently
>> during removal (i.e. an interrupt handler if the IRQ is not already disabled).
>> Though relying on this behavior to safely remove a device is _not_ by anyway
>> recommended.
>
> I got it,so, setting the drive data to be NULL should be as early as possible.
>
>>
>>> + ? ? ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>
>>> ?#ifdef CONFIG_MTD_PARTITIONS
>>> ? ? ? ?if (info->nr_parts)
>>> @@ -141,10 +160,12 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
>>>
>>> ? ? ? ?map_destroy(info->mtd);
>>> ? ? ? ?iounmap(info->map.virt);
>>> - ? ? ? if (info->map.cached)
>>> - ? ? ? ? ? ? ? iounmap(info->map.cached);
>>> + ? ? ? iounmap(info->map.cached);
>>
>> See above, the map.cached is supposed to be optional and can only
>> be removed if it's mapped, no force here.
>>
>>> ? ? ? ?kfree(info->parts);
>>> ? ? ? ?kfree(info);
>>> + ? ? ? release_mem_region(res->start, resource_size(res));
>>> + ? ? ? platform_set_drvdata(dev, NULL);
>>> +
>>> ? ? ? ?return 0;
>>> ?}
>>>
>>> --
>>> 1.6.3.3
>>>
>>
>
>
>
> --
> *linux-arm-kernel mailing list
> mail addr:linux-arm-kernel at lists.infradead.org
> you can subscribe by:
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> * linux-arm-NUC900 mailing list
> mail addr:NUC900 at googlegroups.com
> main web: https://groups.google.com/group/NUC900
> you can subscribe it by sending me mail:
> mcuos.com at gmail.com
>



-- 
*linux-arm-kernel mailing list
mail addr:linux-arm-kernel at lists.infradead.org
you can subscribe by:
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

* linux-arm-NUC900 mailing list
mail addr:NUC900 at googlegroups.com
main web: https://groups.google.com/group/NUC900
you can subscribe it by sending me mail:
mcuos.com at gmail.com


From eric.y.miao at gmail.com  Sat Jun  5 03:58:32 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Sat, 5 Jun 2010 15:58:32 +0800
Subject: [PATCH 1/3] MTD/pxa: patch for error return value method of 
	pxa2xx-flash.c
In-Reply-To: <AANLkTikJiPjl3LKVqgqtlK2YEePXDf7K6EdOlUE4uzBb@mail.gmail.com>
References: <4C09F15E.9020408@gmail.com>
	<AANLkTinLfGD-x-861sFK9r2zW5aEZvyXIB4PFKJl8NDZ@mail.gmail.com> 
	<AANLkTikJiPjl3LKVqgqtlK2YEePXDf7K6EdOlUE4uzBb@mail.gmail.com>
Message-ID: <AANLkTilQQcjCCF1bG7qfJ27sOD8JcGzCYhCf3kVmzXw7@mail.gmail.com>

On Sat, Jun 5, 2010 at 3:38 PM, Wan ZongShun <mcuos.com at gmail.com> wrote:
> Hi Eric,
>
> Thanks for your review.
>
> 2010/6/5 Eric Miao <eric.y.miao at gmail.com>:
>> 2010/6/5 Wan ZongShun <mcuos.com at gmail.com>:
>>> This patch is to re-implement the 'pxa2xx-flash.c' error return value method
>>> of probe() and remove() function,the old return way can arouse the 'info' memory
>>> leak risk.
>>>
>>> Signed-off-by :Wan ZongShun <mcuos.com at gmail.com>
>>>
>>> ---
>>> ?drivers/mtd/maps/pxa2xx-flash.c | ? 47 ++++++++++++++++++++++++++++----------
>>> ?1 files changed, 34 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
>>> index dd90880..1d2583f 100644
>>> --- a/drivers/mtd/maps/pxa2xx-flash.c
>>> +++ b/drivers/mtd/maps/pxa2xx-flash.c
>>> @@ -60,12 +60,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>> ? ? ? ?int ret = 0;
>>>
>>> ? ? ? ?res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> - ? ? ? if (!res)
>>> - ? ? ? ? ? ? ? return -ENODEV;
>>> + ? ? ? if (!res) {
>>> + ? ? ? ? ? ? ? ret = -ENODEV;
>>> + ? ? ? ? ? ? ? goto fail0;
>>> + ? ? ? }
>>
>> Can just return -ENODEV, why bother goto here?
>>
>>> +
>>> + ? ? ? if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
>>> + ? ? ? ? ? ? ? ret = -EBUSY;
>>> + ? ? ? ? ? ? ? goto fail0;
>>> + ? ? ? }
>>>
>>
>> Same here, nothing to release, can just return -EBUSY here. Provided I
>> always doubt the necessity of request_mem_region() here since the resource
>> should have been claimed when the platform device is registered, this is
>> possibly going to claim a sub-region of that resource. But that's another
>> story.
>
> I agree with you.
> So, keep it be there or remove it?
>

I'd recommend not to add it in this patch. You can have another patch
to add it if it's necessary.

> Could Keeping it make a more compatibility code?
>
>
>>
>>> ? ? ? ?info = kzalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
>>> - ? ? ? if (!info)
>>> - ? ? ? ? ? ? ? return -ENOMEM;
>>> + ? ? ? if (!info) {
>>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>>> + ? ? ? ? ? ? ? goto fail1;
>>> + ? ? ? }
>>>
>>> ? ? ? ?info->map.name = (char *) flash->name;
>>> ? ? ? ?info->map.bankwidth = flash->width;
>>> @@ -78,13 +87,17 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>> ? ? ? ?if (!info->map.virt) {
>>> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap %s\n",
>>> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
>>> - ? ? ? ? ? ? ? return -ENOMEM;
>>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>>> + ? ? ? ? ? ? ? goto fail2;
>>> ? ? ? ?}
>>> ? ? ? ?info->map.cached =
>>> ? ? ? ? ? ? ? ?ioremap_cached(info->map.phys, info->map.size);
>>> - ? ? ? if (!info->map.cached)
>>> + ? ? ? if (!info->map.cached) {
>>> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap cached %s\n",
>>> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
>>
>>
>> This might not be an error at all, it's a warning. The cached mapping is
>> for performance reason on some platforms, it should be working all right
>> without it.
>
> Thanks, I just have a doubt regarding this condition judement, so
> thanks for your comments.
>
>>
>>> + ? ? ? ? ? ? ? ret = -ENOMEM;
>>> + ? ? ? ? ? ? ? goto fail3;
>>> + ? ? ? }
>>> ? ? ? ?info->map.inval_cache = pxa2xx_map_inval_cache;
>>> ? ? ? ?simple_map_init(&info->map);
>>>
>>> @@ -97,10 +110,8 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>> ? ? ? ?info->mtd = do_map_probe(flash->map_name, &info->map);
>>>
>>> ? ? ? ?if (!info->mtd) {
>>> - ? ? ? ? ? ? ? iounmap((void *)info->map.virt);
>>> - ? ? ? ? ? ? ? if (info->map.cached)
>>> - ? ? ? ? ? ? ? ? ? ? ? iounmap(info->map.cached);
>>> - ? ? ? ? ? ? ? return -EIO;
>>> + ? ? ? ? ? ? ? ret = -EIO;
>>
>> See above.
>>
>>> + ? ? ? ? ? ? ? goto fail4;
>>> ? ? ? ?}
>>> ? ? ? ?info->mtd->owner = THIS_MODULE;
>>>
>>> @@ -124,13 +135,21 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
>>>
>>> ? ? ? ?platform_set_drvdata(pdev, info);
>>> ? ? ? ?return 0;
>>> +
>>> +fail4: iounmap(info->map.cached);
>>> +fail3: iounmap(info->map.virt);
>>> +fail2: kfree(info);
>>> +fail1: release_mem_region(res->start, resource_size(res));
>>> +fail0:
>>> + ? ? ? return ret;
>>> ?}
>>>
>>> ?static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
>>> ?{
>>> ? ? ? ?struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
>>> + ? ? ? struct resource *res;
>>>
>>> - ? ? ? platform_set_drvdata(dev, NULL);
>>
>> What's wrong with the above statement? And normally there is some benefit
>> of setting drive data to be NULL, as the driver data could be used concurrently
>> during removal (i.e. an interrupt handler if the IRQ is not already disabled).
>> Though relying on this behavior to safely remove a device is _not_ by anyway
>> recommended.
>
> I got it,so, setting the drive data to be NULL should be as early as possible.
>

Normally yes. But I don't think that's a guarantee of a safe removal though.


From eric.y.miao at gmail.com  Sat Jun  5 03:59:56 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Sat, 5 Jun 2010 15:59:56 +0800
Subject: [PATCH 1/3] MTD/pxa: patch for error return value method of 
	pxa2xx-flash.c
In-Reply-To: <AANLkTilydl5oKETCC69C_QY6xJa3mIXve097JU6qevfp@mail.gmail.com>
References: <4C09F15E.9020408@gmail.com>
	<AANLkTinLfGD-x-861sFK9r2zW5aEZvyXIB4PFKJl8NDZ@mail.gmail.com> 
	<AANLkTikJiPjl3LKVqgqtlK2YEePXDf7K6EdOlUE4uzBb@mail.gmail.com> 
	<AANLkTilydl5oKETCC69C_QY6xJa3mIXve097JU6qevfp@mail.gmail.com>
Message-ID: <AANLkTile8PqagLri8n1Y0Xn03e8STx7XQODUx83woYNE@mail.gmail.com>

On Sat, Jun 5, 2010 at 3:53 PM, Wan ZongShun <mcuos.com at gmail.com> wrote:
> Hi Eric,
>
> This following piece of code:
>
> ? ? ? ?if (!info->map.virt) {
> ? ? ? ? ? ? ? ?printk(KERN_WARNING "Failed to ioremap %s\n",
> ? ? ? ? ? ? ? ? ? ? ? info->map.name);
> ? ? ? ? ? ? ? ?ret = -ENOMEM;
> ? ? ? ? ? ? ? ?goto fail2;
> ? ? ? ?}
>
> Shouldn't ?the 'KERN_ERR' in stead of the 'KERN_WARNING '?
> Because the ?'info->map.virt == NULL' can arouse the serious crash.
>

The thing is you need to figure out if it is mandatory because we
have another info->map.cached just in case. Disaster is both can
not be mapped.


From mcuos.com at gmail.com  Sat Jun  5 05:07:06 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 05 Jun 2010 17:07:06 +0800
Subject: [PATCHv2 1/3] MTD/pxa: use __devinit for pxa2xx_flash_probe
Message-ID: <4C0A13BA.6050700@gmail.com>

This patch is to use the '__devinit' for pxa2xx_flash_probe.

Signed-off-by: Wan ZongShun <mcuos.com at gmail.com>
Acked-by: Eric Miao <eric.y.miao at gmail.com>

---
 drivers/mtd/maps/pxa2xx-flash.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index dd90880..d8ae634 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -51,7 +51,7 @@ struct pxa2xx_flash_info {
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };


-static int __init pxa2xx_flash_probe(struct platform_device *pdev)
+static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
-- 
1.6.3.3


From mcuos.com at gmail.com  Sat Jun  5 05:10:03 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 05 Jun 2010 17:10:03 +0800
Subject: [PATCHv2 2/3] MTD/pxa: use resource_size(res) for pxa2xx-flash
Message-ID: <4C0A146B.1060306@gmail.com>

The size calculation is end - start + 1. But,sometimes, the '1' can
be forgotten carelessly, witch will have potential risk, so use resource_size
should be good habit.

Signed-off-by: Wan ZongShun <mcuos.com at gmail.com>
Acked-by: Eric Miao <eric.y.miao at gmail.com>

---
 drivers/mtd/maps/pxa2xx-flash.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index d8ae634..b5bb1a4 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -70,7 +70,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	info->map.name = (char *) flash->name;
 	info->map.bankwidth = flash->width;
 	info->map.phys = res->start;
-	info->map.size = res->end - res->start + 1;
+	info->map.size = resource_size(res);
 	info->parts = flash->parts;
 	info->nr_parts = flash->nr_parts;

-- 
1.6.3.3


From mcuos.com at gmail.com  Sat Jun  5 05:14:36 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 05 Jun 2010 17:14:36 +0800
Subject: [PATCHv2 3/3] MTD/pxa: patch for error return value method of
	pxa2xx-flash
Message-ID: <4C0A157C.1050909@gmail.com>

This patch is to re-implement the 'pxa2xx-flash.c' error return value method
of probe() and remove() function,the old return way can arouse the 'info' memory
leak risk.

This patch has been reviewed by Eric, according to his advice, I modify some wrong
issues of previous patch and resend to maillist.

Signed-off-by: Wan ZongShun <mcuos.com at gmail.com>

---
 drivers/mtd/maps/pxa2xx-flash.c |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index b5bb1a4..e789358 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -78,7 +78,8 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	if (!info->map.virt) {
 		printk(KERN_WARNING "Failed to ioremap %s\n",
 		       info->map.name);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail1;
 	}
 	info->map.cached =
 		ioremap_cached(info->map.phys, info->map.size);
@@ -97,10 +98,8 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	info->mtd = do_map_probe(flash->map_name, &info->map);

 	if (!info->mtd) {
-		iounmap((void *)info->map.virt);
-		if (info->map.cached)
-			iounmap(info->map.cached);
-		return -EIO;
+		ret = -EIO;
+		goto fail2;
 	}
 	info->mtd->owner = THIS_MODULE;

@@ -124,6 +123,12 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)

 	platform_set_drvdata(pdev, info);
 	return 0;
+
+fail2:	iounmap(info->map.virt);
+	if (info->map.cached)
+		iounmap(info->map.cached);
+fail1:	kfree(info);
+	return ret;
 }

 static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
-- 
1.6.3.3


From mcuos.com at gmail.com  Sat Jun  5 05:37:21 2010
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Sat, 05 Jun 2010 17:37:21 +0800
Subject: [PATCH] MTD/pxa: use __devexit, __devinit  and __devexit_p for pxa3xx
	nand
Message-ID: <4C0A1AD1.5090008@gmail.com>

This patch is to use __devexit, __devinit  and __devexit_p for pxa3xx nand driver.

Signed-off-by: Wan ZongShun <mcuos.com at gmail.com>

---
 drivers/mtd/nand/pxa3xx_nand.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index e02fa4f..7ba1853 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1206,7 +1206,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->chip_delay = 25;
 }

-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
@@ -1354,7 +1354,7 @@ fail_free_mtd:
 	return ret;
 }

-static int pxa3xx_nand_remove(struct platform_device *pdev)
+static int __devexit pxa3xx_nand_remove(struct platform_device *pdev)
 {
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
 	struct pxa3xx_nand_info *info = mtd->priv;
@@ -1419,7 +1419,7 @@ static struct platform_driver pxa3xx_nand_driver = {
 		.name	= "pxa3xx-nand",
 	},
 	.probe		= pxa3xx_nand_probe,
-	.remove		= pxa3xx_nand_remove,
+	.remove		= __devexit_p(pxa3xx_nand_remove),
 	.suspend	= pxa3xx_nand_suspend,
 	.resume		= pxa3xx_nand_resume,
 };
-- 
1.6.3.3


From dedekind1 at gmail.com  Sat Jun  5 07:50:05 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 05 Jun 2010 14:50:05 +0300
Subject: UBIFS: Oops while rebooting 2.6.34-rc6
In-Reply-To: <20100507152640.GX30801@buzzloop.caiaq.de>
References: <20100507131652.GT30801@buzzloop.caiaq.de>
	<1273245826.4537.294.camel@localhost>
	<20100507152640.GX30801@buzzloop.caiaq.de>
Message-ID: <1275738605.20281.2.camel@localhost>

On Fri, 2010-05-07 at 17:26 +0200, Daniel Mack wrote:
> > > # reboot
> > > # [  671.190085] UBIFS: un-mount UBI device 0, volume 1
> > > The system is going down NOW!
> > > Sent SIGTERM to all processes
> > > [  672.083833] Unable to handle kernel NULL pointer dereference at virtual address 000000ac
> > > [  672.094587] pgd = c0004000
> > > [  672.097301] [000000ac] *pgd=00000000
> > > [  672.100850] Internal error: Oops: 817 [#1]
> > > [  672.104919] last sysfs file: /sys/devices/platform/spi_gpio.0/spi0.2/value
> > 
> > It's Firday, and I want to go home, so here is another quick idea for
> > you where to dig.
> > 
> > When the system reboots it re-mounts the FS to RO mode, usually. And
> > there is some emergency remount business (see do_emergency_remount()),
> > which will re-mount the FS even if there are files opened for writing.
> > 
> > So, if there is a UBIFS or VFS bug, and somehow one process is in
> > make_reservation() and is about to write something, and another process
> > managed to re-mount the FS to R/O mode, then we may ooops, because UBIFS
> > frees these 'wbuf' objects when it is mounted to R/O (see
> > ubifs_remount_ro()).
> > 
> > So, inject printks to ubifs_remount_ro() to check this theory.
> > 
> > Have a nice weekend and bughunting!
> 
> Thanks for your feedback - I'll give that a try next week.

Was you able to reproduce this oops?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From sshtylyov at mvista.com  Sat Jun  5 13:18:17 2010
From: sshtylyov at mvista.com (Sergei Shtylyov)
Date: Sat, 05 Jun 2010 21:18:17 +0400
Subject: [PATCHv2 1/3] MTD/pxa: use __devinit for pxa2xx_flash_probe
In-Reply-To: <4C0A13BA.6050700@gmail.com>
References: <4C0A13BA.6050700@gmail.com>
Message-ID: <4C0A86D9.2070106@mvista.com>

Wan ZongShun wrote:

> This patch is to use the '__devinit' for pxa2xx_flash_probe.

    Why? Is it hot-pluggable device? I guess not...

> Signed-off-by: Wan ZongShun <mcuos.com at gmail.com>
> Acked-by: Eric Miao <eric.y.miao at gmail.com>

WBR, Sergei



From eric.y.miao at gmail.com  Sun Jun  6 05:27:58 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Sun, 6 Jun 2010 17:27:58 +0800
Subject: [PATCHv2 1/3] MTD/pxa: use __devinit for pxa2xx_flash_probe
In-Reply-To: <4C0A86D9.2070106@mvista.com>
References: <4C0A13BA.6050700@gmail.com> <4C0A86D9.2070106@mvista.com>
Message-ID: <AANLkTinRQ2TwU0fj2k70GdNFKmOVQ4DLc2xELu7HnnZ5@mail.gmail.com>

On Sun, Jun 6, 2010 at 1:18 AM, Sergei Shtylyov <sshtylyov at mvista.com> wrote:
> Wan ZongShun wrote:
>
>> This patch is to use the '__devinit' for pxa2xx_flash_probe.
>
> ? Why? Is it hot-pluggable device? I guess not...
>

Then I guess the __devexit is not applicable to pxa2xx_flash_remove as well.
Apart from the _probe() being unnecessarily built in when HOTPLUG is
defined, is there any drawbacks. It does make code a little bit consistent
from my POV.

>> Signed-off-by: Wan ZongShun <mcuos.com at gmail.com>
>> Acked-by: Eric Miao <eric.y.miao at gmail.com>
>
> WBR, Sergei
>
>


From dwmw2 at infradead.org  Sun Jun  6 06:15:08 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Sun, 06 Jun 2010 11:15:08 +0100
Subject: [PATCH] mtd: nand: mpc5121_nfc.c: Fix build failures
In-Reply-To: <1275323836-15711-1-git-send-email-agust@denx.de>
References: <1275323836-15711-1-git-send-email-agust@denx.de>
Message-ID: <1275819308.17903.3099.camel@macbook.infradead.org>

On Mon, 2010-05-31 at 18:37 +0200, Anatolij Gustschin wrote:
> Fixes build errors caused by the:
>  - OF device_node pointer being moved into struct device
>  - removal of the match_table field from struct of_platform_driver
> 
> Signed-off-by: Anatolij Gustschin <agust at denx.de>
> Cc: Grant Likely <grant.likely at secretlab.ca>

Um, this isn't applicable to 2.6.35, is it?

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From agust at denx.de  Mon Jun  7 03:09:19 2010
From: agust at denx.de (Anatolij Gustschin)
Date: Mon, 7 Jun 2010 09:09:19 +0200
Subject: [PATCH] mtd: nand: mpc5121_nfc.c: Fix build failures
In-Reply-To: <1275819308.17903.3099.camel@macbook.infradead.org>
References: <1275323836-15711-1-git-send-email-agust@denx.de>
	<1275819308.17903.3099.camel@macbook.infradead.org>
Message-ID: <20100607090919.20129f51@wker>

On Sun, 06 Jun 2010 11:15:08 +0100
David Woodhouse <dwmw2 at infradead.org> wrote:

> On Mon, 2010-05-31 at 18:37 +0200, Anatolij Gustschin wrote:
> > Fixes build errors caused by the:
> >  - OF device_node pointer being moved into struct device
> >  - removal of the match_table field from struct of_platform_driver
> > 
> > Signed-off-by: Anatolij Gustschin <agust at denx.de>
> > Cc: Grant Likely <grant.likely at secretlab.ca>
> 
> Um, this isn't applicable to 2.6.35, is it?

Do you mean it isn't applicable to 2.6.34? This patch is needed and
applicable to 2.6.35-rc1. It has already been collected by Grant
and the breakage is fixed in 2.6.35-rc2.


From vbarshak at mvista.com  Mon Jun  7 13:12:56 2010
From: vbarshak at mvista.com (Valentine Barshak)
Date: Mon, 07 Jun 2010 21:12:56 +0400
Subject: AMD/Fujitsu (cfi_cmdset_0002) lock/unlock implementation question.
Message-ID: <4C0D2898.5060404@mvista.com>

Is anybody working on adding lock/unlock functionality to the 
cfi_cmdset_0002.c?
This stuff seems highly h/w-dependent. I'm interested in particular in 
sector lock/unlock functionality for S29GL-N Spansion chips.
Any info regarding this feature for cmdset_0002 is greatly appreciated.

Thanks,
Val.



From tbm at cyrius.com  Mon Jun  7 14:31:01 2010
From: tbm at cyrius.com (Martin Michlmayr)
Date: Mon, 7 Jun 2010 19:31:01 +0100
Subject: [PATCH] mtd: m25p80: Add support for Macronix 25L8005
Message-ID: <20100607183101.GA378@jirafa.cyrius.com>

Add support for Macronix 25L8005.  Tested on a HP t5325 Thin Client.

Signed-off-by: Martin Michlmayr <tbm at cyrius.com>

index 81e49a9..372df59 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -641,6 +641,7 @@ static const struct spi_device_id m25p_ids[] = {
 
 	/* Macronix */
 	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
+	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
 	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, 0) },
 	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },

-- 
Martin Michlmayr
http://www.cyrius.com/


From dedekind1 at gmail.com  Tue Jun  8 04:45:30 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 08 Jun 2010 11:45:30 +0300
Subject: [PATCH] ubi : generate random image_seq when attaching empty
	MTD device
In-Reply-To: <4C07B8C3.7080304@parrot.com>
References: <4C07B8C3.7080304@parrot.com>
Message-ID: <1275986730.4535.0.camel@localhost>

On Thu, 2010-06-03 at 16:14 +0200, Matthieu CASTET wrote:
> generate random image_seq when attaching empty MTD device (kernel do the 
> ubi formating).

Your patch did not apply to the ubi-2.6.git master, because it
conflicted with my latest changes. But I amended it and pushed, but you
should probably check.

Thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From taliaferro62 at gmail.com  Tue Jun  8 09:44:36 2010
From: taliaferro62 at gmail.com (twebb)
Date: Tue, 8 Jun 2010 09:44:36 -0400
Subject: UBIFS failed to recover master node
In-Reply-To: <1274763914.2106.1.camel@localhost>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763914.2106.1.camel@localhost>
Message-ID: <AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>

>> I've had several cases where our MLC NAND flash appears corrupted in
>> such a way that one of three UBIFS volumes can not be mounted due to
>> "failed to recover master node". ?I haven't been able to reproduce the
>> problem, but we've had at least 5 incidents where this has occurred.
>> (A partial capture from one of the failures is below.)
>>
>> I'm starting to investigate this problem and don't know if this is a
>> UBIFS/UBI problem or a NAND driver problem. ?I'm starting the process
>> of back-porting the latest UBIFS code to our 2.6.29 kernel - hoping
>> that new UBIFS code will solve the problem. ?However, this may also be
>> a driver problem and I wonder if I also need to update that driver
>> (pxa3xx_nand). ?Any suggestions for debugging this problem?
>>
>> Thanks,
>> twebb
>>
>>
>> capture:
>> [root at ESIedge mtd-utils]# mount -t ubifs ubi0_0 /mnt/
>> [ ?239.605869] UBI error: ubi_io_read: error -74 while reading 516096
>> bytes from PEB 4:8192, read 516096 bytes
>> [ ?239.616317] UBIFS error (pid 676): ubifs_scan: corrupt empty space
>> at LEB 2:268135
>> [ ?239.623996] UBIFS error (pid 676): ubifs_scanned_corruption:
>> corruption at LEB 2:268135
>> [ ?239.642101] UBIFS error (pid 676): ubifs_scan: LEB 2 scanning failed
>> [ ?239.976396] UBI error: ubi_io_read: error -74 while reading 516096
>> bytes from PEB 4:8192, read 516096 bytes
>> [ ?239.986742] UBIFS error (pid 676): ubifs_recover_master_node:
>> failed to recover master node
>> mount: mounting ubi0_0 on /mnt/ failed: Invalid argument
>
> Please, enable all debugging messages, mount this flash again, and send
> the messages.
>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>

I've attached a log file that captures the problem I'm seeing.  The
log includes failures on 2 of 4 UBIFS volumes that are part of a
single MTD device (and shows the other 2 volumes being
mounted/umounted without error).

It appears from the log that the problem is associated with "corrupt
empty space" which can be seen in the log at lines 28, 313, 347, and
359.  Could this be HW ECC failing to correct bit errors on reads?
Any suggestions on what this problem would be helpful.

I'm using MLC NAND (Samsung K9LBG08U0D) on a Marvell Armada PXA16x.

Regards,
twebb
-------------- next part --------------
[root at ESIedge /]#           
[root at ESIedge /]#           
[root at ESIedge /]# mount -t ubifs ubi:system /mnt
[  406.611932] UBIFS DBG (pid 702): ubifs_bg_thread: background thread "ubifs_bgt0_0" started, PID 702
[  406.703525] UBIFS: recovery needed                                                                 
[  406.760791] UBI error: ubi_io_read: error -74 while reading 135168 bytes from PEB 1539:389120, read 135168 bytes
[  406.771020] [<c003623c>] (dump_stack+0x0/0x14) from [<c028fac4>] (ubi_io_read+0x1a8/0x23c)    
[  406.779326] [<c028f91c>] (ubi_io_read+0x0/0x23c) from [<c028ea00>] (ubi_eba_read_leb+0x2dc/0x3f4) 
[  406.788257] [<c028e724>] (ubi_eba_read_leb+0x0/0x3f4) from [<c028cf0c>] (ubi_leb_read+0xdc/0x134)
[  406.797182] [<c028ce30>] (ubi_leb_read+0x0/0x134) from [<c0186960>] (ubifs_start_scan+0xd0/0x150) 
[  406.806115]  r7:0000010e r6:0005d000 r5:d9dfe2e0 r4:c05619c0                                     
[  406.811816] [<c0186890>] (ubifs_start_scan+0x0/0x150) from [<c019c294>] (ubifs_recover_leb+0xa4/0xa1c) 
[  406.821174] [<c019c1f0>] (ubifs_recover_leb+0x0/0xa1c) from [<c01874f0>] (replay_buds+0x108/0xb1c)    
[  406.830179] [<c01873e8>] (replay_buds+0x0/0xb1c) from [<c0188804>] (ubifs_replay_journal+0x900/0x1164) 
[  406.839516] [<c0187f04>] (ubifs_replay_journal+0x0/0x1164) from [<c0179c00>] (ubifs_fill_super+0xa3c/0x1b84)
[  406.849385] [<c01791c4>] (ubifs_fill_super+0x0/0x1b84) from [<c017c17c>] (ubifs_get_sb+0x2d0/0x34c)
[  406.858477] [<c017beac>] (ubifs_get_sb+0x0/0x34c) from [<c00b35bc>] (vfs_kern_mount+0x58/0xa4)    
[  406.867147] [<c00b3564>] (vfs_kern_mount+0x0/0xa4) from [<c00b3668>] (do_kern_mount+0x40/0xdc)   
[  406.875801]  r8:c052d720 r7:d9a99000 r6:d9a50000 r5:d81e4000 r4:00008000                        
[  406.882554] [<c00b3628>] (do_kern_mount+0x0/0xdc) from [<c00c94b8>] (do_mount+0x6d8/0x728)     
[  406.890871]  r8:d9a99000 r7:d81e4000 r6:00000000 r5:00000000 r4:00000000                      
[  406.897606] [<c00c8de0>] (do_mount+0x0/0x728) from [<c00c9598>] (sys_mount+0x90/0xdc)        
[  406.905480] [<c00c9508>] (sys_mount+0x0/0xdc) from [<c0031e40>] (ret_fast_syscall+0x0/0x2c) 
[  406.913882]  r7:00000015 r6:000cb0f4 r5:be96c99c r4:000ce018                               
[  406.920335] UBIFS error (pid 700): ubifs_recover_leb: corrupt empty space LEB 270:380928, corruption starts at 16836
[  406.930895] UBIFS error (pid 700): ubifs_scanned_corruption: corruption at LEB 270:16836 
[  406.938990] UBIFS error (pid 700): ubifs_scanned_corruption: first 8192 bytes from LEB 270:16836  
[  406.947825] 00000000: ffffffef ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  406.959347] 00000020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  406.970869] 00000040: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  406.982404] 00000060: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  406.993922] 00000080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.005449] 000000a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.016969] 000000c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.028488] 000000e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.040011] 00000100: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.051534] 00000120: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.063056] 00000140: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.074581] 00000160: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.086099] 00000180: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.097621] 000001a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.109147] 000001c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.120670] 000001e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.132193] 00000200: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.143713] 00000220: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.155235] 00000240: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.166759] 00000260: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.178282] 00000280: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.189810] 000002a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.201335] 000002c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.212857] 000002e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.224382] 00000300: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.235903] 00000320: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.247428] 00000340: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.258947] 00000360: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.270471] 00000380: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.281994] 000003a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.293517] 000003c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.305040] 000003e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.316559] 00000400: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.328082] 00000420: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.339606] 00000440: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.351129] 00000460: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.362653] 00000480: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.374171] 000004a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.385695] 000004c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.397220] 000004e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.408740] 00000500: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.420268] 00000520: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.431794] 00000540: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.443315] 00000560: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.454840] 00000580: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.466363] 000005a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.477887] 000005c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.489406] 000005e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.500929] 00000600: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.512452] 00000620: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.523975] 00000640: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.535499] 00000660: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.547018] 00000680: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.558541] 000006a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.570067] 000006c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.581588] 000006e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.593139] 00000700: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.604659] 00000720: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.616189] 00000740: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.627713] 00000760: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.639235] 00000780: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.650761] 000007a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.662280] 000007c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.673801] 000007e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.685326] 00000800: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.696848] 00000820: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.708373] 00000840: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.719894] 00000860: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.731423] 00000880: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.742948] 000008a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.754470] 000008c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.765993] 000008e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.777513] 00000900: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.789035] 00000920: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.800562] 00000940: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.812091] 00000960: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.823615] 00000980: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.835135] 000009a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.846656] 000009c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.858181] 000009e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  407.869702] 00000a00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.881230] 00000a20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.892756] 00000a40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.904277] 00000a60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.915803] 00000a80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.927325] 00000aa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.938849] 00000ac0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.950370] 00000ae0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.961890] 00000b00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.973414] 00000b20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.984937] 00000b40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  407.996462] 00000b60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.007982] 00000b80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.019504] 00000ba0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.031029] 00000bc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.042550] 00000be0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.054074] 00000c00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.065594] 00000c20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.077116] 00000c40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.088640] 00000c60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.100164] 00000c80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.111688] 00000ca0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.123207] 00000cc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.134729] 00000ce0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.146253] 00000d00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.157776] 00000d20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.169301] 00000d40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.180822] 00000d60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.192350] 00000d80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.203876] 00000da0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  408.215405] 00000dc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.226930] 00000de0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.238450] 00000e00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.249974] 00000e20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.261496] 00000e40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.273018] 00000e60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.284543] 00000e80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.296062] 00000ea0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.307584] 00000ec0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.319109] 00000ee0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.330632] 00000f00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.342155] 00000f20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.353674] 00000f40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.365197] 00000f60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.376721] 00000f80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.388243] 00000fa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.399771] 00000fc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.411296] 00000fe0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.422818] 00001000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.434342] 00001020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.445865] 00001040: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.457389] 00001060: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.468908] 00001080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.480433] 000010a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.491956] 000010c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.503477] 000010e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.515001] 00001100: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.526522] 00001120: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.538043] 00001140: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.549567] 00001160: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.561091] 00001180: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.572615] 000011a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.584134] 000011c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.595655] 000011e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.607182] 00001200: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.618711] 00001220: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.630237] 00001240: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.641756] 00001260: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.653278] 00001280: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.664802] 000012a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.676324] 000012c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.687849] 000012e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.699368] 00001300: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.710892] 00001320: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.722416] 00001340: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.733938] 00001360: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.745462] 00001380: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.756980] 000013a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.768503] 000013c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.780029] 000013e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.791549] 00001400: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.803074] 00001420: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.814593] 00001440: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.826115] 00001460: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.837640] 00001480: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.849162] 000014a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.860688] 000014c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.872207] 000014e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.883728] 00001500: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.895253] 00001520: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.906774] 00001540: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.918300] 00001560: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.929820] 00001580: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.941340] 000015a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.952866] 000015c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.964388] 000015e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.975912] 00001600: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.987432] 00001620: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  408.998954] 00001640: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.010481] 00001660: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.022009] 00001680: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.033533] 000016a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.045053] 000016c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.056575] 000016e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.068099] 00001700: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.079622] 00001720: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.091147] 00001740: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.102666] 00001760: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.114188] 00001780: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.125712] 000017a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.137233] 000017c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.148759] 000017e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.160280] 00001800: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.171800] 00001820: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.183325] 00001840: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.194847] 00001860: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.206372] 00001880: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.217892] 000018a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.229413] 000018c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.240939] 000018e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.252460] 00001900: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.263984] 00001920: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.275504] 00001940: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.287026] 00001960: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.298551] 00001980: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.310074] 000019a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.321596] 000019c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.333117] 000019e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.344638] 00001a00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.356162] 00001a20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.367685] 00001a40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.379209] 00001a60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.390730] 00001a80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.402251] 00001aa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.413777] 00001ac0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.425297] 00001ae0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.436823] 00001b00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.448341] 00001b20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.459865] 00001b40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.471389] 00001b60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.482910] 00001b80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.494435] 00001ba0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.505955] 00001bc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.517476] 00001be0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.529000] 00001c00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.540525] 00001c20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.552048] 00001c40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.563567] 00001c60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.575088] 00001c80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.586612] 00001ca0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.598136] 00001cc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.609660] 00001ce0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.621182] 00001d00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.632710] 00001d20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.644234] 00001d40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.655757] 00001d60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.667282] 00001d80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.678801] 00001da0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.690325] 00001dc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.701848] 00001de0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.713371] 00001e00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.724894] 00001e20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.736413] 00001e40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.747935] 00001e60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.759460] 00001e80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.770984] 00001ea0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.782507] 00001ec0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.794026] 00001ee0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.805549] 00001f00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.817073] 00001f20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.828596] 00001f40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.840122] 00001f60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.851639] 00001f80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.863161] 00001fa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.874686] 00001fc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.886208] 00001fe0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................ 
[  409.897721] UBIFS error (pid 700): ubifs_recover_leb: LEB 270 scanning failed  
[  409.905396] UBIFS DBG (pid 702): ubifs_bg_thread: background thread "ubifs_bgt0_0" stops 
mount: mounting ubi:system on /mnt failed: Structure needs cleaning                        
[root at ESIedge /]# 
[root at ESIedge /]# 
[root at ESIedge /]# 
[root at ESIedge /]# mount -t ubifs ubi:userdata /mnt                                     
[  461.811798] UBIFS DBG (pid 706): ubifs_bg_thread: background thread "ubifs_bgt0_1" started, PID 706 
[  461.870200] UBI error: ubi_io_read: error -74 while reading 516096 bytes from PEB 1005:8192, read 516096 bytes
[  461.880258] [<c003623c>] (dump_stack+0x0/0x14) from [<c028fac4>] (ubi_io_read+0x1a8/0x23c) 
[  461.888565] [<c028f91c>] (ubi_io_read+0x0/0x23c) from [<c028ea00>] (ubi_eba_read_leb+0x2dc/0x3f4)
[  461.897492] [<c028e724>] (ubi_eba_read_leb+0x0/0x3f4) from [<c028cf0c>] (ubi_leb_read+0xdc/0x134) 
[  461.906412] [<c028ce30>] (ubi_leb_read+0x0/0x134) from [<c0186960>] (ubifs_start_scan+0xd0/0x150)                    
[  461.915336]  r7:00000001 r6:00000000 r5:d815b4c0 r4:0007e000              
[  461.921038] [<c0186890>] (ubifs_start_scan+0x0/0x150) from [<c0186db0>] (ubifs_scan+0x28/0x334) 
[  461.929780] [<c0186d88>] (ubifs_scan+0x0/0x334) from [<c01856d0>] (ubifs_read_master+0x44/0xd70)
[  461.938582] [<c018568c>] (ubifs_read_master+0x0/0xd70) from [<c0179abc>] (ubifs_fill_super+0x8f8/0x1b84)
[  461.948113] [<c01791c4>] (ubifs_fill_super+0x0/0x1b84) from [<c017c17c>] (ubifs_get_sb+0x2d0/0x34c) 
[  461.957202] [<c017beac>] (ubifs_get_sb+0x0/0x34c) from [<c00b35bc>] (vfs_kern_mount+0x58/0xa4)
[  461.965865] [<c00b3564>] (vfs_kern_mount+0x0/0xa4) from [<c00b3668>] (do_kern_mount+0x40/0xdc) 
[  461.974520]  r8:c052d720 r7:d81f1000 r6:d9df3000 r5:d8087000 r4:00008000                      
[  461.981273] [<c00b3628>] (do_kern_mount+0x0/0xdc) from [<c00c94b8>] (do_mount+0x6d8/0x728)   
[  461.989598]  r8:d81f1000 r7:d8087000 r6:00000000 r5:00000000 r4:00000000                    
[  461.996325] [<c00c8de0>] (do_mount+0x0/0x728) from [<c00c9598>] (sys_mount+0x90/0xdc)      
[  462.004207] [<c00c9508>] (sys_mount+0x0/0xdc) from [<c0031e40>] (ret_fast_syscall+0x0/0x2c)  
[  462.012613]  r7:00000015 r6:000cb0f4 r5:bef1599c r4:000ce018                                
[  462.025346] UBIFS error (pid 704): ubifs_scan: corrupt empty space at LEB 1:327722         
[  462.032965] UBIFS error (pid 704): ubifs_scanned_corruption: corruption at LEB 1:327722   
[  462.041003] UBIFS error (pid 704): ubifs_scanned_corruption: first 8192 bytes from LEB 1:327722 
[  462.049751] 00000000: ffffffef ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.061275] 00000020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.072804] 00000040: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.084329] 00000060: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.095856] 00000080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.107388] 000000a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.118912] 000000c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.130445] 000000e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.141967] 00000100: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.153495] 00000120: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.165027] 00000140: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.176550] 00000160: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.188081] 00000180: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.199608] 000001a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.211134] 000001c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.222672] 000001e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.234199] 00000200: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.245728] 00000220: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.257253] 00000240: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.268781] 00000260: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.280313] 00000280: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.291838] 000002a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.303367] 000002c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.314893] 000002e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.326420] 00000300: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.337950] 00000320: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.349476] 00000340: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.361007] 00000360: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.372530] 00000380: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.384059] 000003a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.395589] 000003c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.407114] 000003e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.418645] 00000400: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.430173] 00000420: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.441697] 00000440: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffdff ffffffff  ................................
[  462.453227] 00000460: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.464753] 00000480: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.476283] 000004a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.487807] 000004c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.499336] 000004e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.510868] 00000500: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.522391] 00000520: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.533923] 00000540: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.545447] 00000560: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.556975] 00000580: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.568505] 000005a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.580032] 000005c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffff7ff ffffffff  ................................
[  462.591587] 000005e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.603115] 00000600: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.614640] 00000620: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.626170] 00000640: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.637696] 00000660: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.649227] 00000680: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.660752] 000006a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.672279] 000006c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.683810] 000006e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.695334] 00000700: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.706865] 00000720: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.718390] 00000740: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.729919] 00000760: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.741448] 00000780: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.752973] 000007a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.764504] 000007c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.776028] 000007e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.787556] 00000800: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.799086] 00000820: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.810612] 00000840: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.822142] 00000860: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.833668] 00000880: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.845195] 000008a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.856725] 000008c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.868249] 000008e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.879782] 00000900: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.891306] 00000920: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.902833] 00000940: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.914364] 00000960: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.925888] 00000980: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.937419] 000009a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.948944] 000009c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.960474] 000009e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.972003] 00000a00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.983527] 00000a20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  462.995059] 00000a40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.006587] 00000a60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.018110] 00000a80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.029645] 00000aa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.041166] 00000ac0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.052696] 00000ae0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.064221] 00000b00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.075749] 00000b20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.087279] 00000b40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.098805] 00000b60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.110337] 00000b80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.121860] 00000ba0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.133389] 00000bc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.144919] 00000be0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.156443] 00000c00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.167975] 00000c20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.179500] 00000c40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.191029] 00000c60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.202557] 00000c80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.214082] 00000ca0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.225613] 00000cc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.237139] 00000ce0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.248665] 00000d00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.260199] 00000d20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.271721] 00000d40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.283251] 00000d60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.294776] 00000d80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.306304] 00000da0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.317835] 00000dc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.329359] 00000de0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.340891] 00000e00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.352416] 00000e20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.363943] 00000e40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.375473] 00000e60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.386999] 00000e80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.398529] 00000ea0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.410054] 00000ec0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.421582] 00000ee0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.433113] 00000f00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.444638] 00000f20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.456168] 00000f40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.467692] 00000f60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.479220] 00000f80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.490751] 00000fa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.502276] 00000fc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.513806] 00000fe0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.525331] 00001000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.536860] 00001020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.548390] 00001040: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.559916] 00001060: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.571446] 00001080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.582970] 000010a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.594498] 000010c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.606028] 000010e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.617553] 00001100: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.629083] 00001120: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.640612] 00001140: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.652137] 00001160: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.663667] 00001180: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.675193] 000011a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.686724] 000011c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.698248] 000011e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.709778] 00001200: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.721307] 00001220: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.732832] 00001240: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.744362] 00001260: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.755887] 00001280: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.767414] 000012a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.778945] 000012c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.790471] 000012e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.802000] 00001300: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.813524] 00001320: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.825053] 00001340: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.836583] 00001360: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.848112] 00001380: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.859641] 000013a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.871164] 000013c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.882691] 000013e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.894223] 00001400: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.905747] 00001420: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.917277] 00001440: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.928802] 00001460: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.940331] 00001480: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.951860] 000014a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.963386] 000014c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.974916] 000014e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.986440] 00001500: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  463.997969] 00001520: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.009501] 00001540: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.021025] 00001560: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.032555] 00001580: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.044081] 000015a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.055608] 000015c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.067138] 000015e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.078662] 00001600: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.090195] 00001620: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.101718] 00001640: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.113246] 00001660: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.124776] 00001680: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.136302] 000016a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.147832] 000016c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.159357] 000016e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.170887] 00001700: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.182417] 00001720: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.193941] 00001740: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.205472] 00001760: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.216997] 00001780: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.228524] 000017a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.240058] 000017c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.251580] 000017e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.263110] 00001800: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.274635] 00001820: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.286163] 00001840: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.297693] 00001860: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.309218] 00001880: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.320751] 000018a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.332274] 000018c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.343801] 000018e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.355332] 00001900: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.366857] 00001920: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.378388] 00001940: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.389914] 00001960: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.401440] 00001980: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.412970] 000019a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.424495] 000019c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.436026] 000019e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.447553] 00001a00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.459078] 00001a20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.470611] 00001a40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.482134] 00001a60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.493665] 00001a80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.505189] 00001aa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.516718] 00001ac0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.528247] 00001ae0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.539775] 00001b00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.551303] 00001b20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.562828] 00001b40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.574357] 00001b60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.585886] 00001b80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.597412] 00001ba0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.608942] 00001bc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.620468] 00001be0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.631995] 00001c00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.643527] 00001c20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.655050] 00001c40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.666581] 00001c60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.678106] 00001c80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.689635] 00001ca0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.701165] 00001cc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.712689] 00001ce0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.724220] 00001d00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.735745] 00001d20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.747272] 00001d40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.758803] 00001d60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.770330] 00001d80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.781859] 00001da0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.793383] 00001dc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.804910] 00001de0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.816442] 00001e00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.827966] 00001e20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.839497] 00001e40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.851024] 00001e60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.862550] 00001e80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.874080] 00001ea0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.885604] 00001ec0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.897136] 00001ee0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.908660] 00001f00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.920190] 00001f20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.931719] 00001f40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.943243] 00001f60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.954775] 00001f80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.966299] 00001fa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.977827] 00001fc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  464.989357] 00001fe0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[  465.000870] UBIFS error (pid 704): ubifs_scan: LEB 1 scanning failed
[  465.063443] UBI error: ubi_io_read: error -74 while reading 516096 bytes from PEB 1005:8192, read 516096 bytes
[  465.073498] [<c003623c>] (dump_stack+0x0/0x14) from [<c028fac4>] (ubi_io_read+0x1a8/0x23c)
[  465.081833] [<c028f91c>] (ubi_io_read+0x0/0x23c) from [<c028ea00>] (ubi_eba_read_leb+0x2dc/0x3f4)
[  465.090752] [<c028e724>] (ubi_eba_read_leb+0x0/0x3f4) from [<c028cf0c>] (ubi_leb_read+0xdc/0x134)
[  465.099675] [<c028ce30>] (ubi_leb_read+0x0/0x134) from [<c019ce4c>] (get_master_node+0x5c/0x2bc)
[  465.108487]  r7:00000001 r6:00001000 r5:ffffff8b r4:d80ff3e0
[  465.114189] [<c019cdf0>] (get_master_node+0x0/0x2bc) from [<c019d148>] (ubifs_recover_master_node+0x9c/0x3f0)
[  465.124155] [<c019d0ac>] (ubifs_recover_master_node+0x0/0x3f0) from [<c01857b4>] (ubifs_read_master+0x128/0xd70)
[  465.134389]  r8:00000000 r7:00000001 r6:00276001 r5:ffffff8b r4:d80ff3e0
[  465.141142] [<c018568c>] (ubifs_read_master+0x0/0xd70) from [<c0179abc>] (ubifs_fill_super+0x8f8/0x1b84)
[  465.150666] [<c01791c4>] (ubifs_fill_super+0x0/0x1b84) from [<c017c17c>] (ubifs_get_sb+0x2d0/0x34c)
[  465.159763] [<c017beac>] (ubifs_get_sb+0x0/0x34c) from [<c00b35bc>] (vfs_kern_mount+0x58/0xa4)
[  465.168407] [<c00b3564>] (vfs_kern_mount+0x0/0xa4) from [<c00b3668>] (do_kern_mount+0x40/0xdc)
[  465.177071]  r8:c052d720 r7:d81f1000 r6:d9df3000 r5:d8087000 r4:00008000
[  465.183833] [<c00b3628>] (do_kern_mount+0x0/0xdc) from [<c00c94b8>] (do_mount+0x6d8/0x728)
[  465.192150]  r8:d81f1000 r7:d8087000 r6:00000000 r5:00000000 r4:00000000
[  465.198886] [<c00c8de0>] (do_mount+0x0/0x728) from [<c00c9598>] (sys_mount+0x90/0xdc)
[  465.206758] [<c00c9508>] (sys_mount+0x0/0xdc) from [<c0031e40>] (ret_fast_syscall+0x0/0x2c)
[  465.215170]  r7:00000015 r6:000cb0f4 r5:bef1599c r4:000ce018
[  465.221083] UBIFS error (pid 704): ubifs_recover_master_node: failed to recover master node
[  465.229471] UBIFS DBG (pid 706): ubifs_bg_thread: background thread "ubifs_bgt0_1" stops
mount: mounting ubi:userdata on /mnt failed: Invalid argument
[root at ESIedge /]#
[root at ESIedge /]#
[root at ESIedge /]# 
[root at ESIedge /]# mount -t ubifs ubi:cache /mnt 
[  794.140806] UBIFS DBG (pid 710): ubifs_bg_thread: background thread "ubifs_bgt0_2" started, PID 710
[  794.325833] UBIFS: mounted UBI device 0, volume 2, name "cache"
[  794.331826] UBIFS: file system size:   362815488 bytes (354312 KiB, 346 MiB, 703 LEBs)
[  794.339774] UBIFS: journal size:       18063360 bytes (17640 KiB, 17 MiB, 35 LEBs)   
[  794.347355] UBIFS: media format:       w4/r0 (latest is w4/r0)                      
[  794.353216] UBIFS: default compressor: lzo                                         
[  794.357314] UBIFS: reserved for root:  4952683 bytes (4836 KiB)                   
[  794.363261] UBIFS DBG (pid 708): mount_ubifs: compiled on:         Jun  8 2010 at 08:30:49 
[  794.371560] UBIFS DBG (pid 708): mount_ubifs: min. I/O unit size:  4096 bytes             
[  794.378725] UBIFS DBG (pid 708): mount_ubifs: LEB size:            516096 bytes (504 KiB)
[  794.386907] UBIFS DBG (pid 708): mount_ubifs: data journal heads:  1                    
[  794.393296] UBIFS DBG (pid 708): mount_ubifs: UUID:                0867B778-8505-4B8C-A599-99D5850BA2C1
[  794.402722] UBIFS DBG (pid 708): mount_ubifs: big_lpt              0           
[  794.409108] UBIFS DBG (pid 708): mount_ubifs: log LEBs:            3 (3 - 5)  
[  794.416162] UBIFS DBG (pid 708): mount_ubifs: LPT area LEBs:       2 (6 - 7) 
[  794.423236] UBIFS DBG (pid 708): mount_ubifs: orphan area LEBs:    1 (8 - 8)
[  794.430310] UBIFS DBG (pid 708): mount_ubifs: main area LEBs:      703 (9 - 711) 
[  794.437708] UBIFS DBG (pid 708): mount_ubifs: index LEBs:          1            
[  794.444087] UBIFS DBG (pid 708): mount_ubifs: total index bytes:   744 (0 KiB, 0 MiB)
[  794.451958] UBIFS DBG (pid 708): mount_ubifs: key hash type:       0                
[  794.458314] UBIFS DBG (pid 708): mount_ubifs: tree fanout:         8      
[  794.464696] UBIFS DBG (pid 708): mount_ubifs: reserved GC LEB:     11    
[  794.471168] UBIFS DBG (pid 708): mount_ubifs: first main LEB:      9    
[  794.477524] UBIFS DBG (pid 708): mount_ubifs: max. znode size      240 
[  794.484076] UBIFS DBG (pid 708): mount_ubifs: max. index node size 192
[  794.490634] UBIFS DBG (pid 708): mount_ubifs: node sizes:          data 48, inode 160, dentry 56
[  794.499452] UBIFS DBG (pid 708): mount_ubifs: node sizes:          trun 56, sb 4096, master 512
[  794.508159] UBIFS DBG (pid 708): mount_ubifs: node sizes:          ref 64, cmt. start 32, orph 32 
[  794.517065] UBIFS DBG (pid 708): mount_ubifs: max. node sizes:     data 4144, inode 4256 dentry 312 
[  794.526146] UBIFS DBG (pid 708): mount_ubifs: dead watermark:      4096  
[  794.532791] UBIFS DBG (pid 708): mount_ubifs: dark watermark:      8192 
[  794.539432] UBIFS DBG (pid 708): mount_ubifs: LEB overhead:        2240  
[  794.546049] UBIFS DBG (pid 708): mount_ubifs: max. dark space:     5758976 (5624 KiB, 5 MiB) 
[  794.554524] UBIFS DBG (pid 708): mount_ubifs: maximum bud bytes:   16515072 (16128 KiB, 15 MiB)
[  794.563254] UBIFS DBG (pid 708): mount_ubifs: BG commit bud bytes: 13418496 (13104 KiB, 12 MiB) 
[  794.571986] UBIFS DBG (pid 708): mount_ubifs: current bud bytes    663552 (648 KiB, 0 MiB) 
[  794.580286] UBIFS DBG (pid 708): mount_ubifs: max. seq. number:    17730 
[  794.586994] UBIFS DBG (pid 708): mount_ubifs: commit number:       3255 
[root at ESIedge /]#   
[root at ESIedge /]#  
[root at ESIedge /]# umount /mnt   
[  810.452088] UBIFS: un-mount UBI device 0, volume 2  
[  810.456904] UBIFS DBG (pid 710): ubifs_bg_thread: background thread "ubifs_bgt0_2" stops 
[root at ESIedge /]#                                                                          
[root at ESIedge /]# mount -t ubifs ubi:storage /mnt
[  818.450714] UBIFS DBG (pid 715): ubifs_bg_thread: background thread "ubifs_bgt0_3" started, PID 715
[  818.657544] UBIFS: mounted UBI device 0, volume 3, name "storage"                                  
[  818.663720] UBIFS: file system size:   2908200960 bytes (2840040 KiB, 2773 MiB, 5635 LEBs)         
[  818.672021] UBIFS: journal size:       33546240 bytes (32760 KiB, 31 MiB, 65 LEBs)                 
[  818.679623] UBIFS: media format:       w4/r0 (latest is w4/r0)                                     
[  818.685455] UBIFS: default compressor: lzo                                                         
[  818.689578] UBIFS: reserved for root:  4952683 bytes (4836 KiB)                                    
[  818.695503] UBIFS DBG (pid 713): mount_ubifs: compiled on:         Jun  8 2010 at 08:30:49         
[  818.703798] UBIFS DBG (pid 713): mount_ubifs: min. I/O unit size:  4096 bytes                      
[  818.710961] UBIFS DBG (pid 713): mount_ubifs: LEB size:            516096 bytes (504 KiB)          
[  818.719170] UBIFS DBG (pid 713): mount_ubifs: data journal heads:  1                               
[  818.725538] UBIFS DBG (pid 713): mount_ubifs: UUID:                85821A0E-6A57-4B04-9875-8E36F675717B
[  818.734961] UBIFS DBG (pid 713): mount_ubifs: big_lpt              0                                   
[  818.741341] UBIFS DBG (pid 713): mount_ubifs: log LEBs:            4 (3 - 6)
[  818.748391] UBIFS DBG (pid 713): mount_ubifs: LPT area LEBs:       2 (7 - 8)
[  818.755468] UBIFS DBG (pid 713): mount_ubifs: orphan area LEBs:    1 (9 - 9)
[  818.762548] UBIFS DBG (pid 713): mount_ubifs: main area LEBs:      5635 (10 - 5644)
[  818.770238] UBIFS DBG (pid 713): mount_ubifs: index LEBs:          9
[  818.776594] UBIFS DBG (pid 713): mount_ubifs: total index bytes:   2231560 (2179 KiB, 2 MiB)
[  818.785068] UBIFS DBG (pid 713): mount_ubifs: key hash type:       0
[  818.791453] UBIFS DBG (pid 713): mount_ubifs: tree fanout:         8
[  818.797808] UBIFS DBG (pid 713): mount_ubifs: reserved GC LEB:     680
[  818.804361] UBIFS DBG (pid 713): mount_ubifs: first main LEB:      10
[  818.810831] UBIFS DBG (pid 713): mount_ubifs: max. znode size      240
[  818.817365] UBIFS DBG (pid 713): mount_ubifs: max. index node size 192
[  818.823919] UBIFS DBG (pid 713): mount_ubifs: node sizes:          data 48, inode 160, dentry 56
[  818.832740] UBIFS DBG (pid 713): mount_ubifs: node sizes:          trun 56, sb 4096, master 512
[  818.841475] UBIFS DBG (pid 713): mount_ubifs: node sizes:          ref 64, cmt. start 32, orph 32
[  818.850386] UBIFS DBG (pid 713): mount_ubifs: max. node sizes:     data 4144, inode 4256 dentry 312
[  818.859466] UBIFS DBG (pid 713): mount_ubifs: dead watermark:      4096
[  818.866084] UBIFS DBG (pid 713): mount_ubifs: dark watermark:      8192
[  818.872728] UBIFS DBG (pid 713): mount_ubifs: LEB overhead:        2240
[  818.879372] UBIFS DBG (pid 713): mount_ubifs: max. dark space:     46161920 (45080 KiB, 44 MiB)
[  818.888079] UBIFS DBG (pid 713): mount_ubifs: maximum bud bytes:   31481856 (30744 KiB, 30 MiB)
[  818.896813] UBIFS DBG (pid 713): mount_ubifs: BG commit bud bytes: 25579008 (24979 KiB, 24 MiB)
[  818.905543] UBIFS DBG (pid 713): mount_ubifs: current bud bytes    655360 (640 KiB, 0 MiB)
[  818.913840] UBIFS DBG (pid 713): mount_ubifs: max. seq. number:    151596
[  818.920654] UBIFS DBG (pid 713): mount_ubifs: commit number:       3223
[root at ESIedge /]#
[root at ESIedge /]# umount /mnt
[  822.710627] UBIFS: un-mount UBI device 0, volume 3
[  822.715445] UBIFS DBG (pid 715): ubifs_bg_thread: background thread "ubifs_bgt0_3" stops
[root at ESIedge /]#
[root at ESIedge /]#


From dedekind1 at gmail.com  Tue Jun  8 10:17:28 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 08 Jun 2010 17:17:28 +0300
Subject: UBIFS failed to recover master node
In-Reply-To: <AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763914.2106.1.camel@localhost>
	<AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>
Message-ID: <1276006648.5677.20.camel@localhost>

On Tue, 2010-06-08 at 09:44 -0400, twebb wrote:
> I've attached a log file that captures the problem I'm seeing.

twebb, you did not enable debugging messages. But it looks like they are
not actually needed. 

>   The
> log includes failures on 2 of 4 UBIFS volumes that are part of a
> single MTD device (and shows the other 2 volumes being
> mounted/umounted without error).
> 
> It appears from the log that the problem is associated with "corrupt
> empty space" which can be seen in the log at lines 28, 313, 347, and
> 359.  Could this be HW ECC failing to correct bit errors on reads?
> Any suggestions on what this problem would be helpful.

Yes, HW fails to correct bit errors. Why these errors are there - this
it the question. May be MLC-related. You need to debug this. Or send me
your board, I can try to take a look

Did you enable UBI extra self checks?


Best Regards,
Artem Bityutskiy (????? ????????)



From kspaans at uwaterloo.ca  Tue Jun  8 09:48:22 2010
From: kspaans at uwaterloo.ca (Kyle Spaans)
Date: Tue, 8 Jun 2010 09:48:22 -0400
Subject: [PATCH] MTD: remove redundant dependency checks in Kconfig files
Message-ID: <20100608134822.GA18437@caffeine.csclub.uwaterloo.ca>

Look for dependency checks for "FOO" when inside of an "if FOO" block and remove them.

Signed-off-by: Kyle Spaans <kspaans at uwaterloo.ca>
Reviewed-by: Robert P. J. Day <rpjday at crashcourse.ca>
---

compile-tested on Ubuntu 10.04

 drivers/mtd/Kconfig         |    1 -
 drivers/mtd/nand/Kconfig    |   30 ++++++++++++++----------------
 drivers/mtd/onenand/Kconfig |    4 ++--
 3 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index f8210bf..71eda03 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -319,7 +319,6 @@ config SM_FTL
 
 config MTD_OOPS
 	tristate "Log panic/oops to an MTD buffer"
-	depends on MTD
 	help
 	  This enables panic and oops messages to be logged to a circular
 	  buffer in a flash partition where it can be read back at some
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ffc3720..4d4066f 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -37,7 +37,6 @@ config MTD_SM_COMMON
 
 config MTD_NAND_MUSEUM_IDS
 	bool "Enable chip ids for obsolete ancient NAND devices"
-	depends on MTD_NAND
 	default n
 	help
 	  Enable this option only when your board has first generation
@@ -101,13 +100,13 @@ config MTD_NAND_AMS_DELTA
 
 config MTD_NAND_OMAP2
 	tristate "NAND Flash device on OMAP2 and OMAP3"
-	depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3)
+	depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3)
 	help
           Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
 
 config MTD_NAND_OMAP_PREFETCH
 	bool "GPMC prefetch support for NAND Flash device"
-	depends on MTD_NAND && MTD_NAND_OMAP2
+	depends on MTD_NAND_OMAP2
 	default y
 	help
 	 The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
@@ -146,7 +145,7 @@ config MTD_NAND_AU1550
 
 config MTD_NAND_BF5XX
 	tristate "Blackfin on-chip NAND Flash Controller driver"
-	depends on (BF54x || BF52x) && MTD_NAND
+	depends on BF54x || BF52x
 	help
 	  This enables the Blackfin on-chip NAND flash controller
 
@@ -236,7 +235,7 @@ config MTD_NAND_S3C2410_CLKSTOP
 
 config MTD_NAND_BCM_UMI
 	tristate "NAND Flash support for BCM Reference Boards"
-	depends on ARCH_BCMRING && MTD_NAND
+	depends on ARCH_BCMRING
 	help
 	  This enables the NAND flash controller on the BCM UMI block.
 
@@ -395,7 +394,7 @@ endchoice
 
 config MTD_NAND_PXA3xx
 	tristate "Support for NAND flash devices on PXA3xx"
-	depends on MTD_NAND && (PXA3xx || ARCH_MMP)
+	depends on PXA3xx || ARCH_MMP
 	help
 	  This enables the driver for the NAND flash device found on
 	  PXA3xx processors
@@ -409,18 +408,18 @@ config MTD_NAND_PXA3xx_BUILTIN
 
 config MTD_NAND_CM_X270
 	tristate "Support for NAND Flash on CM-X270 modules"
-	depends on MTD_NAND && MACH_ARMCORE
+	depends on MACH_ARMCORE
 
 config MTD_NAND_PASEMI
 	tristate "NAND support for PA Semi PWRficient"
-	depends on MTD_NAND && PPC_PASEMI
+	depends on PPC_PASEMI
 	help
 	  Enables support for NAND Flash interface on PA Semi PWRficient
 	  based boards
 
 config MTD_NAND_TMIO
 	tristate "NAND Flash device on Toshiba Mobile IO Controller"
-	depends on MTD_NAND && MFD_TMIO
+	depends on MFD_TMIO
 	help
 	  Support for NAND flash connected to a Toshiba Mobile IO
 	  Controller in some PDAs, including the Sharp SL6000x.
@@ -434,7 +433,6 @@ config MTD_NAND_NANDSIM
 
 config MTD_NAND_PLATFORM
 	tristate "Support for generic platform NAND driver"
-	depends on MTD_NAND
 	help
 	  This implements a generic NAND driver for on-SOC platform
 	  devices. You will need to provide platform-specific functions
@@ -442,14 +440,14 @@ config MTD_NAND_PLATFORM
 
 config MTD_ALAUDA
 	tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
-	depends on MTD_NAND && USB
+	depends on USB
 	help
 	  These two (and possibly other) Alauda-based cardreaders for
 	  SmartMedia and xD allow raw flash access.
 
 config MTD_NAND_ORION
 	tristate "NAND Flash support for Marvell Orion SoC"
-	depends on PLAT_ORION && MTD_NAND
+	depends on PLAT_ORION
 	help
 	  This enables the NAND flash controller on Orion machines.
 
@@ -458,7 +456,7 @@ config MTD_NAND_ORION
 
 config MTD_NAND_FSL_ELBC
 	tristate "NAND support for Freescale eLBC controllers"
-	depends on MTD_NAND && PPC_OF
+	depends on PPC_OF
 	help
 	  Various Freescale chips, including the 8313, include a NAND Flash
 	  Controller Module with built-in hardware ECC capabilities.
@@ -467,7 +465,7 @@ config MTD_NAND_FSL_ELBC
 
 config MTD_NAND_FSL_UPM
 	tristate "Support for NAND on Freescale UPM"
-	depends on MTD_NAND && (PPC_83xx || PPC_85xx)
+	depends on PPC_83xx || PPC_85xx
 	select FSL_LBC
 	help
 	  Enables support for NAND Flash chips wired onto Freescale PowerPC
@@ -495,7 +493,7 @@ config MTD_NAND_NOMADIK
 
 config MTD_NAND_SH_FLCTL
 	tristate "Support for NAND on Renesas SuperH FLCTL"
-	depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE)
+	depends on SUPERH || ARCH_SHMOBILE
 	help
 	  Several Renesas SuperH CPU has FLCTL. This option enables support
 	  for NAND Flash using FLCTL.
@@ -515,7 +513,7 @@ config MTD_NAND_TXX9NDFMC
 
 config MTD_NAND_SOCRATES
 	tristate "Support for NAND on Socrates board"
-	depends on MTD_NAND && SOCRATES
+	depends on SOCRATES
 	help
 	  Enables support for NAND Flash chips wired onto Socrates board.
 
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 9a49d68..3f32289 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -25,14 +25,14 @@ config MTD_ONENAND_GENERIC
 
 config MTD_ONENAND_OMAP2
 	tristate "OneNAND on OMAP2/OMAP3 support"
-	depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3)
+	depends on ARCH_OMAP2 || ARCH_OMAP3
 	help
 	  Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU
 	  via the GPMC memory controller.
 
 config MTD_ONENAND_SAMSUNG
         tristate "OneNAND on Samsung SOC controller support"
-        depends on MTD_ONENAND && (ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210)
+        depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
         help
           Support for a OneNAND flash device connected to an Samsung SOC
           S3C64XX/S5PC1XX controller.
-- 
1.5.6.5

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20100608/167a252f/attachment.sig>

From taliaferro62 at gmail.com  Tue Jun  8 11:00:04 2010
From: taliaferro62 at gmail.com (twebb)
Date: Tue, 8 Jun 2010 11:00:04 -0400
Subject: UBIFS failed to recover master node
In-Reply-To: <1276006648.5677.20.camel@localhost>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763914.2106.1.camel@localhost>
	<AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>
	<1276006648.5677.20.camel@localhost>
Message-ID: <AANLkTilYTO_TgJMVrkmY1yAUK5dGTjyzgNIhndNui3r1@mail.gmail.com>

On Tue, Jun 8, 2010 at 10:17 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2010-06-08 at 09:44 -0400, twebb wrote:
>> I've attached a log file that captures the problem I'm seeing.
>
> twebb, you did not enable debugging messages. But it looks like they are
> not actually needed.

I config'd kernel with...
CONFIG_MTD_UBI_DEBUG=y
CONFIG_UBIFS_FS_DEBUG=y

Did I miss something else?

>
>> ? The
>> log includes failures on 2 of 4 UBIFS volumes that are part of a
>> single MTD device (and shows the other 2 volumes being
>> mounted/umounted without error).
>>
>> It appears from the log that the problem is associated with "corrupt
>> empty space" which can be seen in the log at lines 28, 313, 347, and
>> 359. ?Could this be HW ECC failing to correct bit errors on reads?
>> Any suggestions on what this problem would be helpful.
>
> Yes, HW fails to correct bit errors. Why these errors are there - this
> it the question. May be MLC-related. You need to debug this. Or send me
> your board, I can try to take a look

I'll look into it, thanks.

>
> Did you enable UBI extra self checks?
>

No.


From egorkat at gmail.com  Tue Jun  8 11:13:37 2010
From: egorkat at gmail.com (Egorkat)
Date: Tue, 8 Jun 2010 15:13:37 +0000 (UTC)
Subject: modprobe nftl hangs
Message-ID: <loom.20100608T165617-407@post.gmane.org>

Good day to ALL!

I'm struggling with M-systems DiskOnChip support under kernel 2.6.34.

Compiled support for DoC as a module under MTD device.
Module loads fine, no errors.
When I make nftl_format /dev/mtd0, I receive warnings:

voyage:~# nftl_format /dev/mtd0
version 1.24 2005/11/07 11:15:13 gleixner
Phase 1. Checking and erasing Erase Zones from 0x00000000 to 0x02000000
Skipping bad zone (factory marked) #0 @ 0x0
Skipping bad zone (factory marked) #1 @ 0x4000
Skipping bad zone (factory marked) #3 @ 0xc000
Skipping bad zone (factory marked) #4 @ 0x10000

After I try to modprobe nftl, I get:
NFTL Media Headers at 0x0 and 0x8000 disagree.
NFTL Media Headers at 0x0 and 0xc000 disagree.
NFTL Media Headers at 0x0 and 0x10000 disagree.
NFTL Media Headers at 0x0 and 0x14000 disagree.
Formatting block 2
Formatting block 5

And in hangs forever...

I think it is a problem in wrong headers at 0x0, which also resides on bad zone
But how to work this around?

With best Regards,
Egorkat.



From taliaferro62 at gmail.com  Tue Jun  8 11:23:11 2010
From: taliaferro62 at gmail.com (twebb)
Date: Tue, 8 Jun 2010 11:23:11 -0400
Subject: UBIFS failed to recover master node
In-Reply-To: <AANLkTilYTO_TgJMVrkmY1yAUK5dGTjyzgNIhndNui3r1@mail.gmail.com>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763914.2106.1.camel@localhost>
	<AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>
	<1276006648.5677.20.camel@localhost>
	<AANLkTilYTO_TgJMVrkmY1yAUK5dGTjyzgNIhndNui3r1@mail.gmail.com>
Message-ID: <AANLkTil23ApPd97_nAsfu0c_mUdVcZEFwCW7St5V8pE0@mail.gmail.com>

>>
>> twebb, you did not enable debugging messages. But it looks like they are
>> not actually needed.
>
> I config'd kernel with...
> CONFIG_MTD_UBI_DEBUG=y
> CONFIG_UBIFS_FS_DEBUG=y
>
> Did I miss something else?
>

Never mind, I now see what I missed:  CONFIG_MTD_UBI_DEBUG_MSG=y


From taliaferro62 at gmail.com  Tue Jun  8 11:33:13 2010
From: taliaferro62 at gmail.com (twebb)
Date: Tue, 8 Jun 2010 11:33:13 -0400
Subject: UBIFS failed to recover master node
In-Reply-To: <1276006648.5677.20.camel@localhost>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763914.2106.1.camel@localhost>
	<AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>
	<1276006648.5677.20.camel@localhost>
Message-ID: <AANLkTimrMIdM2anf2_mgiJ5BS2ykPFukStdpEe1Vna0V@mail.gmail.com>

>
> twebb, you did not enable debugging messages. But it looks like they are
> not actually needed.
>

Here's a new log of one of the failures with debugging messages
(CONFIG_MTD_UBI_DEBUG_MSG=y) enabled.  As you said, it appears that
the extra traces aren't necessary since the real issue seems to be the
corrupt empty space.

twebb
-------------- next part --------------
[root at ESIedge /]#
[root at ESIedge /]# mount -t ubifs ubi:system /mnt
[   69.456519] UBI DBG (pid 698): ubi_open_volume_nm: open device 0, volume system, mode 1
[   69.464604] UBI DBG (pid 698): ubi_open_volume: open device 0, volume 0, mode 1        
[   69.471972] UBI DBG (pid 698): ubi_open_volume: open device 0, volume 0, mode 2        
[   69.484766] UBI DBG (pid 698): ubi_is_mapped: test LEB 0:0                             
[   69.490674] UBI DBG (pid 698): ubi_leb_read: read 4096 bytes from LEB 0:0:0            
[   69.498417] UBI DBG (pid 698): ubi_leb_read: read 516096 bytes from LEB 0:1:0          
[   69.505667] UBIFS DBG (pid 700): ubifs_bg_thread: background thread "ubifs_bgt0_0" started, PID 700
[   69.555788] UBI DBG (pid 698): ubi_leb_read: read 516096 bytes from LEB 0:2:0                      
[   69.604044] UBI DBG (pid 698): ubi_leb_read: read 88 bytes from LEB 0:329:344520                   
[   69.612009] UBIFS: recovery needed                                                                 
[   69.615419] UBI DBG (pid 698): ubi_leb_read: read 4096 bytes from LEB 0:329:348160                 
[   69.623375] UBI DBG (pid 698): ubi_leb_read: read 4096 bytes from LEB 0:7:315392                   
[   69.631273] UBI DBG (pid 698): ubi_leb_read: read 12 bytes from LEB 0:7:311296                     
[   69.639263] UBI DBG (pid 698): ubi_leb_read: read 13 bytes from LEB 0:7:311687                     
[   69.646557] UBI DBG (pid 698): ubi_leb_read: read 13 bytes from LEB 0:7:311674                     
[   69.653825] UBI DBG (pid 698): ubi_leb_read: read 13 bytes from LEB 0:7:311552                     
[   69.661084] UBI DBG (pid 698): ubi_leb_read: read 13 bytes from LEB 0:7:307813                     
[   69.668797] UBI DBG (pid 698): ubi_leb_read: read 19 bytes from LEB 0:7:307794                     
[   69.676315] UBI DBG (pid 698): ubi_leb_read: read 516096 bytes from LEB 0:6:0                      
[   69.722922] UBI DBG (pid 698): ubi_leb_read: read 516096 bytes from LEB 0:3:0                      
[   69.732637] UBI DBG (pid 698): ubi_leb_read: read 135168 bytes from LEB 0:270:380928               
[   69.750158] UBI error: ubi_io_read: error -74 while reading 135168 bytes from PEB 1539:389120, read 135168 bytes
[   69.760389] [<c003623c>] (dump_stack+0x0/0x14) from [<c0290240>] (ubi_io_read+0x1a8/0x23c)
[   69.768719] [<c0290098>] (ubi_io_read+0x0/0x23c) from [<c028f17c>] (ubi_eba_read_leb+0x2dc/0x3f4)
[   69.777642] [<c028eea0>] (ubi_eba_read_leb+0x0/0x3f4) from [<c028d4a0>] (ubi_leb_read+0x108/0x164)
[   69.786644] [<c028d398>] (ubi_leb_read+0x0/0x164) from [<c0186960>] (ubifs_start_scan+0xd0/0x150)
[   69.795571] [<c0186890>] (ubifs_start_scan+0x0/0x150) from [<c019c294>] (ubifs_recover_leb+0xa4/0xa1c)
[   69.804934] [<c019c1f0>] (ubifs_recover_leb+0x0/0xa1c) from [<c01874f0>] (replay_buds+0x108/0xb1c)
[   69.813944] [<c01873e8>] (replay_buds+0x0/0xb1c) from [<c0188804>] (ubifs_replay_journal+0x900/0x1164)
[   69.823297] [<c0187f04>] (ubifs_replay_journal+0x0/0x1164) from [<c0179c00>] (ubifs_fill_super+0xa3c/0x1b84)
[   69.833172] [<c01791c4>] (ubifs_fill_super+0x0/0x1b84) from [<c017c17c>] (ubifs_get_sb+0x2d0/0x34c)
[   69.842268] [<c017beac>] (ubifs_get_sb+0x0/0x34c) from [<c00b35bc>] (vfs_kern_mount+0x58/0xa4)
[   69.850935] [<c00b3564>] (vfs_kern_mount+0x0/0xa4) from [<c00b3668>] (do_kern_mount+0x40/0xdc)
[   69.859570]  r8:c052d720 r7:d807a000 r6:d81db000 r5:d9b5a000 r4:00008000
[   69.866322] [<c00b3628>] (do_kern_mount+0x0/0xdc) from [<c00c94b8>] (do_mount+0x6d8/0x728)
[   69.874639]  r8:d807a000 r7:d9b5a000 r6:00000000 r5:00000000 r4:00000000 
[   69.881392] [<c00c8de0>] (do_mount+0x0/0x728) from [<c00c9598>] (sys_mount+0x90/0xdc) 
[   69.889239] [<c00c9508>] (sys_mount+0x0/0xdc) from [<c0031e40>] (ret_fast_syscall+0x0/0x2c) 
[   69.897642]  r7:00000015 r6:000cb0f4 r5:bee5599c r4:000ce018 
[   69.904068] UBIFS error (pid 698): ubifs_recover_leb: corrupt empty space LEB 270:380928, corruption starts at 16836
[   69.914648] UBIFS error (pid 698): ubifs_scanned_corruption: corruption at LEB 270:16836
[   69.922767] UBIFS error (pid 698): ubifs_scanned_corruption: first 8192 bytes from LEB 270:16836 
[   69.931598] 00000000: ffffffef ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   69.943127] 00000020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   69.954651] 00000040: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   69.966173] 00000060: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   69.977698] 00000080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   69.989218] 000000a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.000757] 000000c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.012282] 000000e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.023804] 00000100: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.035328] 00000120: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.046847] 00000140: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.058396] 00000160: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.069922] 00000180: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.081446] 000001a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.092967] 000001c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.104486] 000001e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.116009] 00000200: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.127533] 00000220: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.139051] 00000240: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.150574] 00000260: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.162101] 00000280: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.173628] 000002a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.185154] 000002c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.196673] 000002e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.208195] 00000300: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.219721] 00000320: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.231244] 00000340: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.242767] 00000360: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.254286] 00000380: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.265808] 000003a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.277339] 000003c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.288863] 000003e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.300388] 00000400: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.311910] 00000420: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.323439] 00000440: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.334964] 00000460: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.346486] 00000480: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.358010] 000004a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.369530] 000004c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.381053] 000004e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.392575] 00000500: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.404097] 00000520: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.415622] 00000540: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.427141] 00000560: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.438663] 00000580: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.450188] 000005a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.461711] 000005c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.473234] 000005e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.484755] 00000600: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.496276] 00000620: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.507801] 00000640: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.519324] 00000660: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.530849] 00000680: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.542367] 000006a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.553888] 000006c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.565413] 000006e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.576935] 00000700: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.588461] 00000720: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.599980] 00000740: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.611503] 00000760: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.623026] 00000780: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.634548] 000007a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.646073] 000007c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.657592] 000007e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.669114] 00000800: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.680640] 00000820: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.692163] 00000840: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.703686] 00000860: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.715206] 00000880: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.726726] 000008a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.738251] 000008c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.749774] 000008e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.761301] 00000900: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.772827] 00000920: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.784348] 00000940: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.795873] 00000960: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.807395] 00000980: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.818920] 000009a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.830439] 000009c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.841963] 000009e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.853485] 00000a00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.865007] 00000a20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.876532] 00000a40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.888052] 00000a60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.899573] 00000a80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.911100] 00000aa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.922629] 00000ac0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.934154] 00000ae0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.945673] 00000b00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.957194] 00000b20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.968720] 00000b40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.980242] 00000b60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   70.991768] 00000b80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.003285] 00000ba0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.014807] 00000bc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.026333] 00000be0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.037854] 00000c00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.049380] 00000c20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.060899] 00000c40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.072420] 00000c60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.083946] 00000c80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.095468] 00000ca0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.106992] 00000cc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.118512] 00000ce0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.130032] 00000d00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.141558] 00000d20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.153079] 00000d40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.164605] 00000d60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.176123] 00000d80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.187645] 00000da0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.199171] 00000dc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.210692] 00000de0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.222218] 00000e00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.233736] 00000e20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.245259] 00000e40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.256783] 00000e60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.268305] 00000e80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.279830] 00000ea0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.291351] 00000ec0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.302880] 00000ee0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.314406] 00000f00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.325927] 00000f20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.337451] 00000f40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.348970] 00000f60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.360493] 00000f80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.372019] 00000fa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.383540] 00000fc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.395064] 00000fe0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.406583] 00001000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.418104] 00001020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.429630] 00001040: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.441153] 00001060: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.452676] 00001080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.464195] 000010a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.475718] 000010c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.487242] 000010e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.498764] 00001100: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.510289] 00001120: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.521811] 00001140: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.533339] 00001160: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.544864] 00001180: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.556386] 000011a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.567910] 000011c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.579429] 000011e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.590954] 00001200: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.602477] 00001220: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.613998] 00001240: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.625523] 00001260: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.637043] 00001280: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.648564] 000012a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.660089] 000012c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.671612] 000012e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.683136] 00001300: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.694655] 00001320: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.706177] 00001340: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.717701] 00001360: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.729226] 00001380: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.740750] 000013a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.752268] 000013c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.763790] 000013e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.775315] 00001400: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.786837] 00001420: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.798362] 00001440: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.809881] 00001460: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.821405] 00001480: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.832927] 000014a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.844449] 000014c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.855974] 000014e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.867493] 00001500: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.879015] 00001520: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.890539] 00001540: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.902064] 00001560: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.913586] 00001580: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.925106] 000015a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.936628] 000015c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.948152] 000015e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.959674] 00001600: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.971201] 00001620: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.982727] 00001640: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   71.994249] 00001660: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.005773] 00001680: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.017296] 000016a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.028820] 000016c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.040340] 000016e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.051867] 00001700: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.063387] 00001720: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.074909] 00001740: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.086433] 00001760: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.097953] 00001780: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.109475] 000017a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.121001] 000017c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.132530] 000017e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.144054] 00001800: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.155575] 00001820: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.167096] 00001840: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.178621] 00001860: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.190142] 00001880: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.201668] 000018a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.213187] 000018c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.224709] 000018e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.236233] 00001900: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.247755] 00001920: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.259280] 00001940: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.270801] 00001960: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.282322] 00001980: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.293846] 000019a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.305368] 000019c0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.316893] 000019e0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.328413] 00001a00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.339934] 00001a20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.351460] 00001a40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.362981] 00001a60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.374506] 00001a80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.386025] 00001aa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.397546] 00001ac0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.409071] 00001ae0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.420592] 00001b00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.432120] 00001b20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.443637] 00001b40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.455159] 00001b60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.466684] 00001b80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.478206] 00001ba0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.489731] 00001bc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.501251] 00001be0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.512771] 00001c00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.524298] 00001c20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.535819] 00001c40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.547343] 00001c60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.558863] 00001c80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.570385] 00001ca0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.581911] 00001cc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.593431] 00001ce0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.604957] 00001d00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.616475] 00001d20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.627997] 00001d40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.639521] 00001d60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.651046] 00001d80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.662569] 00001da0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.674087] 00001dc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.685611] 00001de0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.697135] 00001e00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.708656] 00001e20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.720182] 00001e40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.731704] 00001e60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.743231] 00001e80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.754755] 00001ea0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.766279] 00001ec0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.777804] 00001ee0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.789323] 00001f00: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.800845] 00001f20: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.812369] 00001f40: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.823891] 00001f60: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.835415] 00001f80: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.846935] 00001fa0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.858457] 00001fc0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.869981] 00001fe0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff  ................................
[   72.881494] UBIFS error (pid 698): ubifs_recover_leb: LEB 270 scanning failed
[   72.889243] UBIFS DBG (pid 700): ubifs_bg_thread: background thread "ubifs_bgt0_0" stops
[   72.916885] UBI DBG (pid 698): ubi_close_volume: close device 0, volume 0, mode 2
[   72.924457] UBI DBG (pid 698): ubi_close_volume: close device 0, volume 0, mode 1
mount: mounting ubi:system on /mnt failed: Structure needs cleaning
[root at ESIedge /]#

From vimal.newwork at gmail.com  Tue Jun  8 13:12:51 2010
From: vimal.newwork at gmail.com (Vimal Singh)
Date: Tue, 8 Jun 2010 22:42:51 +0530
Subject: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
In-Reply-To: <1275637205-489-1-git-send-email-s-ghorai@ti.com>
References: <s-ghorai@ti.com> <1275637205-489-1-git-send-email-s-ghorai@ti.com>
Message-ID: <AANLkTinf8OcvHbLggdEJNGLvlAtSeExKri-IqNlwLpYD@mail.gmail.com>

Reviewed-by: Vimal Singh <vimal.newwork at gmail.com>

On Fri, Jun 4, 2010 at 1:10 PM, Sukumar Ghorai <s-ghorai at ti.com> wrote:
> ? The following set of patches applies on top of for-next branch.
> ? ? ? ?http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
> ? Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
>
> ? And these are the patches required to address the following input -
> ? ? 1. The NAND driver needs to stop tinkering with the GPMC registers
> ? ? ? ?The omap General Purpose Memory Controller (GPMC) registers are omap
> ? ? ? ?specific, and not driver specific. Tinkering with these registers can
> ? ? ? ?cause issues with the other devices on the GPMC.
>
> ? ? 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
> ? ? ? ?Passing hardcoded GPMC virtual addressess is sure way to mess up things.
> ? ? ? ?This should all become unnecessary once the NAND drivers stops messing
> ? ? ? ?with the GPMC registers directly.
> ? ? Discussion: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg27630.html
>
> ? Changes in this series -
> ? ? ? ? ? ? ? ?Unused function removed.
>
> ?Functions related to ecc and prefetch engine are optimized.
> ?v4: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg29458.html
>
> ?Few functionality was missing ?like - There should be some locking as only
> ? one chipselect can use the ECC or prefetch engine at a time. If you have
> ? NAND in two chipselects, bad things would happen.
> ?v3: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28715.html
>
> ?Additionally, it was needed to implement more functions for the platform
> ?init code to use.
> ?v2: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28467.html
>
> ?v1: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28164.html
>
>
> Sukumar Ghorai (3):
> ? ? ? ?omap3 gpmc: functionality enhancement
> ? ? ? ?omap3 nand: cleanup virtual address usages
> ? ? ? ?omap3 nand: fix issue in board file to detect nand
> ?arch/arm/mach-omap2/board-cm-t35.c ? ? ? ? | ? 20 +---
> ?arch/arm/mach-omap2/board-devkit8000.c ? ? | ? 25 +---
> ?arch/arm/mach-omap2/board-omap3beagle.c ? ?| ? 24 +---
> ?arch/arm/mach-omap2/board-omap3touchbook.c | ? 25 +---
> ?arch/arm/mach-omap2/board-overo.c ? ? ? ? ?| ? 24 +---
> ?arch/arm/mach-omap2/board-sdp-flash.c ? ? ?| ? ?5 -
> ?arch/arm/mach-omap2/gpmc-nand.c ? ? ? ? ? ?| ? 39 ++----
> ?arch/arm/mach-omap2/gpmc.c ? ? ? ? ? ? ? ? | ?228 +++++++++++++++++++++++++---
> ?arch/arm/plat-omap/include/plat/gpmc.h ? ? | ? 36 ++++-
> ?arch/arm/plat-omap/include/plat/nand.h ? ? | ? ?6 +-
> ?drivers/mtd/nand/omap2.c ? ? ? ? ? ? ? ? ? | ?229 ++++++++--------------------
> ?11 files changed, 320 insertions(+), 341 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>



-- 
Regards,
Vimal Singh


From m.szyprowski at samsung.com  Wed Jun  9 10:05:30 2010
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Wed, 09 Jun 2010 16:05:30 +0200
Subject: [PATCH] Samsung OneNAND updates
Message-ID: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>

Hello,

This short patch series updates OneNAND framework and Samsung SoC
OneNAND driver. The first two makes a little cleanup in the framework
and the driver, while the next two adds support for runtime badblock
check feature.

This patch series includes:

[PATCH 1/4] OneNAND: Introduce chip_probe function
[PATCH 2/4] s5pc110: Implement s5pc110 chip_probe for OneNAND probe
[PATCH 3/4] OneNAND: Add runtime badblock check feature
[PATCH 4/4] s5pc110: OneNAND runtime badblock check

Best regards
-- 
Marek Szyprowski
Samsung Poland R&D Center


From m.szyprowski at samsung.com  Wed Jun  9 10:05:31 2010
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Wed, 09 Jun 2010 16:05:31 +0200
Subject: [PATCH 1/4] OneNAND: Introduce chip_probe function
In-Reply-To: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
References: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1276092335-3245-2-git-send-email-m.szyprowski@samsung.com>

From: Kyungmin Park <kyungmin.park at samsung.com>

This patch splits OneNAND probe operation into chip and interface probe
operations. This way the code can be restructured to be more readable on
chips that require special workarounds during probe operation (like
OneNAND chip on Samsung S5PC110).

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>

---
 drivers/mtd/onenand/onenand_base.c |   44 ++++++++++++++++++++++++++---------
 include/linux/mtd/onenand.h        |    1 +
 2 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 26caf25..fc91c4a 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -3730,17 +3730,16 @@ out:
 }
 
 /**
- * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * onenand_chip_probe - [OneNAND Interface] Probe the OneNAND device
  * @param mtd		MTD device structure
  *
  * OneNAND detection method:
  *   Compare the values from command with ones from register
  */
-static int onenand_probe(struct mtd_info *mtd)
+static int onenand_chip_probe(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
-	int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;
-	int density;
+	int bram_maf_id, bram_dev_id, maf_id, dev_id;
 	int syscfg;
 
 	/* Save system configuration 1 */
@@ -3763,12 +3762,6 @@ static int onenand_probe(struct mtd_info *mtd)
 	/* Restore system configuration 1 */
 	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
 
-	/* Workaround */
-	if (syscfg & ONENAND_SYS_CFG1_SYNC_WRITE) {
-		bram_maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
-		bram_dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
-	}
-
 	/* Check manufacturer ID */
 	if (onenand_check_maf(bram_maf_id))
 		return -ENXIO;
@@ -3776,13 +3769,37 @@ static int onenand_probe(struct mtd_info *mtd)
 	/* Read manufacturer and device IDs from Register */
 	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
 	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
-	ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
-	this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
 
 	/* Check OneNAND device */
 	if (maf_id != bram_maf_id || dev_id != bram_dev_id)
 		return -ENXIO;
 
+	return 0;
+}
+
+/**
+ * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * @param mtd		MTD device structure
+ *
+ * Probe OneNAND chip
+ */
+static int onenand_probe(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	int maf_id, dev_id, ver_id;
+	int density;
+	int ret;
+
+	ret = this->chip_probe(mtd);
+	if (ret)
+		return ret;
+
+	/* Read manufacturer and device IDs from Register */
+	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
+	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
+	ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
+	this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
+
 	/* Flash device information */
 	onenand_print_device_info(dev_id, ver_id);
 	this->device_id = dev_id;
@@ -3909,6 +3926,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	if (!this->unlock_all)
 		this->unlock_all = onenand_unlock_all;
 
+	if (!this->chip_probe)
+		this->chip_probe = onenand_chip_probe;
+
 	if (!this->read_bufferram)
 		this->read_bufferram = onenand_read_bufferram;
 	if (!this->write_bufferram)
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index c26ff86..57c3bb4 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -114,6 +114,7 @@ struct onenand_chip {
 	unsigned short (*read_word)(void __iomem *addr);
 	void (*write_word)(unsigned short value, void __iomem *addr);
 	void (*mmcontrol)(struct mtd_info *mtd, int sync_read);
+	int (*chip_probe)(struct mtd_info *mtd);
 	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 	int (*scan_bbt)(struct mtd_info *mtd);
 
-- 
1.6.4



From m.szyprowski at samsung.com  Wed Jun  9 10:05:32 2010
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Wed, 09 Jun 2010 16:05:32 +0200
Subject: [PATCH 2/4] s5pc110: Implement s5pc110 chip_probe for OneNAND probe
In-Reply-To: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
References: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1276092335-3245-3-git-send-email-m.szyprowski@samsung.com>

From: Kyungmin Park <kyungmin.park at samsung.com>

This patch introduces a noop chip probe callback for OneNAND Samsung
S5PC110 driver. This way the workarounds can be removed from the
onenand_setup function and onenand framework.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>

---
 drivers/mtd/onenand/samsung.c |   20 +++++++-------------
 1 files changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 2750317..fa4b743 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -738,6 +738,11 @@ static void s3c_unlock_all(struct mtd_info *mtd)
 	s3c_onenand_check_lock_status(mtd);
 }
 
+static int s5pc110_chip_probe(struct mtd_info *mtd)
+{
+	return 0;
+}
+
 static void s3c_onenand_setup(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
@@ -757,6 +762,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
 		/* Use generic onenand functions */
 		onenand->cmd_map = s5pc1xx_cmd_map;
 		this->read_bufferram = s5pc110_read_bufferram;
+		this->chip_probe = s5pc110_chip_probe;
 		return;
 	} else {
 		BUG();
@@ -781,7 +787,6 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	struct mtd_info *mtd;
 	struct resource *r;
 	int size, err;
-	unsigned long onenand_ctrl_cfg = 0;
 
 	pdata = pdev->dev.platform_data;
 	/* No need to check pdata. the platform data is optional */
@@ -900,14 +905,6 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 		}
 
 		onenand->phys_base = onenand->base_res->start;
-
-		onenand_ctrl_cfg = readl(onenand->dma_addr + 0x100);
-		if ((onenand_ctrl_cfg & ONENAND_SYS_CFG1_SYNC_WRITE) &&
-		    onenand->dma_addr)
-			writel(onenand_ctrl_cfg & ~ONENAND_SYS_CFG1_SYNC_WRITE,
-					onenand->dma_addr + 0x100);
-		else
-			onenand_ctrl_cfg = 0;
 	}
 
 	if (onenand_scan(mtd, 1)) {
@@ -915,10 +912,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 		goto scan_failed;
 	}
 
-	if (onenand->type == TYPE_S5PC110) {
-		if (onenand_ctrl_cfg && onenand->dma_addr)
-			writel(onenand_ctrl_cfg, onenand->dma_addr + 0x100);
-	} else {
+	if (onenand->type != TYPE_S5PC110) {
 		/* S3C doesn't handle subpage write */
 		mtd->subpage_sft = 0;
 		this->subpagesize = mtd->writesize;
-- 
1.6.4



From m.szyprowski at samsung.com  Wed Jun  9 10:05:34 2010
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Wed, 09 Jun 2010 16:05:34 +0200
Subject: [PATCH 4/4] s5pc110: OneNAND runtime badblock check
In-Reply-To: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
References: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1276092335-3245-5-git-send-email-m.szyprowski@samsung.com>

From: Kyungmin Park <kyungmin.park at samsung.com>

This patch enables runtime badblock check for Samsung OneNAND driver
depending on the value of CONFIG_MTD_RUNTIME_BADBLOCK_CHECK option.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>

---
 drivers/mtd/onenand/samsung.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index fa4b743..c2bbeae 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -837,8 +837,12 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	/* Set onenand_chip also */
 	this->base = onenand->base;
 
-	/* Use runtime badblock check */
+	/* Skip unlock all check */
 	this->options |= ONENAND_SKIP_UNLOCK_CHECK;
+#ifdef CONFIG_MTD_RUNTIME_BADBLOCK_CHECK
+	/* Use runtime badblock check */
+	this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK;
+#endif
 
 	if (onenand->type != TYPE_S5PC110) {
 		r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-- 
1.6.4



From m.szyprowski at samsung.com  Wed Jun  9 10:05:33 2010
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Wed, 09 Jun 2010 16:05:33 +0200
Subject: [PATCH 3/4] OneNAND: Add runtime badblock check feature
In-Reply-To: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
References: <1276092335-3245-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1276092335-3245-4-git-send-email-m.szyprowski@samsung.com>

From: Kyungmin Park <kyungmin.park at samsung.com>

This patch adds support for runtime badblock check feature to OneNAND
framework.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>

---
 drivers/mtd/Kconfig                |    6 +++
 drivers/mtd/mtdpart.c              |    3 +
 drivers/mtd/onenand/onenand_base.c |   14 +++---
 drivers/mtd/onenand/onenand_bbt.c  |   79 ++++++++++++++++++++++++++++++++++-
 include/linux/mtd/onenand.h        |    1 +
 5 files changed, 93 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index f8210bf..46af961 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -328,6 +328,12 @@ config MTD_OOPS
 	  To use, add console=ttyMTDx to the kernel command line,
 	  where x is the MTD device number to use.
 
+config MTD_RUNTIME_BADBLOCK_CHECK
+	bool "Runtime badblock check support"
+	depends on MTD
+	help
+	  This enables check badblocks at access time.
+
 source "drivers/mtd/chips/Kconfig"
 
 source "drivers/mtd/maps/Kconfig"
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index b8043a9..f11d944 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -485,6 +485,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 	}
 
 	slave->mtd.ecclayout = master->ecclayout;
+
+#ifndef CONFIG_MTD_RUNTIME_BADBLOCK_CHECK
 	if (master->block_isbad) {
 		uint64_t offs = 0;
 
@@ -495,6 +497,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 			offs += slave->mtd.erasesize;
 		}
 	}
+#endif
 
 out_register:
 	/* register our partition */
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index fc91c4a..93597ff 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1536,6 +1536,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 	int ret = 0, readcmd;
 	size_t len = ops->ooblen;
 	u_char *buf = ops->oobbuf;
+	int update = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %zi\n",
 		__func__, (unsigned int) from, len);
@@ -1550,13 +1551,15 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 		return ONENAND_BBT_READ_FATAL_ERROR;
 	}
 
-	/* Grab the lock and see if the device is available */
-	onenand_get_device(mtd, FL_READING);
-
 	column = from & (mtd->oobsize - 1);
 
 	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
+	if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+		readcmd = ONENAND_CMD_READ;
+		update = 1;
+	}
+
 	while (read < len) {
 		cond_resched();
 
@@ -1565,7 +1568,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 
 		this->command(mtd, readcmd, from, mtd->oobsize);
 
-		onenand_update_bufferram(mtd, from, 0);
+		onenand_update_bufferram(mtd, from, update);
 
 		ret = this->bbt_wait(mtd, FL_READING);
 		if (unlikely(ret))
@@ -1589,9 +1592,6 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 		}
 	}
 
-	/* Deselect and wake up anyone waiting on the device */
-	onenand_release_device(mtd);
-
 	ops->oobretlen = read;
 	return ret;
 }
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index a91fcac..802cf20 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -3,11 +3,17 @@
  *
  *  Bad Block Table support for the OneNAND driver
  *
- *  Copyright(c) 2005 Samsung Electronics
+ *  Copyright(c) 2005-2010 Samsung Electronics
  *  Kyungmin Park <kyungmin.park at samsung.com>
  *
  *  Derived from nand_bbt.c
  *
+ *  Legend in badblock table:
+ *     0x00	Normal
+ *     0x01	RESERVED
+ *     0x02	Used for runtime badblock check
+ *     0x03	Bad block (initial or runtime)
+ *
  *  TODO:
  *    Split BBT core and chip specific BBT.
  */
@@ -17,6 +23,16 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
+#define BBT_NORMAL_BITS			0x00
+#define BBT_RUNTIME_BADBLOCK_BITS	0x02
+#define BBT_BADBLOCK_BITS		0x03
+
+#ifdef CONFIG_MTD_RUNTIME_BADBLOCK_CHECK
+#define BBT_SCAN_PAGE			1
+#else
+#define BBT_SCAN_PAGE			2
+#endif
+
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
  * @param buf		the buffer to search
@@ -44,6 +60,52 @@ static int check_short_pattern(uint8_t *buf, int len, int paglen, struct nand_bb
 }
 
 /**
+ * read_page_oob - [GENERIC] Read oob for runtime badblock check
+ * @param mtd          MTD device structure
+ * @param from         the length of buffer to search
+ * @param buf          temporary buffer
+ *
+ * Read page oob at runtime badblock check
+ */
+static int read_page_oob(struct mtd_info *mtd, loff_t from, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct bbm_info *bbm = this->bbm;
+	struct nand_bbt_descr *bd = bbm->badblock_pattern;
+	struct mtd_oob_ops ops;
+	int ret, scanlen, block, j, res;
+
+	scanlen = 0;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooblen = 32;
+	ops.oobbuf = buf;
+	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
+	/* Get block number * 2 */
+	block = (int) ((from >> this->erase_shift) << 1);
+
+	/* Set normal block first */
+	res = BBT_NORMAL_BITS;
+	bbm->bbt[block >> 3] &= ~(0x3 << (block & 0x6));
+	bbm->bbt[block >> 3] |= res << (block & 0x6);
+
+	for (j = 0; j < BBT_SCAN_PAGE; j++) {
+		ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
+		if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
+			res = BBT_BADBLOCK_BITS;
+			bbm->bbt[block >> 3] |= res << (block & 0x6);
+			printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
+					block >> 1, (unsigned int) from);
+			mtd->ecc_stats.badblocks++;
+			break;
+		}
+	}
+
+	return res;
+}
+
+/**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
  * @param mtd		MTD device structure
  * @param buf		temporary buffer
@@ -67,7 +129,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 
 	printk(KERN_INFO "Scanning device for bad blocks\n");
 
-	len = 2;
+	len = BBT_SCAN_PAGE;
 
 	/* We need only read few bytes from the OOB area */
 	scanlen = ooblen = 0;
@@ -99,7 +161,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 				return -EIO;
 
 			if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
-				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
+				bbm->bbt[i >> 3] |= BBT_BADBLOCK_BITS << (i & 0x6);
 				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
 					i >> 1, (unsigned int) from);
 				mtd->ecc_stats.badblocks++;
@@ -152,6 +214,11 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 	block = (int) (onenand_block(this, offs) << 1);
 	res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
+	if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+		if (res == BBT_RUNTIME_BADBLOCK_BITS)
+			res = read_page_oob(mtd, offs, this->page_buf);
+	}
+
 	DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
 		(unsigned int) offs, block >> 1, res);
 
@@ -201,6 +268,12 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	if (!bbm->isbad_bbt)
 		bbm->isbad_bbt = onenand_isbad_bbt;
 
+	if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+		printk(KERN_INFO "Scanning device for bad blocks (skipped)\n");
+		memset(bbm->bbt, 0xAA, len);
+		return 0;
+	}
+
 	/* Scan the device to build a memory based bad block table */
 	if ((ret = onenand_memory_bbt(mtd, bd))) {
 		printk(KERN_ERR "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n");
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 57c3bb4..059b5f7 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -181,6 +181,7 @@ struct onenand_chip {
 #define ONENAND_HAS_2PLANE		(0x0004)
 #define ONENAND_HAS_4KB_PAGE		(0x0008)
 #define ONENAND_SKIP_UNLOCK_CHECK	(0x0100)
+#define ONENAND_RUNTIME_BADBLOCK_CHECK	(0x0200)
 #define ONENAND_PAGEBUF_ALLOC		(0x1000)
 #define ONENAND_OOBBUF_ALLOC		(0x2000)
 
-- 
1.6.4



From egorkat at gmail.com  Wed Jun  9 11:12:46 2010
From: egorkat at gmail.com (Egorkat)
Date: Wed, 9 Jun 2010 15:12:46 +0000 (UTC)
Subject: modprobe nftl hangs
References: <loom.20100608T165617-407@post.gmane.org>
Message-ID: <loom.20100609T171030-617@post.gmane.org>

May be dmesg will be helpful:

DiskOnChip found at 0xc8000
DiskOnChip 2000 responds to DWORD access
Detected 2 chips per floor.
NAND device: Manufacturer ID: 0x98, Chip ID: 0x73 (Toshiba NAND 16MiB 3,3V 8-bit)
2 NAND chips detected
Found DiskOnChip ANAND Media Header at 0x0
Found DiskOnChip ANAND Media Header at 0x4000
    DataOrgID        = ANAND
    NumEraseUnits    = 2048
    FirstPhysicalEUN = 0
    FormattedSize    = 32833536
    UnitSizeFactor   = 0
UnitSizeFactor=0x00 detected.  Correct value is assumed to be 0xff.
Bad block table at page 1, version 0x55
Bad block table at page 33, version 0x55
nand_read_bbt: Bad block at 0x00000000c000
nand_read_bbt: Bad block at 0x000000010000
nand_read_bbt: Bad block at 0x000000348000
Found alias of DOC at 0xc8000 to 0xca000

also - cat /proc/mtd
dev:    size   erasesize  name
mtd0: 02000000 00004000 "DiskOnChip 2000 (NFTL Model)"




From egorkat at gmail.com  Wed Jun  9 11:35:22 2010
From: egorkat at gmail.com (Egorkat)
Date: Wed, 9 Jun 2010 15:35:22 +0000 (UTC)
Subject: modprobe nftl hangs
References: <loom.20100608T165617-407@post.gmane.org>
Message-ID: <loom.20100609T173244-749@post.gmane.org>

and also - nftl_format /dev/mtd0
version 1.24 2005/11/07 11:15:13 gleixner
Phase 1. Checking and erasing Erase Zones from 0x00000000 to 0x02000000
Skipping bad zone (factory marked) #0 @ 0x0
Skipping bad zone (factory marked) #1 @ 0x4000
Skipping bad zone (factory marked) #2 @ 0x8000
Skipping bad zone (factory marked) #3 @ 0xc000
Skipping bad zone (factory marked) #4 @ 0x10000
Skipping bad zone (factory marked) #5 @ 0x14000
         Erasing Zone #210 @ 0x348000: Erase failed (Input/output error)
        Checking Zone #2047 @ 0x1ffc000
Phase 2.a Writing NFTL Media Header and Bad Unit Table
Phase 2.b Writing Spare NFTL Media Header and Spare Bad Unit Table
Phase 3. Writing Unit Control Information to each Erase Unit

after it - modprobe nftl hangs and dmesg shows this -
NFTL Media Headers at 0x0 and 0x8000 disagree.
NFTL Media Headers at 0x0 and 0xc000 disagree.
NFTL Media Headers at 0x0 and 0x10000 disagree.
NFTL Media Headers at 0x0 and 0x14000 disagree.
NFTL Media Headers at 0x0 and 0x18000 disagree.
NFTL Media Headers at 0x0 and 0x1c000 disagree.
Formatting block 2
Formatting block 5
Formatting block 6
Formatting block 7

thats it... no luck no /dev/nftla...



From stanley.miao at windriver.com  Thu Jun 10 05:09:51 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Thu, 10 Jun 2010 17:09:51 +0800
Subject: The "struct nand_oobinfo" is able to record only 32 ECC code
	positions, which
Message-ID: <1276160994-7599-1-git-send-email-stanley.miao@windriver.com>

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up. 


Stanley.


From stanley.miao at windriver.com  Thu Jun 10 05:09:54 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Thu, 10 Jun 2010 17:09:54 +0800
Subject: [PATCH 3/3] Place the cleanmarker in OOB area according to the mode
	MTD_OOB_AUTO
In-Reply-To: <1276160994-7599-3-git-send-email-stanley.miao@windriver.com>
References: <1276160994-7599-1-git-send-email-stanley.miao@windriver.com>
	<1276160994-7599-2-git-send-email-stanley.miao@windriver.com>
	<1276160994-7599-3-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276160994-7599-4-git-send-email-stanley.miao@windriver.com>

In the current linux kernel, Jffs2 writes the cleanmarker according to the
mode MTD_OOB_AUTO, so modify the layout of the cleanmarker from
MTD_OOB_PLACE to MTD_OOB_AUTO in flash_eraseall.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   40 ++++++++++++++++++++++------------------
 1 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index 4e2108b..f0f0371 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -34,7 +34,7 @@
 #include <time.h>
 #include <getopt.h>
 #include <sys/ioctl.h>
-#include <sys/mount.h>
+#include <sys/param.h>
 #include "crc32.h"
 
 #include <mtd/mtd-user.h>
@@ -75,9 +75,11 @@ static int get_linux_version(void)
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
-	int fd, clmpos = 0, clmlen = 8;
+	int fd;
 	erase_info_t erase;
 	int isNAND, bbtest = 1;
+	unsigned char oobbuf[128];
+	memset(oobbuf, 0xFF, 128);
 
 	process_options(argc, argv);
 
@@ -98,11 +100,18 @@ int main (int argc, char *argv[])
 	if (jffs2) {
 		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
 		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-		if (!isNAND)
+		if (!isNAND) {
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
-		else {
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+		} else {
+			int already_read, num, i, start;
 			struct nand_ecclayout ecclayout;
 
+			cleanmarker.totlen = cpu_to_je32(8);
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+
 			memset(&ecclayout, 0, sizeof(ecclayout));
 			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
 				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
@@ -122,19 +131,14 @@ int main (int argc, char *argv[])
 				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
 				ecclayout.eccbytes = oi.eccbytes;
 			}
-
-			/* Get the position of the free bytes */
-			if (!ecclayout.oobfree[0].length) {
-				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
-				return 1;
+			already_read = 0;
+			for (i = 0; (already_read < 8) && ecclayout.oobfree[i].length; i++) {
+				num = MIN(8 - already_read, ecclayout.oobfree[i].length);
+				start = ecclayout.oobfree[i].offset;
+				memcpy(oobbuf + start, (unsigned char *)&cleanmarker + already_read, num);
+				already_read += num;
 			}
-			clmpos = ecclayout.oobfree[0].offset;
-			clmlen = ecclayout.oobfree[0].length;
-			if (clmlen > 8)
-				clmlen = 8;
-			cleanmarker.totlen = cpu_to_je32(8);
 		}
-		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
 	}
 
 	for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) {
@@ -174,9 +178,9 @@ int main (int argc, char *argv[])
 		/* write cleanmarker */
 		if (isNAND) {
 			struct mtd_oob_buf oob;
-			oob.ptr = (unsigned char *) &cleanmarker;
-			oob.start = erase.start + clmpos;
-			oob.length = clmlen;
+			oob.ptr = oobbuf;
+			oob.start = erase.start;
+			oob.length = meminfo.oobsize;
 			if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
 				fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
 				continue;
-- 
1.5.4.3



From stanley.miao at windriver.com  Thu Jun 10 05:09:53 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Thu, 10 Jun 2010 17:09:53 +0800
Subject: [PATCH 2/3] Discard the legacy interface MEMGETOOBSEL in
	flash_eraseall
In-Reply-To: <1276160994-7599-2-git-send-email-stanley.miao@windriver.com>
References: <1276160994-7599-1-git-send-email-stanley.miao@windriver.com>
	<1276160994-7599-2-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276160994-7599-3-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
to keep compatible with the old linux kernel, a linux version detection
function is added.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   71 ++++++++++++++++++++++++++++++++----------------------
 1 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index a22fc49..4e2108b 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -43,6 +43,8 @@
 #define PROGRAM "flash_eraseall"
 #define VERSION "$Revision: 1.22 $"
 
+#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
 static const char *exe_name;
 static const char *mtd_device;
 static int quiet;		/* true -- don't output progress */
@@ -55,6 +57,21 @@ static void display_version (void);
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
 
+static int get_linux_version(void)
+{
+	FILE *fd;
+	int a = 0, b = 0, c = 0;
+	
+	fd = fopen("/proc/version", "r");
+	if (fd) {
+		fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
+		fclose(fd);
+	}
+
+	return LINUX_VERSION(a, b, c); 
+}
+
+
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
@@ -84,41 +101,37 @@ int main (int argc, char *argv[])
 		if (!isNAND)
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
 		else {
-			struct nand_oobinfo oobinfo;
-
-			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
-				fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", exe_name, mtd_device);
-				return 1;
-			}
+			struct nand_ecclayout ecclayout;
 
-			/* Check for autoplacement */
-			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
-				/* Get the position of the free bytes */
-				if (!oobinfo.oobfree[0][1]) {
-					fprintf (stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+			memset(&ecclayout, 0, sizeof(ecclayout));
+			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+					fprintf(stderr,	"%s: %s: unable to get NAND oob layout\n", \
+							exe_name, mtd_device);
 					return 1;
 				}
-				clmpos = oobinfo.oobfree[0][0];
-				clmlen = oobinfo.oobfree[0][1];
-				if (clmlen > 8)
-					clmlen = 8;
 			} else {
-				/* Legacy mode */
-				switch (meminfo.oobsize) {
-					case 8:
-						clmpos = 6;
-						clmlen = 2;
-						break;
-					case 16:
-						clmpos = 8;
-						clmlen = 8;
-						break;
-					case 64:
-						clmpos = 16;
-						clmlen = 8;
-						break;
+				struct nand_oobinfo oi;
+
+				if (ioctl(fd, MEMGETOOBSEL, &oi) != 0) {
+					fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", \
+							exe_name, mtd_device);
+					return 1;
 				}
+				memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+				ecclayout.eccbytes = oi.eccbytes;
+			}
+
+			/* Get the position of the free bytes */
+			if (!ecclayout.oobfree[0].length) {
+				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+				return 1;
 			}
+			clmpos = ecclayout.oobfree[0].offset;
+			clmlen = ecclayout.oobfree[0].length;
+			if (clmlen > 8)
+				clmlen = 8;
 			cleanmarker.totlen = cpu_to_je32(8);
 		}
 		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
-- 
1.5.4.3



From stanley.miao at windriver.com  Thu Jun 10 05:09:52 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Thu, 10 Jun 2010 17:09:52 +0800
Subject: [PATCH 1/3] clean up the legacy interfaces in nandwrite.c
In-Reply-To: <1276160994-7599-1-git-send-email-stanley.miao@windriver.com>
References: <1276160994-7599-1-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276160994-7599-2-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 nandwrite.c |  215 +++++++++++++---------------------------------------------
 1 files changed, 48 insertions(+), 167 deletions(-)

diff --git a/nandwrite.c b/nandwrite.c
index e691ebd..a0a843b 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -45,26 +45,21 @@
 #define MAX_PAGE_SIZE	4096
 #define MAX_OOB_SIZE	128
 
-// oob layouts to pass into the kernel as default
-static struct nand_oobinfo none_oobinfo = {
-	.useecc = MTD_NANDECC_OFF,
-};
-
-static struct nand_oobinfo jffs2_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 0, 1, 2, 3, 6, 7 }
-};
-
-static struct nand_oobinfo yaffs_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_oobinfo autoplace_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE
-};
+#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+static int get_linux_version(void)
+{
+	FILE *fd;
+	int a = 0, b = 0, c = 0;
+	
+	fd = fopen("/proc/version", "r");
+	if (fd) {
+		fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
+		fclose(fd);
+	}
+
+	return LINUX_VERSION(a, b, c);
+}
 
 static void display_help (void)
 {
@@ -72,13 +67,7 @@ static void display_help (void)
 "Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
 "Writes to the specified MTD device.\n"
 "\n"
-"  -a, --autoplace         Use auto oob layout\n"
-"  -j, --jffs2             Force jffs2 oob layout (legacy support)\n"
-"  -y, --yaffs             Force yaffs oob layout (legacy support)\n"
-"  -f, --forcelegacy       Force legacy support on autoplacement-enabled mtd\n"
-"                          device\n"
 "  -m, --markbad           Mark blocks bad if write fails\n"
-"  -n, --noecc             Write without ecc\n"
 "  -o, --oob               Image contains oob data\n"
 "  -r, --raw               Image contains the raw oob data dumped by nanddump\n"
 "  -s addr, --start=addr   Set start address (default is 0)\n"
@@ -112,12 +101,7 @@ static int		mtdoffset = 0;
 static bool		quiet = false;
 static bool		writeoob = false;
 static bool		rawoob = false;
-static bool		autoplace = false;
 static bool		markbad = false;
-static bool		forcejffs2 = false;
-static bool		forceyaffs = false;
-static bool		forcelegacy = false;
-static bool		noecc = false;
 static bool		pad = false;
 static int		blockalign = 1; /*default to using 16K block size */
 
@@ -127,22 +111,17 @@ static void process_options (int argc, char * const argv[])
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "ab:fjmnopqrs:y";
+		static const char *short_options = "b:mopqrs:";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
-			{"autoplace", no_argument, 0, 'a'},
 			{"blockalign", required_argument, 0, 'b'},
-			{"forcelegacy", no_argument, 0, 'f'},
-			{"jffs2", no_argument, 0, 'j'},
 			{"markbad", no_argument, 0, 'm'},
-			{"noecc", no_argument, 0, 'n'},
 			{"oob", no_argument, 0, 'o'},
 			{"pad", no_argument, 0, 'p'},
 			{"quiet", no_argument, 0, 'q'},
 			{"raw", no_argument, 0, 'r'},
 			{"start", required_argument, 0, 's'},
-			{"yaffs", no_argument, 0, 'y'},
 			{0, 0, 0, 0},
 		};
 
@@ -166,21 +145,6 @@ static void process_options (int argc, char * const argv[])
 			case 'q':
 				quiet = true;
 				break;
-			case 'a':
-				autoplace = true;
-				break;
-			case 'j':
-				forcejffs2 = true;
-				break;
-			case 'y':
-				forceyaffs = true;
-				break;
-			case 'f':
-				forcelegacy = true;
-				break;
-			case 'n':
-				noecc = true;
-				break;
 			case 'm':
 				markbad = true;
 				break;
@@ -258,8 +222,7 @@ int main(int argc, char * const argv[])
 	struct mtd_oob_buf oob;
 	loff_t offs;
 	int ret;
-	int oobinfochanged = 0;
-	struct nand_oobinfo old_oobinfo;
+	struct nand_ecclayout ecclayout;
 	bool failed = true;
 	// contains all the data read from the file so far for the current eraseblock
 	unsigned char *filebuf = NULL;
@@ -315,86 +278,30 @@ int main(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (autoplace) {
-		/* Read the current oob info */
-		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMGETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-
-		// autoplace ECC ?
-		if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
-
-			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
-				perror ("MEMSETOOBSEL");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-			oobinfochanged = 1;
-		}
-	}
 
-	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
-		if (ret == 0) {
-			oobinfochanged = 2;
-		} else {
-			switch (errno) {
-			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				oobinfochanged = 1;
-				break;
-			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-		}
-	}
-
-	/*
-	 * force oob layout for jffs2 or yaffs ?
-	 * Legacy support
-	 */
-	if (forcejffs2 || forceyaffs) {
-		struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
-
-		if (autoplace) {
-			fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n");
-			goto restoreoob;
-		}
-		if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) {
-			fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n");
-			goto restoreoob;
-		}
-		if (meminfo.oobsize == 8) {
-			if (forceyaffs) {
-				fprintf (stderr, "YAFSS cannot operate on 256 Byte page size");
-				goto restoreoob;
-			}
-			/* Adjust number of ecc bytes */
-			jffs2_oobinfo.eccbytes = 3;
+	oob.length = meminfo.oobsize;
+	oob.ptr =  oobbuf;
+
+	memset(&ecclayout, 0, sizeof(ecclayout));
+	if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+		if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+			perror("ECCGETLAYOUT");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
+	} else {
+		struct nand_oobinfo oi;
 
-		if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) {
-			perror ("MEMSETOOBSEL");
-			goto restoreoob;
+		if (ioctl (fd, MEMGETOOBSEL, &oi) != 0) {
+			perror ("MEMGETOOBSEL");
+			close (fd);
+			exit (EXIT_FAILURE);
 		}
+		memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+		memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+		ecclayout.eccbytes = oi.eccbytes;
 	}
 
-	oob.length = meminfo.oobsize;
-	oob.ptr = noecc ? oobreadbuf : oobbuf;
-
 	/* Determine if we are reading from standard input or from a file. */
 	if (strcmp(img, standard_input) == 0) {
 		ifd = STDIN_FILENO;
@@ -558,6 +465,8 @@ int main(int argc, char * const argv[])
 		}
 
 		if (writeoob) {
+			int i, start, len;
+			int tags_pos = 0;
 			oobreadbuf = writebuf + meminfo.writesize;
 
 			// Read more data for the OOB from the input if there isn't enough in the buffer
@@ -594,40 +503,19 @@ int main(int argc, char * const argv[])
 				}
 			}
 
-			if (noecc) {
-				oob.ptr = oobreadbuf;
-			} else {
-				int i, start, len;
-				int tags_pos = 0;
-				/*
-				 *  We use autoplacement and have the oobinfo with the autoplacement
-				 * information from the kernel available
-				 *
-				 * Modified to support out of order oobfree segments,
-				 * such as the layout used by diskonchip.c
-				 */
-				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
-					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
-						/* Set the reserved bytes to 0xff */
-						start = old_oobinfo.oobfree[i][0];
-						len = old_oobinfo.oobfree[i][1];
-						if (rawoob)
-							memcpy(oobbuf + start,
-									oobreadbuf + start, len);
-						else
-							memcpy(oobbuf + start,
-									oobreadbuf + tags_pos, len);
-						tags_pos += len;
-					}
-				} else {
-					/* Set at least the ecc byte positions to 0xff */
-					start = old_oobinfo.eccbytes;
-					len = meminfo.oobsize - start;
+			for (i = 0; ecclayout.oobfree[i].length; i++) {
+				/* Set the reserved bytes to 0xff */
+				start = ecclayout.oobfree[i].offset;
+				len = ecclayout.oobfree[i].length;
+				if (rawoob)
 					memcpy(oobbuf + start,
-							oobreadbuf + start,
-							len);
-				}
+							oobreadbuf + start, len);
+				else
+					memcpy(oobbuf + start,
+							oobreadbuf + tags_pos, len);
+				tags_pos += len;
 			}
+
 			/* Write OOB data first, as ecc will be placed in there*/
 			oob.start = mtdoffset;
 			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
@@ -686,13 +574,6 @@ closeall:
 	close(ifd);
 
 restoreoob:
-	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-	}
 
 	close(fd);
 
-- 
1.5.4.3



From naveen.mamindlapalli at gmail.com  Thu Jun 10 05:13:16 2010
From: naveen.mamindlapalli at gmail.com (Naveen Mamindlapalli)
Date: Thu, 10 Jun 2010 14:43:16 +0530
Subject: NAND bad block table creation
Message-ID: <AANLkTimMvLdm54CwALZClYKxZc6vu7NV24pXltQqGH1q@mail.gmail.com>

Hi All,

I am going through mtd subsystem code for bad block management
information. The linux kernel version I am using is linux-2.6.34. In
the create_bbt( )? function in drivers/mtd/nand/nand_bbt.c, the for
loop which checks for whether a block is bad or not is incrementing by
2 (line 436) . That means alternate NAND blocks are checked to find
out whether that block is bad or not.

Is this correct?

Code is pasted below ( drivers/mtd/nand/nand_bbt.c ):

    417         for (i = startblock; i < numblocks;) {
    418                 int ret;
    419
    420                 if (bd->options & NAND_BBT_SCANALLPAGES)
    421                         ret = scan_block_full(mtd, bd, from,
buf, readlen,
    422                                               scanlen, len);
    423                 else
    424                         ret = scan_block_fast(mtd, bd, from, buf, len);
    425
    426                 if (ret < 0)
    427                         return ret;
    428
    429                 if (ret) {
    430                         this->bbt[i >> 3] |= 0x03 << (i & 0x6);
    431                         printk(KERN_WARNING "Bad eraseblock %d
at 0x%012llx\n",
    432                                i >> 1, (unsigned long long)from);
    433                         mtd->ecc_stats.badblocks++;
    434                 }
    435
    436                 i += 2;
    437                 from += (1 << this->bbt_erase_shift);
    438         }

Thanks and Regards,
Naveen


From egorkat at gmail.com  Thu Jun 10 08:43:13 2010
From: egorkat at gmail.com (Egorkat)
Date: Thu, 10 Jun 2010 12:43:13 +0000 (UTC)
Subject: MTD support for old DoC chips MD2201-D72
Message-ID: <loom.20100610T134317-652@post.gmane.org>

Good day, All!

I've faced the problem in 2.6.34 with support for old DiskonChip drives.
I have 4 DoCs - one is MD2202-D32 (is recognised) and 3 MD2201-D72.
modprobe diskonchip says - 
[  151.499542] DiskOnChip found at 0xc8000
[  151.504542] DiskOnChip 2000 responds to DWORD access
[  151.509769] Detected 3 chips per floor.
[  151.509769] No NAND device found.
[  151.517548] DiskOnChip found at 0xca000
[  151.519541] DiskOnChip 2000 responds to DWORD access
[  151.521541] Detected 3 chips per floor.
[  151.527544] No NAND device found.
[  151.536658] No valid DiskOnChip devices found

Here is output from dinfo utility - 
                           D I N F O - utility 
                  Version 5.1.4.0.8, Last Update: 22 Oct 2002
                   Copyright (C) M-Systems, 1992 - 2002
                 ----------------------------------------

 DiskOnChip 1 - GENERAL INFO.
	Physical Address:  0xC8000
	DiskOnChip Type :  DiskOnChip 2000
	Flash Type      :  TC5864
	FormatType      :  NFTL
	TrueFFS version :  5.1.4
	Driver Version  :  DOS 5.1.4
	Sectors         :  9
	Heads           :  16
	Cylinders       :  1002
	Boot Area Size  :  49152 Bytes
	Logical Sectors :  144288
	Phy. UnitSize   :  8192 Bytes
	Physical Size   :  75497472 (72 MB)
	Unit Size       :  8192 Bytes
	Media Size      :  75497472 Bytes (72 MB)
	Chip Size       :  8388608 Bytes (8 MB)
	No Of Chips     :  9
	Interleaving    :  1

 DiskOnChip 2 - GENERAL INFO.
	Physical Address:  0xCA000
	DiskOnChip Type :  DiskOnChip 2000
	Flash Type      :  TC5864
	FormatType      :  NFTL
	TrueFFS version :  5.1.4
	Driver Version  :  DOS 5.1.4
	Sectors         :  9
	Heads           :  16
	Cylinders       :  1002
	Boot Area Size  :  49152 Bytes
	Logical Sectors :  144288
	Phy. UnitSize   :  8192 Bytes
	Physical Size   :  75497472 (72 MB)
	Unit Size       :  8192 Bytes
	Media Size      :  75497472 Bytes (72 MB)
	Chip Size       :  8388608 Bytes (8 MB)
	No Of Chips     :  9
	Interleaving    :  1

Is it possible to add support for that chip in mtd? May be I can supply more
information?

Thanks in advance!



From dwmw2 at infradead.org  Thu Jun 10 09:01:54 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Thu, 10 Jun 2010 14:01:54 +0100
Subject: MTD support for old DoC chips MD2201-D72
In-Reply-To: <loom.20100610T134317-652@post.gmane.org>
References: <loom.20100610T134317-652@post.gmane.org>
Message-ID: <1276174914.9474.0.camel@macbook.infradead.org>

On Thu, 2010-06-10 at 12:43 +0000, Egorkat wrote:
> 
> Is it possible to add support for that chip in mtd? May be I can
> supply more
> information? 

What are the device and manufacturer IDs? Do you have
CONFIG_MTD_NAND_MUSEUM_IDS set?

-- 
dwmw2



From taliaferro62 at gmail.com  Thu Jun 10 09:08:49 2010
From: taliaferro62 at gmail.com (twebb)
Date: Thu, 10 Jun 2010 09:08:49 -0400
Subject: UBIFS failed to recover master node
In-Reply-To: <1276006648.5677.20.camel@localhost>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763914.2106.1.camel@localhost>
	<AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>
	<1276006648.5677.20.camel@localhost>
Message-ID: <AANLkTilHpprYBKnYrw4wTEWjYyQBFJoJZRCwEQbSUOuP@mail.gmail.com>

>
> Yes, HW fails to correct bit errors. Why these errors are there - this
> it the question. May be MLC-related. You need to debug this. Or send me
> your board, I can try to take a look
>
> Did you enable UBI extra self checks?
>

It does appear to be an MLC-related problem - either read or write
disturb appears to have made an "empty" page not really empty.  Would
UBI extra self checks handle this situation?  I'm not familiar with
what the extra checks do - I'll look in the code.

Since read/write disturb errors are a trait of MLC, I'm curious how
others are dealing with this condition?  ECC can't correct for it
because it's supposed to be a blank page, implying no ECC is present.
So if a read or write disturb occurs and the blank page is no longer
blank - how does driver and/or UBI/UBIFS handle this?  Seems that the
remaining "good" block data would have to be moved to another LEB and
the current block somehow marked as dirty.


From dedekind1 at gmail.com  Thu Jun 10 09:14:04 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 10 Jun 2010 16:14:04 +0300
Subject: UBIFS failed to recover master node
In-Reply-To: <AANLkTilHpprYBKnYrw4wTEWjYyQBFJoJZRCwEQbSUOuP@mail.gmail.com>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763914.2106.1.camel@localhost>
	<AANLkTin31PwUfXVHGV89VGrWG89RbIcY1L1I_VEO7mSk@mail.gmail.com>
	<1276006648.5677.20.camel@localhost>
	<AANLkTilHpprYBKnYrw4wTEWjYyQBFJoJZRCwEQbSUOuP@mail.gmail.com>
Message-ID: <1276175644.5016.38.camel@localhost>

On Thu, 2010-06-10 at 09:08 -0400, twebb wrote:
> >
> > Yes, HW fails to correct bit errors. Why these errors are there - this
> > it the question. May be MLC-related. You need to debug this. Or send me
> > your board, I can try to take a look
> >
> > Did you enable UBI extra self checks?
> >
> 
> It does appear to be an MLC-related problem - either read or write
> disturb appears to have made an "empty" page not really empty.  Would
> UBI extra self checks handle this situation?  I'm not familiar with
> what the extra checks do - I'll look in the code.

No.

> Since read/write disturb errors are a trait of MLC, I'm curious how
> others are dealing with this condition?  ECC can't correct for it
> because it's supposed to be a blank page, implying no ECC is present.
> So if a read or write disturb occurs and the blank page is no longer
> blank - how does driver and/or UBI/UBIFS handle this?  Seems that the
> remaining "good" block data would have to be moved to another LEB and
> the current block somehow marked as dirty.

ubi_leb_change() could do this.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From matthieu.castet at parrot.com  Thu Jun 10 09:37:22 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Thu, 10 Jun 2010 15:37:22 +0200
Subject: [PATCH] ubi : generate random image_seq when attaching empty
	MTD device
In-Reply-To: <1275986730.4535.0.camel@localhost>
References: <4C07B8C3.7080304@parrot.com> <1275986730.4535.0.camel@localhost>
Message-ID: <4C10EA92.5020505@parrot.com>

Artem Bityutskiy a ?crit :
> On Thu, 2010-06-03 at 16:14 +0200, Matthieu CASTET wrote:
>> generate random image_seq when attaching empty MTD device (kernel do the 
>> ubi formating).
> 
> Your patch did not apply to the ubi-2.6.git master, because it
> conflicted with my latest changes. But I amended it and pushed, but you
> should probably check.
> 
It looks fine.

Thanks.


From egorkat at gmail.com  Thu Jun 10 09:46:56 2010
From: egorkat at gmail.com (Egorkat)
Date: Thu, 10 Jun 2010 13:46:56 +0000 (UTC)
Subject: MTD support for old DoC chips MD2201-D72
References: <loom.20100610T134317-652@post.gmane.org>
	<1276174914.9474.0.camel@macbook.infradead.org>
Message-ID: <loom.20100610T154548-504@post.gmane.org>

David Woodhouse <dwmw2 <at> infradead.org> writes:

> 
> On Thu, 2010-06-10 at 12:43 +0000, Egorkat wrote:
> > 
> > Is it possible to add support for that chip in mtd? May be I can
> > supply more
> > information? 
> 
> What are the device and manufacturer IDs? Do you have
> CONFIG_MTD_NAND_MUSEUM_IDS set?
> 

I don't know device ids. Is there a way to find it out without recompiling the
kernel with that parameter?




From eric at eukrea.com  Thu Jun 10 10:03:04 2010
From: eric at eukrea.com (=?utf-8?q?Eric=20B=C3=A9nard?=)
Date: Thu, 10 Jun 2010 16:03:04 +0200
Subject: [PATCH 1/2] mxc_nand: fix Unbalanced enable for IRQ
Message-ID: <1276178584-10074-1-git-send-email-eric@eukrea.com>

* preset should be done before sending the reset command

* without this, I get the following error on an i.MX35 :
[    0.900000] ------------[ cut here ]------------
[    0.900000] WARNING: at kernel/irq/manage.c:290 __enable_irq+0x4c/0x88()
[    0.900000] Unbalanced enable for IRQ 33
[    0.900000] Modules linked in:
[    0.900000] [<c002ffb8>] (unwind_backtrace+0x0/0xf0) from [<c02f7d0c>] (dump_stack+0x18/0x1c)
[    0.900000] [<c02f7d0c>] (dump_stack+0x18/0x1c) from [<c0049a44>] (warn_slowpath_common+0x54/0x6c)
[    0.900000] [<c0049a44>] (warn_slowpath_common+0x54/0x6c) from [<c0049b00>] (warn_slowpath_fmt+0x38/0x40)
[    0.900000] [<c0049b00>] (warn_slowpath_fmt+0x38/0x40) from [<c008f65c>] (__enable_irq+0x4c/0x88)
[    0.900000] [<c008f65c>] (__enable_irq+0x4c/0x88) from [<c008fca0>] (enable_irq+0x54/0x98)
[    0.900000] [<c008fca0>] (enable_irq+0x54/0x98) from [<c021e618>] (wait_op_done+0x40/0x134)
[    0.900000] [<c021e618>] (wait_op_done+0x40/0x134) from [<c021e808>] (send_cmd+0x30/0x38)
[    0.900000] [<c021e808>] (send_cmd+0x30/0x38) from [<c021eb8c>] (mxc_nand_command+0x26c/0x328)
[    0.900000] [<c021eb8c>] (mxc_nand_command+0x26c/0x328) from [<c021aa60>] (nand_scan_ident+0x188/0x6c0)
[    0.900000] [<c021aa60>] (nand_scan_ident+0x188/0x6c0) from [<c001a9cc>] (mxcnd_probe+0x2b8/0x3d0)
[    0.900000] [<c001a9cc>] (mxcnd_probe+0x2b8/0x3d0) from [<c01f9e88>] (platform_drv_probe+0x20/0x24)
[    0.900000] [<c01f9e88>] (platform_drv_probe+0x20/0x24) from [<c01f8c38>] (driver_probe_device+0xb0/0x164)
[    0.900000] [<c01f8c38>] (driver_probe_device+0xb0/0x164) from [<c01f8d54>] (__driver_attach+0x68/0x8c)
[    0.900000] [<c01f8d54>] (__driver_attach+0x68/0x8c) from [<c01f8348>] (bus_for_each_dev+0x50/0x84)
[    0.900000] [<c01f8348>] (bus_for_each_dev+0x50/0x84) from [<c01f8a9c>] (driver_attach+0x20/0x28)
[    0.900000] [<c01f8a9c>] (driver_attach+0x20/0x28) from [<c01f7c00>] (bus_add_driver+0x144/0x2dc)
[    0.900000] [<c01f7c00>] (bus_add_driver+0x144/0x2dc) from [<c01f906c>] (driver_register+0xb0/0x13c)
[    0.900000] [<c01f906c>] (driver_register+0xb0/0x13c) from [<c01fa13c>] (platform_driver_register+0x4c/0x60)
[    0.900000] [<c01fa13c>] (platform_driver_register+0x4c/0x60) from [<c01fa170>] (platform_driver_probe+0x20/0xa0)
[    0.900000] [<c01fa170>] (platform_driver_probe+0x20/0xa0) from [<c001a708>] (mxc_nd_init+0x18/0x24)
[    0.900000] [<c001a708>] (mxc_nd_init+0x18/0x24) from [<c002938c>] (do_one_initcall+0x64/0x1bc)
[    0.900000] [<c002938c>] (do_one_initcall+0x64/0x1bc) from [<c00084c4>] (kernel_init+0xe8/0x1ac)
[    0.900000] [<c00084c4>] (kernel_init+0xe8/0x1ac) from [<c002aee8>] (kernel_thread_exit+0x0/0x8)
[    0.900000] ---[ end trace 8bf72ac6ba089a19 ]---
[    1.140000] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron NAND 256MiB 3,3V 8-bit)

Signed-off-by: Eric B?nard <eric at eukrea.com>
---
 drivers/mtd/nand/mxc_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 82e9438..8878503 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -604,8 +604,8 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 	/* Command pre-processing step */
 	switch (command) {
 	case NAND_CMD_RESET:
-		send_cmd(host, command, false);
 		preset(mtd);
+		send_cmd(host, command, false);
 		break;
 
 	case NAND_CMD_STATUS:
-- 
1.6.3.3



From egorkat at gmail.com  Fri Jun 11 03:47:13 2010
From: egorkat at gmail.com (Egorkat)
Date: Fri, 11 Jun 2010 07:47:13 +0000 (UTC)
Subject: MTD support for old DoC chips MD2201-D72
References: <loom.20100610T134317-652@post.gmane.org>
	<1276174914.9474.0.camel@macbook.infradead.org>
Message-ID: <loom.20100611T094114-41@post.gmane.org>

Great! After recompiling my kernel with that parameter, I successfully can load
diskonchip module! Thanks for advice!

But that doesn't helped me in my primary problem - modprobe nftl also hangs... 
With these chip behavior is almost equal to MD2202-D32:

modprobe diskonchip -
DiskOnChip found at 0xc8000
DiskOnChip 2000 responds to DWORD access
Detected 3 chips per floor.
NAND device: Manufacturer ID: 0x98, Chip ID: 0xe6 (Toshiba NAND 8MiB 3,3V 8-bit)
9 NAND chips detected
Found DiskOnChip ANAND Media Header at 0xc000
Found DiskOnChip ANAND Media Header at 0x10000
 DataOrgID        = ANAND
 NumEraseUnits    = 4605
 FirstPhysicalEUN = 3
 FormattedSize    = 73875456
 UnitSizeFactor   = 0
UnitSizeFactor=0x00 detected.  Correct value is assumed to be 0xfe.
Setting virtual erase size to 16384
Bad block table at page 97, version 0x55
Bad block table at page 129, version 0x55
Found alias of DOC at 0xc8000 to 0xca000

mtd_debug info /dev/mtd0 -
mtd.type = MTD_NANDFLASH
mtd.flags = MTD_CAP_NANDFLASH
mtd.size = 75497472 (72M)
mtd.erasesize = 16384 (16K)
mtd.writesize = 512
mtd.oobsize = 16
regions = 0

nftl_format /dev/mtd0 -
version 1.24 2005/11/07 11:15:13 gleixner
Phase 1. Checking and erasing Erase Zones from 0x00000000 to 0x04800000
Skipping bad zone (factory marked) #3 @ 0xc000
Skipping bad zone (factory marked) #4 @ 0x10000
Skipping bad zone (factory marked) #6 @ 0x18000
Skipping bad zone (factory marked) #7 @ 0x1c000
Skipping bad zone (factory marked) #8 @ 0x20000
Skipping bad zone (factory marked) #9 @ 0x24000
Skipping bad zone (factory marked) #10 @ 0x28000
        Checking Zone #4607 @ 0x47fc000
Phase 2.a Writing NFTL Media Header and Bad Unit Table
Phase 2.b Writing Spare NFTL Media Header and Spare Bad Unit Table
Phase 3. Writing Unit Control Information to each Erase Unit

and modprobe nftl - 
[ 1695.537469] NFTL Media Headers at 0x0 and 0xc000 disagree.
[ 1695.541610] NFTL Media Headers at 0x0 and 0x10000 disagree.
[ 1699.540763] Formatting block 6
[ 1699.580575] Formatting block 7
[ 1699.620227] Formatting block 8
[ 1699.660541] Formatting block 9
[ 1699.699122] Formatting block 10
[ 1851.005969] NFTL: cannot calculate a geometry to match size of 0x23e80.
[ 1851.008110] NFTL: using C:1021 H:16 S:9 (== 0x23e50 sects)




From egorkat at gmail.com  Fri Jun 11 03:48:23 2010
From: egorkat at gmail.com (Egorkat)
Date: Fri, 11 Jun 2010 07:48:23 +0000 (UTC)
Subject: modprobe nftl hangs
References: <loom.20100608T165617-407@post.gmane.org>
Message-ID: <loom.20100611T094726-371@post.gmane.org>

Situation repeats with another chip - MD2201-D72:


modprobe diskonchip -
DiskOnChip found at 0xc8000
DiskOnChip 2000 responds to DWORD access
Detected 3 chips per floor.
NAND device: Manufacturer ID: 0x98, Chip ID: 0xe6 (Toshiba NAND 8MiB 3,3V 8-bit)
9 NAND chips detected
Found DiskOnChip ANAND Media Header at 0xc000
Found DiskOnChip ANAND Media Header at 0x10000
 DataOrgID        = ANAND
 NumEraseUnits    = 4605
 FirstPhysicalEUN = 3
 FormattedSize    = 73875456
 UnitSizeFactor   = 0
UnitSizeFactor=0x00 detected.  Correct value is assumed to be 0xfe.
Setting virtual erase size to 16384
Bad block table at page 97, version 0x55
Bad block table at page 129, version 0x55
Found alias of DOC at 0xc8000 to 0xca000

mtd_debug info /dev/mtd0 -
mtd.type = MTD_NANDFLASH
mtd.flags = MTD_CAP_NANDFLASH
mtd.size = 75497472 (72M)
mtd.erasesize = 16384 (16K)
mtd.writesize = 512
mtd.oobsize = 16
regions = 0

nftl_format /dev/mtd0 -
version 1.24 2005/11/07 11:15:13 gleixner
Phase 1. Checking and erasing Erase Zones from 0x00000000 to 0x04800000
Skipping bad zone (factory marked) #3 @ 0xc000
Skipping bad zone (factory marked) #4 @ 0x10000
Skipping bad zone (factory marked) #6 @ 0x18000
Skipping bad zone (factory marked) #7 @ 0x1c000
Skipping bad zone (factory marked) #8 @ 0x20000
Skipping bad zone (factory marked) #9 @ 0x24000
Skipping bad zone (factory marked) #10 @ 0x28000
        Checking Zone #4607 @ 0x47fc000
Phase 2.a Writing NFTL Media Header and Bad Unit Table
Phase 2.b Writing Spare NFTL Media Header and Spare Bad Unit Table
Phase 3. Writing Unit Control Information to each Erase Unit

and modprobe nftl - 
[ 1695.537469] NFTL Media Headers at 0x0 and 0xc000 disagree.
[ 1695.541610] NFTL Media Headers at 0x0 and 0x10000 disagree.
[ 1699.540763] Formatting block 6
[ 1699.580575] Formatting block 7
[ 1699.620227] Formatting block 8
[ 1699.660541] Formatting block 9
[ 1699.699122] Formatting block 10
[ 1851.005969] NFTL: cannot calculate a geometry to match size of 0x23e80.
[ 1851.008110] NFTL: using C:1021 H:16 S:9 (== 0x23e50 sects)
and nothing... it hangs forever...




From stanley.miao at windriver.com  Fri Jun 11 05:36:14 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 11 Jun 2010 17:36:14 +0800
Subject: [PATCH 2/3] Discard the legacy interface MEMGETOOBSEL in
	flash_eraseall
In-Reply-To: <1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276248975-1822-3-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
to keep compatible with the old linux kernel, a linux version detection
function is added.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   71 ++++++++++++++++++++++++++++++++----------------------
 1 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index a22fc49..4e2108b 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -43,6 +43,8 @@
 #define PROGRAM "flash_eraseall"
 #define VERSION "$Revision: 1.22 $"
 
+#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
 static const char *exe_name;
 static const char *mtd_device;
 static int quiet;		/* true -- don't output progress */
@@ -55,6 +57,21 @@ static void display_version (void);
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
 
+static int get_linux_version(void)
+{
+	FILE *fd;
+	int a = 0, b = 0, c = 0;
+	
+	fd = fopen("/proc/version", "r");
+	if (fd) {
+		fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
+		fclose(fd);
+	}
+
+	return LINUX_VERSION(a, b, c); 
+}
+
+
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
@@ -84,41 +101,37 @@ int main (int argc, char *argv[])
 		if (!isNAND)
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
 		else {
-			struct nand_oobinfo oobinfo;
-
-			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
-				fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", exe_name, mtd_device);
-				return 1;
-			}
+			struct nand_ecclayout ecclayout;
 
-			/* Check for autoplacement */
-			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
-				/* Get the position of the free bytes */
-				if (!oobinfo.oobfree[0][1]) {
-					fprintf (stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+			memset(&ecclayout, 0, sizeof(ecclayout));
+			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+					fprintf(stderr,	"%s: %s: unable to get NAND oob layout\n", \
+							exe_name, mtd_device);
 					return 1;
 				}
-				clmpos = oobinfo.oobfree[0][0];
-				clmlen = oobinfo.oobfree[0][1];
-				if (clmlen > 8)
-					clmlen = 8;
 			} else {
-				/* Legacy mode */
-				switch (meminfo.oobsize) {
-					case 8:
-						clmpos = 6;
-						clmlen = 2;
-						break;
-					case 16:
-						clmpos = 8;
-						clmlen = 8;
-						break;
-					case 64:
-						clmpos = 16;
-						clmlen = 8;
-						break;
+				struct nand_oobinfo oi;
+
+				if (ioctl(fd, MEMGETOOBSEL, &oi) != 0) {
+					fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", \
+							exe_name, mtd_device);
+					return 1;
 				}
+				memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+				ecclayout.eccbytes = oi.eccbytes;
+			}
+
+			/* Get the position of the free bytes */
+			if (!ecclayout.oobfree[0].length) {
+				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+				return 1;
 			}
+			clmpos = ecclayout.oobfree[0].offset;
+			clmlen = ecclayout.oobfree[0].length;
+			if (clmlen > 8)
+				clmlen = 8;
 			cleanmarker.totlen = cpu_to_je32(8);
 		}
 		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
-- 
1.5.4.3



From stanley.miao at windriver.com  Fri Jun 11 05:36:15 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 11 Jun 2010 17:36:15 +0800
Subject: [PATCH 3/3] Place the cleanmarker in OOB area according to the mode
	MTD_OOB_AUTO
In-Reply-To: <1276248975-1822-3-git-send-email-stanley.miao@windriver.com>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-3-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276248975-1822-4-git-send-email-stanley.miao@windriver.com>

In the current linux kernel, Jffs2 writes the cleanmarker according to the
mode MTD_OOB_AUTO, so modify the layout of the cleanmarker from
MTD_OOB_PLACE to MTD_OOB_AUTO in flash_eraseall.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   40 ++++++++++++++++++++++------------------
 1 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index 4e2108b..f0f0371 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -34,7 +34,7 @@
 #include <time.h>
 #include <getopt.h>
 #include <sys/ioctl.h>
-#include <sys/mount.h>
+#include <sys/param.h>
 #include "crc32.h"
 
 #include <mtd/mtd-user.h>
@@ -75,9 +75,11 @@ static int get_linux_version(void)
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
-	int fd, clmpos = 0, clmlen = 8;
+	int fd;
 	erase_info_t erase;
 	int isNAND, bbtest = 1;
+	unsigned char oobbuf[128];
+	memset(oobbuf, 0xFF, 128);
 
 	process_options(argc, argv);
 
@@ -98,11 +100,18 @@ int main (int argc, char *argv[])
 	if (jffs2) {
 		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
 		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-		if (!isNAND)
+		if (!isNAND) {
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
-		else {
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+		} else {
+			int already_read, num, i, start;
 			struct nand_ecclayout ecclayout;
 
+			cleanmarker.totlen = cpu_to_je32(8);
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+
 			memset(&ecclayout, 0, sizeof(ecclayout));
 			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
 				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
@@ -122,19 +131,14 @@ int main (int argc, char *argv[])
 				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
 				ecclayout.eccbytes = oi.eccbytes;
 			}
-
-			/* Get the position of the free bytes */
-			if (!ecclayout.oobfree[0].length) {
-				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
-				return 1;
+			already_read = 0;
+			for (i = 0; (already_read < 8) && ecclayout.oobfree[i].length; i++) {
+				num = MIN(8 - already_read, ecclayout.oobfree[i].length);
+				start = ecclayout.oobfree[i].offset;
+				memcpy(oobbuf + start, (unsigned char *)&cleanmarker + already_read, num);
+				already_read += num;
 			}
-			clmpos = ecclayout.oobfree[0].offset;
-			clmlen = ecclayout.oobfree[0].length;
-			if (clmlen > 8)
-				clmlen = 8;
-			cleanmarker.totlen = cpu_to_je32(8);
 		}
-		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
 	}
 
 	for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) {
@@ -174,9 +178,9 @@ int main (int argc, char *argv[])
 		/* write cleanmarker */
 		if (isNAND) {
 			struct mtd_oob_buf oob;
-			oob.ptr = (unsigned char *) &cleanmarker;
-			oob.start = erase.start + clmpos;
-			oob.length = clmlen;
+			oob.ptr = oobbuf;
+			oob.start = erase.start;
+			oob.length = meminfo.oobsize;
 			if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
 				fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
 				continue;
-- 
1.5.4.3



From stanley.miao at windriver.com  Fri Jun 11 05:36:12 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 11 Jun 2010 17:36:12 +0800
Subject: Fix mtd-utils bugs
Message-ID: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>

Re-send them because I didn't give a email subject in last version.

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up. 


Stanley.


From stanley.miao at windriver.com  Fri Jun 11 05:36:13 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 11 Jun 2010 17:36:13 +0800
Subject: [PATCH 1/3] clean up the legacy interfaces in nandwrite.c
In-Reply-To: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276248975-1822-2-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 nandwrite.c |  215 +++++++++++++---------------------------------------------
 1 files changed, 48 insertions(+), 167 deletions(-)

diff --git a/nandwrite.c b/nandwrite.c
index e691ebd..a0a843b 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -45,26 +45,21 @@
 #define MAX_PAGE_SIZE	4096
 #define MAX_OOB_SIZE	128
 
-// oob layouts to pass into the kernel as default
-static struct nand_oobinfo none_oobinfo = {
-	.useecc = MTD_NANDECC_OFF,
-};
-
-static struct nand_oobinfo jffs2_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 0, 1, 2, 3, 6, 7 }
-};
-
-static struct nand_oobinfo yaffs_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_oobinfo autoplace_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE
-};
+#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+static int get_linux_version(void)
+{
+	FILE *fd;
+	int a = 0, b = 0, c = 0;
+	
+	fd = fopen("/proc/version", "r");
+	if (fd) {
+		fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
+		fclose(fd);
+	}
+
+	return LINUX_VERSION(a, b, c);
+}
 
 static void display_help (void)
 {
@@ -72,13 +67,7 @@ static void display_help (void)
 "Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
 "Writes to the specified MTD device.\n"
 "\n"
-"  -a, --autoplace         Use auto oob layout\n"
-"  -j, --jffs2             Force jffs2 oob layout (legacy support)\n"
-"  -y, --yaffs             Force yaffs oob layout (legacy support)\n"
-"  -f, --forcelegacy       Force legacy support on autoplacement-enabled mtd\n"
-"                          device\n"
 "  -m, --markbad           Mark blocks bad if write fails\n"
-"  -n, --noecc             Write without ecc\n"
 "  -o, --oob               Image contains oob data\n"
 "  -r, --raw               Image contains the raw oob data dumped by nanddump\n"
 "  -s addr, --start=addr   Set start address (default is 0)\n"
@@ -112,12 +101,7 @@ static int		mtdoffset = 0;
 static bool		quiet = false;
 static bool		writeoob = false;
 static bool		rawoob = false;
-static bool		autoplace = false;
 static bool		markbad = false;
-static bool		forcejffs2 = false;
-static bool		forceyaffs = false;
-static bool		forcelegacy = false;
-static bool		noecc = false;
 static bool		pad = false;
 static int		blockalign = 1; /*default to using 16K block size */
 
@@ -127,22 +111,17 @@ static void process_options (int argc, char * const argv[])
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "ab:fjmnopqrs:y";
+		static const char *short_options = "b:mopqrs:";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
-			{"autoplace", no_argument, 0, 'a'},
 			{"blockalign", required_argument, 0, 'b'},
-			{"forcelegacy", no_argument, 0, 'f'},
-			{"jffs2", no_argument, 0, 'j'},
 			{"markbad", no_argument, 0, 'm'},
-			{"noecc", no_argument, 0, 'n'},
 			{"oob", no_argument, 0, 'o'},
 			{"pad", no_argument, 0, 'p'},
 			{"quiet", no_argument, 0, 'q'},
 			{"raw", no_argument, 0, 'r'},
 			{"start", required_argument, 0, 's'},
-			{"yaffs", no_argument, 0, 'y'},
 			{0, 0, 0, 0},
 		};
 
@@ -166,21 +145,6 @@ static void process_options (int argc, char * const argv[])
 			case 'q':
 				quiet = true;
 				break;
-			case 'a':
-				autoplace = true;
-				break;
-			case 'j':
-				forcejffs2 = true;
-				break;
-			case 'y':
-				forceyaffs = true;
-				break;
-			case 'f':
-				forcelegacy = true;
-				break;
-			case 'n':
-				noecc = true;
-				break;
 			case 'm':
 				markbad = true;
 				break;
@@ -258,8 +222,7 @@ int main(int argc, char * const argv[])
 	struct mtd_oob_buf oob;
 	loff_t offs;
 	int ret;
-	int oobinfochanged = 0;
-	struct nand_oobinfo old_oobinfo;
+	struct nand_ecclayout ecclayout;
 	bool failed = true;
 	// contains all the data read from the file so far for the current eraseblock
 	unsigned char *filebuf = NULL;
@@ -315,86 +278,30 @@ int main(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (autoplace) {
-		/* Read the current oob info */
-		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMGETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-
-		// autoplace ECC ?
-		if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
-
-			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
-				perror ("MEMSETOOBSEL");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-			oobinfochanged = 1;
-		}
-	}
 
-	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
-		if (ret == 0) {
-			oobinfochanged = 2;
-		} else {
-			switch (errno) {
-			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				oobinfochanged = 1;
-				break;
-			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-		}
-	}
-
-	/*
-	 * force oob layout for jffs2 or yaffs ?
-	 * Legacy support
-	 */
-	if (forcejffs2 || forceyaffs) {
-		struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
-
-		if (autoplace) {
-			fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n");
-			goto restoreoob;
-		}
-		if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) {
-			fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n");
-			goto restoreoob;
-		}
-		if (meminfo.oobsize == 8) {
-			if (forceyaffs) {
-				fprintf (stderr, "YAFSS cannot operate on 256 Byte page size");
-				goto restoreoob;
-			}
-			/* Adjust number of ecc bytes */
-			jffs2_oobinfo.eccbytes = 3;
+	oob.length = meminfo.oobsize;
+	oob.ptr =  oobbuf;
+
+	memset(&ecclayout, 0, sizeof(ecclayout));
+	if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+		if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+			perror("ECCGETLAYOUT");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
+	} else {
+		struct nand_oobinfo oi;
 
-		if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) {
-			perror ("MEMSETOOBSEL");
-			goto restoreoob;
+		if (ioctl (fd, MEMGETOOBSEL, &oi) != 0) {
+			perror ("MEMGETOOBSEL");
+			close (fd);
+			exit (EXIT_FAILURE);
 		}
+		memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+		memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+		ecclayout.eccbytes = oi.eccbytes;
 	}
 
-	oob.length = meminfo.oobsize;
-	oob.ptr = noecc ? oobreadbuf : oobbuf;
-
 	/* Determine if we are reading from standard input or from a file. */
 	if (strcmp(img, standard_input) == 0) {
 		ifd = STDIN_FILENO;
@@ -558,6 +465,8 @@ int main(int argc, char * const argv[])
 		}
 
 		if (writeoob) {
+			int i, start, len;
+			int tags_pos = 0;
 			oobreadbuf = writebuf + meminfo.writesize;
 
 			// Read more data for the OOB from the input if there isn't enough in the buffer
@@ -594,40 +503,19 @@ int main(int argc, char * const argv[])
 				}
 			}
 
-			if (noecc) {
-				oob.ptr = oobreadbuf;
-			} else {
-				int i, start, len;
-				int tags_pos = 0;
-				/*
-				 *  We use autoplacement and have the oobinfo with the autoplacement
-				 * information from the kernel available
-				 *
-				 * Modified to support out of order oobfree segments,
-				 * such as the layout used by diskonchip.c
-				 */
-				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
-					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
-						/* Set the reserved bytes to 0xff */
-						start = old_oobinfo.oobfree[i][0];
-						len = old_oobinfo.oobfree[i][1];
-						if (rawoob)
-							memcpy(oobbuf + start,
-									oobreadbuf + start, len);
-						else
-							memcpy(oobbuf + start,
-									oobreadbuf + tags_pos, len);
-						tags_pos += len;
-					}
-				} else {
-					/* Set at least the ecc byte positions to 0xff */
-					start = old_oobinfo.eccbytes;
-					len = meminfo.oobsize - start;
+			for (i = 0; ecclayout.oobfree[i].length; i++) {
+				/* Set the reserved bytes to 0xff */
+				start = ecclayout.oobfree[i].offset;
+				len = ecclayout.oobfree[i].length;
+				if (rawoob)
 					memcpy(oobbuf + start,
-							oobreadbuf + start,
-							len);
-				}
+							oobreadbuf + start, len);
+				else
+					memcpy(oobbuf + start,
+							oobreadbuf + tags_pos, len);
+				tags_pos += len;
 			}
+
 			/* Write OOB data first, as ecc will be placed in there*/
 			oob.start = mtdoffset;
 			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
@@ -686,13 +574,6 @@ closeall:
 	close(ifd);
 
 restoreoob:
-	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-	}
 
 	close(fd);
 
-- 
1.5.4.3



From joakim.tjernlund at transmode.se  Fri Jun 11 05:44:27 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Fri, 11 Jun 2010 11:44:27 +0200
Subject: [PATCH 2/3] Discard the legacy interface MEMGETOOBSEL
	in	flash_eraseall
In-Reply-To: <1276248975-1822-3-git-send-email-stanley.miao@windriver.com>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	<1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-3-git-send-email-stanley.miao@windriver.com>
Message-ID: <OFDBEF7A42.BA0205E8-ONC125773F.0034F62C-C125773F.00358229@transmode.se>

>
> The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
> is not enough for many big NAND chips. Therefore, this structure is replaced
> by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
> Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
>
> Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
> to keep compatible with the old linux kernel, a linux version detection
> function is added.
>
> Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
> ---
>  flash_eraseall.c |   71 ++++++++++++++++++++++++++++++++----------------------
>  1 files changed, 42 insertions(+), 29 deletions(-)
>
> diff --git a/flash_eraseall.c b/flash_eraseall.c
> index a22fc49..4e2108b 100644
> --- a/flash_eraseall.c
> +++ b/flash_eraseall.c
> @@ -43,6 +43,8 @@
>  #define PROGRAM "flash_eraseall"
>  #define VERSION "$Revision: 1.22 $"
>
> +#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
> +
>  static const char *exe_name;
>  static const char *mtd_device;
>  static int quiet;      /* true -- don't output progress */
> @@ -55,6 +57,21 @@ static void display_version (void);
>  static struct jffs2_unknown_node cleanmarker;
>  int target_endian = __BYTE_ORDER;
>
> +static int get_linux_version(void)
> +{
> +   FILE *fd;
> +   int a = 0, b = 0, c = 0;
> +
> +   fd = fopen("/proc/version", "r");
> +   if (fd) {
> +      fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
> +      fclose(fd);
> +   }
> +
> +   return LINUX_VERSION(a, b, c);
> +}
> +
> +

The fopen could fail and if it does, I think you should default to "assume latest kernel"
Same goes for fscanf, you should at least test the return value.

   Jocke



From joakim.tjernlund at transmode.se  Fri Jun 11 05:53:44 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Fri, 11 Jun 2010 11:53:44 +0200
Subject: [PATCH 2/3] Discard the legacy interface MEMGETOOBSEL
	in	flash_eraseall
In-Reply-To: <OFDBEF7A42.BA0205E8-ONC125773F.0034F62C-C125773F.00358229@LocalDomain>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	<1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-3-git-send-email-stanley.miao@windriver.com>
	<OFDBEF7A42.BA0205E8-ONC125773F.0034F62C-C125773F.00358229@LocalDomain>
Message-ID: <OF17604B8E.95B0C75E-ONC125773F.00361B51-C125773F.00365BD5@transmode.se>

Joakim Tjernlund/Transmode wrote on 2010/06/11 11:44:27:
>
> >
> > The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
> > is not enough for many big NAND chips. Therefore, this structure is replaced
> > by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
> > Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
> >
> > Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
> > to keep compatible with the old linux kernel, a linux version detection
> > function is added.
> >
> > Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
> > ---
> >  flash_eraseall.c |   71 ++++++++++++++++++++++++++++++++----------------------
> >  1 files changed, 42 insertions(+), 29 deletions(-)
> >
> > diff --git a/flash_eraseall.c b/flash_eraseall.c
> > index a22fc49..4e2108b 100644
> > --- a/flash_eraseall.c
> > +++ b/flash_eraseall.c
> > @@ -43,6 +43,8 @@
> >  #define PROGRAM "flash_eraseall"
> >  #define VERSION "$Revision: 1.22 $"
> >
> > +#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
> > +
> >  static const char *exe_name;
> >  static const char *mtd_device;
> >  static int quiet;      /* true -- don't output progress */
> > @@ -55,6 +57,21 @@ static void display_version (void);
> >  static struct jffs2_unknown_node cleanmarker;
> >  int target_endian = __BYTE_ORDER;
> >
> > +static int get_linux_version(void)
> > +{
> > +   FILE *fd;
> > +   int a = 0, b = 0, c = 0;
> > +
> > +   fd = fopen("/proc/version", "r");
> > +   if (fd) {
> > +      fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
> > +      fclose(fd);
> > +   }
> > +
> > +   return LINUX_VERSION(a, b, c);
> > +}
> > +
> > +
> The fopen could fail and if it does, I think you should default to "assume
> latest kernel"
> Same goes for fscanf, you should at least test the return value.

Forgot, use uname(2) instead of /proc/version

Does the above scanf work on "2.6.31-gentoo-r6"?

  Jocke



From stanley.miao at windriver.com  Fri Jun 11 06:36:08 2010
From: stanley.miao at windriver.com (stanley.miao)
Date: Fri, 11 Jun 2010 18:36:08 +0800
Subject: [PATCH 2/3] Discard the legacy interface MEMGETOOBSEL
	in	flash_eraseall
In-Reply-To: <OF17604B8E.95B0C75E-ONC125773F.00361B51-C125773F.00365BD5@transmode.se>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	<1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-3-git-send-email-stanley.miao@windriver.com>
	<OFDBEF7A42.BA0205E8-ONC125773F.0034F62C-C125773F.00358229@LocalDomain>
	<OF17604B8E.95B0C75E-ONC125773F.00361B51-C125773F.00365BD5@transmode.se>
Message-ID: <4C121198.5030807@windriver.com>

Joakim Tjernlund wrote:
> Joakim Tjernlund/Transmode wrote on 2010/06/11 11:44:27:
>   
>>> The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
>>> is not enough for many big NAND chips. Therefore, this structure is replaced
>>> by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
>>> Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
>>>
>>> Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
>>> to keep compatible with the old linux kernel, a linux version detection
>>> function is added.
>>>
>>> Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
>>> ---
>>>  flash_eraseall.c |   71 ++++++++++++++++++++++++++++++++----------------------
>>>  1 files changed, 42 insertions(+), 29 deletions(-)
>>>
>>> diff --git a/flash_eraseall.c b/flash_eraseall.c
>>> index a22fc49..4e2108b 100644
>>> --- a/flash_eraseall.c
>>> +++ b/flash_eraseall.c
>>> @@ -43,6 +43,8 @@
>>>  #define PROGRAM "flash_eraseall"
>>>  #define VERSION "$Revision: 1.22 $"
>>>
>>> +#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
>>> +
>>>  static const char *exe_name;
>>>  static const char *mtd_device;
>>>  static int quiet;      /* true -- don't output progress */
>>> @@ -55,6 +57,21 @@ static void display_version (void);
>>>  static struct jffs2_unknown_node cleanmarker;
>>>  int target_endian = __BYTE_ORDER;
>>>
>>> +static int get_linux_version(void)
>>> +{
>>> +   FILE *fd;
>>> +   int a = 0, b = 0, c = 0;
>>> +
>>> +   fd = fopen("/proc/version", "r");
>>> +   if (fd) {
>>> +      fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
>>> +      fclose(fd);
>>> +   }
>>> +
>>> +   return LINUX_VERSION(a, b, c);
>>> +}
>>> +
>>> +
>>>       
>> The fopen could fail and if it does, I think you should default to "assume
>> latest kernel"
>> Same goes for fscanf, you should at least test the return value.
>>     

I am not sure what kernel version the proc file "version" began to exist.
If the fopen failed, it must be a old kernel, so I set the default to 
the old kernel.
It is the same with the current mtd-utils.

>
> Forgot, use uname(2) instead of /proc/version
>   

Why ?

> Does the above scanf work on "2.6.31-gentoo-r6"?
>   

I didn't do the test on all the platforms. Is there any reason that 
cause it not to work ?


Thanks
Stanley.
>   Jocke
>
>
>   



From joakim.tjernlund at transmode.se  Fri Jun 11 06:44:22 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Fri, 11 Jun 2010 12:44:22 +0200
Subject: [PATCH 2/3] Discard the legacy interface MEMGETOOBSEL
	in	flash_eraseall
In-Reply-To: <4C121198.5030807@windriver.com>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	<1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-3-git-send-email-stanley.miao@windriver.com>
	<OFDBEF7A42.BA0205E8-ONC125773F.0034F62C-C125773F.00358229@LocalDomain>
	<OF17604B8E.95B0C75E-ONC125773F.00361B51-C125773F.00365BD5@transmode.se>
	<4C121198.5030807@windriver.com>
Message-ID: <OF6FD3E8A2.2EDC41D1-ONC125773F.0039DD3B-C125773F.003AFE83@transmode.se>

"stanley.miao" <stanley.miao at windriver.com> wrote on 2010/06/11 12:36:08:
>
> Joakim Tjernlund wrote:
> > Joakim Tjernlund/Transmode wrote on 2010/06/11 11:44:27:
> >
> >>> The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
> >>> is not enough for many big NAND chips. Therefore, this structure is replaced
> >>> by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
> >>> Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
> >>>
> >>> Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
> >>> to keep compatible with the old linux kernel, a linux version detection
> >>> function is added.
> >>>
> >>> Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
> >>> ---
> >>>  flash_eraseall.c |   71 ++++++++++++++++++++++++++++++++----------------------
> >>>  1 files changed, 42 insertions(+), 29 deletions(-)
> >>>
> >>> diff --git a/flash_eraseall.c b/flash_eraseall.c
> >>> index a22fc49..4e2108b 100644
> >>> --- a/flash_eraseall.c
> >>> +++ b/flash_eraseall.c
> >>> @@ -43,6 +43,8 @@
> >>>  #define PROGRAM "flash_eraseall"
> >>>  #define VERSION "$Revision: 1.22 $"
> >>>
> >>> +#define LINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
> >>> +
> >>>  static const char *exe_name;
> >>>  static const char *mtd_device;
> >>>  static int quiet;      /* true -- don't output progress */
> >>> @@ -55,6 +57,21 @@ static void display_version (void);
> >>>  static struct jffs2_unknown_node cleanmarker;
> >>>  int target_endian = __BYTE_ORDER;
> >>>
> >>> +static int get_linux_version(void)
> >>> +{
> >>> +   FILE *fd;
> >>> +   int a = 0, b = 0, c = 0;
> >>> +
> >>> +   fd = fopen("/proc/version", "r");
> >>> +   if (fd) {
> >>> +      fscanf(fd, "Linux version %d.%d.%d", &a, &b, &c);
> >>> +      fclose(fd);
> >>> +   }
> >>> +
> >>> +   return LINUX_VERSION(a, b, c);
> >>> +}
> >>> +
> >>> +
> >>>
> >> The fopen could fail and if it does, I think you should default to "assume
> >> latest kernel"
> >> Same goes for fscanf, you should at least test the return value.
> >>
>

Forgot to say: Hi
:)

> I am not sure what kernel version the proc file "version" began to exist.

But the proc FS might not be mounted.

> If the fopen failed, it must be a old kernel, so I set the default to
> the old kernel.
> It is the same with the current mtd-utils.

I think that behaviour is wrong, one should assume current kernel should
one fail to retrive the exact version since it is much more likly that
the user is running someting new enough.

>
> >
> > Forgot, use uname(2) instead of /proc/version
> >
>
> Why ?

Cleaner, faster, shorter, more portable, less likely to fail.

>
> > Does the above scanf work on "2.6.31-gentoo-r6"?
> >
>
> I didn't do the test on all the platforms. Is there any reason that
> cause it not to work ?

I don't remeber how picky scanf is, will it parse the numbers correctly
when you have non WS trailing chars? In any case you need to check the
return value so you know if it failed.

  Jocke



From dbaryshkov at gmail.com  Fri Jun 11 07:58:51 2010
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Fri, 11 Jun 2010 15:58:51 +0400
Subject: [PATCH] physmap: fix mtdconcat support if physmap/mtdconcat were
	compiled as modules
Message-ID: <1276257531-7566-1-git-send-email-dbaryshkov@gmail.com>

physmap/physmap_of contained compile-time check for mtd concatenation.
However thos modules did not consider that mtd concatenation can be
built as modules. Fix physmap/physmap_of to also support
CONFIG_MTD_CONCAT=m

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Cc: Stefan Roese <sr at denx.de>
---
 drivers/mtd/maps/physmap.c    |    4 ++--
 drivers/mtd/maps/physmap_of.c |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index d9603f7..7750757 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -59,7 +59,7 @@ static int physmap_flash_remove(struct platform_device *dev)
 #else
 		del_mtd_device(info->cmtd);
 #endif
-#ifdef CONFIG_MTD_CONCAT
+#if defined(CONFIG_MTD_CONCAT) || defined(CONFIG_MTD_CONCAT_MODULE)
 		if (info->cmtd != info->mtd[0])
 			mtd_concat_destroy(info->cmtd);
 #endif
@@ -155,7 +155,7 @@ static int physmap_flash_probe(struct platform_device *dev)
 		/*
 		 * We detected multiple devices. Concatenate them together.
 		 */
-#ifdef CONFIG_MTD_CONCAT
+#if defined(CONFIG_MTD_CONCAT) || defined(CONFIG_MTD_CONCAT_MODULE)
 		info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev));
 		if (info->cmtd == NULL)
 			err = -ENXIO;
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 101ee6e..8cb80e1 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -103,7 +103,7 @@ static int of_flash_remove(struct of_device *dev)
 		return 0;
 	dev_set_drvdata(&dev->dev, NULL);
 
-#ifdef CONFIG_MTD_CONCAT
+#if defined(CONFIG_MTD_CONCAT) || defined(CONFIG_MTD_CONCAT_MODULE)
 	if (info->cmtd != info->list[0].mtd) {
 		del_mtd_device(info->cmtd);
 		mtd_concat_destroy(info->cmtd);
@@ -292,7 +292,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
 		/*
 		 * We detected multiple devices. Concatenate them together.
 		 */
-#ifdef CONFIG_MTD_CONCAT
+#if defined(CONFIG_MTD_CONCAT) || defined(CONFIG_MTD_CONCAT_MODULE)
 		info->cmtd = mtd_concat_create(mtd_list, info->list_size,
 					       dev_name(&dev->dev));
 		if (info->cmtd == NULL)
-- 
1.7.1



From joakim.tjernlund at transmode.se  Fri Jun 11 08:11:33 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Fri, 11 Jun 2010 14:11:33 +0200
Subject: [PATCH 2/3] Discard the legacy interface
	MEMGETOOBSEL	in	flash_eraseall
In-Reply-To: <OF6FD3E8A2.2EDC41D1-ONC125773F.0039DD3B-C125773F.003AFE83@transmode.se>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	<1276248975-1822-2-git-send-email-stanley.miao@windriver.com>
	<1276248975-1822-3-git-send-email-stanley.miao@windriver.com>	<OFDBEF7A42.BA0205E8-ONC125773F.0034F62C-C125773F.00358229@LocalDomain>
	<OF17604B8E.95B0C75E-ONC125773F.00361B51-C125773F.00365BD5@transmode.se>	<4C121198.5030807@windriver.com>
	<OF6FD3E8A2.2EDC41D1-ONC125773F.0039DD3B-C125773F.003AFE83@transmode.se>
Message-ID: <OFD47C0229.927FA4AC-ONC125773F.0042C2E4-C125773F.0042F9D3@transmode.se>

> "stanley.miao" <stanley.miao at windriver.com> wrote on 2010/06/11 12:36:08:
> >
> > Joakim Tjernlund wrote:
> > > Joakim Tjernlund/Transmode wrote on 2010/06/11 11:44:27:

> >
> > >
> > > Forgot, use uname(2) instead of /proc/version
> > >
> >
> > Why ?
>
> Cleaner, faster, shorter, more portable, less likely to fail.

Here is a quick example of uname(2):

#include <stdio.h>
#include <sys/utsname.h>

int main()
{
	int a, b, c , ret;
	struct utsname buf;

	ret = uname (&buf);
	if (ret < 0)
		return -1;
	ret = sscanf(buf.release, "%d.%d.%d", &a, &b, &c);
	if (ret != 3)
		return -1;
	printf("a:%d, b:%d, c:%d, ret:%d\n", a, b, c, ret);
	return 0;
}



From jon at ringle.org  Fri Jun 11 22:46:43 2010
From: jon at ringle.org (Jon Ringle)
Date: Fri, 11 Jun 2010 22:46:43 -0400
Subject: detecting that ubifs switched to ro after problem
Message-ID: <AANLkTik2mO4lpL5QA1kzMf4zp-Prd-SdhSNLVcHB9isl@mail.gmail.com>

Hi,

I'd like to be able to somehow detect that ubifs has taken the action
of switching from rw to ro due to some error detected in the ubifs
filesystem. If I can detect this then maybe I can do something about
it, such as copying the ubifs contents to a .tar.bz2 in /tmp,
mkfs.ubifs, and restore .tar.bz2 back again.

Is there a way I can do this?

Thanks,
Jon


From 21cnbao at gmail.com  Sat Jun 12 02:27:12 2010
From: 21cnbao at gmail.com (Barry Song)
Date: Sat, 12 Jun 2010 14:27:12 +0800
Subject: [PATCH 1/2] mtd: m25p80: Rework probing/JEDEC code
In-Reply-To: <20090818214622.GA22651@oksana.dev.rtsoft.ru>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru>
Message-ID: <AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>

On Wed, Aug 19, 2009 at 5:46 AM, Anton Vorontsov
<avorontsov at ru.mvista.com> wrote:
>
> Previosly the driver always tried JEDEC probing, assuming that non-JEDEC
> chips will return '0'. But truly non-JEDEC chips (like CAT25) won't do
> that, their behaviour on RDID command is undefined, so the driver should
> not call jedec_probe() for these chips.
>
> Also, be less strict on error conditions, don't fail to probe if JEDEC
> found a chip that is different from what platform code told, instead
> just print some warnings and use an information obtained via JEDEC. In
This patch caused a problem:
even though the external flash doesn't exist, it will still pass the
probe() and be registerred into kernel and given the partition table.
You may refer to this bug report:
http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=5975&start=0

> that case we should not trust partitions any longer, but they might be
> still useful (i.e. they could protect some parts of the chip).
>
> Signed-off-by: Anton Vorontsov <avorontsov at ru.mvista.com>
> ---
> ?drivers/mtd/devices/m25p80.c | ? 69 ++++++++++++++++++++++++-----------------
> ?1 files changed, 40 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index 0d74b38..b75e319 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -581,6 +581,14 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
> ? ? ? ?jedec = jedec << 8;
> ? ? ? ?jedec |= id[2];
>
> + ? ? ? /*
> + ? ? ? ?* Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants,
> + ? ? ? ?* which depend on technology process. Officially RDID command doesn't
> + ? ? ? ?* exist for non-JEDEC chips, but for compatibility they return ID 0.
> + ? ? ? ?*/
> + ? ? ? if (jedec == 0)
> + ? ? ? ? ? ? ? return NULL;
> +
> ? ? ? ?ext_jedec = id[3] << 8 | id[4];
>
> ? ? ? ?for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
> @@ -602,7 +610,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
> ?*/
> ?static int __devinit m25p_probe(struct spi_device *spi)
> ?{
> - ? ? ? const struct spi_device_id ? ? ?*id;
> + ? ? ? const struct spi_device_id ? ? ?*id = spi_get_device_id(spi);
> ? ? ? ?struct flash_platform_data ? ? ?*data;
> ? ? ? ?struct m25p ? ? ? ? ? ? ? ? ? ? *flash;
> ? ? ? ?struct flash_info ? ? ? ? ? ? ? *info;
> @@ -615,41 +623,44 @@ static int __devinit m25p_probe(struct spi_device *spi)
> ? ? ? ? */
> ? ? ? ?data = spi->dev.platform_data;
> ? ? ? ?if (data && data->type) {
> + ? ? ? ? ? ? ? const struct spi_device_id *plat_id;
> +
> ? ? ? ? ? ? ? ?for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
> - ? ? ? ? ? ? ? ? ? ? ? id = &m25p_ids[i];
> - ? ? ? ? ? ? ? ? ? ? ? info = (void *)m25p_ids[i].driver_data;
> - ? ? ? ? ? ? ? ? ? ? ? if (strcmp(data->type, id->name))
> + ? ? ? ? ? ? ? ? ? ? ? plat_id = &m25p_ids[i];
> + ? ? ? ? ? ? ? ? ? ? ? if (strcmp(data->type, plat_id->name))
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?continue;
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?}
>
> - ? ? ? ? ? ? ? /* unrecognized chip? */
> - ? ? ? ? ? ? ? if (i == ARRAY_SIZE(m25p_ids) - 1) {
> - ? ? ? ? ? ? ? ? ? ? ? DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_name(&spi->dev), data->type);
> - ? ? ? ? ? ? ? ? ? ? ? info = NULL;
> -
> - ? ? ? ? ? ? ? /* recognized; is that chip really what's there? */
> - ? ? ? ? ? ? ? } else if (info->jedec_id) {
> - ? ? ? ? ? ? ? ? ? ? ? id = jedec_probe(spi);
> -
> - ? ? ? ? ? ? ? ? ? ? ? if (id != &m25p_ids[i]) {
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_warn(&spi->dev, "found %s, expected %s\n",
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id ? id->name : "UNKNOWN",
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? m25p_ids[i].name);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info = NULL;
> - ? ? ? ? ? ? ? ? ? ? ? }
> - ? ? ? ? ? ? ? }
> - ? ? ? } else {
> - ? ? ? ? ? ? ? id = jedec_probe(spi);
> - ? ? ? ? ? ? ? if (!id)
> - ? ? ? ? ? ? ? ? ? ? ? id = spi_get_device_id(spi);
> -
> - ? ? ? ? ? ? ? info = (void *)id->driver_data;
> + ? ? ? ? ? ? ? if (plat_id)
> + ? ? ? ? ? ? ? ? ? ? ? id = plat_id;
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
> ? ? ? ?}
>
> - ? ? ? if (!info)
> - ? ? ? ? ? ? ? return -ENODEV;
> + ? ? ? info = (void *)id->driver_data;
> +
> + ? ? ? if (info->jedec_id) {
> + ? ? ? ? ? ? ? const struct spi_device_id *jid;
> +
> + ? ? ? ? ? ? ? jid = jedec_probe(spi);
> + ? ? ? ? ? ? ? if (!jid) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?id->name);
> + ? ? ? ? ? ? ? } else if (jid != id) {
> + ? ? ? ? ? ? ? ? ? ? ? /*
> + ? ? ? ? ? ? ? ? ? ? ? ?* JEDEC knows better, so overwrite platform ID. We
> + ? ? ? ? ? ? ? ? ? ? ? ?* can't trust partitions any longer, but we'll let
> + ? ? ? ? ? ? ? ? ? ? ? ?* mtd apply them anyway, since some partitions may be
> + ? ? ? ? ? ? ? ? ? ? ? ?* marked read-only, and we don't want to lose that
> + ? ? ? ? ? ? ? ? ? ? ? ?* information, even if it's not 100% accurate.
> + ? ? ? ? ? ? ? ? ? ? ? ?*/
> + ? ? ? ? ? ? ? ? ? ? ? dev_warn(&spi->dev, "found %s, expected %s\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jid->name, id->name);
> + ? ? ? ? ? ? ? ? ? ? ? id = jid;
> + ? ? ? ? ? ? ? ? ? ? ? info = (void *)jid->driver_data;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
>
> ? ? ? ?flash = kzalloc(sizeof *flash, GFP_KERNEL);
> ? ? ? ?if (!flash)
> --
> 1.6.3.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at ?http://www.tux.org/lkml/

From karl.beldan at gmail.com  Sat Jun 12 06:25:13 2010
From: karl.beldan at gmail.com (Karl Beldan)
Date: Sat, 12 Jun 2010 12:25:13 +0200
Subject: [PATCH] mtd: denali: add Kconfig dependency
Message-ID: <1276338313-12224-1-git-send-email-karl.beldan@gmail.com>

Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
---
 drivers/mtd/nand/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ffc3720..8fe82c8 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -61,6 +61,7 @@ config MTD_NAND_DENALI
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
         hex "Denali NAND size scratch register address"
         default "0xFF108018"
+        depends on MTD_NAND_DENALI
         help
           Some platforms place the NAND chip size in a scratch register
           because (some versions of) the driver aren't able to automatically
-- 
1.7.0.2.323.g0d092



From dedekind1 at gmail.com  Sat Jun 12 07:36:19 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 14:36:19 +0300
Subject: [PATCH v5 2/3] mtd-utils: support >4GiB devices
In-Reply-To: <1273745471.22706.163.camel@localhost>
References: <cd4bcbb843643dc463d2a2853766bcf57c23f546@localhost.localdomain>
	<5e05b5a05a30b2dc2035b87a60bb82f3137174cb@localhost.localdomain>
	<1273745471.22706.163.camel@localhost>
Message-ID: <1276342579.19028.116.camel@localhost>

On Thu, 2010-05-13 at 13:11 +0300, Artem Bityutskiy wrote:
> >  nandwrite.c           |   60 +++++-----
> >  13 files changed, 570 insertions(+), 171 deletions(-)
> >  create mode 100644 mtd_ioctl.c
> >  create mode 100644 mtd_ioctl.h
> 
> Any chance to extend and use mtd-utils/ubi-utils/src/libmtd.c instead of
> mtd_ioctl.c?

Does silence mean that that answer is "no"? :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sat Jun 12 07:43:34 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 14:43:34 +0300
Subject: [PATCH] mtd-utils: Support 4096+64 page sizes.
In-Reply-To: <1274176439-22351-1-git-send-email-eballetbo@gmail.com>
References: <1274176439-22351-1-git-send-email-eballetbo@gmail.com>
Message-ID: <1276343014.19028.117.camel@localhost>

On Tue, 2010-05-18 at 11:53 +0200, Enric Balletbo i Serra wrote:
> From: Enric Balletbo i Serra <eballetbo at iseebcn.com>
> 
> Add support for oobsize 64 and writesize 4096 in nanddump & nandwrite.
> 
> Signed-off-by: Enric Balletbo i Serra <eballetbo at iseebcn.com>
> ---
>  nanddump.c  |    1 +
>  nandwrite.c |    1 +

Pushed to mtd-utils.git, thank you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sat Jun 12 07:53:28 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 14:53:28 +0300
Subject: [PATCH 4/8] fs/ubifs: Use ERR_CAST
In-Reply-To: <Pine.LNX.4.64.1005221200050.13021@ask.diku.dk>
References: <Pine.LNX.4.64.1005221200050.13021@ask.diku.dk>
Message-ID: <1276343608.19028.118.camel@localhost>

On Sat, 2010-05-22 at 12:00 +0200, Julia Lawall wrote:
> From: Julia Lawall <julia at diku.dk>
> 
> Use ERR_CAST(x) rather than ERR_PTR(PTR_ERR(x)).  The former makes more
> clear what is the purpose of the operation, which otherwise looks like a
> no-op.

Pushed to the ubifs-2.6.git tree, thank you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sat Jun 12 10:17:57 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 17:17:57 +0300
Subject: [PATCH] UBI: fix delete compatible internal volume scan
In-Reply-To: <1274595417.8881.36.camel@localhost.localdomain>
References: <AANLkTimuYmRDCZCkoB9YHifngCwjp9_B2ucFQ1seaiM9@mail.gmail.com>
	<1274595417.8881.36.camel@localhost.localdomain>
Message-ID: <1276352277.19028.119.camel@localhost>

On Sun, 2010-05-23 at 09:16 +0300, Artem Bityutskiy wrote:
> On Tue, 2010-05-18 at 23:10 +0530, Brijesh Singh wrote:
> > This patch resolves a possible bug. Scan is adding delete compatible
> > blocks to both corr list and used list.
> > It should return after adding the block to corr list.
> > 
> > Signed-off-by: Brijesh Singh <brijesh.s.singh at gmail.com>
> 
> I'm not sure this patch is enough. I think we should add a 'compat' flag
> to the 'struct ubi_mkvol_req' structure, to make it possible to create
> volumes with different compatibility flags. Then we need to write a test
> and add it to the UBI test-suite at 'mtd-utils/tests/ubi-tests/'.
> 
> Then once we have tested and fixed this, we should merge this and also
> send to the '-stable' trees.
> 
> I remember I did give the compat option a test, but probably not that
> good.
> 
> I'll try to do what I've described as soon as I have time, but you guys
> could do this as well, if you have bandwidth.

I did not have time to do this so far, but still planning to do. Did you
go any further with your ubil?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Sat Jun 12 10:21:01 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 17:21:01 +0300
Subject: [patch] mtd/sst25l: check for null consistently
In-Reply-To: <20100522201626.GJ22515@bicker>
References: <20100522201626.GJ22515@bicker>
Message-ID: <1276352461.19028.120.camel@localhost>

On Sat, 2010-05-22 at 22:16 +0200, Dan Carpenter wrote:
> The rest of the function assumes that "data" can be null.  I don't know
> the code well enough to say whether it can actually be null, but there 
> is no harm in checking here.
> 
> Signed-off-by: Dan Carpenter <error27 at gmail.com>

Pushed to l2-mtd-2.6.git, Thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sat Jun 12 10:22:55 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 17:22:55 +0300
Subject: ubifs became broken on contigous power-fails
In-Reply-To: <1274694991.22999.52.camel@localhost>
References: <E1OBqfw-0002Rs-00.pazdnikov-list-ru@f27.mail.ru>
	<201005241249.28629.pazdnikov@prosoft.ural.ru>
	<1274689080.22999.43.camel@localhost>
	<201005241550.48074.pazdnikov@prosoft.ural.ru>
	<1274694991.22999.52.camel@localhost>
Message-ID: <1276352575.19028.121.camel@localhost>

On Mon, 2010-05-24 at 12:56 +0300, Artem Bityutskiy wrote:
> On Mon, 2010-05-24 at 15:50 +0600, Alexander Pazdnikov wrote:
> > > Could you enable debugging messages when mounging it after power cuts?
> > > The messages generate a lot of noise, so you need to disable them before
> > > starting the real test. The idea is to get UBIFS debugging messages when
> > > errors occur.
> > Sorry, I've hurried up, and after applying your pathes reflash all of the 
> > devices with new firmware.
> > But I'll setup some devices with all firmware to catch this issue again.
> > 
> > > I never had time to really dig this and fix. Would be nice if you could
> > > do this because I will unlikely have time in the nearest future, but I
> > > can help you.
> > Thank you, I'll continue testings and can supply with debug information.
> > 
> > > One think you can do is to make sure you do not fill UBIFS completely,
> > > then you will avoid hitting these budgeting bugs, also known as ENOSPC
> > > issues (I think btrfs uses this terminology).
> > In the issue above there is 11% used space and 89% free space.
> > I've got this issue only when mounting fs in RO and then remounting it in RW.
> 
> OK. Try my patch. Also, it is worth running your tests with UBIFS extra
> self checks enabled.

Did it help?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sat Jun 12 10:26:34 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 17:26:34 +0300
Subject: [PATCH 1/2] mtd: physmap: add physmap_unmapped_area() for
	no-mmu XIP
In-Reply-To: <1274599824-17530-1-git-send-email-vapier@gentoo.org>
References: <1274599824-17530-1-git-send-email-vapier@gentoo.org>
Message-ID: <1276352794.19028.122.camel@localhost>

On Sun, 2010-05-23 at 03:30 -0400, Mike Frysinger wrote:
> From: Bernd Schmidt <bernds_cb1 at t-online.de>
> 
> Currently, romfs XIP doesn't work in flash memory (the kernel crashes
> with a null pointer dereference).  The problem is that the mtd physmap
> driver isn't setting up a get_unmapped_area pointer for the mtd
> partitions it creates.
> 
> Signed-off-by: Bernd Schmidt <bernds_cb1 at t-online.de>
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed both to my l2-mtd-2.6.git / dunno.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sat Jun 12 10:26:59 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 17:26:59 +0300
Subject: [PATCH] OneNAND: Introduce chip_probe function
In-Reply-To: <20100528020311.GA1608@july>
References: <20100528020311.GA1608@july>
Message-ID: <1276352819.19028.123.camel@localhost>

On Fri, 2010-05-28 at 11:03 +0900, Kyungmin Park wrote:
> Samsung SoCs use the own OneNAND controler and detect OneNAND chip at power on.
> To use this feature, introduce the chip_probe function.
> 
> Also remove workaround for Samsung SoCs.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>

Pushed both to my l2-mtd-2.6.git / dunno.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sat Jun 12 10:32:09 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 12 Jun 2010 17:32:09 +0300
Subject: [PATCH] MTD: remove redundant dependency checks in Kconfig files
In-Reply-To: <20100608134822.GA18437@caffeine.csclub.uwaterloo.ca>
References: <20100608134822.GA18437@caffeine.csclub.uwaterloo.ca>
Message-ID: <1276353129.19028.124.camel@localhost>

On Tue, 2010-06-08 at 09:48 -0400, Kyle Spaans wrote:
> Look for dependency checks for "FOO" when inside of an "if FOO" block and remove them.
> 
> Signed-off-by: Kyle Spaans <kspaans at uwaterloo.ca>
> Reviewed-by: Robert P. J. Day <rpjday at crashcourse.ca>

Pushed to l2-mtd-2.6.git / master, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From agust at denx.de  Sat Jun 12 15:35:38 2010
From: agust at denx.de (Anatolij Gustschin)
Date: Sat, 12 Jun 2010 21:35:38 +0200
Subject: [PATCH v3] mtdchar: fix mmap() for MTD RAM/ROM char devices
Message-ID: <1276371338-14253-1-git-send-email-agust@denx.de>

For no-mmu systems mmap() on RAM/ROM devices already works
but for systems with mmu it probably was not tested and
currently doesn't work.

This patch allows using mmap() on MTD RAM/ROM devices on systems
with MMU. It has been tested on mpc5121e based platform with
MR0A16A MRAM device attached over LocalBus.

Signed-off-by: Anatolij Gustschin <agust at denx.de>
---
Changes since patch v2:
 - improved commit message and patch description
 - rebased to apply cleanly on current mtd-2.6 tree

 drivers/mtd/mtdchar.c |   30 +++++++++++++++++++++++++++++-
 1 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 8b223c0..f3b848e 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -18,6 +18,7 @@
 #include <linux/mount.h>
 
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
 #include <linux/mtd/compatmac.h>
 
 #include <asm/uaccess.h>
@@ -941,9 +942,36 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma)
 #ifdef CONFIG_MMU
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
+	struct map_info *map = mtd->priv;
+	unsigned long start;
+	unsigned long off;
+	u32 len;
+
+	if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
+		if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+			return -EINVAL;
+		off = vma->vm_pgoff << PAGE_SHIFT;
+		start = map->phys;
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
+		start &= PAGE_MASK;
+		if ((vma->vm_end - vma->vm_start + off) > len)
+			return -EINVAL;
+
+		off += start;
+		vma->vm_pgoff = off >> PAGE_SHIFT;
+		vma->vm_flags |= VM_IO | VM_RESERVED;
+
+#ifdef pgprot_noncached
+		if (file->f_flags & O_DSYNC || off >= __pa(high_memory))
+			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+		if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+				       vma->vm_end - vma->vm_start,
+				       vma->vm_page_prot))
+			return -EAGAIN;
 
-	if (mtd->type == MTD_RAM || mtd->type == MTD_ROM)
 		return 0;
+	}
 	return -ENOSYS;
 #else
 	return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;
-- 
1.7.0.4



From vapier.adi at gmail.com  Sat Jun 12 21:31:11 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Sat, 12 Jun 2010 21:31:11 -0400
Subject: [PATCH v3] mtdchar: fix mmap() for MTD RAM/ROM char devices
In-Reply-To: <1276371338-14253-1-git-send-email-agust@denx.de>
References: <1276371338-14253-1-git-send-email-agust@denx.de>
Message-ID: <AANLkTikutI1bWUpG4FDWwwKOGSEfik-ycZZLs37AjDtK@mail.gmail.com>

On Sat, Jun 12, 2010 at 15:35, Anatolij Gustschin wrote:
> For no-mmu systems mmap() on RAM/ROM devices already works
> but for systems with mmu it probably was not tested and
> currently doesn't work.

nope, never did

> + ? ? ? ? ? ? ? if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
> + ? ? ? ? ? ? ? ? ? ? ? return -EINVAL;

i'm pretty sure this is inappropriate and doesnt belong here
-mike


From nm127 at freemail.hu  Sun Jun 13 04:05:38 2010
From: nm127 at freemail.hu (=?UTF-8?B?TsOpbWV0aCBNw6FydG9u?=)
Date: Sun, 13 Jun 2010 10:05:38 +0200
Subject: [PATCH] fix typo in FAQ
Message-ID: <4C149152.9090501@freemail.hu>


Signed-off-by: M?rton N?meth <nm127 at freemail.hu>
---
diff --git a/faq/general.xml b/faq/general.xml
index 1c0551f..be1a0d4 100644
--- a/faq/general.xml
+++ b/faq/general.xml
@@ -225,7 +225,7 @@ release the chip again.
 Some NOR chips power on with all of the eraseblocks in a locked state.
 The MTD layer doesn't unlock these devices by default. If you are accessing
 these devices from user-space, you can use the <CODE>flash_unlock</CODE> tool to
-unlock the MTD device(s). If you are using the MTD device as aw rite-able root
+unlock the MTD device(s). If you are using the MTD device as a write-able root
 file-system you will either need to have the boot loader unlock the eraseblocks
 before booting the kernel, or add code to the MTD map driver for your board to
 unlock them.


From dedekind1 at gmail.com  Sun Jun 13 04:38:26 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 11:38:26 +0300
Subject: [PATCH] fix typo in FAQ
In-Reply-To: <4C149152.9090501@freemail.hu>
References: <4C149152.9090501@freemail.hu>
Message-ID: <1276418306.19028.171.camel@localhost>

On Sun, 2010-06-13 at 10:05 +0200, N?meth M?rton wrote:
> Signed-off-by: M?rton N?meth <nm127 at freemail.hu>
> ---
> diff --git a/faq/general.xml b/faq/general.xml
> index 1c0551f..be1a0d4 100644
> --- a/faq/general.xml
> +++ b/faq/general.xml
> @@ -225,7 +225,7 @@ release the chip again.
>  Some NOR chips power on with all of the eraseblocks in a locked state.
>  The MTD layer doesn't unlock these devices by default. If you are accessing
>  these devices from user-space, you can use the <CODE>flash_unlock</CODE> tool to
> -unlock the MTD device(s). If you are using the MTD device as aw rite-able root
> +unlock the MTD device(s). If you are using the MTD device as a write-able root
>  file-system you will either need to have the boot loader unlock the eraseblocks
>  before booting the kernel, or add code to the MTD map driver for your board to
>  unlock them.

Pushed, thank you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 04:57:49 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 11:57:49 +0300
Subject: Mtd_debug patch
In-Reply-To: <C825AD54.2A59A%beavers@anx.com>
References: <C825AD54.2A59A%beavers@anx.com>
Message-ID: <1276419469.19028.176.camel@localhost>

Hi Stephen,

On Fri, 2010-05-28 at 17:26 -0400, Stephen Beaver wrote:
> The attached patch to the current version of mtd_debug (grabbed
> on5/28/2010) adds two new capabilities:
> 
> usage: mtd_debug info   <device>
>        mtd_debug read   <device> <offset> <len> <dest-filename>
>        mtd_debug write  <device> <offset> <len> <source-filename>
>       mtd_debug verify <device> <offset> <cmp-filename>
>       mtd_debug erase  <device> <offset> <len>
>       mtd_debug blank  <device> <offset> <len>
> 
> mtd_debug blank ... checks that an area of flash memory if blank (all
> 0xFFs) ie it verifies that an erase succeeded.
> mtd_debug verify ... checks that the contents of the flash memory
> match the specified file. Ie it verifies that a write succeeded.
> 
> These functions allow things like:
> 
> #!/bin/sh
> 
> mtd_debug erase /dev/mtd1 0 0x200000
> mtd_debug write /dev/mtd1 0 0x150000 uImage
> if ( mtd_debug verifiy /dev/mtd1 0 uImage ) ; then
>    reboot
> else
>    # Better try again, or we will die
> fi

Looks like a useful feature, but I cannot apply your patch because it is
not applicable to the latest mtd-utils.git. Also, your patch has many
trailing white-spaces. Could you please re-send it in inlined form - it
will make it easier to review it and reply to you (it it difficult to
comment attached patches).

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Sun Jun 13 05:08:04 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:08:04 +0300
Subject: [patch] mtd: return success on blktrans_ioctl()
In-Reply-To: <20100531140337.GV5483@bicker>
References: <20100531140337.GV5483@bicker>
Message-ID: <1276420084.19028.182.camel@localhost>

On Mon, 2010-05-31 at 16:03 +0200, Dan Carpenter wrote:
> There was a break missing so we returned -ENOTTY on success instead of
> zero.  This was introduced by 048d8719956: "mtd: blktrans: Hotplug fixes"
> 
> Signed-off-by: Dan Carpenter <error27 at gmail.com>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 05:05:03 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:05:03 +0300
Subject: [PATCH] mtd: Added an ioctl to query the lock status of a
	flash sector.
In-Reply-To: <20100531131214.GA15887@riccoc20.at.omicron.at>
References: <20100531131214.GA15887@riccoc20.at.omicron.at>
Message-ID: <1276419903.19028.180.camel@localhost>

On Mon, 2010-05-31 at 15:12 +0200, Richard Cochran wrote:
> This patchs adds a way for user space programs to find out whether a
> flash sector is locked. An optional driver method in the mtd_info struct
> provides the information.
> 
> Signed-off-by: Richard Cochran <richard.cochran at omicron.at>
> ---
>  drivers/mtd/chips/cfi_cmdset_0001.c |    8 ++++++++
>  drivers/mtd/mtdchar.c               |   14 ++++++++++++++
>  drivers/mtd/mtdpart.c               |   10 ++++++++++
>  include/linux/mtd/mtd.h             |    1 +
>  include/mtd/mtd-abi.h               |    1 +
>  5 files changed, 34 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
> index 5fbf29e..67caca7 100644
> --- a/drivers/mtd/chips/cfi_cmdset_0001.c
> +++ b/drivers/mtd/chips/cfi_cmdset_0001.c
> @@ -63,6 +63,7 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
>  static void cfi_intelext_sync (struct mtd_info *);
>  static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
>  static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
> +static int cfi_intelext_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
>  #ifdef CONFIG_MTD_OTP
>  static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
>  static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
> @@ -448,6 +449,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
>  	mtd->sync    = cfi_intelext_sync;
>  	mtd->lock    = cfi_intelext_lock;
>  	mtd->unlock  = cfi_intelext_unlock;
> +	mtd->locked  = cfi_intelext_locked;
>  	mtd->suspend = cfi_intelext_suspend;
>  	mtd->resume  = cfi_intelext_resume;
>  	mtd->flags   = MTD_CAP_NORFLASH;

I think it is tiny bit nicer to name 'is_locked', which is a bit more
consistent with the already existing 'block_isbad'?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 05:16:06 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:16:06 +0300
Subject: [PATCH] ixp4xx: add support for static flash partitions
In-Reply-To: <20100531162434.GA4599@riccoc20.at.omicron.at>
References: <20100531162434.GA4599@riccoc20.at.omicron.at>
Message-ID: <1276420566.19028.184.camel@localhost>

On Mon, 2010-05-31 at 18:24 +0200, Richard Cochran wrote:
> This patch adds support for static flash partitioning from a platform
> device. Also, we clean up some weirdness where statements were separated
> by commas instead of semicolons. While we are at it, fix some minor bad
> white space, too.
> 
> Signed-off-by: Richard Cochran <richard.cochran at omicron.at>
> ---
>  drivers/mtd/maps/ixp4xx.c |   37 ++++++++++++++++++++++++++++---------
>  1 files changed, 28 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
> index 7b05152..5345d11 100644
> --- a/drivers/mtd/maps/ixp4xx.c
> +++ b/drivers/mtd/maps/ixp4xx.c
> @@ -108,7 +108,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
>  
>  	if (from & 1) {
>  		*dest++ = BYTE1(flash_read16(src));
> -                src++;
> +		src++;
>  		--len;
>  	}

Your patch mostly applies, except of this chunk, which was modified
before by

commit 53f2b1c86a1fa1414be93571062ac4c263fa9fbc
Author: Jon Ringle <jon at ringle.org>
Date:   Wed Jan 13 09:36:10 2010 -0500

    mtd: ixp4xx: fix reading from half-word boundary
    
    Fix handling of reads that don't start on a half-word boundary.
    
    Signed-off-by: Jon Ringle <jon at ringle.org>
    Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

I could fix your patch up myself, but I do not know the code, so please,
re-send a patch against the latest mtd-2.6 tree.
-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 05:26:40 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:26:40 +0300
Subject: [PATCH 1/2] mtd: OneNAND: Add runtime badblock check feature
In-Reply-To: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>
References: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>
Message-ID: <1276421200.19028.192.camel@localhost>

On Tue, 2010-06-01 at 17:17 +0900, Joonyoung Shim wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
> 
> This patch is to support runtime badblock checking. This supports only
> OneNAND currently. The OneNAND badblock checking when boots occurs boot
> time delay. We can reduce boot time because can detect badblock at
> runtime.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>

Hi, this feature is interesting. But why not to use bad block table
instead of adding more complexity to the already very complex and
difficult to follow code?

Also, if you really want this, it should be rather lazy checking, where
you read OOB on demand, and then save this information to the in-ram
BBT, and when you get another ->block_isbad() for a block which was
previously checked, you do not read OOB for the second time.

CCing Thomas, if we are lucky, he'll provide good input.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 05:40:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:40:15 +0300
Subject: [RFC][PATCH 17/26] MTD: Nand: Add JZ4740 NAND driver
In-Reply-To: <1275505950-17334-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
	<1275505950-17334-1-git-send-email-lars@metafoo.de>
Message-ID: <1276422015.19028.204.camel@localhost>

On Wed, 2010-06-02 at 21:12 +0200, Lars-Peter Clausen wrote:
> This patch adds support for the NAND controller on JZ4740 SoCs.
> 
> Signed-off-by: Lars-Peter Clausen <lars at metafoo.de>
> Cc: David Woodhouse <dwmw2 at infradead.org>
> Cc: linux-mtd at lists.infradead.org
> ---
>  drivers/mtd/nand/Kconfig        |    6 +
>  drivers/mtd/nand/Makefile       |    1 +
>  drivers/mtd/nand/jz4740_nand.c  |  442 +++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/jz4740_nand.h |   34 +++
>  4 files changed, 483 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/jz4740_nand.c
>  create mode 100644 include/linux/mtd/jz4740_nand.h

I doubt "include/linux/" is the right place to define 'struct
jz_nand_platform_data' - it should instead live is somwhere in
arch/mips/

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 05:42:54 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:42:54 +0300
Subject: [PATCH] mtd: m25p80: Add support for Macronix 25L8005
In-Reply-To: <20100607183101.GA378@jirafa.cyrius.com>
References: <20100607183101.GA378@jirafa.cyrius.com>
Message-ID: <1276422174.19028.205.camel@localhost>

On Mon, 2010-06-07 at 19:31 +0100, Martin Michlmayr wrote:
> Add support for Macronix 25L8005.  Tested on a HP t5325 Thin Client.
> 
> Signed-off-by: Martin Michlmayr <tbm at cyrius.com>

Pushed to l2-mtd-2.6.git / master.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 05:47:34 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:47:34 +0300
Subject: detecting that ubifs switched to ro after problem
In-Reply-To: <AANLkTik2mO4lpL5QA1kzMf4zp-Prd-SdhSNLVcHB9isl@mail.gmail.com>
References: <AANLkTik2mO4lpL5QA1kzMf4zp-Prd-SdhSNLVcHB9isl@mail.gmail.com>
Message-ID: <1276422454.19028.209.camel@localhost>

On Fri, 2010-06-11 at 22:46 -0400, Jon Ringle wrote:
> Hi,
> 
> I'd like to be able to somehow detect that ubifs has taken the action
> of switching from rw to ro due to some error detected in the ubifs
> filesystem. If I can detect this then maybe I can do something about
> it, such as copying the ubifs contents to a .tar.bz2 in /tmp,
> mkfs.ubifs, and restore .tar.bz2 back again.
> 
> Is there a way I can do this?

I think with 2fde99cb55fb9d9b88180512a5e8a5d939d27fec you can check for
R/O state from /proc/mounts. Also, you can use something like inotify to
watch /proc/mounts changes and react if UBIFS became r/o.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Sun Jun 13 05:51:58 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:51:58 +0300
Subject: Fix mtd-utils bugs
In-Reply-To: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276422718.19028.211.camel@localhost>

On Fri, 2010-06-11 at 17:36 +0800, Stanley.Miao wrote:
> Re-send them because I didn't give a email subject in last version.
> 
> The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
> is not enough for many big NAND chips. Therefore, this structure is replaced
> by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
> Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
> 
> Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
> keep compatible with the old linux kernel, a linux version detection function
> is added.
> 
> YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
> "forcejffs2", "forceyaffs" anymore. Now clean them up. 

Please, make sure your submissions have proper version. I have limited
amount of time and do not want to spend it figuring out which patch is
the latest. Use the best kernel practices and apply prefix your stuff
with [PATCHv3] or something like that.

Could you please re-submit your latest version?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 05:57:26 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 12:57:26 +0300
Subject: [PATCH] mtd: denali: add Kconfig dependency
In-Reply-To: <1276338313-12224-1-git-send-email-karl.beldan@gmail.com>
References: <1276338313-12224-1-git-send-email-karl.beldan@gmail.com>
Message-ID: <1276423046.19028.212.camel@localhost>

On Sat, 2010-06-12 at 12:25 +0200, Karl Beldan wrote:
> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
> ---
>  drivers/mtd/nand/Kconfig |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index ffc3720..8fe82c8 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -61,6 +61,7 @@ config MTD_NAND_DENALI
>  config MTD_NAND_DENALI_SCRATCH_REG_ADDR
>          hex "Denali NAND size scratch register address"
>          default "0xFF108018"
> +        depends on MTD_NAND_DENALI
>          help
>            Some platforms place the NAND chip size in a scratch register
>            because (some versions of) the driver aren't able to automatically

Pushed to l2-mtd-2.6.git / master, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 06:07:03 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 13:07:03 +0300
Subject: detecting that ubifs switched to ro after problem
In-Reply-To: <1276422454.19028.209.camel@localhost>
References: <AANLkTik2mO4lpL5QA1kzMf4zp-Prd-SdhSNLVcHB9isl@mail.gmail.com>
	<1276422454.19028.209.camel@localhost>
Message-ID: <1276423623.19028.213.camel@localhost>

On Sun, 2010-06-13 at 12:47 +0300, Artem Bityutskiy wrote:
> On Fri, 2010-06-11 at 22:46 -0400, Jon Ringle wrote:
> > Hi,
> > 
> > I'd like to be able to somehow detect that ubifs has taken the action
> > of switching from rw to ro due to some error detected in the ubifs
> > filesystem. If I can detect this then maybe I can do something about
> > it, such as copying the ubifs contents to a .tar.bz2 in /tmp,
> > mkfs.ubifs, and restore .tar.bz2 back again.
> > 
> > Is there a way I can do this?
> 
> I think with 2fde99cb55fb9d9b88180512a5e8a5d939d27fec you can check for
> R/O state from /proc/mounts. Also, you can use something like inotify to
> watch /proc/mounts changes and react if UBIFS became r/o.

Just added:

http://www.linux-mtd.infradead.org/faq/ubifs.html#L_detect_ro

for your convenience.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 06:08:53 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 13:08:53 +0300
Subject: [PATCH] UBI: fix delete compatible internal volume scan
In-Reply-To: <1276352277.19028.119.camel@localhost>
References: <AANLkTimuYmRDCZCkoB9YHifngCwjp9_B2ucFQ1seaiM9@mail.gmail.com>
	<1274595417.8881.36.camel@localhost.localdomain>
	<1276352277.19028.119.camel@localhost>
Message-ID: <1276423733.19028.215.camel@localhost>

On Sat, 2010-06-12 at 17:17 +0300, Artem Bityutskiy wrote:
> On Sun, 2010-05-23 at 09:16 +0300, Artem Bityutskiy wrote:
> > On Tue, 2010-05-18 at 23:10 +0530, Brijesh Singh wrote:
> > > This patch resolves a possible bug. Scan is adding delete compatible
> > > blocks to both corr list and used list.
> > > It should return after adding the block to corr list.
> > > 
> > > Signed-off-by: Brijesh Singh <brijesh.s.singh at gmail.com>
> > 
> > I'm not sure this patch is enough. I think we should add a 'compat' flag
> > to the 'struct ubi_mkvol_req' structure, to make it possible to create
> > volumes with different compatibility flags. Then we need to write a test
> > and add it to the UBI test-suite at 'mtd-utils/tests/ubi-tests/'.
> > 
> > Then once we have tested and fixed this, we should merge this and also
> > send to the '-stable' trees.
> > 
> > I remember I did give the compat option a test, but probably not that
> > good.
> > 
> > I'll try to do what I've described as soon as I have time, but you guys
> > could do this as well, if you have bandwidth.
> 
> I did not have time to do this so far, but still planning to do. Did you
> go any further with your ubil?

Actually, what I'm thinking to do is to create a test that creates
various UBI images with different types of volume compatibility flags,
and then tries to attach them. We have libubigen in mtd-utils, and with
this library it should be is quite easy to create different images.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Jun 13 06:14:08 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 13 Jun 2010 13:14:08 +0300
Subject: Fix mtd-utils bugs
In-Reply-To: <1276422718.19028.211.camel@localhost>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
	<1276422718.19028.211.camel@localhost>
Message-ID: <1276424048.19028.217.camel@localhost>

On Sun, 2010-06-13 at 12:51 +0300, Artem Bityutskiy wrote:
> On Fri, 2010-06-11 at 17:36 +0800, Stanley.Miao wrote:
> > Re-send them because I didn't give a email subject in last version.
> > 
> > The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
> > is not enough for many big NAND chips. Therefore, this structure is replaced
> > by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
> > Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
> > 
> > Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
> > keep compatible with the old linux kernel, a linux version detection function
> > is added.
> > 
> > YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
> > "forcejffs2", "forceyaffs" anymore. Now clean them up. 
> 
> Please, make sure your submissions have proper version. I have limited
> amount of time and do not want to spend it figuring out which patch is
> the latest. Use the best kernel practices and apply prefix your stuff
> with [PATCHv3] or something like that.
> 
> Could you please re-submit your latest version?

Also, it is nice to put a short changelog, but I can live without it.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From kyungmin.park at samsung.com  Sun Jun 13 19:19:22 2010
From: kyungmin.park at samsung.com (Kyungmin Park)
Date: Mon, 14 Jun 2010 08:19:22 +0900
Subject: [PATCH 1/2] mtd: OneNAND: Add runtime badblock check feature
In-Reply-To: <1276421200.19028.192.camel@localhost>
References: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>
	<1276421200.19028.192.camel@localhost>
Message-ID: <012f01cb0b4e$db1a7550$914f5ff0$%park@samsung.com>

Hi,

> -----Original Message-----
> From: Artem Bityutskiy [mailto:dedekind1 at gmail.com]
> Sent: Sunday, June 13, 2010 6:27 PM
> To: Joonyoung Shim
> Cc: linux-mtd at lists.infradead.org; Kyungmin Park; Thomas Gleixner
> Subject: Re: [PATCH 1/2] mtd: OneNAND: Add runtime badblock check feature
> 
> On Tue, 2010-06-01 at 17:17 +0900, Joonyoung Shim wrote:
> > From: Kyungmin Park <kyungmin.park at samsung.com>
> >
> > This patch is to support runtime badblock checking. This supports only
> > OneNAND currently. The OneNAND badblock checking when boots occurs boot
> > time delay. We can reduce boot time because can detect badblock at
> > runtime.
> >
> > Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> 
> Hi, this feature is interesting. But why not to use bad block table
> instead of adding more complexity to the already very complex and
> difficult to follow code?

> 
> Also, if you really want this, it should be rather lazy checking, where
> you read OOB on demand, and then save this information to the in-ram
> BBT, and when you get another ->block_isbad() for a block which was
> previously checked, you do not read OOB for the second time.

It's based on BBT already. Now I set the BBT values as 0x2 and then check it at runtime and then mark it 0 for good, 3 for bad block.

Right, it's same word lazy checking and runtime check.

The original ideas are from UBI scan it read all blocks again at probe.
I just scan almost block read once at ubi scan.

Thank you,
Kyungmin Park

> 
> CCing Thomas, if we are lucky, he'll provide good input.
> 
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun 14 00:07:00 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 14 Jun 2010 07:07:00 +0300
Subject: [PATCH 1/2] mtd: OneNAND: Add runtime badblock check feature
In-Reply-To: <012f01cb0b4e$db1a7550$914f5ff0$%park@samsung.com>
References: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>
	<1276421200.19028.192.camel@localhost>
	<012f01cb0b4e$db1a7550$914f5ff0$%park@samsung.com>
Message-ID: <1276488420.19028.229.camel@localhost>

On Mon, 2010-06-14 at 08:19 +0900, Kyungmin Park wrote:
> > Also, if you really want this, it should be rather lazy checking, where
> > you read OOB on demand, and then save this information to the in-ram
> > BBT, and when you get another ->block_isbad() for a block which was
> > previously checked, you do not read OOB for the second time.
> 
> It's based on BBT already. Now I set the BBT values as 0x2 and then
> check it at runtime and then mark it 0 for good, 3 for bad block.

I meant why you are optimizing the in-ram BBT instead of just keeping
and maintaining the BBT on the flash media?

> Right, it's same word lazy checking and runtime check.

I think you should rename it. "Runtime" is not descriptive, because even
without your patch the BBT is built "runtime". But "lazy" BBT creation
is quite descriptive.

> The original ideas are from UBI scan it read all blocks again at probe.
> I just scan almost block read once at ubi scan.

Right. So I asked why not to just have the BBT on flash?

Also, I doubt we need yet another config option and chip option - why
not to make lazy BBT just to be the default?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From u.kleine-koenig at pengutronix.de  Mon Jun 14 03:01:51 2010
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Mon, 14 Jun 2010 09:01:51 +0200
Subject: [PATCH] mtd/mxc_nand: remove unused variable
Message-ID: <1276498911-28115-1-git-send-email-u.kleine-koenig@pengutronix.de>

This fixes:

	drivers/mtd/nand/mxc_nand.c: In function 'mxcnd_resume':
	drivers/mtd/nand/mxc_nand.c:901: warning: unused variable 'host'

Removing this variable was missed in 9c14b153e6af.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/mtd/nand/mxc_nand.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 0d76b16..ef610bf 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -898,7 +898,6 @@ static int mxcnd_resume(struct platform_device *pdev)
 {
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
 	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
 	int ret = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
-- 
1.7.1



From eric at eukrea.com  Mon Jun 14 03:07:46 2010
From: eric at eukrea.com (=?UTF-8?B?RXJpYyBCw6luYXJk?=)
Date: Mon, 14 Jun 2010 09:07:46 +0200
Subject: [PATCH] mxc_nand: fix PM
In-Reply-To: <1274982919-13251-1-git-send-email-eric@eukrea.com>
References: <1274942000-3580-2-git-send-email-eric@eukrea.com>
	<1274982919-13251-1-git-send-email-eric@eukrea.com>
Message-ID: <4C15D542.2060102@eukrea.com>

Hi Sascha,

Le 27/05/2010 19:55, Eric B?nard a ?crit :
> * when resuming, we get the following log :
> nand_resume called for a chip which is not in suspended state
> * this happens because mtd->suspend and mtd->resume are already
> called from the mtd layer, thus they were called a second time
> in mxc_nand so mtd complains when trying to resume for the
> second time
> * the fix is to remove these call and thus remove the supend and
> resume functions of mxc_nand
>
any news concerning this patch ?

Eric

> Signed-off-by: Eric B?nard<eric at eukrea.com>
> Cc: s.hauer at pengutronix.de
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-mtd at lists.infradead.org
> ---
>   drivers/mtd/nand/mxc_nand.c |   44 +------------------------------------------
>   1 files changed, 1 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
> index 314e2bf..217b247 100644
> --- a/drivers/mtd/nand/mxc_nand.c
> +++ b/drivers/mtd/nand/mxc_nand.c
> @@ -892,53 +892,11 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
>   	return 0;
>   }
>
> -#ifdef CONFIG_PM
> -static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
> -{
> -	struct mtd_info *mtd = platform_get_drvdata(pdev);
> -	struct nand_chip *nand_chip = mtd->priv;
> -	struct mxc_nand_host *host = nand_chip->priv;
> -	int ret = 0;
> -
> -	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
> -
> -	ret = mtd->suspend(mtd);
> -
> -	/*
> -	 * nand_suspend locks the device for exclusive access, so
> -	 * the clock must already be off.
> -	 */
> -	BUG_ON(!ret&&  host->clk_act);
> -
> -	return ret;
> -}
> -
> -static int mxcnd_resume(struct platform_device *pdev)
> -{
> -	struct mtd_info *mtd = platform_get_drvdata(pdev);
> -	struct nand_chip *nand_chip = mtd->priv;
> -	struct mxc_nand_host *host = nand_chip->priv;
> -	int ret = 0;
> -
> -	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
> -
> -	mtd->resume(mtd);
> -
> -	return ret;
> -}
> -
> -#else
> -# define mxcnd_suspend   NULL
> -# define mxcnd_resume    NULL
> -#endif				/* CONFIG_PM */
> -
>   static struct platform_driver mxcnd_driver = {
>   	.driver = {
>   		   .name = DRIVER_NAME,
> -		   },
> +	},
>   	.remove = __devexit_p(mxcnd_remove),
> -	.suspend = mxcnd_suspend,
> -	.resume = mxcnd_resume,
>   };
>
>   static int __init mxc_nd_init(void)



From u.kleine-koenig at pengutronix.de  Mon Jun 14 04:35:57 2010
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Mon, 14 Jun 2010 10:35:57 +0200
Subject: [PATCH] mtd/mxc_nand: remove unused variable
In-Reply-To: <1276498911-28115-1-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1276498911-28115-1-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <20100614083557.GB12159@pengutronix.de>

On Mon, Jun 14, 2010 at 09:01:51AM +0200, Uwe Kleine-K?nig wrote:
> This fixes:
> 
> 	drivers/mtd/nand/mxc_nand.c: In function 'mxcnd_resume':
> 	drivers/mtd/nand/mxc_nand.c:901: warning: unused variable 'host'
> 
> Removing this variable was missed in 9c14b153e6af.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
This conflicts with Eric's "mxc_nand: fix PM" patch which also solves
this issue. 

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From u.kleine-koenig at pengutronix.de  Mon Jun 14 04:43:51 2010
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Mon, 14 Jun 2010 10:43:51 +0200
Subject: [PATCH] mxc_nand: fix PM
In-Reply-To: <1274982919-13251-1-git-send-email-eric@eukrea.com>
References: <1274942000-3580-2-git-send-email-eric@eukrea.com>
	<1274982919-13251-1-git-send-email-eric@eukrea.com>
Message-ID: <20100614084351.GC12159@pengutronix.de>

Hello Eric,

On Thu, May 27, 2010 at 07:55:19PM +0200, Eric B?nard wrote:
> * when resuming, we get the following log :
> nand_resume called for a chip which is not in suspended state
> * this happens because mtd->suspend and mtd->resume are already
> called from the mtd layer, thus they were called a second time
> in mxc_nand so mtd complains when trying to resume for the
> second time
> * the fix is to remove these call and thus remove the supend and
> resume functions of mxc_nand
the commit log looks IMHO ugly.  Better make it (including Subject):

mtd/mxc_nand: don't call mtd->{suspend,resume} explicitly

The mtd layer is responsible to call mtd->{suspend,resume}.  Doing it
again in the driver is wrong and results in a warning:

	nand_resume called for a chip which is not in suspended state

at resume time.  Removing the calls from the resume and suspend
functions makes them empty allowing them to be deleted completely.

Signed-off-by: Eric B?nard <eric at eukrea.com>
Acked-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-mtd at lists.infradead.org

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From agust at denx.de  Mon Jun 14 05:22:13 2010
From: agust at denx.de (Anatolij Gustschin)
Date: Mon, 14 Jun 2010 11:22:13 +0200
Subject: [PATCH v3] mtdchar: fix mmap() for MTD RAM/ROM char devices
In-Reply-To: <AANLkTikutI1bWUpG4FDWwwKOGSEfik-ycZZLs37AjDtK@mail.gmail.com>
References: <1276371338-14253-1-git-send-email-agust@denx.de>
	<AANLkTikutI1bWUpG4FDWwwKOGSEfik-ycZZLs37AjDtK@mail.gmail.com>
Message-ID: <20100614112213.695ac5d2@wker>

On Sat, 12 Jun 2010 21:31:11 -0400
Mike Frysinger <vapier.adi at gmail.com> wrote:

> On Sat, Jun 12, 2010 at 15:35, Anatolij Gustschin wrote:
> > For no-mmu systems mmap() on RAM/ROM devices already works
> > but for systems with mmu it probably was not tested and
> > currently doesn't work.
> 
> nope, never did

Do you mean it never worked on mmu systems?

> 
> > + ? ? ? ? ? ? ? if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
> > + ? ? ? ? ? ? ? ? ? ? ? return -EINVAL;
> 
> i'm pretty sure this is inappropriate and doesnt belong here

Then I'll drop this in the next patch.

Thanks,
Anatolij


From glecerf at gmail.com  Mon Jun 14 06:33:45 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Mon, 14 Jun 2010 12:33:45 +0200
Subject: [PATCH] mtd: cfi_probe: print manufacturer and id of probed chip
Message-ID: <20100614103345.26103.40429.stgit@dev.siriade.com>

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_probe.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index b2acd32..5f5ba3e 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -235,9 +235,9 @@ static int __xipram cfi_chip_setup(struct map_info *map,
 	cfi_qry_mode_off(base, map, cfi);
 	xip_allowed(base, map);
 
-	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
+	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. mfr=0x%08x id=0x%08x\n",
 	       map->name, cfi->interleave, cfi->device_type*8, base,
-	       map->bankwidth*8);
+	       map->bankwidth*8, cfi->mfr, cfi->id);
 
 	return 1;
 }




From pjohn at mvista.com  Mon Jun 14 07:04:17 2010
From: pjohn at mvista.com (Philby John)
Date: Mon, 14 Jun 2010 16:34:17 +0530
Subject: [PATCH] mtd: Fix bug using smp_processor_id() in preemptible
	ubi_bgt1d kthread
Message-ID: <1276513457.16642.3.camel@localhost.localdomain>

mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume,
on the NOR flash, the kernel thread ubi_bgt1d calls
cfi_amdstd_write_buffers() --> do_write_buffer() -->
INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls
smp_processor_id() in preemptible code, which you are not supposed to.
Fix the problem by disabling preemption.

The kernel error messages seen when trying to create UBI volume is
BUG: using smp_processor_id() in preemptible [00000000] code: ubi_bgt1d/843
caller is __udelay+0x14/0x70
Call Trace:
[<ffffffff8110b0d4>] dump_stack+0x8/0x34
[<ffffffff812ee1ac>] debug_smp_processor_id+0x114/0x130
[<ffffffff812e9274>] __udelay+0x14/0x70
[<ffffffff81337c0c>] cfi_amdstd_write_buffers+0xa9c/0xd70
[<ffffffff8134cab0>] ubi_io_sync_erase+0x248/0x390
[<ffffffff8134d714>] erase_worker+0x6c/0x4f8
[<ffffffff8134e4fc>] do_work+0xac/0x138
[<ffffffff8134e6a0>] ubi_thread+0x118/0x1a8
[<ffffffff8115ebe0>] kthread+0x88/0x90
[<ffffffff81115650>] kernel_thread_helper+0x10/0x18

Signed-off-by: Philby John <pjohn at mvista.com>
---
 include/linux/mtd/cfi.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index 574d9ee..9673213 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -495,7 +495,9 @@ static inline void cfi_udelay(int us)
 	if (us >= 1000) {
 		msleep((us+999)/1000);
 	} else {
+		preempt_disable();
 		udelay(us);
+		preempt_enable();
 		cond_resched();
 	}
 }
-- 
1.6.3.3.333.g4d53f





From naveen.mamindlapalli at gmail.com  Mon Jun 14 08:13:57 2010
From: naveen.mamindlapalli at gmail.com (Naveen Mamindlapalli)
Date: Mon, 14 Jun 2010 17:43:57 +0530
Subject: Bad block management in MTD subsystem
Message-ID: <AANLkTinvO85ebDTPmezVSxbWTKVRFe-O1dc-j-bQz3lT@mail.gmail.com>

Hi All,

Is there any bad block management method implemented in Linux mtd subsystem?
How the bad blocks are taken care by


From naveen.mamindlapalli at gmail.com  Mon Jun 14 08:23:27 2010
From: naveen.mamindlapalli at gmail.com (Naveen Mamindlapalli)
Date: Mon, 14 Jun 2010 17:53:27 +0530
Subject: Bad block management in MTD subsystem
In-Reply-To: <AANLkTinvO85ebDTPmezVSxbWTKVRFe-O1dc-j-bQz3lT@mail.gmail.com>
References: <AANLkTinvO85ebDTPmezVSxbWTKVRFe-O1dc-j-bQz3lT@mail.gmail.com>
Message-ID: <AANLkTikN7WNLosoPpo1M-Hz_X_g4DZm7oEUMwKjjuHjV@mail.gmail.com>

Please ignore my previous mail.

Thanks and Regards,
Naveen

On Mon, Jun 14, 2010 at 5:43 PM, Naveen Mamindlapalli
<naveen.mamindlapalli at gmail.com> wrote:
> Hi All,
>
> Is there any bad block management method implemented in Linux mtd subsystem?
> How the bad blocks are taken care by
>


From jamie at shareable.org  Mon Jun 14 11:04:25 2010
From: jamie at shareable.org (Jamie Lokier)
Date: Mon, 14 Jun 2010 16:04:25 +0100
Subject: [PATCH] mtd: Fix bug using smp_processor_id() in preemptible
	ubi_bgt1d kthread
In-Reply-To: <1276513457.16642.3.camel@localhost.localdomain>
References: <1276513457.16642.3.camel@localhost.localdomain>
Message-ID: <20100614150425.GC9550@shareable.org>

Philby John wrote:
> mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread
> 
> On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume,
> on the NOR flash, the kernel thread ubi_bgt1d calls
> cfi_amdstd_write_buffers() --> do_write_buffer() -->
> INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls
> smp_processor_id() in preemptible code, which you are not supposed to.
> Fix the problem by disabling preemption.

The MTD code just calls udelay().
Are you sure it isn't permitted to call udelay() from preemptible code?
I think it is fine.

Perhaps MIPS udelay() should be disabling preemption itself, or
(as x86 does) using raw_smp_processor_id() instead?  Or perhaps the x86
version is a bug because the current CPU might change during the delay loop?

See git commit 5c1ea08215f1f830dfaf4819a5f22efca41c3832
"x86: enable preemption in delay"

I don't think it makes sense to disable preemption in all udelay()
calls in drivers, so my NAK to this MTD patch.  To workaround,
consider putting the preempt_disable in MIPS udelay(), or using
raw_smp_processor_id() in it, after reading the above git commit's
message.  A proper fix would accept a context switch during the delay
and rescale the remaining count, but even on x86 they haven't done
that yet :-)

Regards,
-- Jamie


From jon at ringle.org  Mon Jun 14 11:15:54 2010
From: jon at ringle.org (Jon Ringle)
Date: Mon, 14 Jun 2010 11:15:54 -0400
Subject: detecting that ubifs switched to ro after problem
In-Reply-To: <1276422454.19028.209.camel@localhost>
References: <AANLkTik2mO4lpL5QA1kzMf4zp-Prd-SdhSNLVcHB9isl@mail.gmail.com>
	<1276422454.19028.209.camel@localhost>
Message-ID: <AANLkTikt_Y_DPNZP7jKvBrHgD230po4lqJWBE5vRVl20@mail.gmail.com>

On Sun, Jun 13, 2010 at 5:47 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Fri, 2010-06-11 at 22:46 -0400, Jon Ringle wrote:
>> Hi,
>>
>> I'd like to be able to somehow detect that ubifs has taken the action
>> of switching from rw to ro due to some error detected in the ubifs
>> filesystem. If I can detect this then maybe I can do something about
>> it, such as copying the ubifs contents to a .tar.bz2 in /tmp,
>> mkfs.ubifs, and restore .tar.bz2 back again.
>>
>> Is there a way I can do this?
>
> I think with 2fde99cb55fb9d9b88180512a5e8a5d939d27fec you can check for
> R/O state from /proc/mounts. Also, you can use something like inotify to
> watch /proc/mounts changes and react if UBIFS became r/o.

Any possibility of having that merged into
git://git.infradead.org/~dedekind/ubifs-v2.6.32.git?


From pjohn at mvista.com  Mon Jun 14 11:37:04 2010
From: pjohn at mvista.com (Philby John)
Date: Mon, 14 Jun 2010 21:07:04 +0530
Subject: [PATCH] mtd: Fix bug using smp_processor_id() in preemptible
	ubi_bgt1d kthread
In-Reply-To: <20100614150425.GC9550@shareable.org>
References: <1276513457.16642.3.camel@localhost.localdomain>
	<20100614150425.GC9550@shareable.org>
Message-ID: <1276529824.17519.24.camel@localhost.localdomain>

On Mon, 2010-06-14 at 16:04 +0100, Jamie Lokier wrote:
> Philby John wrote:
> > mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread
> > 
> > On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume,
> > on the NOR flash, the kernel thread ubi_bgt1d calls
> > cfi_amdstd_write_buffers() --> do_write_buffer() -->
> > INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls
> > smp_processor_id() in preemptible code, which you are not supposed to.
> > Fix the problem by disabling preemption.
> 
> The MTD code just calls udelay().
> Are you sure it isn't permitted to call udelay() from preemptible code?
> I think it is fine.


The mips code uses __udelay() where the macro current_cpu_data returns
the actual data structure on a per CPU basis by calling
smp_processor_id(). Since I have enabled CONFIG_DEBUG_PREEMPT, this
would call debug_smp_processor_id(). This function would check

a)if the thread is preemptiable. If preemption is disabled, normal flow.
b)If irqs are disabled, if yes normal flow.
c)if the thread is bound to a single cpu, if yes normal flow
d)or if its an early bootup

None of these condition get satisfied and hence the kernel error
messages are seen. So I think yes for MIPS, udelay() shouldn't be called
in preemptiable code.

> 
> Perhaps MIPS udelay() should be disabling preemption itself,

I will need to investigate this. Will follow up soon.

>  or
> (as x86 does) using raw_smp_processor_id() instead?

I have enabled CONFIG_DEBUG_PREEMPT so this would call
debug_smp_processor_id() instead of raw_smp_processor_id().

>   Or perhaps the x86
> version is a bug because the current CPU might change during the delay loop?
> 

Yes, isn't this a possibility? In that case shouldn't we be using
spin_lock_irqsave() ?

> See git commit 5c1ea08215f1f830dfaf4819a5f22efca41c3832
> "x86: enable preemption in delay"
> 
> I don't think it makes sense to disable preemption in all udelay()
> calls in drivers, so my NAK to this MTD patch.  To workaround,
> consider putting the preempt_disable in MIPS udelay(),

This would definitely work.

>  or using
> raw_smp_processor_id() in it, after reading the above git commit's
> message.

Will look into this.

Thanks
Philby



From alexander.stein at systec-electronic.com  Mon Jun 14 11:54:34 2010
From: alexander.stein at systec-electronic.com (Alexander Stein)
Date: Mon, 14 Jun 2010 17:54:34 +0200
Subject: jffs2: inflate returned -5
Message-ID: <201006141754.34912.alexander.stein@systec-electronic.com>

Hello,

I recently got a kernel panic during boot while accessing a JFFS2 filesystem 
on NOR flash. There was an error message as stated in the topic ' inflate 
returned -5'. The board is using an AT91SAM9G20.
I checked the source and this seems to be fs/jffs2/comp_zlib.c:180. But what 
I'm wondering about is that zlib_inflate is called with flush = Z_FINISH which 
means that not enough room for data or no progress is possible, according to 
the zlib headers.
In which cases can this occur? I think there should be enough memory available 
(32MB attached).

Here is the full kernel log:
Uncompressing 
Linux...................................................................................................... 
done, booting the kernel.
Linux version 2.6.31.12 (alex at ws-stein) (gcc version 4.4.1 (Sourcery G++ Lite 
2009q3-67) ) #72 Mon Jun 14 16:00:39 CEST 2010
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: SYS TEC ECUcore-9G20
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 396 MHz, master 132 MHz, main 18.432 MHz
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 8128
Kernel command line: console=ttyS0,115200 root=/dev/mtdblock3 rootfstype=jffs2 
mtdparts=physmap-flash.0:384k(uboot)ro,128k(ubootenv),4M(home),-(root)
PID hash table entries: 128 (order: 7, 512 bytes)
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 25288KB available (2796K code, 4146K data, 112K init, 0K highmem)
SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
RCU-based detection of stalled CPUs is enabled.
NR_IRQS:192
AT91: 96 gpio irqs in 3 banks
Console: colour dummy device 80x30
console [ttyS0] enabled
Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
... MAX_LOCKDEP_SUBCLASSES:  8
... MAX_LOCK_DEPTH:          48
... MAX_LOCKDEP_KEYS:        8191
... CLASSHASH_SIZE:          4096
... MAX_LOCKDEP_ENTRIES:     16384
... MAX_LOCKDEP_CHAINS:      32768
... CHAINHASH_SIZE:          16384
 memory used by lock dependency info: 3615 kB
 per task-struct memory footprint: 1152 bytes
Calibrating delay loop... 197.42 BogoMIPS (lpj=987136)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
regulator: core version 0.5
NET: Registered protocol family 16
AT91: Power Management
AT91: Starting after software reset
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
NET: Registered protocol family 1
Initializing RT-Tester: OK
squashfs: version 4.0 (2009/01/31) Phillip Lougher
JFFS2 version 2.2. (NAND) ? 2001-2006 Red Hat, Inc.
msgmni has been set to 49
io scheduler noop registered
io scheduler anticipatory registered (default)
atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
atmel_usart.1: ttyS1 at MMIO 0xfffb0000 (irq = 6) is a ATMEL_SERIAL
atmel_usart.2: ttyS2 at MMIO 0xfffb4000 (irq = 7) is a ATMEL_SERIAL
atmel_usart.3: ttyS3 at MMIO 0xfffb8000 (irq = 8) is a ATMEL_SERIAL
brd: module loaded
loop: module loaded
ssc ssc.0: Atmel SSC device at 0xc2888000 (irq 14)
MACB_mii_bus: probed
eth0: Atmel MACB at 0xfffc4000 irq 21 (00:50:c2:39:37:07)
eth0: attached PHY driver [KS8721BL] (mii_bus:phy_addr=ffffffff:01, irq=-1)
physmap platform flash device: 01000000 at 10000000
physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank
 Amd/Fujitsu Extended Query Table at 0x0040
physmap-flash.0: CFI does not contain boot bank location. Assuming top.
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
4 cmdlinepart partitions found on MTD device physmap-flash.0
Creating 4 MTD partitions on "physmap-flash.0":
0x000000000000-0x000000060000 : "uboot"
0x000000060000-0x000000080000 : "ubootenv"
0x000000080000-0x000000480000 : "home"
0x000000480000-0x000001000000 : "root"
atmel_spi atmel_spi.1: Atmel SPI Controller at 0xfffcc000 (irq 13)
at25 spi1.0: 2 KByte at25160 eeprom, pagesize 32
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
at91_ohci at91_ohci: AT91 OHCI
at91_ohci at91_ohci: new USB bus registered, assigned bus number 1
at91_ohci at91_ohci: irq 20, io mem 0x00500000
usb usb1: New USB device found, idVendor=1d6b, idProduct=0001
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: AT91 OHCI
usb usb1: Manufacturer: Linux 2.6.31.12 ohci_hcd
usb usb1: SerialNumber: at91
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
udc: at91_udc version 3 May 2006
g_serial gadget: Gadget Serial v2.4
g_serial gadget: g_serial ready
mice: PS/2 mouse device common for all mice
i2c /dev entries driver
rtc-pcf8563 0-0051: chip found, driver version 0.4.3
rtc-pcf8563 0-0051: rtc core: registered rtc-pcf8563 as rtc0
i2c-gpio i2c-gpio: using pins 55 (SDA) and 56 (SCL)
lm75 0-0048: hwmon0: sensor 'tmp101'
usbcore: registered new interface driver usbhid
usbhid: v2.6:USB HID core driver
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
rtc-pcf8563 0-0051: setting system clock to 2010-06-14 14:07:49 UTC 
(1276524469)
VFS: Mounted root (jffs2 filesystem) on device 31:3.
Freeing init memory: 112K
inflate returned -5
Kernel panic - not syncing: Attempted to kill init!
[<c002986c>] (unwind_backtrace+0x0/0xd4) from [<c022cf1c>] (panic+0x40/0x118)
[<c022cf1c>] (panic+0x40/0x118) from [<c0037550>] (find_new_reaper+0x6c/0x88)
[<c0037550>] (find_new_reaper+0x6c/0x88) from [<c00387d4>] 
(forget_original_parent+0x24/0x100)
[<c00387d4>] (forget_original_parent+0x24/0x100) from [<c00388c0>] 
(exit_notify+0x10/0x148)
[<c00388c0>] (exit_notify+0x10/0x148) from [<c0038bc0>] (do_exit+0x1c8/0x254)
[<c0038bc0>] (do_exit+0x1c8/0x254) from [<c0038cdc>] (do_group_exit+0x90/0xc4)
[<c0038cdc>] (do_group_exit+0x90/0xc4) from [<c0042b8c>] 
(get_signal_to_deliver+0x248/0x278)
[<c0042b8c>] (get_signal_to_deliver+0x248/0x278) from [<c002729c>] 
(do_signal+0x74/0x160)
[<c002729c>] (do_signal+0x74/0x160) from [<c0024d4c>] (work_pending+0x1c/0x20)
INFO: RCU detected CPU 0 stall (t=4294938571/1000 jiffies)
[<c002986c>] (unwind_backtrace+0x0/0xd4) from [<c0066668>] 
(print_cpu_stall+0x30/0x98)
[<c0066668>] (print_cpu_stall+0x30/0x98) from [<c0066728>] 
(__rcu_pending+0x10/0xa0)
[<c0066728>] (__rcu_pending+0x10/0xa0) from [<c00667c8>] 
(rcu_pending+0x10/0x44)
[<c00667c8>] (rcu_pending+0x10/0x44) from [<c003f328>] 
(update_process_times+0x30/0x58)
[<c003f328>] (update_process_times+0x30/0x58) from [<c00549ac>] 
(tick_sched_timer+0x88/0xc4)
[<c00549ac>] (tick_sched_timer+0x88/0xc4) from [<c004c558>] 
(__run_hrtimer+0x50/0xa4)
[<c004c558>] (__run_hrtimer+0x50/0xa4) from [<c004d0f4>] 
(hrtimer_interrupt+0x17c/0x1f8)
[<c004d0f4>] (hrtimer_interrupt+0x17c/0x1f8) from [<c01ae4ec>] 
(ch2_irq+0x20/0x28)
[<c01ae4ec>] (ch2_irq+0x20/0x28) from [<c0063ba8>] 
(handle_IRQ_event+0x24/0xc4)
[<c0063ba8>] (handle_IRQ_event+0x24/0xc4) from [<c0065478>] 
(handle_level_irq+0xb0/0x114)
[<c0065478>] (handle_level_irq+0xb0/0x114) from [<c0024068>] 
(asm_do_IRQ+0x68/0x90)
[<c0024068>] (asm_do_IRQ+0x68/0x90) from [<c0024994>] (__irq_svc+0x34/0x60)
Exception stack(0xc1c1fdf0 to 0xc1c1fe38)
fde0:                                     0000c31b 00000000 000003c4 c031db60
fe00: 000026ca c1c20000 00000001 c1c1ff04 c1c01200 c1d41580 c1c1ffb0 00000000
fe20: c1c20328 c1c1fe38 c022cfd4 c0128fe0 20000013 ffffffff
[<c0024994>] (__irq_svc+0x34/0x60) from [<c0128fe0>] (__delay+0x0/0xc)

Best regards
Alexander


From richardcochran at gmail.com  Mon Jun 14 12:10:33 2010
From: richardcochran at gmail.com (Richard Cochran)
Date: Mon, 14 Jun 2010 18:10:33 +0200
Subject: [PATCH] mtd: Added an ioctl to query the lock status of a
	flash sector.
In-Reply-To: <1276419903.19028.180.camel@localhost>
References: <20100531131214.GA15887@riccoc20.at.omicron.at>
	<1276419903.19028.180.camel@localhost>
Message-ID: <20100614161033.GA24877@riccoc20.at.omicron.at>

On Sun, Jun 13, 2010 at 12:05:03PM +0300, Artem Bityutskiy wrote:
> I think it is tiny bit nicer to name 'is_locked', which is a bit more
> consistent with the already existing 'block_isbad'?

Okay, here it is again.

Thanks,
Richard


This patchs adds a way for user space programs to find out whether a
flash sector is locked. An optional driver method in the mtd_info struct
provides the information.

Signed-off-by: Richard Cochran <richard.cochran at omicron.at>
---
 drivers/mtd/chips/cfi_cmdset_0001.c |   10 ++++++++++
 drivers/mtd/mtdchar.c               |   14 ++++++++++++++
 drivers/mtd/mtdpart.c               |   10 ++++++++++
 include/linux/mtd/mtd.h             |    1 +
 include/mtd/mtd-abi.h               |    1 +
 5 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 62f3ea9..2fadb02 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -63,6 +63,8 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
 static void cfi_intelext_sync (struct mtd_info *);
 static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
+				  uint64_t len);
 #ifdef CONFIG_MTD_OTP
 static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
@@ -448,6 +450,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
 	mtd->sync    = cfi_intelext_sync;
 	mtd->lock    = cfi_intelext_lock;
 	mtd->unlock  = cfi_intelext_unlock;
+	mtd->is_locked = cfi_intelext_is_locked;
 	mtd->suspend = cfi_intelext_suspend;
 	mtd->resume  = cfi_intelext_resume;
 	mtd->flags   = MTD_CAP_NORFLASH;
@@ -2139,6 +2142,13 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	return ret;
 }
 
+static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
+				  uint64_t len)
+{
+	return cfi_varsize_frob(mtd, do_getlockstatus_oneblock,
+				ofs, len, NULL) ? 1 : 0;
+}
+
 #ifdef CONFIG_MTD_OTP
 
 typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 8b223c0..a8e69dd 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -676,6 +676,20 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
 		break;
 	}
 
+	case MEMISLOCKED:
+	{
+		struct erase_info_user einfo;
+
+		if (copy_from_user(&einfo, argp, sizeof(einfo)))
+			return -EFAULT;
+
+		if (!mtd->is_locked)
+			ret = -EOPNOTSUPP;
+		else
+			ret = mtd->is_locked(mtd, einfo.start, einfo.length);
+		break;
+	}
+
 	/* Legacy interface */
 	case MEMGETOOBSEL:
 	{
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index b8043a9..4c539de 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -264,6 +264,14 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	return part->master->unlock(part->master, ofs + part->offset, len);
 }
 
+static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+	struct mtd_part *part = PART(mtd);
+	if ((len + ofs) > mtd->size)
+		return -EINVAL;
+	return part->master->is_locked(part->master, ofs + part->offset, len);
+}
+
 static void part_sync(struct mtd_info *mtd)
 {
 	struct mtd_part *part = PART(mtd);
@@ -402,6 +410,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 		slave->mtd.lock = part_lock;
 	if (master->unlock)
 		slave->mtd.unlock = part_unlock;
+	if (master->is_locked)
+		slave->mtd.is_locked = part_is_locked;
 	if (master->block_isbad)
 		slave->mtd.block_isbad = part_block_isbad;
 	if (master->block_markbad)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 5326435..43b7d72 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -216,6 +216,7 @@ struct mtd_info {
 	/* Chip-supported device locking */
 	int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 	int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
+	int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
 	/* Power Management functions */
 	int (*suspend) (struct mtd_info *mtd);
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index be51ae2..e12872e 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -110,6 +110,7 @@ struct otp_info {
 #define MEMERASE64		_IOW('M', 20, struct erase_info_user64)
 #define MEMWRITEOOB64		_IOWR('M', 21, struct mtd_oob_buf64)
 #define MEMREADOOB64		_IOWR('M', 22, struct mtd_oob_buf64)
+#define MEMISLOCKED		_IOR('M', 23, struct erase_info_user)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
-- 
1.6.3.3



From richardcochran at gmail.com  Mon Jun 14 12:15:19 2010
From: richardcochran at gmail.com (Richard Cochran)
Date: Mon, 14 Jun 2010 18:15:19 +0200
Subject: [PATCH] ixp4xx: add support for static flash partitions
In-Reply-To: <1276420566.19028.184.camel@localhost>
References: <20100531162434.GA4599@riccoc20.at.omicron.at>
	<1276420566.19028.184.camel@localhost>
Message-ID: <20100614161519.GB24877@riccoc20.at.omicron.at>

On Sun, Jun 13, 2010 at 12:16:06PM +0300, Artem Bityutskiy wrote:
> I could fix your patch up myself, but I do not know the code, so please,
> re-send a patch against the latest mtd-2.6 tree.

Okay, here it is again, this time against today's master branch of 
git://git.infradead.org/mtd-2.6.git

Thanks,
Richard


This patch adds support for static flash partitioning from a platform
device. Also, we clean up some weirdness where statements were separated
by commas instead of semicolons. While we are at it, fix some minor bad
white space, too.

Signed-off-by: Richard Cochran <richard.cochran at omicron.at>
---
 drivers/mtd/maps/ixp4xx.c |   35 +++++++++++++++++++++++++++--------
 1 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index e0a5e04..1f9fde0 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -118,7 +118,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
 		*dest++ = BYTE1(data);
 		src += 2;
 		len -= 2;
-        }
+	}
 
 	if (len > 0)
 		*dest++ = BYTE0(flash_read16(src));
@@ -185,6 +185,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 {
 	struct flash_platform_data *plat = dev->dev.platform_data;
 	struct ixp4xx_flash_info *info;
+	const char *part_type = NULL;
+	int nr_parts = 0;
 	int err = -1;
 
 	if (!plat)
@@ -218,9 +220,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 	 */
 	info->map.bankwidth = 2;
 	info->map.name = dev_name(&dev->dev);
-	info->map.read = ixp4xx_read16,
-	info->map.write = ixp4xx_probe_write16,
-	info->map.copy_from = ixp4xx_copy_from,
+	info->map.read = ixp4xx_read16;
+	info->map.write = ixp4xx_probe_write16;
+	info->map.copy_from = ixp4xx_copy_from;
 
 	info->res = request_mem_region(dev->resource->start,
 			resource_size(dev->resource),
@@ -248,11 +250,28 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 	info->mtd->owner = THIS_MODULE;
 
 	/* Use the fast version */
-	info->map.write = ixp4xx_write16,
+	info->map.write = ixp4xx_write16;
+
+#ifdef CONFIG_MTD_PARTITIONS
+	nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
+					dev->resource->start);
+#endif
+	if (nr_parts > 0) {
+		part_type = "dynamic";
+	} else {
+		info->partitions = plat->parts;
+		nr_parts = plat->nr_parts;
+		part_type = "static";
+	}
+	if (nr_parts == 0) {
+		printk(KERN_NOTICE "IXP4xx flash: no partition info "
+			"available, registering whole flash\n");
+		err = add_mtd_device(info->mtd);
+	} else {
+		printk(KERN_NOTICE "IXP4xx flash: using %s partition "
+			"definition\n", part_type);
+		err = add_mtd_partitions(info->mtd, info->partitions, nr_parts);
 
-	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start);
-	if (err > 0) {
-		err = add_mtd_partitions(info->mtd, info->partitions, err);
 		if(err)
 			printk(KERN_ERR "Could not parse partitions\n");
 	}
-- 
1.6.3.3




From pjohn at mvista.com  Mon Jun 14 12:40:18 2010
From: pjohn at mvista.com (Philby John)
Date: Mon, 14 Jun 2010 22:10:18 +0530
Subject: [PATCH] mtd: Fix bug using smp_processor_id() in preemptible
	ubi_bgt1d kthread
In-Reply-To: <20100614150425.GC9550@shareable.org>
References: <1276513457.16642.3.camel@localhost.localdomain>
	<20100614150425.GC9550@shareable.org>
Message-ID: <1276533618.17818.8.camel@localhost.localdomain>

On Mon, 2010-06-14 at 16:04 +0100, Jamie Lokier wrote:
> Philby John wrote:
> > mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread
> > 
> > On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume,
> > on the NOR flash, the kernel thread ubi_bgt1d calls
> > cfi_amdstd_write_buffers() --> do_write_buffer() -->
> > INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls
> > smp_processor_id() in preemptible code, which you are not supposed to.
> > Fix the problem by disabling preemption.
> 
> The MTD code just calls udelay().
> Are you sure it isn't permitted to call udelay() from preemptible code?
> I think it is fine.

It isn't really udelay() but smp_processor_id() that you are not to call
from a preemptible thread. Now I also see Ed Swierk has done a similar
thing https://patchwork.kernel.org/patch/4049/ and he comments "..which
calls smp_processor_id(), which is not supposed to be called from a
preemptible thread."


So perhaps I can use preempt_disable() around just this call in function
__udelay()?

Regards,
Philby



From hartleys at visionengravers.com  Mon Jun 14 12:57:54 2010
From: hartleys at visionengravers.com (H Hartley Sweeten)
Date: Mon, 14 Jun 2010 11:57:54 -0500
Subject: [PATCH] mtd: physmap.c: use resource_size()
Message-ID: <0D753D10438DA54287A00B02708426976371223143@AUSP01VMBX24.collaborationhost.net>

Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
Cc: David Woodhouse <David.Woodhouse at intel.com>

---

diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 426461a..829aa4b 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -106,12 +106,12 @@ static int physmap_flash_probe(struct platform_device *dev)
 
 	for (i = 0; i < dev->num_resources; i++) {
 		printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
-		       (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
+		       (unsigned long long)resource_size(&dev->resource[i]),
 		       (unsigned long long)dev->resource[i].start);
 
 		if (!devm_request_mem_region(&dev->dev,
 			dev->resource[i].start,
-			dev->resource[i].end - dev->resource[i].start + 1,
+			resource_size(&dev->resource[i]),
 			dev_name(&dev->dev))) {
 			dev_err(&dev->dev, "Could not reserve memory region\n");
 			err = -ENOMEM;
@@ -120,7 +120,7 @@ static int physmap_flash_probe(struct platform_device *dev)
 
 		info->map[i].name = dev_name(&dev->dev);
 		info->map[i].phys = dev->resource[i].start;
-		info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1;
+		info->map[i].size = resource_size(&dev->resource[i]);
 		info->map[i].bankwidth = physmap_data->width;
 		info->map[i].set_vpp = physmap_data->set_vpp;
 		info->map[i].pfow_base = physmap_data->pfow_base;


From vapier.adi at gmail.com  Mon Jun 14 14:21:08 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 14 Jun 2010 14:21:08 -0400
Subject: [PATCH v3] mtdchar: fix mmap() for MTD RAM/ROM char devices
In-Reply-To: <20100614112213.695ac5d2@wker>
References: <1276371338-14253-1-git-send-email-agust@denx.de> 
	<AANLkTikutI1bWUpG4FDWwwKOGSEfik-ycZZLs37AjDtK@mail.gmail.com> 
	<20100614112213.695ac5d2@wker>
Message-ID: <AANLkTilYAgKHkOkfw4rTlS1SbWvRs99fC-Wwa7jutUEM@mail.gmail.com>

On Mon, Jun 14, 2010 at 05:22, Anatolij Gustschin wrote:
> On Sat, 12 Jun 2010 21:31:11 -0400 Mike Frysinger wrote:
>> On Sat, Jun 12, 2010 at 15:35, Anatolij Gustschin wrote:
>> > For no-mmu systems mmap() on RAM/ROM devices already works
>> > but for systems with mmu it probably was not tested and
>> > currently doesn't work.
>>
>> nope, never did
>
> Do you mean it never worked on mmu systems?

it probably wasnt tested too heavily if at all
-mike


From pazdnikov at prosoft.ural.ru  Tue Jun 15 01:02:01 2010
From: pazdnikov at prosoft.ural.ru (Alexander Pazdnikov)
Date: Tue, 15 Jun 2010 11:02:01 +0600
Subject: ubifs became broken on contigous power-fails
In-Reply-To: <1276352575.19028.121.camel@localhost>
References: <E1OBqfw-0002Rs-00.pazdnikov-list-ru@f27.mail.ru>
	<1274694991.22999.52.camel@localhost>
	<1276352575.19028.121.camel@localhost>
Message-ID: <201006151102.01851.pazdnikov@prosoft.ural.ru>

? ????????? ?? ??????? 12 ???? 2010 20:22:55 ????? Artem Bityutskiy ???????:
> On Mon, 2010-05-24 at 12:56 +0300, Artem Bityutskiy wrote:
> > On Mon, 2010-05-24 at 15:50 +0600, Alexander Pazdnikov wrote:
> > > > Could you enable debugging messages when mounging it after power
> > > > cuts? The messages generate a lot of noise, so you need to disable
> > > > them before starting the real test. The idea is to get UBIFS
> > > > debugging messages when errors occur.
> > >
> > > Sorry, I've hurried up, and after applying your pathes reflash all of
> > > the devices with new firmware.
> > > But I'll setup some devices with all firmware to catch this issue
> > > again.
> > >
> > > > I never had time to really dig this and fix. Would be nice if you
> > > > could do this because I will unlikely have time in the nearest
> > > > future, but I can help you.
> > >
> > > Thank you, I'll continue testings and can supply with debug
> > > information.
> > >
> > > > One think you can do is to make sure you do not fill UBIFS
> > > > completely, then you will avoid hitting these budgeting bugs, also
> > > > known as ENOSPC issues (I think btrfs uses this terminology).
> > >
> > > In the issue above there is 11% used space and 89% free space.
> > > I've got this issue only when mounting fs in RO and then remounting it
> > > in RW.
> >
> > OK. Try my patch. Also, it is worth running your tests with UBIFS extra
> > self checks enabled.
> 
> Did it help?
> 
Artem, thank you very much, yes - it helped, all of 10 testing devices 
survived with repeatable powerfails (1,2,3,4,5,6,7,8,9,10 minutes in this 
sequence) for a week.
Now we leave 3 devices for this test.

Appologize me, please, I've not tested again for the RO-RW recovery on remount 
with this patch to supply you with debug info.

-- 
Best Regards,
Alexander Pazdnikov


From agust at denx.de  Tue Jun 15 03:30:15 2010
From: agust at denx.de (Anatolij Gustschin)
Date: Tue, 15 Jun 2010 09:30:15 +0200
Subject: [PATCH v4] mtdchar: fix mmap() for MTD RAM/ROM char devices
In-Reply-To: <1276371338-14253-1-git-send-email-agust@denx.de>
References: <1276371338-14253-1-git-send-email-agust@denx.de>
Message-ID: <1276587015-13506-1-git-send-email-agust@denx.de>

For no-mmu systems mmap() on RAM/ROM devices already works
but for systems with mmu it probably was not tested and
doesn't work.

This patch allows using mmap() on MTD RAM/ROM devices on systems
with MMU. It has been tested on mpc5121e based platform with
MR0A16A MRAM device attached over LocalBus.

Signed-off-by: Anatolij Gustschin <agust at denx.de>
---
Changes since v3:
 - remove vma->vm_pgoff check as suggested by Mike
 - update commit message

Changes since v2:
 - improved commit message and patch description
 - rebased to apply cleanly on current mtd-2.6 tree

 drivers/mtd/mtdchar.c |   28 +++++++++++++++++++++++++++-
 1 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 8b223c0..c3e5423 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -18,6 +18,7 @@
 #include <linux/mount.h>
 
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
 #include <linux/mtd/compatmac.h>
 
 #include <asm/uaccess.h>
@@ -941,9 +942,34 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma)
 #ifdef CONFIG_MMU
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
+	struct map_info *map = mtd->priv;
+	unsigned long start;
+	unsigned long off;
+	u32 len;
+
+	if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
+		off = vma->vm_pgoff << PAGE_SHIFT;
+		start = map->phys;
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
+		start &= PAGE_MASK;
+		if ((vma->vm_end - vma->vm_start + off) > len)
+			return -EINVAL;
+
+		off += start;
+		vma->vm_pgoff = off >> PAGE_SHIFT;
+		vma->vm_flags |= VM_IO | VM_RESERVED;
+
+#ifdef pgprot_noncached
+		if (file->f_flags & O_DSYNC || off >= __pa(high_memory))
+			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+		if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+				       vma->vm_end - vma->vm_start,
+				       vma->vm_page_prot))
+			return -EAGAIN;
 
-	if (mtd->type == MTD_RAM || mtd->type == MTD_ROM)
 		return 0;
+	}
 	return -ENOSYS;
 #else
 	return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;
-- 
1.7.0.4



From pjohn at mvista.com  Tue Jun 15 08:26:34 2010
From: pjohn at mvista.com (Philby John)
Date: Tue, 15 Jun 2010 17:56:34 +0530
Subject: [PATCH] mtd: Fix bug using smp_processor_id() in preemptible
	ubi_bgt1d kthread
In-Reply-To: <20100614150425.GC9550@shareable.org>
References: <1276513457.16642.3.camel@localhost.localdomain>
	<20100614150425.GC9550@shareable.org>
Message-ID: <1276604794.19810.3.camel@localhost.localdomain>

Hello Jamie,

On Mon, 2010-06-14 at 16:04 +0100, Jamie Lokier wrote:
> Philby John wrote:
> > mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread
> > 
> > On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume,
> > on the NOR flash, the kernel thread ubi_bgt1d calls
> > cfi_amdstd_write_buffers() --> do_write_buffer() -->
> > INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls
> > smp_processor_id() in preemptible code, which you are not supposed to.
> > Fix the problem by disabling preemption.
> 
> The MTD code just calls udelay().
> Are you sure it isn't permitted to call udelay() from preemptible code?
> I think it is fine.
> 
> Perhaps MIPS udelay() should be disabling preemption itself, or
> (as x86 does) using raw_smp_processor_id() instead?

Sorry for the noise. I now find that raw_smp_processor_id() has been
implemented specific to MIPS in the latest kernel, I was using 2.6.32.

Thanks and regards,
Philby



From pjohn at mvista.com  Tue Jun 15 08:59:39 2010
From: pjohn at mvista.com (Philby John)
Date: Tue, 15 Jun 2010 18:29:39 +0530
Subject: UBIFS mount failure on NOR flash
Message-ID: <1276606779.20001.18.camel@localhost.localdomain>

Hello,

Platform: Cavium CN5020
Filesystem: UBIFS
Flash Type: NOR
Flash Size: 8MB
Partition Details Kernel Log:
Creating 2 MTD partitions on "phys_mapped_flash":
0x000000000000-0x000000700000 : "Octeon BOOT partition"
0x000000700000-0x000000800000 : "Octeon test partition"


$mount -t ubifs ubi1:test /mnt/nor
UBIFS error (pid 851): init_constants_early: too few LEBs (12), min. is 17
mount: wrong fs type, bad option, bad superblock on ubi1:test,
       missing codepage or helper program, or other error
       (for several filesystems (e.g. nfs, cifs) you might
       need a /sbin/mount.<type> helper program)
       In some cases useful info is found in syslog - try
       dmesg | tail  or so


But JFFS2 is able to mount the same partition flawlessly. Shouldn't
UBIFS be able to do the same? What I would like to know is, is this the
expected behavior or a bug? If its a bug I would like to look into it.

Thanks and regards,
Philby



From s-ghorai at ti.com  Tue Jun 15 09:26:37 2010
From: s-ghorai at ti.com (Ghorai, Sukumar)
Date: Tue, 15 Jun 2010 18:56:37 +0530
Subject: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
In-Reply-To: <AANLkTinf8OcvHbLggdEJNGLvlAtSeExKri-IqNlwLpYD@mail.gmail.com>
References: <s-ghorai@ti.com> <1275637205-489-1-git-send-email-s-ghorai@ti.com>
	<AANLkTinf8OcvHbLggdEJNGLvlAtSeExKri-IqNlwLpYD@mail.gmail.com>
Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030DDBEF8A@dbde02.ent.ti.com>

Tony,

> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork at gmail.com]
> Sent: Tuesday, June 08, 2010 10:43 PM
> To: Ghorai, Sukumar
> Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org;
> tony at atomide.com; mike at compulab.co.il
> Subject: Re: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related
> code
> 
> Reviewed-by: Vimal Singh <vimal.newwork at gmail.com>
> 
> On Fri, Jun 4, 2010 at 1:10 PM, Sukumar Ghorai <s-ghorai at ti.com> wrote:
> > ? The following set of patches applies on top of for-next branch.
> > ? ? ? ?http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-
> 2.6.git
> > ? Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle
> board
> >
> > ? And these are the patches required to address the following input -
> > ? ? 1. The NAND driver needs to stop tinkering with the GPMC registers
> > ? ? ? ?The omap General Purpose Memory Controller (GPMC) registers are
> omap
> > ? ? ? ?specific, and not driver specific. Tinkering with these registers
> can
> > ? ? ? ?cause issues with the other devices on the GPMC.
> >
> > ? ? 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
> > ? ? ? ?Passing hardcoded GPMC virtual addressess is sure way to mess up
> things.
> > ? ? ? ?This should all become unnecessary once the NAND drivers stops
> messing
> > ? ? ? ?with the GPMC registers directly.
> > ? ? Discussion: http://www.mail-archive.com/linux-
> omap at vger.kernel.org/msg27630.html
> >
> > ? Changes in this series -
> > ? ? ? ? ? ? ? ?Unused function removed.
> >
> > ?Functions related to ecc and prefetch engine are optimized.
> > ?v4: http://www.mail-archive.com/linux-
> omap at vger.kernel.org/msg29458.html
> >
> > ?Few functionality was missing ?like - There should be some locking as
> only
> > ? one chipselect can use the ECC or prefetch engine at a time. If you
> have
> > ? NAND in two chipselects, bad things would happen.
> > ?v3: http://www.mail-archive.com/linux-
> omap at vger.kernel.org/msg28715.html
> >
> > ?Additionally, it was needed to implement more functions for the
> platform
> > ?init code to use.
> > ?v2: http://www.mail-archive.com/linux-
> omap at vger.kernel.org/msg28467.html
> >
> > ?v1: http://www.mail-archive.com/linux-
> omap at vger.kernel.org/msg28164.html
> >
> >
> > Sukumar Ghorai (3):
> > ? ? ? ?omap3 gpmc: functionality enhancement
> > ? ? ? ?omap3 nand: cleanup virtual address usages
> > ? ? ? ?omap3 nand: fix issue in board file to detect nand
> > ?arch/arm/mach-omap2/board-cm-t35.c ? ? ? ? | ? 20 +---
> > ?arch/arm/mach-omap2/board-devkit8000.c ? ? | ? 25 +---
> > ?arch/arm/mach-omap2/board-omap3beagle.c ? ?| ? 24 +---
> > ?arch/arm/mach-omap2/board-omap3touchbook.c | ? 25 +---
> > ?arch/arm/mach-omap2/board-overo.c ? ? ? ? ?| ? 24 +---
> > ?arch/arm/mach-omap2/board-sdp-flash.c ? ? ?| ? ?5 -
> > ?arch/arm/mach-omap2/gpmc-nand.c ? ? ? ? ? ?| ? 39 ++----
> > ?arch/arm/mach-omap2/gpmc.c ? ? ? ? ? ? ? ? | ?228
> +++++++++++++++++++++++++---
> > ?arch/arm/plat-omap/include/plat/gpmc.h ? ? | ? 36 ++++-
> > ?arch/arm/plat-omap/include/plat/nand.h ? ? | ? ?6 +-
> > ?drivers/mtd/nand/omap2.c ? ? ? ? ? ? ? ? ? | ?229 ++++++++-------------
> -------
> > ?11 files changed, 320 insertions(+), 341 deletions(-)

[Ghorai] Any comments or input on these patch?

> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at ?http://vger.kernel.org/majordomo-info.html
> >
> 
> 
> 
> --
> Regards,
> Vimal Singh


From dedekind1 at gmail.com  Tue Jun 15 09:37:27 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 15 Jun 2010 16:37:27 +0300
Subject: UBIFS mount failure on NOR flash
In-Reply-To: <1276606779.20001.18.camel@localhost.localdomain>
References: <1276606779.20001.18.camel@localhost.localdomain>
Message-ID: <1276609047.19028.270.camel@localhost>

On Tue, 2010-06-15 at 18:29 +0530, Philby John wrote:
> Hello,
> 
> Platform: Cavium CN5020
> Filesystem: UBIFS
> Flash Type: NOR
> Flash Size: 8MB
> Partition Details Kernel Log:
> Creating 2 MTD partitions on "phys_mapped_flash":
> 0x000000000000-0x000000700000 : "Octeon BOOT partition"
> 0x000000700000-0x000000800000 : "Octeon test partition"
> 
> 
> $mount -t ubifs ubi1:test /mnt/nor
> UBIFS error (pid 851): init_constants_early: too few LEBs (12), min. is 17
> mount: wrong fs type, bad option, bad superblock on ubi1:test,
>        missing codepage or helper program, or other error
>        (for several filesystems (e.g. nfs, cifs) you might
>        need a /sbin/mount.<type> helper program)
>        In some cases useful info is found in syslog - try
>        dmesg | tail  or so
> 
> 
> But JFFS2 is able to mount the same partition flawlessly. Shouldn't
> UBIFS be able to do the same? What I would like to know is, is this the
> expected behavior or a bug? If its a bug I would like to look into it.

Yes, this is expected. For such a tiny flash partition you should rather
use JFFS2. I've just created a FAQ entry for you:

http://www.linux-mtd.infradead.org/faq/ubifs.html#L_few_lebs

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From pjohn at mvista.com  Tue Jun 15 10:05:07 2010
From: pjohn at mvista.com (Philby John)
Date: Tue, 15 Jun 2010 19:35:07 +0530
Subject: UBIFS mount failure on NOR flash
In-Reply-To: <1276609047.19028.270.camel@localhost>
References: <1276606779.20001.18.camel@localhost.localdomain>
	<1276609047.19028.270.camel@localhost>
Message-ID: <4C178893.9010204@mvista.com>

On 06/15/2010 07:07 PM, Artem Bityutskiy wrote:
> On Tue, 2010-06-15 at 18:29 +0530, Philby John wrote:
>> Hello,
>>
>> Platform: Cavium CN5020
>> Filesystem: UBIFS
>> Flash Type: NOR
>> Flash Size: 8MB
>> Partition Details Kernel Log:
>> Creating 2 MTD partitions on "phys_mapped_flash":
>> 0x000000000000-0x000000700000 : "Octeon BOOT partition"
>> 0x000000700000-0x000000800000 : "Octeon test partition"
>>
>>
>> $mount -t ubifs ubi1:test /mnt/nor
>> UBIFS error (pid 851): init_constants_early: too few LEBs (12), min. is 17
>> mount: wrong fs type, bad option, bad superblock on ubi1:test,
>>         missing codepage or helper program, or other error
>>         (for several filesystems (e.g. nfs, cifs) you might
>>         need a /sbin/mount.<type>  helper program)
>>         In some cases useful info is found in syslog - try
>>         dmesg | tail  or so
>>
>>
>> But JFFS2 is able to mount the same partition flawlessly. Shouldn't
>> UBIFS be able to do the same? What I would like to know is, is this the
>> expected behavior or a bug? If its a bug I would like to look into it.
>
> Yes, this is expected. For such a tiny flash partition you should rather
> use JFFS2. I've just created a FAQ entry for you:
>
> http://www.linux-mtd.infradead.org/faq/ubifs.html#L_few_lebs
>

Okay, thanks for the clarification.

Regards,
Philby


From vapier.adi at gmail.com  Tue Jun 15 12:55:54 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 15 Jun 2010 12:55:54 -0400
Subject: [PATCH v4] mtdchar: fix mmap() for MTD RAM/ROM char devices
In-Reply-To: <1276587015-13506-1-git-send-email-agust@denx.de>
References: <1276371338-14253-1-git-send-email-agust@denx.de> 
	<1276587015-13506-1-git-send-email-agust@denx.de>
Message-ID: <AANLkTim_deM9PCcoHxnC6g59tKn0eaWeD2q7-uI0cnJG@mail.gmail.com>

On Tue, Jun 15, 2010 at 03:30, Anatolij Gustschin wrote:
> For no-mmu systems mmap() on RAM/ROM devices already works
> but for systems with mmu it probably was not tested and
> doesn't work.
>
> This patch allows using mmap() on MTD RAM/ROM devices on systems
> with MMU. It has been tested on mpc5121e based platform with
> MR0A16A MRAM device attached over LocalBus.

i dont really have a way of testing the MMU path, but this looks sane.
Acked-by: Mike Frysinger <vapier at gentoo.org>
-mike


From vaurora at redhat.com  Tue Jun 15 14:39:42 2010
From: vaurora at redhat.com (Valerie Aurora)
Date: Tue, 15 Jun 2010 11:39:42 -0700
Subject: [PATCH 12/38] whiteout: jffs2 whiteout support
In-Reply-To: <1276627208-17242-1-git-send-email-vaurora@redhat.com>
References: <1276627208-17242-1-git-send-email-vaurora@redhat.com>
Message-ID: <1276627208-17242-13-git-send-email-vaurora@redhat.com>

From: Felix Fietkau <nbd at openwrt.org>

Add support for whiteout dentries to jffs2.

XXX - David Woodhouse suggests several changes and provides an
untested patch.  See:

http://patchwork.ozlabs.org/patch/50466/

Signed-off-by: Felix Fietkau <nbd at openwrt.org>
Signed-off-by: Valerie Aurora <vaurora at redhat.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: linux-mtd at lists.infradead.org
---
 fs/jffs2/dir.c        |   72 +++++++++++++++++++++++++++++++++++++++++++++++-
 fs/jffs2/fs.c         |    4 +++
 fs/jffs2/super.c      |    2 +-
 include/linux/jffs2.h |    2 +
 4 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 7aa4417..c259193 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -34,6 +34,8 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
 static int jffs2_rename (struct inode *, struct dentry *,
 			 struct inode *, struct dentry *);
 
+static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *);
+
 const struct file_operations jffs2_dir_operations =
 {
 	.read =		generic_read_dir,
@@ -56,6 +58,7 @@ const struct inode_operations jffs2_dir_inode_operations =
 	.mknod =	jffs2_mknod,
 	.rename =	jffs2_rename,
 	.check_acl =	jffs2_check_acl,
+	.whiteout =     jffs2_whiteout,
 	.setattr =	jffs2_setattr,
 	.setxattr =	jffs2_setxattr,
 	.getxattr =	jffs2_getxattr,
@@ -98,8 +101,14 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
 			fd = fd_list;
 		}
 	}
-	if (fd)
-		ino = fd->ino;
+	if (fd) {
+		spin_lock(&target->d_lock);
+		if (fd->type == DT_WHT)
+			target->d_flags |= DCACHE_WHITEOUT;
+		else
+			ino = fd->ino;
+		spin_unlock(&target->d_lock);
+	}
 	mutex_unlock(&dir_f->sem);
 	if (ino) {
 		inode = jffs2_iget(dir_i->i_sb, ino);
@@ -498,6 +507,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
 		return PTR_ERR(inode);
 	}
 
+	if (dentry->d_flags & DCACHE_WHITEOUT) {
+		inode->i_flags |= S_OPAQUE;
+		ri->flags = cpu_to_je16(JFFS2_INO_FLAG_OPAQUE);
+	}
+
 	inode->i_op = &jffs2_dir_inode_operations;
 	inode->i_fop = &jffs2_dir_operations;
 
@@ -779,6 +793,60 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
 	return 0;
 }
 
+static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry,
+			   struct dentry *new_dentry)
+{
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb);
+	struct jffs2_inode_info *victim_f = NULL;
+	uint32_t now;
+	int ret;
+
+	/* If it's a directory, then check whether it is really empty */
+	if (new_dentry->d_inode) {
+		victim_f = JFFS2_INODE_INFO(old_dentry->d_inode);
+		if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+			struct jffs2_full_dirent *fd;
+
+			mutex_lock(&victim_f->sem);
+			for (fd = victim_f->dents; fd; fd = fd->next) {
+				if (fd->ino) {
+					mutex_unlock(&victim_f->sem);
+					return -ENOTEMPTY;
+				}
+			}
+			mutex_unlock(&victim_f->sem);
+		}
+	}
+
+	now = get_seconds();
+	ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_WHT,
+			    new_dentry->d_name.name, new_dentry->d_name.len, now);
+	if (ret)
+		return ret;
+
+	spin_lock(&new_dentry->d_lock);
+	new_dentry->d_flags |= DCACHE_WHITEOUT;
+	spin_unlock(&new_dentry->d_lock);
+	d_add(new_dentry, NULL);
+
+	if (victim_f) {
+		/* There was a victim. Kill it off nicely */
+		drop_nlink(old_dentry->d_inode);
+		/* Don't oops if the victim was a dirent pointing to an
+		   inode which didn't exist. */
+		if (victim_f->inocache) {
+			mutex_lock(&victim_f->sem);
+			if (S_ISDIR(old_dentry->d_inode->i_mode))
+				victim_f->inocache->pino_nlink = 0;
+			else
+				victim_f->inocache->pino_nlink--;
+			mutex_unlock(&victim_f->sem);
+		}
+	}
+
+	return 0;
+}
+
 static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 			 struct inode *new_dir_i, struct dentry *new_dentry)
 {
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 3451a81..c1e333c 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -301,6 +301,10 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
 
 		inode->i_op = &jffs2_dir_inode_operations;
 		inode->i_fop = &jffs2_dir_operations;
+
+		if (je16_to_cpu(latest_node.flags) & JFFS2_INO_FLAG_OPAQUE)
+			inode->i_flags |= S_OPAQUE;
+
 		break;
 	}
 	case S_IFREG:
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 9a80e8e..c12cd1c 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -172,7 +172,7 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 
 	sb->s_op = &jffs2_super_operations;
 	sb->s_export_op = &jffs2_export_ops;
-	sb->s_flags = sb->s_flags | MS_NOATIME;
+	sb->s_flags = sb->s_flags | MS_NOATIME | MS_WHITEOUT;
 	sb->s_xattr = jffs2_xattr_handlers;
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 	sb->s_flags |= MS_POSIXACL;
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index 2b32d63..65533bb 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -87,6 +87,8 @@
 #define JFFS2_INO_FLAG_USERCOMPR  2	/* User has requested a specific
 					   compression type */
 
+#define JFFS2_INO_FLAG_OPAQUE     4	/* Directory is opaque (for union mounts) */
+
 
 /* These can go once we've made sure we've caught all uses without
    byteswapping */
-- 
1.6.3.3



From vaurora at redhat.com  Tue Jun 15 14:39:45 2010
From: vaurora at redhat.com (Valerie Aurora)
Date: Tue, 15 Jun 2010 11:39:45 -0700
Subject: [PATCH 15/38] fallthru: jffs2 fallthru support
In-Reply-To: <1276627208-17242-1-git-send-email-vaurora@redhat.com>
References: <1276627208-17242-1-git-send-email-vaurora@redhat.com>
Message-ID: <1276627208-17242-16-git-send-email-vaurora@redhat.com>

From: Felix Fietkau <nbd at openwrt.org>

Add support for fallthru dentries to jffs2.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: linux-mtd at lists.infradead.org
Signed-off-by: Felix Fietkau <nbd at openwrt.org>
Signed-off-by: Valerie Aurora <vaurora at redhat.com>
---
 fs/jffs2/dir.c        |   36 +++++++++++++++++++++++++++++++++---
 include/linux/jffs2.h |    6 ++++++
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index c259193..98397b3 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -35,6 +35,7 @@ static int jffs2_rename (struct inode *, struct dentry *,
 			 struct inode *, struct dentry *);
 
 static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *);
+static int jffs2_fallthru (struct inode *, struct dentry *);
 
 const struct file_operations jffs2_dir_operations =
 {
@@ -59,6 +60,7 @@ const struct inode_operations jffs2_dir_inode_operations =
 	.rename =	jffs2_rename,
 	.check_acl =	jffs2_check_acl,
 	.whiteout =     jffs2_whiteout,
+	.fallthru =     jffs2_fallthru,
 	.setattr =	jffs2_setattr,
 	.setxattr =	jffs2_setxattr,
 	.getxattr =	jffs2_getxattr,
@@ -103,10 +105,14 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
 	}
 	if (fd) {
 		spin_lock(&target->d_lock);
-		if (fd->type == DT_WHT)
+		switch (fd->type) {
+		case DT_WHT:
 			target->d_flags |= DCACHE_WHITEOUT;
-		else
+		case JFFS2_DT_FALLTHRU:
+			target->d_flags |= DCACHE_FALLTHRU;
+		default:
 			ino = fd->ino;
+		}
 		spin_unlock(&target->d_lock);
 	}
 	mutex_unlock(&dir_f->sem);
@@ -164,7 +170,10 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
 				  fd->name, fd->ino, fd->type, curofs, offset));
 			continue;
 		}
-		if (!fd->ino) {
+		if (fd->type == JFFS2_DT_FALLTHRU)
+			/* XXX Should really do a lookup for the real inode number here */
+			fd->ino = 100;
+		else if (!fd->ino && (fd->type != DT_WHT)) {
 			D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name));
 			offset++;
 			continue;
@@ -793,6 +802,26 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
 	return 0;
 }
 
+static int jffs2_fallthru (struct inode *dir, struct dentry *dentry)
+{
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb);
+	uint32_t now;
+	int ret;
+
+	now = get_seconds();
+	ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_UNKNOWN,
+			    dentry->d_name.name, dentry->d_name.len, now);
+	if (ret)
+		return ret;
+
+	d_instantiate(dentry, NULL);
+	spin_lock(&dentry->d_lock);
+	dentry->d_flags |= DCACHE_FALLTHRU;
+	spin_unlock(&dentry->d_lock);
+
+	return 0;
+}
+
 static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry,
 			   struct dentry *new_dentry)
 {
@@ -825,6 +854,7 @@ static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry,
 		return ret;
 
 	spin_lock(&new_dentry->d_lock);
+	new_dentry->d_flags &= ~DCACHE_FALLTHRU;
 	new_dentry->d_flags |= DCACHE_WHITEOUT;
 	spin_unlock(&new_dentry->d_lock);
 	d_add(new_dentry, NULL);
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index 65533bb..dbe8c93 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -114,6 +114,12 @@ struct jffs2_unknown_node
 	jint32_t hdr_crc;
 };
 
+/*
+ * Non-standard directory entry type(s), for on-disk use
+ */
+
+#define                JFFS2_DT_FALLTHRU       (DT_WHT + 1)
+
 struct jffs2_raw_dirent
 {
 	jint16_t magic;
-- 
1.6.3.3



From boagenator at gmail.com  Tue Jun 15 19:03:02 2010
From: boagenator at gmail.com (Alex Boag-Munroe)
Date: Wed, 16 Jun 2010 00:03:02 +0100
Subject: ubiattach fails
Message-ID: <AANLkTimAdhNT_WGSk6CwmRNAOjGfWkXv_Oj2I3cSlDKk@mail.gmail.com>

Hey folks, quick question.  I'm playing, or at least trying to play,
with ubifs on my HTC Hero.  Running ubiattach /dev/ubi_ctrl -m 4 gives
the error:

ubiattach: error!: cannot attach mtd4 error 22 (Invalid argument)

I get the following in dmesg:

[  779.384338] UBI: attaching mtd4 to ubi0
[  779.385253] UBI: physical eraseblock size:   131072 bytes (128 KiB)
[  779.385742] UBI: logical eraseblock size:    126976 bytes
[  779.386627] UBI: smallest flash I/O unit:    2048
[  779.387115] UBI: VID header offset:          2048 (aligned 2048)
[  779.387969] UBI: data offset:                4096
[  779.389251] msm_nand_read_oob: unsupported ops->len, 64
[  779.390319] msm_nand_read_oob: unsupported ops->len, 64
[  779.390777] msm_nand_read_oob: unsupported ops->len, 64
[  779.391021] msm_nand_read_oob: unsupported ops->len, 64
[  779.391448] UBI error: ubi_io_read: error -22 while reading 64
bytes from PEB 0:0, read 0 bytes

I would appreciate any help anyone can provide, thank you.

-- 
Alex Boag-Munroe

Lack of planning on your part does not constitute an emergency on mine.


From marek.vasut at gmail.com  Tue Jun 15 19:59:08 2010
From: marek.vasut at gmail.com (Marek Vasut)
Date: Wed, 16 Jun 2010 01:59:08 +0200
Subject: [PATCH] ixp4xx: add support for static flash partitions
In-Reply-To: <20100614161519.GB24877@riccoc20.at.omicron.at>
References: <20100531162434.GA4599@riccoc20.at.omicron.at>
	<1276420566.19028.184.camel@localhost>
	<20100614161519.GB24877@riccoc20.at.omicron.at>
Message-ID: <201006160159.08491.marek.vasut@gmail.com>

Dne Po 14. ?ervna 2010 18:15:19 Richard Cochran napsal(a):
> On Sun, Jun 13, 2010 at 12:16:06PM +0300, Artem Bityutskiy wrote:
> > I could fix your patch up myself, but I do not know the code, so please,
> > re-send a patch against the latest mtd-2.6 tree.
> 
> Okay, here it is again, this time against today's master branch of
> git://git.infradead.org/mtd-2.6.git
> 
> Thanks,
> Richard
> 
> 
> This patch adds support for static flash partitioning from a platform
> device. Also, we clean up some weirdness where statements were separated
> by commas instead of semicolons. While we are at it, fix some minor bad
> white space, too.
> 
> Signed-off-by: Richard Cochran <richard.cochran at omicron.at>
> ---
>  drivers/mtd/maps/ixp4xx.c |   35 +++++++++++++++++++++++++++--------
>  1 files changed, 27 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
> index e0a5e04..1f9fde0 100644
> --- a/drivers/mtd/maps/ixp4xx.c
> +++ b/drivers/mtd/maps/ixp4xx.c
> @@ -118,7 +118,7 @@ static void ixp4xx_copy_from(struct map_info *map, void
> *to, *dest++ = BYTE1(data);
>  		src += 2;
>  		len -= 2;
> -        }
> +	}
> 
>  	if (len > 0)
>  		*dest++ = BYTE0(flash_read16(src));
> @@ -185,6 +185,8 @@ static int ixp4xx_flash_probe(struct platform_device
> *dev) {
>  	struct flash_platform_data *plat = dev->dev.platform_data;
>  	struct ixp4xx_flash_info *info;
> +	const char *part_type = NULL;
> +	int nr_parts = 0;
>  	int err = -1;
> 
>  	if (!plat)
> @@ -218,9 +220,9 @@ static int ixp4xx_flash_probe(struct platform_device
> *dev) */
>  	info->map.bankwidth = 2;
>  	info->map.name = dev_name(&dev->dev);
> -	info->map.read = ixp4xx_read16,
> -	info->map.write = ixp4xx_probe_write16,
> -	info->map.copy_from = ixp4xx_copy_from,
> +	info->map.read = ixp4xx_read16;
> +	info->map.write = ixp4xx_probe_write16;
> +	info->map.copy_from = ixp4xx_copy_from;
> 
>  	info->res = request_mem_region(dev->resource->start,
>  			resource_size(dev->resource),
> @@ -248,11 +250,28 @@ static int ixp4xx_flash_probe(struct platform_device
> *dev) info->mtd->owner = THIS_MODULE;
> 
>  	/* Use the fast version */
> -	info->map.write = ixp4xx_write16,
> +	info->map.write = ixp4xx_write16;
> +
> +#ifdef CONFIG_MTD_PARTITIONS
> +	nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
> +					dev->resource->start);
> +#endif
> +	if (nr_parts > 0) {
> +		part_type = "dynamic";
> +	} else {
> +		info->partitions = plat->parts;
> +		nr_parts = plat->nr_parts;
> +		part_type = "static";
> +	}
> +	if (nr_parts == 0) {
> +		printk(KERN_NOTICE "IXP4xx flash: no partition info "
> +			"available, registering whole flash\n");
> +		err = add_mtd_device(info->mtd);
> +	} else {
> +		printk(KERN_NOTICE "IXP4xx flash: using %s partition "
> +			"definition\n", part_type);
> +		err = add_mtd_partitions(info->mtd, info->partitions, nr_parts);
> 
> -	err = parse_mtd_partitions(info->mtd, probes, &info->partitions,
> dev->resource->start); -	if (err > 0) {
> -		err = add_mtd_partitions(info->mtd, info->partitions, err);
>  		if(err)
>  			printk(KERN_ERR "Could not parse partitions\n");
>  	}


Maybe send the formating fixes in a separate patch. Thanks


From dedekind1 at gmail.com  Wed Jun 16 02:22:37 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 16 Jun 2010 09:22:37 +0300
Subject: [PATCH] UBI: fix delete compatible internal volume scan
In-Reply-To: <1274595417.8881.36.camel@localhost.localdomain>
References: <AANLkTimuYmRDCZCkoB9YHifngCwjp9_B2ucFQ1seaiM9@mail.gmail.com>
	<1274595417.8881.36.camel@localhost.localdomain>
Message-ID: <1276669357.19028.280.camel@localhost>

On Sun, 2010-05-23 at 09:16 +0300, Artem Bityutskiy wrote:
> On Tue, 2010-05-18 at 23:10 +0530, Brijesh Singh wrote:
> > This patch resolves a possible bug. Scan is adding delete compatible
> > blocks to both corr list and used list.
> > It should return after adding the block to corr list.
> > 
> > Signed-off-by: Brijesh Singh <brijesh.s.singh at gmail.com>
> 
> I'm not sure this patch is enough. I think we should add a 'compat' flag
> to the 'struct ubi_mkvol_req' structure, to make it possible to create
> volumes with different compatibility flags. Then we need to write a test
> and add it to the UBI test-suite at 'mtd-utils/tests/ubi-tests/'.

Ok, that was nonsense. First of all, compatibility flags are applicable
only for internal volumes, and we do not want to allow users creating
internal volumes, even for testing.

Secondly, your patch is right.

Thirdly, even without your patch everything works just fine, because
even though we also add this PEB to the used tree, we'll never ever use
it, so it will not cause problems.

Thus, I'll just apply your patch, thank you.

> Then once we have tested and fixed this, we should merge this and also
> send to the '-stable' trees.

And not need to send it to '-stable'.

> I remember I did give the compat option a test, but probably not that
> good.

They actually seem to work fine.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun 16 02:44:06 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 16 Jun 2010 09:44:06 +0300
Subject: detecting that ubifs switched to ro after problem
In-Reply-To: <AANLkTikt_Y_DPNZP7jKvBrHgD230po4lqJWBE5vRVl20@mail.gmail.com>
References: <AANLkTik2mO4lpL5QA1kzMf4zp-Prd-SdhSNLVcHB9isl@mail.gmail.com>
	<1276422454.19028.209.camel@localhost>
	<AANLkTikt_Y_DPNZP7jKvBrHgD230po4lqJWBE5vRVl20@mail.gmail.com>
Message-ID: <1276670646.19028.283.camel@localhost>

On Mon, 2010-06-14 at 11:15 -0400, Jon Ringle wrote:
> On Sun, Jun 13, 2010 at 5:47 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Fri, 2010-06-11 at 22:46 -0400, Jon Ringle wrote:
> >> Hi,
> >>
> >> I'd like to be able to somehow detect that ubifs has taken the action
> >> of switching from rw to ro due to some error detected in the ubifs
> >> filesystem. If I can detect this then maybe I can do something about
> >> it, such as copying the ubifs contents to a .tar.bz2 in /tmp,
> >> mkfs.ubifs, and restore .tar.bz2 back again.
> >>
> >> Is there a way I can do this?
> >
> > I think with 2fde99cb55fb9d9b88180512a5e8a5d939d27fec you can check for
> > R/O state from /proc/mounts. Also, you can use something like inotify to
> > watch /proc/mounts changes and react if UBIFS became r/o.
> 
> Any possibility of having that merged into
> git://git.infradead.org/~dedekind/ubifs-v2.6.32.git?

It is there since 2010-05-23, you just need to use "git pull" from time
to time :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From brijesh.s.singh at gmail.com  Wed Jun 16 04:52:12 2010
From: brijesh.s.singh at gmail.com (Brijesh Singh)
Date: Wed, 16 Jun 2010 14:22:12 +0530
Subject: [PATCH] UBI: fix delete compatible internal volume scan
In-Reply-To: <1276669357.19028.280.camel@localhost>
References: <AANLkTimuYmRDCZCkoB9YHifngCwjp9_B2ucFQ1seaiM9@mail.gmail.com>
	<1274595417.8881.36.camel@localhost.localdomain>
	<1276669357.19028.280.camel@localhost>
Message-ID: <AANLkTim9DUdPdqqpXqrH9n7RqXrb9VTyc3AT36Kk6Wf7@mail.gmail.com>

Hi,
On Wed, Jun 16, 2010 at 11:52 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Sun, 2010-05-23 at 09:16 +0300, Artem Bityutskiy wrote:
>> On Tue, 2010-05-18 at 23:10 +0530, Brijesh Singh wrote:
>> > This patch resolves a possible bug. Scan is adding delete compatible
>> > blocks to both corr list and used list.
>> > It should return after adding the block to corr list.
>> >
>> > Signed-off-by: Brijesh Singh <brijesh.s.singh at gmail.com>
>>
>> I'm not sure this patch is enough. I think we should add a 'compat' flag
>> to the 'struct ubi_mkvol_req' structure, to make it possible to create
>> volumes with different compatibility flags. Then we need to write a test
>> and add it to the UBI test-suite at 'mtd-utils/tests/ubi-tests/'.
>
> Ok, that was nonsense. First of all, compatibility flags are applicable
> only for internal volumes, and we do not want to allow users creating
> internal volumes, even for testing.
>
> Secondly, your patch is right.
>
> Thirdly, even without your patch everything works just fine, because
> even though we also add this PEB to the used tree, we'll never ever use
> it, so it will not cause problems.
I created internal delete compatible volume. My assumption was that
this volume gets deleted in older versions of UBI. So, UBI should not
add this PEB to used tree. Please correct me if my assumption is
wrong.
I have one question: Should UBI ensure that delete compatible volume
is deleted? If yes, should these erase blocks be deleted at
initialization (not lazily)?
> Thus, I'll just apply your patch, thank you.
>
>> Then once we have tested and fixed this, we should merge this and also
>> send to the '-stable' trees.
>
> And not need to send it to '-stable'.
>
>> I remember I did give the compat option a test, but probably not that
>> good.
>
> They actually seem to work fine.

Thanks,
Brijesh


From dedekind1 at gmail.com  Wed Jun 16 05:30:29 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 16 Jun 2010 12:30:29 +0300
Subject: [PATCH] UBI: fix delete compatible internal volume scan
In-Reply-To: <AANLkTim9DUdPdqqpXqrH9n7RqXrb9VTyc3AT36Kk6Wf7@mail.gmail.com>
References: <AANLkTimuYmRDCZCkoB9YHifngCwjp9_B2ucFQ1seaiM9@mail.gmail.com>
	<1274595417.8881.36.camel@localhost.localdomain>
	<1276669357.19028.280.camel@localhost>
	<AANLkTim9DUdPdqqpXqrH9n7RqXrb9VTyc3AT36Kk6Wf7@mail.gmail.com>
Message-ID: <1276680629.19028.329.camel@localhost>

On Wed, 2010-06-16 at 14:22 +0530, Brijesh Singh wrote:
> > Thirdly, even without your patch everything works just fine, because
> > even though we also add this PEB to the used tree, we'll never ever use
> > it, so it will not cause problems.
> I created internal delete compatible volume. My assumption was that
> this volume gets deleted in older versions of UBI.

Right.

>  So, UBI should not
> add this PEB to used tree.

As I described, it should not indeed. But adding it to the used tree
does not cause problems in practice. I mean that old UBI binaries which
do not contain your patch will also work just fine.

I've pushed your patch to the UBI tree.

>  Please correct me if my assumption is
> wrong.

It is right.

> I have one question: Should UBI ensure that delete compatible volume
> is deleted? If yes, should these erase blocks be deleted at
> initialization (not lazily)?

Hmm, good question. I think it is fine to delete them asynchronously. I
do not see any problems with that. If we have, e.g., a power cut before
they are actually erased, we will erased them next time we mount.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From norris at broadcom.com  Wed Jun 16 12:42:07 2010
From: norris at broadcom.com (Brian Norris)
Date: Wed, 16 Jun 2010 09:42:07 -0700
Subject: [PATCH] mtd-utils: formatting of odd-sized OOB in nanddump
Message-ID: <1276706527-4563-1-git-send-email-norris@broadcom.com>

Changed OOB output formatting in nanddump.
Most NAND devices have OOB regions with multiples of 16 bytes.
With newer devices, a 218-byte OOB does not split nicely into
lines of 16 bytes. This patch fixes the formatting, allowing a
last line of 10 bytes instead of 16.

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 nanddump.c |   31 ++++++++++++++++++++++---------
 1 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index e44ab36..190a653 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -381,15 +381,28 @@ int main(int argc, char * const argv[])
 			}
 
 			for (i = 0; i < meminfo.oobsize; i += 16) {
-				sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
-						"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-						oobbuf[i], oobbuf[i+1], oobbuf[i+2],
-						oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
-						oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
-						oobbuf[i+9], oobbuf[i+10], oobbuf[i+11],
-						oobbuf[i+12], oobbuf[i+13], oobbuf[i+14],
-						oobbuf[i+15]);
-				write(ofd, pretty_buf, 60);
+				/* Check if we have a full 16 bytes left in the OOB */
+				if (i+15 < meminfo.oobsize) {
+					/* Print 16 bytes */
+					sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
+							"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+							oobbuf[i], oobbuf[i+1], oobbuf[i+2],
+							oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
+							oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
+							oobbuf[i+9], oobbuf[i+10], oobbuf[i+11],
+							oobbuf[i+12], oobbuf[i+13], oobbuf[i+14],
+							oobbuf[i+15]);
+					write(ofd, pretty_buf, 60);
+				} else {
+					/* Print 10 bytes */
+					sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
+							"%02x %02x %02x %02x\n",
+							oobbuf[i], oobbuf[i+1], oobbuf[i+2],
+							oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
+							oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
+							oobbuf[i+9]);
+					write(ofd, pretty_buf, 42);
+				}
 			}
 		} else
 			write(ofd, oobbuf, meminfo.oobsize);
-- 
1.7.1




From stanley.miao at windriver.com  Thu Jun 17 00:10:06 2010
From: stanley.miao at windriver.com (stanley.miao)
Date: Thu, 17 Jun 2010 12:10:06 +0800
Subject: Fix mtd-utils bugs
In-Reply-To: <1276424048.19028.217.camel@localhost>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	
	<1276422718.19028.211.camel@localhost>
	<1276424048.19028.217.camel@localhost>
Message-ID: <4C19A01E.6060607@windriver.com>

Artem Bityutskiy wrote:
> On Sun, 2010-06-13 at 12:51 +0300, Artem Bityutskiy wrote:
>   
>> On Fri, 2010-06-11 at 17:36 +0800, Stanley.Miao wrote:
>>     
>>> Re-send them because I didn't give a email subject in last version.
>>>
>>> The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
>>> is not enough for many big NAND chips. Therefore, this structure is replaced
>>> by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
>>> Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
>>>
>>> Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
>>> keep compatible with the old linux kernel, a linux version detection function
>>> is added.
>>>
>>> YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
>>> "forcejffs2", "forceyaffs" anymore. Now clean them up. 
>>>       
>> Please, make sure your submissions have proper version. I have limited
>> amount of time and do not want to spend it figuring out which patch is
>> the latest. Use the best kernel practices and apply prefix your stuff
>> with [PATCHv3] or something like that.
>>
>> Could you please re-submit your latest version?
>>     
>
> Also, it is nice to put a short changelog, but I can live without it.
>   

Sorry for the delayed reply. I was on vacation in the past 6 days.

I will re-send them soon.

Stanley.



From mware at elphinstone.net  Thu Jun 17 00:44:19 2010
From: mware at elphinstone.net (Mark Ware)
Date: Thu, 17 Jun 2010 14:44:19 +1000
Subject: [RFC/PATCH] doc2000: Fix uninitialized variable in
	doc_ecc_decode()
In-Reply-To: <4BFDCEC3.7070601@elphinstone.net>
References: <4BFDCEC3.7070601@elphinstone.net>
Message-ID: <4C19A823.4080804@elphinstone.net>

No comments?
I know DOC2000 is pretty old now, but somebody must remember them!

Regards,
Mark

Mark Ware wrote:
> The variable 'syn' was being used uninitialized.  Also
> fixed incorrect use of syn[] vs s[].
> 
> Tested on powerpc board with 64MB DOC2000.
> ---
> 
> I am porting from a 2.4.18 kernel to 2.6.32, and I saw random media header
> mismatches causing a failure to detect the DOC device partitions.  Tracing
> through, I saw this variable being used uninitialized and I suspect
> incorrectly also.
> 
> I do not really understand how the ecc/syndrome code works, so I do not
> know if this patch is the correct solution, but it did make my problem
> go away...
> 
> CC: Thomas Gleixner as I believe he may have written this function initially.
> 
>  drivers/mtd/nand/diskonchip.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
> index a5bf9ff..7da2321 100644
> --- a/drivers/mtd/nand/diskonchip.c
> +++ b/drivers/mtd/nand/diskonchip.c
> @@ -145,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
>  	uint8_t parity;
>  	uint16_t ds[4], s[5], tmp, errval[8], syn[4];
>  
> +	memset(syn, 0, sizeof(syn));
>  	/* Convert the ecc bytes into words */
>  	ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8);
>  	ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6);
> @@ -168,9 +169,9 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
>  			s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
>  	}
>  
> -	/* Calc s[i] = s[i] / alpha^(v + i) */
> +	/* Calc syn[i] = s[i] / alpha^(v + i) */
>  	for (i = 0; i < NROOTS; i++) {
> -		if (syn[i])
> +		if (s[i])
>  			syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
>  	}
>  	/* Call the decoder library */



From barnes.leo at gmail.com  Thu Jun 17 04:42:29 2010
From: barnes.leo at gmail.com (Leo Barnes)
Date: Thu, 17 Jun 2010 10:42:29 +0200
Subject: UBIFS performance measurements
Message-ID: <AANLkTikVqjmLiBDq6bdtTcHKwZxlxAVCBg3-WGXMzbmF@mail.gmail.com>

Hello!

I have a few questions regarding sequential write speeds in UBIFS and
how to measure them.

1. If I want to measure sequential (and later on, random) write speed
in UBIFS, should I do the writes using the O_SYNC flag or just do a
fsync after writing? I worry that using the O_SYNC flag will reduce
the write performance since the file system is meant to be used
asynchronously and I want my measurements to be as close as possible
to how the file system is meant to be used.

2. If I do not use O_SYNC, will using fflush and fsync guarantee that
all written data has been written to flash when they return?

3. If I do not use fflush before fsync, I assume, after reading the
FAQ, that I am not guaranteed that all data has been written. Is this
correct?

4. Does the commandline sync command do the same thing as fflush/fsync?

5. Does sync/fsync force garbage collection? In other words, if I have
deleted lots of files from an UBIFS volume, will I be ensured that
their corresponding eraseblocks will actually be freed if I do a sync?

Any other tips regarding how to perform valid write performance
measurements on UBIFS would be welcome.

Best regards,
//Leo


From fabio.giovagnini at aurion-tech.com  Thu Jun 17 07:23:38 2010
From: fabio.giovagnini at aurion-tech.com (Fabio Giovagnini)
Date: Thu, 17 Jun 2010 13:23:38 +0200
Subject: SST39VF6402B kernel compatibility
Message-ID: <201006171323.38152.fabio.giovagnini@aurion-tech.com>

Hi All,
I'm building Linux version 2.6.35-rc2+ for sh27203.
Is this release full compliant with SST39VF6402B or do I need more over 
patches?

Thanks a lot


-- 
Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Cell. +39.335.83.50.919
www.aurion-tech.com


From glecerf at gmail.com  Thu Jun 17 07:39:31 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Thu, 17 Jun 2010 13:39:31 +0200
Subject: SST39VF6402B kernel compatibility
In-Reply-To: <201006171323.38152.fabio.giovagnini@aurion-tech.com>
References: <201006171323.38152.fabio.giovagnini@aurion-tech.com>
Message-ID: <AANLkTimdCaGHZUxhpp7nfuqrTRmT4rVzEGvVRLYyWzKQ@mail.gmail.com>

2010/6/17 Fabio Giovagnini <fabio.giovagnini at aurion-tech.com>:
> Hi All,

Hi Fabio,

> I'm building Linux version 2.6.35-rc2+ for sh27203.
> Is this release full compliant with SST39VF6402B or do I need more over
> patches?

This should be OK (
http://git.infradead.org/mtd-2.6.git/commitdiff/5a0563f0ad0c9864b735e9ae23e55f7fa9c73bf5
)
But I would appreciate your confirmation on this, just to be sure.

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From fabio.giovagnini at aurion-tech.com  Thu Jun 17 08:49:28 2010
From: fabio.giovagnini at aurion-tech.com (Fabio Giovagnini)
Date: Thu, 17 Jun 2010 14:49:28 +0200
Subject: SST39VF6402B kernel compatibility
In-Reply-To: <AANLkTimdCaGHZUxhpp7nfuqrTRmT4rVzEGvVRLYyWzKQ@mail.gmail.com>
References: <201006171323.38152.fabio.giovagnini@aurion-tech.com>
	<AANLkTimdCaGHZUxhpp7nfuqrTRmT4rVzEGvVRLYyWzKQ@mail.gmail.com>
Message-ID: <201006171449.28404.fabio.giovagnini@aurion-tech.com>

I checked out your link, and I compared with the original one of my kernel 
tree.
The file is the same.

Thanks a lot


In data gioved? 17 giugno 2010 13:39:31, Guillaume LECERF ha scritto:
: > 2010/6/17 Fabio Giovagnini <fabio.giovagnini at aurion-tech.com>:
> > Hi All,
> 
> Hi Fabio,
> 
> > I'm building Linux version 2.6.35-rc2+ for sh27203.
> > Is this release full compliant with SST39VF6402B or do I need more over
> > patches?
> 
> This should be OK (
> http://git.infradead.org/mtd-2.6.git/commitdiff/5a0563f0ad0c9864b735e9ae23e
> 55f7fa9c73bf5 )
> But I would appreciate your confirmation on this, just to be sure.
> 

-- 
Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Cell. +39.335.83.50.919
www.aurion-tech.com


From eric at eukrea.com  Thu Jun 17 14:59:04 2010
From: eric at eukrea.com (=?utf-8?q?Eric=20B=C3=A9nard?=)
Date: Thu, 17 Jun 2010 20:59:04 +0200
Subject: [PATCH v2] mtd/mxc_nand: don't call mtd->{suspend,resume} explicitly
In-Reply-To: <1276801147-4103-3-git-send-email-eric@eukrea.com>
References: <1276801147-4103-1-git-send-email-eric@eukrea.com>
	<1276801147-4103-2-git-send-email-eric@eukrea.com>
	<1276801147-4103-3-git-send-email-eric@eukrea.com>
Message-ID: <1276801147-4103-4-git-send-email-eric@eukrea.com>

The mtd layer is responsible to call mtd->{suspend,resume}.  Doing it
again in the driver is wrong and results in a warning:

	nand_resume called for a chip which is not in suspended state

at resume time.  Removing the calls from the resume and suspend
functions makes them empty allowing them to be deleted completely.

Signed-off-by: Eric B?nard <eric at eukrea.com>
Acked-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-mtd at lists.infradead.org
---
v2:
	fix commit log (writen by Uwe Kleine-K?nig)

 drivers/mtd/nand/mxc_nand.c |   44 +------------------------------------------
 1 files changed, 1 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 0d76b16..ad19dc6 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -873,53 +873,11 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
-	int ret = 0;
-
-	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
-
-	ret = mtd->suspend(mtd);
-
-	/*
-	 * nand_suspend locks the device for exclusive access, so
-	 * the clock must already be off.
-	 */
-	BUG_ON(!ret && host->clk_act);
-
-	return ret;
-}
-
-static int mxcnd_resume(struct platform_device *pdev)
-{
-	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
-	int ret = 0;
-
-	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
-
-	mtd->resume(mtd);
-
-	return ret;
-}
-
-#else
-# define mxcnd_suspend   NULL
-# define mxcnd_resume    NULL
-#endif				/* CONFIG_PM */
-
 static struct platform_driver mxcnd_driver = {
 	.driver = {
 		   .name = DRIVER_NAME,
-		   },
+	},
 	.remove = __devexit_p(mxcnd_remove),
-	.suspend = mxcnd_suspend,
-	.resume = mxcnd_resume,
 };
 
 static int __init mxc_nd_init(void)
-- 
1.6.3.3



From norris at broadcom.com  Thu Jun 17 15:35:11 2010
From: norris at broadcom.com (Brian Norris)
Date: Thu, 17 Jun 2010 12:35:11 -0700
Subject: [PATCH] mtd: nand: nand_ids.c: added two entries for NAND chips
Message-ID: <1276803311-6361-1-git-send-email-norris@broadcom.com>

Included the basic size info for NAND chips with ID of 0xAD or
0xD7. The first can be found in Hynix HY27SF161G2M, while the
second can be found in Micron MT29F64G08 and the Samsung K9LBG08U0D
(among others). Also, some 64 Gbit (or larger) chips identify as
0xD7 because they contain multiple smaller 32 Gbit chips. I
assume it's safe to classify these under the 32 Gbit listing.

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 drivers/mtd/nand/nand_ids.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 89907ed..a04b891 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -85,6 +85,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 128MiB 3,3V 8-bit",	0xD1, 0, 128, 0, LP_OPTIONS},
 	{"NAND 128MiB 1,8V 16-bit",	0xB1, 0, 128, 0, LP_OPTIONS16},
 	{"NAND 128MiB 3,3V 16-bit",	0xC1, 0, 128, 0, LP_OPTIONS16},
+	{"NAND 128MiB 1,8V 16-bit",     0xAD, 0, 128, 0, LP_OPTIONS16},
 
 	/* 2 Gigabit */
 	{"NAND 256MiB 1,8V 8-bit",	0xAA, 0, 256, 0, LP_OPTIONS},
@@ -110,6 +111,9 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, LP_OPTIONS16},
 	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, LP_OPTIONS16},
 
+	/* 32 Gigabit */
+	{"NAND 4GiB 3,3V 8-bit",	0xD7, 0, 4096, 0, LP_OPTIONS16},
+
 	/*
 	 * Renesas AND 1 Gigabit. Those chips do not support extended id and
 	 * have a strange page/block layout !  The chosen minimum erasesize is
-- 
1.7.1




From haojian.zhuang at gmail.com  Fri Jun 18 01:32:42 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:32:42 +0800
Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
Message-ID: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com>


From haojian.zhuang at gmail.com  Fri Jun 18 01:33:29 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:33:29 +0800
Subject: [PATCH 0/25] update pxa3xx nand
Message-ID: <AANLkTimrYNN0JYnWw5peeuVYkiOF7Yz5Hn5oIBXdlg9m@mail.gmail.com>

This patch series are used to upgrade NAND controller of PXA series.

1. Support multi chips.
2. Support new NAND controller in PXA series.
3. Support MLC NAND.
4. Support BCH ECC.
5. Optimize flash definition.


From haojian.zhuang at gmail.com  Fri Jun 18 01:33:38 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:33:38 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce read id 
	times
Message-ID: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com>


From leiwen at marvell.com  Wed Jun  2 09:50:25 2010
From: leiwen at marvell.com (Lei Wen)
Date: Wed, 2 Jun 2010 21:50:25 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce
Message-ID: <mailman.5.1276839262.27306.linux-mtd@lists.infradead.org>

read id times

We certainly don't need to send read id command times by times, since
we already know what the id is after the first read id...

So create a common timing which could ensure it would successfully read id
out all supported chip. Then follow the build-in table to reconfigure
the timing.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   72 ++++++++++++++++-----------------------
 1 files changed, 30 insertions(+), 42 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 013e075..f939083 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -226,23 +226,26 @@ const static struct pxa3xx_nand_cmdset cmdset = {
 };

 static struct pxa3xx_nand_timing __devinitdata timing[] = {
+	/* common timing used to detect flash id */
+	{ 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
 	/* Samsung NAND series */
-	{ 10,  0, 20, 40, 30, 40, 11123, 110, 10, },
+	{ 10,  0, 20,  40, 30,  40, 11123, 110, 10, },
 	/* Micron NAND series */
-	{ 10, 25, 15, 25, 15, 30, 25000,  60, 10, },
+	{ 10, 25, 15,  25, 15,  30, 25000,  60, 10, },
 	/* ST NAND series */
-	{ 10, 35, 15, 25, 15, 25, 25000,  60, 10, },
+	{ 10, 35, 15,  25, 15,  25, 25000,  60, 10, },
 };

 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-	{ 0x46ec,  32,  512, 16, 16, 4096, &timing[0], },
-	{ 0xdaec,  64, 2048,  8,  8, 2048, &timing[0], },
-	{ 0xd7ec, 128, 4096,  8,  8, 8192, &timing[0], },
-	{ 0xa12c,  64, 2048,  8,  8, 1024, &timing[1], },
-	{ 0xb12c,  64, 2048, 16, 16, 1024, &timing[1], },
-	{ 0xdc2c,  64, 2048,  8,  8, 4096, &timing[1], },
-	{ 0xcc2c,  64, 2048, 16, 16, 4096, &timing[1], },
-	{ 0xba20,  64, 2048, 16, 16, 2048, &timing[2], },
+	{      0,   0,    0,  0,  0,    0, &timing[0], },
+	{ 0x46ec,  32,  512, 16, 16, 4096, &timing[1], },
+	{ 0xdaec,  64, 2048,  8,  8, 2048, &timing[1], },
+	{ 0xd7ec, 128, 4096,  8,  8, 8192, &timing[1], },
+	{ 0xa12c,  64, 2048,  8,  8, 1024, &timing[2], },
+	{ 0xb12c,  64, 2048, 16, 16, 1024, &timing[2], },
+	{ 0xdc2c,  64, 2048,  8,  8, 4096, &timing[2], },
+	{ 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2], },
+	{ 0xba20,  64, 2048, 16, 16, 2048, &timing[3], },
 };

 #define NDTR0_tCH(c)	(min((c), 7) << 19)
@@ -859,12 +862,6 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	uint32_t ndcr = 0x00000FFF; /* disable all interrupts */

-	if (f->page_size != 2048 && f->page_size != 512)
-		return -EINVAL;
-
-	if (f->flash_width != 16 && f->flash_width != 8)
-		return -EINVAL;
-
 	/* calculate flash information */
 	info->oob_size = (f->page_size == 2048) ? 64 : 16;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
@@ -976,36 +973,27 @@ static int pxa3xx_nand_detect_flash(struct
pxa3xx_nand_info *info,
 		if (pxa3xx_nand_detect_config(info) == 0)
 			return 0;

-	for (i = 0; i<pdata->num_flash; ++i) {
-		f = pdata->flash + i;
-
-		if (pxa3xx_nand_config_flash(info, f))
-			continue;
-
-		if (__readid(info, &id))
-			continue;
-
-		if (id == f->chip_id)
-			return 0;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
-
-		f = &builtin_flash_types[i];
-
-		if (pxa3xx_nand_config_flash(info, f))
-			continue;
-
-		if (__readid(info, &id))
-			continue;
-
-		if (id == f->chip_id)
+	f = &builtin_flash_types[0];
+	pxa3xx_nand_config_flash(info, f);
+	if (__readid(info, &id))
+		goto fail_detect;
+
+	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
+		if (i < pdata->num_flash)
+			f = pdata->flash + i;
+		else
+			f = &builtin_flash_types[i - pdata->num_flash + 1];
+		if (f->chip_id == id) {
+			dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
+			pxa3xx_nand_config_flash(info, f);
 			return 0;
+		}
 	}

 	dev_warn(&info->pdev->dev,
-		 "failed to detect configured nand flash; found %04x instead of\n",
+			"failed to detect configured nand flash; found %04x instead of\n",
 		 id);
+fail_detect:
 	return -ENODEV;
 }

-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:33:46 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:33:46 +0800
Subject: [PATCH 03/25] pxa3xx_nand: remove the flash info in driver structure
Message-ID: <AANLkTimbCSM3Kk-Mq3MhRDyhHAaERR-dXhtuplauB3ki@mail.gmail.com>


From leiwen at marvell.com  Wed Jun  2 09:54:33 2010
From: leiwen at marvell.com (Lei Wen)
Date: Wed, 2 Jun 2010 21:54:33 +0800
Subject: [PATCH 03/25] pxa3xx_nand: remove the flash info in driver structure
Message-ID: <mailman.6.1276839272.27306.linux-mtd@lists.infradead.org>

After probe, all info already transfer to driver structure.
There is no need to keep the original flash info.
So that we could safely free the flash info in memory, which may grows
larger when more flash is suported.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   70 ++++++++++++++++++++++++++--------------
 1 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index f939083..291610a 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -152,7 +152,6 @@ struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;

 	struct platform_device	 *pdev;
-	const struct pxa3xx_nand_flash *flash_info;

 	struct clk		*clk;
 	void __iomem		*mmio_base;
@@ -166,6 +165,7 @@ struct pxa3xx_nand_info {
 	int			drcmr_cmd;

 	unsigned char		*data_buff;
+	unsigned char		*oob_buff;
 	dma_addr_t 		data_buff_phys;
 	size_t			data_buff_size;
 	int 			data_dma_ch;
@@ -184,7 +184,8 @@ struct pxa3xx_nand_info {
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */

-	size_t			data_size;	/* data size in FIFO */
+	unsigned int		page_size;	/* page size of attached chip */
+	unsigned int		data_size;	/* data size in FIFO */
 	int 			retcode;
 	struct completion 	cmd_complete;

@@ -193,6 +194,10 @@ struct pxa3xx_nand_info {
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;

+	/* timing calcuted from setting */
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
+
 	/* calculated from pxa3xx_nand_flash data */
 	size_t		oob_size;
 	size_t		read_id_bytes;
@@ -293,6 +298,8 @@ static void pxa3xx_nand_set_timing(struct
pxa3xx_nand_info *info,
 		NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
 		NDTR1_tAR(ns2cycle(t->tAR, nand_clk));

+	info->ndtr0cs0 = ndtr0;
+	info->ndtr1cs0 = ndtr1;
 	nand_writel(info, NDTR0CS0, ndtr0);
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
@@ -316,22 +323,29 @@ static int wait_for_event(struct
pxa3xx_nand_info *info, uint32_t event)
 	return -ETIMEDOUT;
 }

-static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
-			uint16_t cmd, int column, int page_addr)
+static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-	const struct pxa3xx_nand_flash *f = info->flash_info;
+	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;

-	/* calculate data size */
-	switch (f->page_size) {
-	case 2048:
-		info->data_size = (info->use_ecc) ? 2088 : 2112;
-		break;
-	case 512:
-		info->data_size = (info->use_ecc) ? 520 : 528;
-		break;
-	default:
-		return -EINVAL;
+	info->data_size = info->page_size;
+	if (!oob_enable) {
+		info->oob_size = 0;
+		return;
 	}
+	switch (info->page_size) {
+		case 2048:
+			info->oob_size = (info->use_ecc) ? 40 : 64;
+			break;
+		case 512:
+			info->oob_size = (info->use_ecc) ? 8 : 16;
+			break;
+	}
+}
+
+static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
+		uint16_t cmd, int column, int page_addr)
+{
+	pxa3xx_set_datasize(info);

 	/* generate values for NDCBx registers */
 	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
@@ -442,6 +456,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 	case STATE_PIO_WRITING:
 		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
 				DIV_ROUND_UP(info->data_size, 4));
+		if (info->oob_size > 0)
+			__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
+					DIV_ROUND_UP(info->oob_size, 4));

 		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);

@@ -454,6 +471,10 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 	case STATE_PIO_READING:
 		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
 				DIV_ROUND_UP(info->data_size, 4));
+		if (info->oob_size > 0)
+			__raw_readsl(info->mmio_base + NDDB, info->oob_buff,
+					DIV_ROUND_UP(info->oob_size, 4));
+
 		break;
 	default:
 		printk(KERN_ERR "%s: invalid state %d\n", __func__,
@@ -468,7 +489,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
 {
 	struct pxa_dma_desc *desc = info->data_desc;
-	int dma_len = ALIGN(info->data_size, 32);
+	int dma_len = ALIGN(info->data_size + info->oob_size, 32);

 	desc->ddadr = DDADR_STOP;
 	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
@@ -863,6 +884,8 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	uint32_t ndcr = 0x00000FFF; /* disable all interrupts */

 	/* calculate flash information */
+	info->page_size = f->page_size;
+	info->oob_buff = info->data_buff + f->page_size;
 	info->oob_size = (f->page_size == 2048) ? 64 : 16;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

@@ -887,7 +910,6 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	info->reg_ndcr = ndcr;

 	pxa3xx_nand_set_timing(info, f->timing);
-	info->flash_info = f;
 	return 0;
 }

@@ -923,7 +945,6 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
 	default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8;

 	/* set info fields needed to __readid */
-	info->flash_info = &default_flash;
 	info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;

@@ -1056,10 +1077,9 @@ static struct nand_ecclayout hw_largepage_ecclayout = {
 static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 				 struct pxa3xx_nand_info *info)
 {
-	const struct pxa3xx_nand_flash *f = info->flash_info;
 	struct nand_chip *this = &info->nand_chip;

-	this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
+	this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;

 	this->waitfunc		= pxa3xx_nand_waitfunc;
 	this->select_chip	= pxa3xx_nand_select_chip;
@@ -1075,9 +1095,9 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
 	this->ecc.calculate	= pxa3xx_nand_ecc_calculate;
 	this->ecc.correct	= pxa3xx_nand_ecc_correct;
-	this->ecc.size		= f->page_size;
+	this->ecc.size		= info->page_size;

-	if (f->page_size == 2048)
+	if (info->page_size == 2048)
 		this->ecc.layout = &hw_largepage_ecclayout;
 	else
 		this->ecc.layout = &hw_smallpage_ecclayout;
@@ -1085,7 +1105,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->chip_delay = 25;
 }

-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
@@ -1284,9 +1304,11 @@ static int pxa3xx_nand_resume(struct
platform_device *pdev)
 	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
 	struct pxa3xx_nand_info *info = mtd->priv;

+	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
 	clk_enable(info->clk);

-	return pxa3xx_nand_config_flash(info, info->flash_info);
+	return 0;
 }
 #else
 #define pxa3xx_nand_suspend	NULL
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:33:54 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:33:54 +0800
Subject: [PATCH 04/25] pxa3xx_nand: make scan procedure more clear
Message-ID: <AANLkTiliVtvBEmJPgkha444k9XGB_dNm0lQ9TCif8AAj@mail.gmail.com>


From haojian.zhuang at gmail.com  Fri Jun 18 01:34:02 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:34:02 +0800
Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
Message-ID: <AANLkTimvhEWIDupsj3Ty8vB9ualwU9RsaIxa0CDgWgYQ@mail.gmail.com>


From haojian.zhuang at gmail.com  Fri Jun 18 01:34:11 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:34:11 +0800
Subject: [PATCH 06/25] pxa3xx_nand: unify prepare command
Message-ID: <AANLkTilhattkx7AiyG-R4zbWSZ3-qkPIM6VhyFW4lk4D@mail.gmail.com>


From haojian.zhuang at gmail.com  Fri Jun 18 01:34:27 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:34:27 +0800
Subject: [PATCH 08/25] mmp: add nand support to pxa168
Message-ID: <AANLkTinxMQjZIG4G1d9WVOiUX8-zHjTuTc1eRuInDRGW@mail.gmail.com>


From haojian.zhuang at gmail.com  Fri Jun 18 01:34:18 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:34:18 +0800
Subject: [PATCH 07/25] pxa3xx_nand: mtd scan id process could be defined by 
	driver itself
Message-ID: <AANLkTilY1gnS_jwZ_xPKhchTLR5cWj7FEla1V76OuMVK@mail.gmail.com>


From leiwen at marvell.com  Wed Jun  2 09:55:51 2010
From: leiwen at marvell.com (Lei Wen)
Date: Wed, 2 Jun 2010 21:55:51 +0800
Subject: [PATCH 07/25] pxa3xx_nand: mtd scan id process could be
Message-ID: <mailman.16.1276839397.27306.linux-mtd@lists.infradead.org>

defined by driver itself

Different NAND driver may require its unique detection. For pxa3xx_nand,
it use its self id database to get the necessary info.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  255 ++++++++++++++++++++++++++--------------
 1 files changed, 165 insertions(+), 90 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 9ab292b..481cb25 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -158,6 +158,7 @@ struct pxa3xx_nand_flash {
 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;

+	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;

 	struct clk		*clk;
@@ -261,6 +262,8 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 	{ 0xba20,  64, 2048, 16, 16, 2048, &timing[3], },
 };

+static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -899,40 +902,6 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
 	return 0;
 }

-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
-				    const struct pxa3xx_nand_platform_data *pdata)
-{
-	const struct pxa3xx_nand_flash *f;
-	uint32_t id = -1;
-	int i;
-
-	if (pdata->keep_config)
-		if (pxa3xx_nand_detect_config(info) == 0)
-			return 0;
-
-	f = &builtin_flash_types[0];
-	pxa3xx_nand_config_flash(info, f);
-	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-
-	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
-		if (i < pdata->num_flash)
-			f = pdata->flash + i;
-		else
-			f = &builtin_flash_types[i - pdata->num_flash + 1];
-		if (f->chip_id == id) {
-			dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
-			pxa3xx_nand_config_flash(info, f);
-			return 0;
-		}
-	}
-
-	dev_warn(&info->pdev->dev,
-			"failed to detect configured nand flash; found %04x instead of\n",
-		 id);
-	return -ENODEV;
-}
-
 /* the maximum possible buffer size for large page with OOB data
  * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
  * data buffer and the DMA descriptor
@@ -974,56 +943,153 @@ static int pxa3xx_nand_init_buff(struct
pxa3xx_nand_info *info)
 	return 0;
 }

-static struct nand_ecclayout hw_smallpage_ecclayout = {
-	.eccbytes = 6,
-	.eccpos = {8, 9, 10, 11, 12, 13 },
-	.oobfree = { {2, 6} }
-};
+static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, uint8_t *buf, int page)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;

-static struct nand_ecclayout hw_largepage_ecclayout = {
-	.eccbytes = 24,
-	.eccpos = {
-		40, 41, 42, 43, 44, 45, 46, 47,
-		48, 49, 50, 51, 52, 53, 54, 55,
-		56, 57, 58, 59, 60, 61, 62, 63},
-	.oobfree = { {2, 38} }
-};
+	chip->read_buf(mtd, buf, mtd->writesize);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (info->retcode == ERR_SBERR) {
+		switch (info->use_ecc) {
+			case 1:
+				mtd->ecc_stats.corrected ++;
+				break;
+
+			case 0:
+			default:
+				break;
+		}
+	}
+	else if (info->retcode == ERR_DBERR) {
+		int buf_blank;
+
+		buf_blank = is_buf_blank(buf, mtd->writesize);
+		if (!buf_blank)
+			mtd->ecc_stats.failed++;
+	}
+
+	return 0;
+}
+
+static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, const uint8_t *buf)
+{
+	chip->write_buf(mtd, buf, mtd->writesize);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	/* Send commands to erase a block */
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+}

-static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
-				 struct pxa3xx_nand_info *info)
+static int __devinit pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct nand_chip *this = &info->nand_chip;
-
-	this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
-
-	this->waitfunc		= pxa3xx_nand_waitfunc;
-	this->select_chip	= pxa3xx_nand_select_chip;
-	this->dev_ready		= pxa3xx_nand_dev_ready;
-	this->cmdfunc		= pxa3xx_nand_cmdfunc;
-	this->read_word		= pxa3xx_nand_read_word;
-	this->read_byte		= pxa3xx_nand_read_byte;
-	this->read_buf		= pxa3xx_nand_read_buf;
-	this->write_buf		= pxa3xx_nand_write_buf;
-	this->verify_buf	= pxa3xx_nand_verify_buf;
-
-	this->ecc.mode		= NAND_ECC_HW;
-	this->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
-	this->ecc.calculate	= pxa3xx_nand_ecc_calculate;
-	this->ecc.correct	= pxa3xx_nand_ecc_correct;
-	this->ecc.size		= info->page_size;
-
-	if (info->page_size == 2048)
-		this->ecc.layout = &hw_largepage_ecclayout;
+	struct mtd_info *mtd = info->mtd;
+	struct nand_chip *chip = mtd->priv;
+
+	/* use the common timing to make a try */
+	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+	if (info->state & STATE_READY)
+		return 1;
 	else
-		this->ecc.layout = &hw_smallpage_ecclayout;
+		return 0;
+}
+
+static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	const struct pxa3xx_nand_flash *f = NULL;
+	struct nand_chip *chip = mtd->priv;
+	uint32_t id = -1;
+	int i, ret;
+
+	if (pdata->keep_config)
+		if (pxa3xx_nand_detect_config(info) == 0)
+			return 0;
+
+	ret = pxa3xx_nand_sensing(info);
+	if (!ret) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_INFO "There is no nand chip on cs 0!\n");

-	this->chip_delay = 25;
+		return -EINVAL;
+	}
+
+	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));
+	if (id != 0)
+		printk(KERN_INFO "Detect a flash id %x\n", id);
+	else {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
+
+		return -EINVAL;
+	}
+
+	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
+		if (i < pdata->num_flash)
+			f = pdata->flash + i;
+		else
+			f = &builtin_flash_types[i - pdata->num_flash + 1];
+
+		/* find the chip in default list */
+		if (f->chip_id == id) {
+			pxa3xx_nand_config_flash(info, f);
+			mtd->writesize = f->page_size;
+			mtd->writesize_shift = ffs(mtd->writesize) - 1;
+			mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
+			mtd->oobsize = mtd->writesize / 32;
+			mtd->erasesize = f->page_size * f->page_per_block;
+			mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
+			mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
+
+			mtd->name = mtd_names[0];
+			break;
+		}
+	}
+
+	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+
+		return -EINVAL;
+	}
+
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = f->page_size;
+	chip->chipsize 	= (uint64_t)f->num_blocks * f->page_per_block
+				* f->page_size;
+	mtd->size = chip->chipsize;
+
+	/* Calculate the address shift from the page size */
+	chip->page_shift = ffs(mtd->writesize) - 1;
+	chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
+	chip->numchips = 1;
+	chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
+
+	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
+	chip->options |= NAND_NO_AUTOINCR;
+	chip->options |= NAND_NO_READRDY;
+	chip->options |= NAND_USE_FLASH_BBT;
+
+	return nand_scan_tail(mtd);
 }

 static int alloc_nand_resource(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct pxa3xx_nand_info *info;
+	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct resource *r;
 	int ret, irq;
@@ -1036,12 +1102,31 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	}

 	info = (struct pxa3xx_nand_info *)(&mtd[1]);
+	chip = (struct nand_chip *)(&mtd[1]);
 	info->pdev = pdev;
-
-	mtd->priv = info;
 	info->mtd = mtd;
+	mtd->priv = info;
 	mtd->owner = THIS_MODULE;

+	chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+	chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+	chip->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
+	chip->ecc.calculate	= pxa3xx_nand_ecc_calculate;
+	chip->ecc.correct	= pxa3xx_nand_ecc_correct;
+	chip->controller        = &info->controller;
+	chip->waitfunc		= pxa3xx_nand_waitfunc;
+	chip->select_chip	= pxa3xx_nand_select_chip;
+	chip->dev_ready		= pxa3xx_nand_dev_ready;
+	chip->cmdfunc		= pxa3xx_nand_cmdfunc;
+	chip->read_word		= pxa3xx_nand_read_word;
+	chip->read_byte		= pxa3xx_nand_read_byte;
+	chip->read_buf		= pxa3xx_nand_read_buf;
+	chip->write_buf		= pxa3xx_nand_write_buf;
+	chip->verify_buf	= pxa3xx_nand_verify_buf;
+	chip->erase_cmd		= pxa3xx_nand_erase_cmd;
+
+	spin_lock_init(&chip->controller->lock);
+	init_waitqueue_head(&chip->controller->wq);
 	info->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
@@ -1109,21 +1194,11 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		goto fail_free_buf;
 	}

-	ret = pxa3xx_nand_detect_flash(info, pdata);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to detect flash\n");
-		ret = -ENODEV;
-		goto fail_free_irq;
-	}
-
-	pxa3xx_nand_init_mtd(mtd, info);
 	platform_set_drvdata(pdev, info);
-
 	return 0;

-fail_free_irq:
-	free_irq(irq, info);
 fail_free_buf:
+	free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
 		dma_free_coherent(&pdev->dev, info->data_buff_size,
@@ -1191,7 +1266,7 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 		return ret;

 	info = platform_get_drvdata(pdev);
-	if (nand_scan(info->mtd, 1)) {
+	if (pxa3xx_nand_scan(info->mtd)) {
 		dev_err(&pdev->dev, "failed to scan nand\n");
 		pxa3xx_nand_remove(pdev);
 		return -ENODEV;
@@ -1202,10 +1277,10 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 		struct mtd_partition *parts;
 		int nr_parts;

-		nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
+		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);

 		if (nr_parts)
-			return add_mtd_partitions(mtd, parts, nr_parts);
+			return add_mtd_partitions(info->mtd, parts, nr_parts);
 	}

 	return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:34:37 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:34:37 +0800
Subject: [PATCH 09/25] pxa3xx_nand: clean the keep configure code
Message-ID: <AANLkTikXQcGjwEpxo-ahNcleAyasY-UfA0Czw8jxGIcQ@mail.gmail.com>


From leiwen at marvell.com  Wed Jun  2 22:26:21 2010
From: leiwen at marvell.com (Lei Wen)
Date: Thu, 3 Jun 2010 10:26:21 +0800
Subject: [PATCH 09/25] pxa3xx_nand: clean the keep configure code
Message-ID: <mailman.17.1276839399.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  165 ++++++++++------------------------------
 1 files changed, 42 insertions(+), 123 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 481cb25..8628fc1 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -146,6 +146,7 @@ struct pxa3xx_nand_cmdset {
 };

 struct pxa3xx_nand_flash {
+	char		*name;
 	uint32_t	chip_id;
 	uint16_t	page_per_block; /* Pages per block (PG_PER_BLK) */
 	uint16_t 	page_size;	/* Page size in bytes (PAGE_SZ) */
@@ -219,13 +220,6 @@ static int use_dma = 1;
 module_param(use_dma, bool, 0444);
 MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");

-/*
- * Default NAND flash controller configuration setup by the
- * bootloader. This configuration is used only when pdata->keep_config is set
- */
-static struct pxa3xx_nand_timing default_timing;
-static struct pxa3xx_nand_flash default_flash;
-
 const static struct pxa3xx_nand_cmdset cmdset = {
 	.read1		= 0x3000,
 	.read2		= 0x0050,
@@ -251,15 +245,15 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 };

 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-	{      0,   0,    0,  0,  0,    0, &timing[0], },
-	{ 0x46ec,  32,  512, 16, 16, 4096, &timing[1], },
-	{ 0xdaec,  64, 2048,  8,  8, 2048, &timing[1], },
-	{ 0xd7ec, 128, 4096,  8,  8, 8192, &timing[1], },
-	{ 0xa12c,  64, 2048,  8,  8, 1024, &timing[2], },
-	{ 0xb12c,  64, 2048, 16, 16, 1024, &timing[2], },
-	{ 0xdc2c,  64, 2048,  8,  8, 4096, &timing[2], },
-	{ 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2], },
-	{ 0xba20,  64, 2048, 16, 16, 2048, &timing[3], },
+	{ 		0,	0,   0,    0,  0,  0,    0, &timing[0], },
+	{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1], },
+	{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1], },
+	{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1], },
+	{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2], },
+	{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2], },
+	{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2], },
+	{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2], },
+	{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3], },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
@@ -275,23 +269,8 @@ static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
 #define NDTR1_tWHR(c)	(min((c), 15) << 4)
 #define NDTR1_tAR(c)	(min((c), 15) << 0)

-#define tCH_NDTR0(r)	(((r) >> 19) & 0x7)
-#define tCS_NDTR0(r)	(((r) >> 16) & 0x7)
-#define tWH_NDTR0(r)	(((r) >> 11) & 0x7)
-#define tWP_NDTR0(r)	(((r) >> 8) & 0x7)
-#define tRH_NDTR0(r)	(((r) >> 3) & 0x7)
-#define tRP_NDTR0(r)	(((r) >> 0) & 0x7)
-
-#define tR_NDTR1(r)	(((r) >> 16) & 0xffff)
-#define tWHR_NDTR1(r)	(((r) >> 4) & 0xf)
-#define tAR_NDTR1(r)	(((r) >> 0) & 0xf)
-
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)(((ns) * (clk / 1000000) / 1000) - 1)
-
-/* convert nand flash controller clock cycles to nano-seconds */
-#define cycle2ns(c, clk)	((((c) + 1) * 1000000 + clk / 500) / (clk / 1000))
-
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
 {
@@ -803,7 +782,6 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,

 	/* calculate flash information */
 	info->page_size = f->page_size;
-	info->oob_buff = info->data_buff + f->page_size;
 	info->oob_size = (f->page_size == 2048) ? 64 : 16;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

@@ -831,73 +809,14 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	return 0;
 }

-static void pxa3xx_nand_detect_timing(struct pxa3xx_nand_info *info,
-				      struct pxa3xx_nand_timing *t)
-{
-	unsigned long nand_clk = clk_get_rate(info->clk);
-	uint32_t ndtr0 = nand_readl(info, NDTR0CS0);
-	uint32_t ndtr1 = nand_readl(info, NDTR1CS0);
-
-	t->tCH = cycle2ns(tCH_NDTR0(ndtr0), nand_clk);
-	t->tCS = cycle2ns(tCS_NDTR0(ndtr0), nand_clk);
-	t->tWH = cycle2ns(tWH_NDTR0(ndtr0), nand_clk);
-	t->tWP = cycle2ns(tWP_NDTR0(ndtr0), nand_clk);
-	t->tRH = cycle2ns(tRH_NDTR0(ndtr0), nand_clk);
-	t->tRP = cycle2ns(tRP_NDTR0(ndtr0), nand_clk);
-
-	t->tR = cycle2ns(tR_NDTR1(ndtr1), nand_clk);
-	t->tWHR = cycle2ns(tWHR_NDTR1(ndtr1), nand_clk);
-	t->tAR = cycle2ns(tAR_NDTR1(ndtr1), nand_clk);
-}
-
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
 	uint32_t ndcr = nand_readl(info, NDCR);
-	struct nand_flash_dev *type = NULL;
-	uint32_t id = -1;
-	int i;
-
-	default_flash.page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
-	default_flash.page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8;
-	default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8;
-
-	/* set info fields needed to __readid */
-	info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2;
-	info->reg_ndcr = ndcr;
-
-
-	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-
-	/* Lookup the flash id */
-	id = (id >> 8) & 0xff;		/* device id is byte 2 */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if (id == nand_flash_ids[i].id) {
-			type =  &nand_flash_ids[i];
-			break;
-		}
-	}
-
-	if (!type)
-		return -ENODEV;
-
-	/* fill the missing flash information */
-	i = __ffs(default_flash.page_per_block * default_flash.page_size);
-	default_flash.num_blocks = type->chipsize << (20 - i);
-
-	info->oob_size = (default_flash.page_size == 2048) ? 64 : 16;
-
-	/* calculate addressing information */
-	info->col_addr_cycles = (default_flash.page_size == 2048) ? 2 : 1;
-
-	if (default_flash.num_blocks * default_flash.page_per_block > 65536)
-		info->row_addr_cycles = 3;
-	else
-		info->row_addr_cycles = 2;

-	pxa3xx_nand_detect_timing(info, &default_timing);
-	memcpy(&default_flash.timing, &default_timing, sizeof(default_timing));
+	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
+	info->reg_ndcr = ndcr & ~(NDCR_INT_MASK | NDCR_ECC_EN | NDCR_DMA_EN
| NDCR_ND_RUN);
+	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);

 	return 0;
 }
@@ -1006,14 +925,17 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 	struct pxa3xx_nand_info *info = mtd->priv;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
 	uint32_t id = -1;
+	uint64_t chipsize;
 	int i, ret;

-	if (pdata->keep_config)
+	if (pdata->keep_config) {
 		if (pxa3xx_nand_detect_config(info) == 0)
-			return 0;
+			goto KEEP_CONFIG;
+	}

 	ret = pxa3xx_nand_sensing(info);
 	if (!ret) {
@@ -1043,22 +965,11 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 			f = &builtin_flash_types[i - pdata->num_flash + 1];

 		/* find the chip in default list */
-		if (f->chip_id == id) {
-			pxa3xx_nand_config_flash(info, f);
-			mtd->writesize = f->page_size;
-			mtd->writesize_shift = ffs(mtd->writesize) - 1;
-			mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
-			mtd->oobsize = mtd->writesize / 32;
-			mtd->erasesize = f->page_size * f->page_per_block;
-			mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
-			mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
-
-			mtd->name = mtd_names[0];
+		if (f->chip_id == id)
 			break;
-		}
 	}

-	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
 		kfree(mtd);
 		info->mtd = NULL;
 		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
@@ -1066,20 +977,28 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 		return -EINVAL;
 	}

+	pxa3xx_nand_config_flash(info, f);
+	pxa3xx_flash_ids[0].name = f->name;
+	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+	pxa3xx_flash_ids[0].pagesize = f->page_size;
+	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
+	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
+	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
+	pxa3xx_flash_ids[0].options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
+KEEP_CONFIG:
+	if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+		return -ENODEV;
+	/* calculate addressing information */
+	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	info->oob_buff = info->data_buff + mtd->writesize;
+	if ((mtd->size >> chip->page_shift) > 65536)
+		info->row_addr_cycles = 3;
+	else
+		info->row_addr_cycles = 2;
+	mtd->name = mtd_names[0];
 	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = f->page_size;
-	chip->chipsize 	= (uint64_t)f->num_blocks * f->page_per_block
-				* f->page_size;
-	mtd->size = chip->chipsize;
-
-	/* Calculate the address shift from the page size */
-	chip->page_shift = ffs(mtd->writesize) - 1;
-	chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
-	chip->numchips = 1;
-	chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
-
-	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
-	chip->options |= NAND_NO_AUTOINCR;
+	chip->ecc.size = mtd->writesize;
+	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16: 0;
 	chip->options |= NAND_NO_READRDY;
 	chip->options |= NAND_USE_FLASH_BBT;

-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:34:46 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:34:46 +0800
Subject: [PATCH 10/25] pxa3xx_nand: add two chip select
Message-ID: <AANLkTilhoWJIMoRD2p7rnLx2s9TUlLjfDyTvN2S-fJHx@mail.gmail.com>


From leiwen at marvell.com  Sun Jun  6 09:58:12 2010
From: leiwen at marvell.com (Lei Wen)
Date: Sun, 6 Jun 2010 21:58:12 +0800
Subject: [PATCH 10/25] pxa3xx_nand: add two chip select
Message-ID: <mailman.19.1276839410.27306.linux-mtd@lists.infradead.org>

Current pxa3xx_nand controller has two chip select which
both be workable. This patch enable this feature.

Update platform driver to support this feature.

Another notice should be taken that:
When you want to use this feature, you should not enable the
keep configuration feature, for two chip select could be
attached with different nand chip. The different page size
and timing requirement make the keep configuration impossible.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c                 |    4 +-
 arch/arm/mach-mmp/avengers_lite.c            |   50 ++
 arch/arm/mach-pxa/cm-x300.c                  |    4 +-
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    4 +-
 arch/arm/mach-pxa/littleton.c                |    4 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    8 +-
 arch/arm/mach-pxa/raumfeld.c                 |    4 +-
 arch/arm/mach-pxa/zylonite.c                 |    4 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    5 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  770 +++++++++++++-------------
 10 files changed, 462 insertions(+), 395 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 244655d..81ad58d 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -126,8 +126,8 @@ static struct mtd_partition aspenite_nand_partitions[] = {

 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= aspenite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(aspenite_nand_partitions),
+	.parts[0]	= aspenite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(aspenite_nand_partitions),
 };

 static struct i2c_board_info aspenite_i2c_info[] __initdata = {
diff --git a/arch/arm/mach-mmp/avengers_lite.c
b/arch/arm/mach-mmp/avengers_lite.c
index 8c3fa5d..a828b1c 100644
--- a/arch/arm/mach-mmp/avengers_lite.c
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -32,12 +32,62 @@ static unsigned long
avengers_lite_pin_config_V16F[] __initdata = {
 	GPIO89_UART2_RXD,
 };

+static struct mtd_partition avengers_nand_partitions_0[] = {
+	{
+		.name		= "bootloader",
+		.offset		= 0,
+		.size		= SZ_1M,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= (SZ_2M + SZ_1M),
+	}, {
+		.name		= "mass0",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_48M,
+	}
+};
+
+static struct mtd_partition avengers_nand_partitions_1[] = {
+	{
+		.name		= "reserved",
+		.offset		= 0,
+		.size		= SZ_2M,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "filesystem",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_512M,
+	}, {
+		.name		= "mass1",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_16M,
+	}, {
+		.name		= "mass2",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_256M,
+	}
+};
+
+static struct pxa3xx_nand_platform_data avengers_nand_info;
+static void __init avengers_init_flash(void)
+{
+	avengers_nand_info.parts[0] = avengers_nand_partitions_0;
+	avengers_nand_info.nr_parts[0] = ARRAY_SIZE(avengers_nand_partitions_0);
+	avengers_nand_info.parts[1] = avengers_nand_partitions_1;
+	avengers_nand_info.nr_parts[1] = ARRAY_SIZE(avengers_nand_partitions_1);
+	avengers_nand_info.enable_arbiter = 1;
+	pxa168_add_nand(&avengers_nand_info);
+}
+
 static void __init avengers_lite_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(avengers_lite_pin_config_V16F));

 	/* on-chip devices */
 	pxa168_add_uart(2);
+	avengers_init_flash();
 }

 MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index fdda6be..ce1f6d3 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -419,8 +419,8 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= cm_x300_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(cm_x300_nand_partitions),
+	.parts[0]	= cm_x300_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(cm_x300_nand_partitions),
 };

 static void __init cm_x300_init_nand(void)
diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c
b/arch/arm/mach-pxa/colibri-pxa3xx.c
index 199afa2..b33559c 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -188,8 +188,8 @@ static struct mtd_partition colibri_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= colibri_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(colibri_nand_partitions),
+	.parts[0]	= colibri_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(colibri_nand_partitions),
 };

 void __init colibri_pxa3xx_init_nand(void)
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 9b90461..717cf92 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -325,8 +325,8 @@ static struct mtd_partition littleton_nand_partitions[] = {

 static struct pxa3xx_nand_platform_data littleton_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= littleton_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(littleton_nand_partitions),
+	.parts[0]	= littleton_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(littleton_nand_partitions),
 };

 static void __init littleton_init_nand(void)
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index 462167a..66c2086 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,10 +389,10 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-	.enable_arbiter = 1,
-	.keep_config = 1,
-	.parts = mxm_8x10_nand_partitions,
-	.nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions)
+	.enable_arbiter	= 1,
+	.keep_config	= 1,
+	.parts[0]	= mxm_8x10_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(mxm_8x10_nand_partitions)
 };

 static void __init mxm_8x10_nand_init(void)
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index d4b61b3..df75d4d 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -350,8 +350,8 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= raumfeld_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(raumfeld_nand_partitions),
+	.parts[0]	= raumfeld_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(raumfeld_nand_partitions),
 };

 /**
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index c479cbe..9e5c6cd 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -356,8 +356,8 @@ static struct mtd_partition zylonite_nand_partitions[] = {

 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= zylonite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(zylonite_nand_partitions),
+	.parts[0]	= zylonite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(zylonite_nand_partitions),
 };

 static void __init zylonite_init_nand(void)
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 7e5a28f..56015bd 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -4,6 +4,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>

+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {

 	/* the data flash bus is shared between the Static Memory
@@ -15,8 +16,8 @@ struct pxa3xx_nand_platform_data {
 	/* allow platform code to keep OBM/bootloader defined NFC config */
 	int	keep_config;

-	const struct mtd_partition		*parts;
-	unsigned int				nr_parts;
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];

 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 8628fc1..215677f 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -51,11 +51,9 @@
 #define NDCR_DWIDTH_M		(0x1 << 26)
 #define NDCR_PAGE_SZ		(0x1 << 24)
 #define NDCR_NCSX		(0x1 << 23)
-#define NDCR_STOP_ON_UNCOR	(0x1 << 22)
 #define NDCR_ND_MODE		(0x3 << 21)
-#define NDCR_NAND_MODE   	(0x0)
 #define NDCR_CLR_PG_CNT		(0x1 << 20)
-#define NDCR_CLR_ECC		(0x1 << 19)
+#define NDCR_STOP_ON_UNCOR	(0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK	(0x7 << 16)
 #define NDCR_RD_ID_CNT(x)	(((x) << 16) & NDCR_RD_ID_CNT_MASK)

@@ -98,6 +96,8 @@

 #define nand_readl(info, off)		\
 	__raw_readl((info)->mmio_base + (off))
+#define get_mtd_by_info(info)		\
+	(struct mtd_info *)((void *)info - sizeof(struct mtd_info))

 /* error code and state */
 enum {
@@ -158,62 +158,63 @@ struct pxa3xx_nand_flash {

 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;
+	/* page size of attached chip */
+	uint16_t		page_size;
+	uint8_t			chip_select;
+	uint8_t			use_ecc;

-	struct nand_hw_control	controller;
-	struct platform_device	 *pdev;
+	/* calculated from pxa3xx_nand_flash data */
+	uint8_t			col_addr_cycles;
+	uint8_t			row_addr_cycles;
+	uint8_t			read_id_bytes;
+
+	/* cached register value */
+	uint32_t		reg_ndcr;
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
+
+	void			*nand_data;
+};

+struct pxa3xx_nand {
 	struct clk		*clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
+	struct nand_hw_control	controller;
+	struct completion 	cmd_complete;
+	struct platform_device	 *pdev;

-	unsigned int 		buf_start;
-	unsigned int		buf_count;
-
-	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
-
-	unsigned char		*data_buff;
-	unsigned char		*oob_buff;
-	dma_addr_t 		data_buff_phys;
-	size_t			data_buff_size;
 	int 			data_dma_ch;
-	struct pxa_dma_desc	*data_desc;
+	dma_addr_t 		data_buff_phys;
 	dma_addr_t 		data_desc_addr;
+	struct pxa_dma_desc	*data_desc;

-	uint32_t		reg_ndcr;
-
-	/* saved column/page_addr during CMD_SEQIN */
-	int			seqin_column;
-	int			seqin_page_addr;
+	struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
+	uint32_t		command;
+	uint16_t		data_size;	/* data size in FIFO */
+	uint16_t		oob_size;
+	uint32_t		bad_count;
+	unsigned char		*dma_buff;
+	unsigned char		*data_buff;
+	unsigned char		*oob_buff;
+	uint32_t		buf_start;
+	uint32_t		buf_count;
+	uint8_t			total_cmds;

 	/* relate to the command */
+	uint8_t			chip_select;
 	unsigned int		state;
-
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
-
-	unsigned int		page_size;	/* page size of attached chip */
-	unsigned int		data_size;	/* data size in FIFO */
 	int 			retcode;
-	struct completion 	cmd_complete;

 	/* generated NDCBx register values */
 	uint32_t		ndcb0;
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;
-
-	/* timing calcuted from setting */
-	uint32_t		ndtr0cs0;
-	uint32_t		ndtr1cs0;
-
-	/* calculated from pxa3xx_nand_flash data */
-	size_t		oob_size;
-	size_t		read_id_bytes;
-
-	unsigned int	col_addr_cycles;
-	unsigned int	row_addr_cycles;
 };

 static int use_dma = 1;
@@ -248,6 +249,7 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 	{ 		0,	0,   0,    0,  0,  0,    0, &timing[0], },
 	{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1], },
 	{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1], },
+	{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, 4096, &timing[1], },
 	{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1], },
 	{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2], },
 	{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2], },
@@ -256,7 +258,7 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 	{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3], },
 };

-static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};

 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
@@ -274,9 +276,11 @@ static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
 {
-	unsigned long nand_clk = clk_get_rate(info->clk);
+	struct pxa3xx_nand *nand = info->nand_data;
+	unsigned long nand_clk;
 	uint32_t ndtr0, ndtr1;

+	nand_clk = clk_get_rate(nand->clk);
 	ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
 		NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
 		NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
@@ -290,25 +294,26 @@ static void pxa3xx_nand_set_timing(struct
pxa3xx_nand_info *info,

 	info->ndtr0cs0 = ndtr0;
 	info->ndtr1cs0 = ndtr1;
-	nand_writel(info, NDTR0CS0, ndtr0);
-	nand_writel(info, NDTR1CS0, ndtr1);
+	nand_writel(nand, NDTR0CS0, ndtr0);
+	nand_writel(nand, NDTR1CS0, ndtr1);
 }

 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
+	struct pxa3xx_nand *nand = info->nand_data;
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;

-	info->data_size = info->page_size;
+	nand->data_size = info->page_size;
 	if (!oob_enable) {
-		info->oob_size = 0;
+		nand->oob_size = 0;
 		return;
 	}
 	switch (info->page_size) {
 		case 2048:
-			info->oob_size = (info->use_ecc) ? 40 : 64;
+			nand->oob_size = (nand->use_ecc) ? 40 : 64;
 			break;
 		case 512:
-			info->oob_size = (info->use_ecc) ? 8 : 16;
+			nand->oob_size = (nand->use_ecc) ? 8 : 16;
 			break;
 	}
 }
@@ -319,22 +324,24 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
  * We enable all the interrupt at the same time, and
  * let pxa3xx_nand_irq to handle all logic.
  */
-static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
+static void pxa3xx_nand_start(struct pxa3xx_nand *nand)
 {
+	struct pxa3xx_nand_info *info;
 	uint32_t ndcr;

+	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
-	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
-	ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
+	ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
+	ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
 	ndcr |= NDCR_ND_RUN;

 	/* clear status bits and run */
-	nand_writel(info, NDCR, 0);
-	nand_writel(info, NDSR, NDSR_MASK);
-	nand_writel(info, NDCR, ndcr);
+	nand_writel(nand, NDCR, 0);
+	nand_writel(nand, NDSR, NDSR_MASK);
+	nand_writel(nand, NDCR, ndcr);
 }

-static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
+static void pxa3xx_nand_stop(struct pxa3xx_nand *nand)
 {
 	uint32_t ndcr;
 	int timeout = NAND_STOP_DELAY;
@@ -342,146 +349,149 @@ static void pxa3xx_nand_stop(struct
pxa3xx_nand_info *info)
 	/* wait RUN bit in NDCR become 0 */
 	do {
 		/* clear status bits */
-		nand_writel(info, NDSR, NDSR_MASK);
-		ndcr = nand_readl(info, NDCR);
+		nand_writel(nand, NDSR, NDSR_MASK);
+		ndcr = nand_readl(nand, NDCR);
 		udelay(1);
 	} while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0));

 	if (timeout <= 0) {
 		ndcr &= ~(NDCR_ND_RUN);
-		nand_writel(info, NDCR, ndcr);
+		nand_writel(nand, NDCR, ndcr);
 	}
 }

-static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
+static void enable_int(struct pxa3xx_nand *nand, uint32_t int_mask)
 {
 	uint32_t ndcr;

-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~int_mask);
+	ndcr = nand_readl(nand, NDCR);
+	nand_writel(nand, NDCR, ndcr & ~int_mask);
 }

-static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
+static void disable_int(struct pxa3xx_nand *nand, uint32_t int_mask)
 {
 	uint32_t ndcr;

-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr | int_mask);
+	ndcr = nand_readl(nand, NDCR);
+	nand_writel(nand, NDCR, ndcr | int_mask);
 }

-static void handle_data_pio(struct pxa3xx_nand_info *info)
+static void handle_data_pio(struct pxa3xx_nand *nand)
 {
-	if (info->state & STATE_IS_WRITE) {
-		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
-				DIV_ROUND_UP(info->data_size, 4));
-		if (info->oob_size > 0)
-			__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
-					DIV_ROUND_UP(info->oob_size, 4));
+	if (nand->state & STATE_IS_WRITE) {
+		__raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
+				DIV_ROUND_UP(nand->data_size, 4));
+		if (nand->oob_size > 0)
+			__raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
+					DIV_ROUND_UP(nand->oob_size, 4));

 	}
 	else {
-		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
-				DIV_ROUND_UP(info->data_size, 4));
-		if (info->oob_size > 0)
-			__raw_readsl(info->mmio_base + NDDB, info->oob_buff,
-					DIV_ROUND_UP(info->oob_size, 4));
+		__raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
+				DIV_ROUND_UP(nand->data_size, 4));
+		if (nand->oob_size > 0)
+			__raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
+					DIV_ROUND_UP(nand->oob_size, 4));
 	}
 }

-static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
+static void start_data_dma(struct pxa3xx_nand *nand, int dir_out)
 {
-	struct pxa_dma_desc *desc = info->data_desc;
-	int dma_len = ALIGN(info->data_size + info->oob_size, 32);
+	struct pxa_dma_desc *desc = nand->data_desc;
+	int dma_len = ALIGN(nand->data_size + nand->oob_size, 32);

 	desc->ddadr = DDADR_STOP;
 	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;

 	if (dir_out) {
-		desc->dsadr = info->data_buff_phys;
-		desc->dtadr = info->mmio_phys + NDDB;
+		desc->dsadr = nand->data_buff_phys;
+		desc->dtadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
 	} else {
-		desc->dtadr = info->data_buff_phys;
-		desc->dsadr = info->mmio_phys + NDDB;
+		desc->dtadr = nand->data_buff_phys;
+		desc->dsadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
 	}

-	DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
-	DDADR(info->data_dma_ch) = info->data_desc_addr;
-	DCSR(info->data_dma_ch) |= DCSR_RUN;
+	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
+	DDADR(nand->data_dma_ch) = nand->data_desc_addr;
+	DCSR(nand->data_dma_ch) |= DCSR_RUN;
 }

 static void pxa3xx_nand_data_dma_irq(int channel, void *data)
 {
-	struct pxa3xx_nand_info *info = data;
+	struct pxa3xx_nand *nand = data;
 	uint32_t dcsr;

 	dcsr = DCSR(channel);
 	DCSR(channel) = dcsr;

 	if (dcsr & DCSR_BUSERR) {
-		info->retcode = ERR_DMABUSERR;
+		nand->retcode = ERR_DMABUSERR;
 	}

-	enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+	enable_int(nand, NDCR_INT_MASK);
+	nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }

 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
-	struct pxa3xx_nand_info *info = devid;
-	unsigned int status, is_completed = 0;
+	struct pxa3xx_nand *nand = devid;
+	struct pxa3xx_nand_info *info;
+	unsigned int status, is_completed = 0, cs;
+	unsigned int ready, cmd_done, page_done, badblock_detect;

-	status = nand_readl(info, NDSR);
+	cs		= nand->chip_select;
+	ready           = (cs) ? NDSR_RDY : NDSR_FLASH_RDY;
+	cmd_done        = (cs) ? NDSR_CS1_CMDD : NDSR_CS0_CMDD;
+	page_done       = (cs) ? NDSR_CS1_PAGED : NDSR_CS0_PAGED;
+	badblock_detect = (cs) ? NDSR_CS1_BBD : NDSR_CS0_BBD;
+	info            = nand->info[cs];

+	status = nand_readl(nand, NDSR);
 	if (status & NDSR_DBERR)
-		info->retcode = ERR_DBERR;
+		nand->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
-		info->retcode = ERR_SBERR;
+		nand->retcode = ERR_SBERR;
 	if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {

-		info->state |= STATE_DATA_PROCESSING;
+		nand->state |= STATE_DATA_PROCESSING;
 		/* whether use dma to transfer data */
-		if (info->use_dma) {
-			disable_int(info, NDSR_WRDREQ);
-			start_data_dma(info, 0);
+		if (nand->use_dma) {
+			disable_int(nand, NDCR_INT_MASK);
+			start_data_dma(nand, nand->state & STATE_IS_WRITE);
 			goto NORMAL_IRQ_EXIT;
 		} else
-			handle_data_pio(info);
+			handle_data_pio(nand);

-		info->state |= STATE_DATA_DONE;
+		nand->state |= STATE_DATA_DONE;
 	}
-	if (status & NDSR_CS0_CMDD) {
-		info->state |= STATE_CMD_DONE;
+	if (status & cmd_done) {
+		nand->state |= STATE_CMD_DONE;
 		is_completed = 1;
 	}
-	if (status & NDSR_FLASH_RDY)
-		info->state |= STATE_READY;
-	if (status & NDSR_CS0_PAGED)
-		info->state |= STATE_PAGE_DONE;
+	if (status & ready)
+		nand->state |= STATE_READY;
+	if (status & page_done)
+		nand->state |= STATE_PAGE_DONE;

 	if (status & NDSR_WRCMDREQ) {
-		nand_writel(info, NDSR, NDSR_WRCMDREQ);
+		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
 		status &= ~NDSR_WRCMDREQ;
-		info->state |= STATE_CMD_WAIT_DONE;
-		nand_writel(info, NDCB0, info->ndcb0);
-		nand_writel(info, NDCB0, info->ndcb1);
-		nand_writel(info, NDCB0, info->ndcb2);
+		nand->state |= STATE_CMD_WAIT_DONE;
+		nand_writel(nand, NDCB0, nand->ndcb0);
+		nand_writel(nand, NDCB0, nand->ndcb1);
+		nand_writel(nand, NDCB0, nand->ndcb2);
 	}

 	/* clear NDSR to let the controller exit the IRQ */
-	nand_writel(info, NDSR, status);
+	nand_writel(nand, NDSR, status);
 	if (is_completed)
-		complete(&info->cmd_complete);
+		complete(&nand->cmd_complete);
 NORMAL_IRQ_EXIT:
 	return IRQ_HANDLED;
 }

-static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
-{
-	struct pxa3xx_nand_info *info = mtd->priv;
-	return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0;
-}
-
 static inline int is_buf_blank(uint8_t *buf, size_t len)
 {
 	for (; len > 0; len--)
@@ -490,40 +500,48 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
 	return 1;
 }

-static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+static int prepare_command_pool(struct pxa3xx_nand *nand, int command,
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
 	int addr_cycle, exec_cmd, ndcb0;
-	struct mtd_info *mtd = info->mtd;
+	struct mtd_info *mtd;
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];

-	ndcb0 = 0;
+	mtd = get_mtd_by_info(info);
+	ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;;
 	addr_cycle = 0;
 	exec_cmd = 1;

 	/* reset data and oob column point to handle data */
-	info->buf_start		= 0;
-	info->buf_count		= 0;
-	info->oob_size		= 0;
-	info->use_ecc		= 0;
+	nand->buf_start		= 0;
+	nand->buf_count		= 0;
+	nand->ndcb0		= ndcb0;
+	nand->data_size		= 0;
+	nand->oob_size		= 0;
+	nand->use_ecc		= 0;
+	nand->use_dma		= 0;
+	nand->state		= 0;
+	nand->command		= command;

 	switch (command) {
 	case NAND_CMD_READ0:
 	case NAND_CMD_PAGEPROG:
-		info->use_ecc = 1;
+		nand->use_ecc = info->use_ecc;
 	case NAND_CMD_READOOB:
 		pxa3xx_set_datasize(info);
+		nand->oob_buff = nand->data_buff + nand->data_size;
+		nand->use_dma = use_dma;
 		break;
 	case NAND_CMD_SEQIN:
 		exec_cmd = 0;
 		break;
 	default:
-		info->ndcb1 = 0;
-		info->ndcb2 = 0;
+		nand->ndcb1 = 0;
+		nand->ndcb2 = 0;
 		break;
 	}

-	info->ndcb0 = ndcb0;
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);

@@ -533,16 +551,16 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,

 		cmd  = cmdset.read1;
 		if (command == NAND_CMD_READOOB)
-			info->buf_start = mtd->writesize + column;
+			nand->buf_start = mtd->writesize + column;
 		else
-			info->buf_start = column;
+			nand->buf_start = column;

 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
 		else
-			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| NDCB0_DBC
 					| addr_cycle
 					| cmd;
@@ -550,35 +568,35 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,
 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
-			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);

-			info->ndcb2 = 0;
+			nand->ndcb2 = 0;
 		}
 		else {
-			info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
 					| (column & 0xFFFF);

 			if (page_addr & 0xFF0000)
-				info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
 			else
-				info->ndcb2 = 0;
+				nand->ndcb2 = 0;
 		}

-		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xFF, info->buf_count);
+		nand->buf_count = mtd->writesize + mtd->oobsize;
+		memset(nand->data_buff, 0xFF, nand->buf_count);

 		break;

 	case NAND_CMD_PAGEPROG:
-		if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) {
+		if (is_buf_blank(nand->data_buff, (mtd->writesize + mtd->oobsize))) {
 			exec_cmd = 0;
 			break;
 		}

 		cmd = cmdset.program;
-		info->state |= STATE_IS_WRITE;
-		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+		nand->state |= STATE_IS_WRITE;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
 				| NDCB0_AUTO_RS
 				| NDCB0_ST_ROW_EN
 				| NDCB0_DBC
@@ -588,38 +606,38 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,

 	case NAND_CMD_READID:
 		cmd = cmdset.read_id;
-		info->buf_count = info->read_id_bytes;
-		info->ndcb0 |= NDCB0_CMD_TYPE(3)
+		nand->buf_count = info->read_id_bytes;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

-		info->data_size = 8;
+		nand->data_size = 8;
 		break;

 	case NAND_CMD_STATUS:
 		cmd = cmdset.read_status;
-		info->buf_count = 1;
-		info->ndcb0 |= NDCB0_CMD_TYPE(4)
+		nand->buf_count = 1;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

-		info->data_size = 8;
+		nand->data_size = 8;
 		break;

 	case NAND_CMD_ERASE1:
 		cmd = cmdset.erase;
-		info->ndcb0 |= NDCB0_CMD_TYPE(2)
+		nand->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
 				| NDCB0_DBC
 				| cmd;
-		info->ndcb1 = page_addr;
-		info->ndcb2 = 0;
+		nand->ndcb1 = page_addr;
+		nand->ndcb2 = 0;

 		break;
 	case NAND_CMD_RESET:
 		cmd = cmdset.reset;
-		info->ndcb0 |= NDCB0_CMD_TYPE(5)
+		nand->ndcb0 |= NDCB0_CMD_TYPE(5)
 				| cmd;

 		break;
@@ -630,7 +648,7 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,

 	default:
 		exec_cmd = 0;
-		printk(KERN_ERR "pxa3xx-nand: non-supported command %x\n", command);
+		dev_err(&nand->pdev->dev, "non-supported command %x\n", command);
 		break;
 	}

@@ -641,6 +659,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 				int column, int page_addr)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	int ret, exec_cmd;

 	/* if this is a x16 device ,then convert the input
@@ -650,32 +669,40 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 	if (info->reg_ndcr & NDCR_DWIDTH_M)
 		column /= 2;

-	exec_cmd = prepare_command_pool(info, command, column, page_addr);
+	/* reset timing */
+	if (nand->chip_select != info->chip_select) {
+		nand->chip_select = info->chip_select;
+		nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
+		nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
+	}
+
+	exec_cmd = prepare_command_pool(nand, command, column, page_addr);
 	if (exec_cmd) {
-		init_completion(&info->cmd_complete);
-		info->state |= STATE_CMD_PREPARED;
-		pxa3xx_nand_start(info);
+		init_completion(&nand->cmd_complete);
+		nand->state |= STATE_CMD_PREPARED;
+		pxa3xx_nand_start(nand);

-		ret = wait_for_completion_timeout(&info->cmd_complete,
+		ret = wait_for_completion_timeout(&nand->cmd_complete,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
-			printk(KERN_ERR "Wait time out!!!\n");
+			dev_err(&nand->pdev->dev, "Wait time out!!!\n");
 		}
 		/* Stop State Machine for next command cycle */
-		pxa3xx_nand_stop(info);
-		disable_int(info, NDCR_INT_MASK);
-		info->state &= ~STATE_CMD_PREPARED;
+		pxa3xx_nand_stop(nand);
+		disable_int(nand, NDCR_INT_MASK);
+		nand->state &= ~STATE_CMD_PREPARED;
 	}
 }

 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	char retval = 0xFF;

-	if (info->buf_start < info->buf_count)
+	if (nand->buf_start < nand->buf_count)
 		/* Has just send a new command? */
-		retval = info->data_buff[info->buf_start++];
+		retval = nand->data_buff[nand->buf_start++];

 	return retval;
 }
@@ -683,11 +710,12 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	u16 retval = 0xFFFF;

-	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
-		retval = *((u16 *)(info->data_buff+info->buf_start));
-		info->buf_start += 2;
+	if (!(nand->buf_start & 0x01) && nand->buf_start < nand->buf_count) {
+		retval = *((u16 *)(nand->data_buff+nand->buf_start));
+		nand->buf_start += 2;
 	}
 	return retval;
 }
@@ -695,20 +723,22 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+	struct pxa3xx_nand *nand = info->nand_data;
+	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);

-	memcpy(buf, info->data_buff + info->buf_start, real_len);
-	info->buf_start += real_len;
+	memcpy(buf, nand->data_buff + nand->buf_start, real_len);
+	nand->buf_start += real_len;
 }

 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+	struct pxa3xx_nand *nand = info->nand_data;
+	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);

-	memcpy(info->data_buff + info->buf_start, buf, real_len);
-	info->buf_start += real_len;
+	memcpy(nand->data_buff + nand->buf_start, buf, real_len);
+	nand->buf_start += real_len;
 }

 static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
@@ -725,10 +755,11 @@ static void pxa3xx_nand_select_chip(struct
mtd_info *mtd, int chip)
 static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;

 	/* pxa3xx_nand_send_command has waited for command complete */
 	if (this->state == FL_WRITING || this->state == FL_ERASING) {
-		if (info->retcode == ERR_NONE)
+		if (nand->retcode == ERR_NONE)
 			return 0;
 		else {
 			/*
@@ -742,47 +773,16 @@ static int pxa3xx_nand_waitfunc(struct mtd_info
*mtd, struct nand_chip *this)
 	return 0;
 }

-static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
-{
-	return;
-}
-
-static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd,
-		const uint8_t *dat, uint8_t *ecc_code)
-{
-	return 0;
-}
-
-static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
-		uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
-{
-	struct pxa3xx_nand_info *info = mtd->priv;
-	/*
-	 * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
-	 * consider it as a ecc error which will tell the caller the
-	 * read fail We have distinguish all the errors, but the
-	 * nand_read_ecc only check this function return value
-	 *
-	 * Corrected (single-bit) errors must also be noted.
-	 */
-	if (info->retcode == ERR_SBERR)
-		return 1;
-	else if (info->retcode != ERR_NONE)
-		return -1;
-
-	return 0;
-}
-
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 				    const struct pxa3xx_nand_flash *f)
 {
-	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand *nand = info->nand_data;
+	struct platform_device *pdev = nand->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	uint32_t ndcr = 0;

 	/* calculate flash information */
 	info->page_size = f->page_size;
-	info->oob_size = (f->page_size == 2048) ? 64 : 16;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

 	/* calculate addressing information */
@@ -804,19 +804,24 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */

 	info->reg_ndcr = ndcr;
+	info->use_ecc = 1;

 	pxa3xx_nand_set_timing(info, f->timing);
 	return 0;
 }

-static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_detect_config(struct pxa3xx_nand *nand)
 {
-	uint32_t ndcr = nand_readl(info, NDCR);
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
+	uint32_t ndcr = nand_readl(nand, NDCR);

-	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
+	if (nand->chip_select > 0) {
+		printk(KERN_ERR "We could not detect configure if two cs is supported!!\n");
+		BUG();
+	}
 	info->reg_ndcr = ndcr & ~(NDCR_INT_MASK | NDCR_ECC_EN | NDCR_DMA_EN
| NDCR_ND_RUN);
-	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
+	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);

 	return 0;
 }
@@ -826,62 +831,40 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
  * data buffer and the DMA descriptor
  */
 #define MAX_BUFF_SIZE	PAGE_SIZE
-
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
-	struct platform_device *pdev = info->pdev;
-	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
-
-	if (use_dma == 0) {
-		info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
-		if (info->data_buff == NULL)
-			return -ENOMEM;
-		return 0;
-	}
-
-	info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
-				&info->data_buff_phys, GFP_KERNEL);
-	if (info->data_buff == NULL) {
-		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
-		return -ENOMEM;
-	}
-
-	info->data_buff_size = MAX_BUFF_SIZE;
-	info->data_desc = (void *)info->data_buff + data_desc_offset;
-	info->data_desc_addr = info->data_buff_phys + data_desc_offset;
+	struct pxa3xx_nand *nand;
+	struct mtd_info *mtd;

-	info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
-				pxa3xx_nand_data_dma_irq, info);
-	if (info->data_dma_ch < 0) {
-		dev_err(&pdev->dev, "failed to request data dma\n");
-		dma_free_coherent(&pdev->dev, info->data_buff_size,
-				info->data_buff, info->data_buff_phys);
-		return info->data_dma_ch;
-	}
+	if (!info)
+		return;

-	return 0;
+	nand = info->nand_data;
+	mtd = get_mtd_by_info(info);
+	kfree(mtd);
+	nand->info[cs] = NULL;
 }

 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 		struct nand_chip *chip, uint8_t *buf, int page)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;

 	chip->read_buf(mtd, buf, mtd->writesize);
 	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);

-	if (info->retcode == ERR_SBERR) {
-		switch (info->use_ecc) {
+	if (nand->retcode == ERR_SBERR) {
+		switch (nand->use_ecc) {
 			case 1:
-				mtd->ecc_stats.corrected ++;
+				mtd->ecc_stats.corrected++;
 				break;

 			case 0:
 			default:
 				break;
 		}
-	}
-	else if (info->retcode == ERR_DBERR) {
+	} else if (nand->retcode == ERR_DBERR) {
 		int buf_blank;

 		buf_blank = is_buf_blank(buf, mtd->writesize);
@@ -901,20 +884,19 @@ static void pxa3xx_nand_write_page_hwecc(struct
mtd_info *mtd,

 static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
 {
-	struct nand_chip *chip = mtd->priv;
 	/* Send commands to erase a block */
-	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
 }

-static int __devinit pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+static int __devinit pxa3xx_nand_sensing(struct pxa3xx_nand *nand)
 {
-	struct mtd_info *mtd = info->mtd;
-	struct nand_chip *chip = mtd->priv;
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
+	struct mtd_info *mtd = get_mtd_by_info(info);

 	/* use the common timing to make a try */
 	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
-	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
-	if (info->state & STATE_READY)
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+	if (nand->state & STATE_READY)
 		return 1;
 	else
 		return 0;
@@ -923,7 +905,8 @@ static int __devinit pxa3xx_nand_sensing(struct
pxa3xx_nand_info *info)
 static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand *nand = info->nand_data;
+	struct platform_device *pdev = nand->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
 	const struct pxa3xx_nand_flash *f = NULL;
@@ -933,28 +916,23 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 	int i, ret;

 	if (pdata->keep_config) {
-		if (pxa3xx_nand_detect_config(info) == 0)
+		if (pxa3xx_nand_detect_config(nand) == 0)
 			goto KEEP_CONFIG;
 	}

-	ret = pxa3xx_nand_sensing(info);
+	ret = pxa3xx_nand_sensing(nand);
 	if (!ret) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_INFO "There is no nand chip on cs 0!\n");
-
+		free_cs_resource(info, nand->chip_select);
 		return -EINVAL;
 	}

 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
+	id = *((uint16_t *)(nand->data_buff));
 	if (id != 0)
-		printk(KERN_INFO "Detect a flash id %x\n", id);
+		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id);
 	else {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
-
+		dev_warn(&nand->pdev->dev, "Read out ID 0, potential timing set wrong!!\n");
+		free_cs_resource(info, nand->chip_select);
 		return -EINVAL;
 	}

@@ -970,10 +948,8 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 	}

 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
-
+		dev_err(&nand->pdev->dev, "ERROR!! flash not defined!!!\n");
+		free_cs_resource(info, nand->chip_select);
 		return -EINVAL;
 	}

@@ -990,15 +966,15 @@ KEEP_CONFIG:
 		return -ENODEV;
 	/* calculate addressing information */
 	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
-	info->oob_buff = info->data_buff + mtd->writesize;
 	if ((mtd->size >> chip->page_shift) > 65536)
 		info->row_addr_cycles = 3;
 	else
 		info->row_addr_cycles = 2;
-	mtd->name = mtd_names[0];
+	info->page_size = mtd->writesize;
+	mtd->name = mtd_names[nand->chip_select];
 	chip->ecc.mode = NAND_ECC_HW;
 	chip->ecc.size = mtd->writesize;
-	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16: 0;
+	chip->options |= (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16: 0;
 	chip->options |= NAND_NO_READRDY;
 	chip->options |= NAND_USE_FLASH_BBT;

@@ -1010,49 +986,25 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	struct pxa3xx_nand_info *info;
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
+	struct pxa3xx_nand *nand;
 	struct resource *r;
-	int ret, irq;
+	int ret, irq, cs;
+	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);

-	mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
-			GFP_KERNEL);
-	if (!mtd) {
+	nand = kzalloc(sizeof(struct pxa3xx_nand), GFP_KERNEL);
+	if (!nand) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
 		return -ENOMEM;
 	}

-	info = (struct pxa3xx_nand_info *)(&mtd[1]);
-	chip = (struct nand_chip *)(&mtd[1]);
-	info->pdev = pdev;
-	info->mtd = mtd;
-	mtd->priv = info;
-	mtd->owner = THIS_MODULE;
-
-	chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
-	chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
-	chip->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
-	chip->ecc.calculate	= pxa3xx_nand_ecc_calculate;
-	chip->ecc.correct	= pxa3xx_nand_ecc_correct;
-	chip->controller        = &info->controller;
-	chip->waitfunc		= pxa3xx_nand_waitfunc;
-	chip->select_chip	= pxa3xx_nand_select_chip;
-	chip->dev_ready		= pxa3xx_nand_dev_ready;
-	chip->cmdfunc		= pxa3xx_nand_cmdfunc;
-	chip->read_word		= pxa3xx_nand_read_word;
-	chip->read_byte		= pxa3xx_nand_read_byte;
-	chip->read_buf		= pxa3xx_nand_read_buf;
-	chip->write_buf		= pxa3xx_nand_write_buf;
-	chip->verify_buf	= pxa3xx_nand_verify_buf;
-	chip->erase_cmd		= pxa3xx_nand_erase_cmd;
-
-	spin_lock_init(&chip->controller->lock);
-	init_waitqueue_head(&chip->controller->wq);
-	info->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(info->clk)) {
+	nand->pdev = pdev;
+	nand->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(nand->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
-		ret = PTR_ERR(info->clk);
-		goto fail_free_mtd;
+		ret = PTR_ERR(nand->clk);
+		goto fail_alloc;
 	}
-	clk_enable(info->clk);
+	clk_enable(nand->clk);

 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (r == NULL) {
@@ -1060,7 +1012,7 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		ret = -ENXIO;
 		goto fail_put_clk;
 	}
-	info->drcmr_dat = r->start;
+	nand->drcmr_dat = r->start;

 	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
 	if (r == NULL) {
@@ -1068,14 +1020,7 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		ret = -ENXIO;
 		goto fail_put_clk;
 	}
-	info->drcmr_cmd = r->start;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no IRQ resource defined\n");
-		ret = -ENXIO;
-		goto fail_put_clk;
-	}
+	nand->drcmr_cmd = r->start;

 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
@@ -1091,80 +1036,142 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		goto fail_put_clk;
 	}

-	info->mmio_base = ioremap(r->start, resource_size(r));
-	if (info->mmio_base == NULL) {
+	nand->mmio_base = ioremap(r->start, resource_size(r));
+	if (nand->mmio_base == NULL) {
 		dev_err(&pdev->dev, "ioremap() failed\n");
 		ret = -ENODEV;
 		goto fail_free_res;
 	}
-	info->mmio_phys = r->start;
-
-	ret = pxa3xx_nand_init_buff(info);
-	if (ret)
-		goto fail_free_io;
+	nand->mmio_phys = r->start;

 	/* initialize all interrupts to be disabled */
-	disable_int(info, NDSR_MASK);
+	disable_int(nand, NDSR_MASK);
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ resource defined\n");
+		ret = -ENXIO;
+		goto fail_put_clk;
+	}

 	ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED,
-			  pdev->name, info);
+			  pdev->name, nand);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
+		ret = -ENXIO;
+		goto fail_free_irq;
+	}
+
+	platform_set_drvdata(pdev, nand);
+	spin_lock_init(&nand->controller.lock);
+	init_waitqueue_head(&nand->controller.wq);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		mtd = kzalloc(sizeof(struct mtd_info)
+				+ sizeof(struct pxa3xx_nand_info),
+				GFP_KERNEL);
+		if (!mtd) {
+			dev_err(&pdev->dev, "failed to allocate memory\n");
+			ret = -ENOMEM;
+			goto fail_free_irq;
+		}
+
+		info = (struct pxa3xx_nand_info *)(&mtd[1]);
+		info->nand_data = nand;
+		info->chip_select = cs;
+		mtd->priv = info;
+		mtd->owner = THIS_MODULE;
+		nand->info[cs] = info;
+
+		chip = (struct nand_chip *)(&mtd[1]);
+		chip->controller        = &nand->controller;
+		chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+		chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+		chip->waitfunc		= pxa3xx_nand_waitfunc;
+		chip->select_chip	= pxa3xx_nand_select_chip;
+		chip->cmdfunc		= pxa3xx_nand_cmdfunc;
+		chip->read_word		= pxa3xx_nand_read_word;
+		chip->read_byte		= pxa3xx_nand_read_byte;
+		chip->read_buf		= pxa3xx_nand_read_buf;
+		chip->write_buf		= pxa3xx_nand_write_buf;
+		chip->verify_buf	= pxa3xx_nand_verify_buf;
+		chip->erase_cmd		= pxa3xx_nand_erase_cmd;
+	}
+
+	if (use_dma == 0) {
+		nand->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+		if (nand->data_buff == NULL) {
+			ret = -ENOMEM;
+			goto fail_free_buf;
+		}
+		goto success_exit;
+	}
+
+	nand->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
+			&nand->data_buff_phys, GFP_KERNEL);
+	if (nand->data_buff == NULL) {
+		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
+		ret = -ENOMEM;
 		goto fail_free_buf;
 	}

-	platform_set_drvdata(pdev, info);
+	nand->data_desc = (void *)nand->data_buff + data_desc_offset;
+	nand->data_desc_addr = nand->data_buff_phys + data_desc_offset;
+	nand->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
+			pxa3xx_nand_data_dma_irq, nand);
+	if (nand->data_dma_ch < 0) {
+		dev_err(&pdev->dev, "failed to request data dma\n");
+		ret = -ENXIO;
+		goto fail_free_buf;
+	}
+success_exit:
 	return 0;

 fail_free_buf:
-	free_irq(irq, info);
-	if (use_dma) {
-		pxa_free_dma(info->data_dma_ch);
-		dma_free_coherent(&pdev->dev, info->data_buff_size,
-			info->data_buff, info->data_buff_phys);
-	} else
-		kfree(info->data_buff);
-fail_free_io:
-	iounmap(info->mmio_base);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		info = nand->info[cs];
+		free_cs_resource(info, cs);
+	}
+fail_free_irq:
+	free_irq(irq, nand);
+	iounmap(nand->mmio_base);
 fail_free_res:
 	release_mem_region(r->start, resource_size(r));
 fail_put_clk:
-	clk_disable(info->clk);
-	clk_put(info->clk);
-fail_free_mtd:
-	kfree(mtd);
+	clk_disable(nand->clk);
+	clk_put(nand->clk);
+fail_alloc:
+	kfree(nand);
 	return ret;
 }

 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand *nand = platform_get_drvdata(pdev);
+	struct pxa3xx_nand_info *info;
+	struct mtd_info *mtd;
 	struct resource *r;
-	int irq;
+	int irq, cs;

 	platform_set_drvdata(pdev, NULL);

-	del_mtd_device(mtd);
-	del_mtd_partitions(mtd);
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0)
-		free_irq(irq, info);
-	if (use_dma) {
-		pxa_free_dma(info->data_dma_ch);
-		dma_free_writecombine(&pdev->dev, info->data_buff_size,
-				info->data_buff, info->data_buff_phys);
-	} else
-		kfree(info->data_buff);
-
-	iounmap(info->mmio_base);
+		free_irq(irq, nand);
+
+	iounmap(nand->mmio_base);
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(r->start, resource_size(r));
-
-	clk_disable(info->clk);
-	clk_put(info->clk);
-
-	kfree(mtd);
+	clk_disable(nand->clk);
+	clk_put(nand->clk);
+
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		info = nand->info[cs];
+		if (!info)
+			continue;
+		mtd = get_mtd_by_info(info);
+		del_mtd_partitions(mtd);
+		del_mtd_device(mtd);
+		free_cs_resource(info, cs);
+	}
 	return 0;
 }

@@ -1172,7 +1179,11 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
-	int ret;
+	struct pxa3xx_nand *nand;
+	struct mtd_info *mtd;
+	static const char *probes[] = { "cmdlinepart", NULL };
+	struct mtd_partition *parts;
+	int nr_parts, ret, cs, probe_success = 0;

 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1184,25 +1195,30 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 	if (ret)
 		return ret;

-	info = platform_get_drvdata(pdev);
-	if (pxa3xx_nand_scan(info->mtd)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
-		pxa3xx_nand_remove(pdev);
-		return -ENODEV;
-	}
-
-	if (mtd_has_cmdlinepart()) {
-		static const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
-
-		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
-
-		if (nr_parts)
-			return add_mtd_partitions(info->mtd, parts, nr_parts);
+	nand = platform_get_drvdata(pdev);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		info = nand->info[cs];
+		mtd = get_mtd_by_info(info);
+		if (pxa3xx_nand_scan(mtd)) {
+			dev_err(&pdev->dev, "failed to scan cs#%d nand\n", cs);
+			continue;
+		}
+		nr_parts = 0;
+		if (mtd_has_cmdlinepart()) {
+			nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
+			if (nr_parts)
+				ret = add_mtd_partitions(mtd, parts, nr_parts);
+		}
+		if (!nr_parts)
+			ret = add_mtd_partitions(mtd, pdata->parts[cs],
+					pdata->nr_parts[cs]);
+		if (!ret)
+			probe_success = 1;
 	}

-	return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
+	if (!probe_success)
+		pxa3xx_nand_remove(pdev);
+	return ret;
 }

 #ifdef CONFIG_PM
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:34:55 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:34:55 +0800
Subject: [PATCH 11/25] pxa3xx_nand: add bch ecc support
Message-ID: <AANLkTikXUmtoINqXaf0XDMF-EDq99rLVsWGS6VyDC1OL@mail.gmail.com>


From leiwen at marvell.com  Sun Jun  6 10:01:35 2010
From: leiwen at marvell.com (Lei Wen)
Date: Sun, 6 Jun 2010 22:01:35 +0800
Subject: [PATCH 11/25] pxa3xx_nand: add bch ecc support
Message-ID: <mailman.21.1276839422.27306.linux-mtd@lists.infradead.org>

Enable the controller internal bch ecc engine when need.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  126 +++++++++++++++++++++++++++++----------
 1 files changed, 93 insertions(+), 33 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 215677f..c75bed6 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -29,6 +29,7 @@
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
 #define NAND_STOP_DELAY		(2 * HZ/50)
 #define PAGE_CHUNK_SIZE		(2048)
+#define BCH_THRESHOLD           (8)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -38,12 +39,15 @@
 #define NDPCR		(0x18) /* Page Count Register */
 #define NDBDR0		(0x1C) /* Bad Block Register 0 */
 #define NDBDR1		(0x20) /* Bad Block Register 1 */
+#define NDECCCTRL	(0x28) /* ECC Control Register */
 #define NDDB		(0x40) /* Data Buffer */
 #define NDCB0		(0x48) /* Command Buffer0 */
 #define NDCB1		(0x4C) /* Command Buffer1 */
 #define NDCB2		(0x50) /* Command Buffer2 */

 #define NDCR_SPARE_EN		(0x1 << 31)
+#define NDSR_ERR_CNT_MASK       (0x1F << 16)
+#define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
 #define NDCR_ECC_EN		(0x1 << 30)
 #define NDCR_DMA_EN		(0x1 << 29)
 #define NDCR_ND_RUN		(0x1 << 28)
@@ -90,6 +94,13 @@
 #define NDCB0_CMD1_MASK		(0xff)
 #define NDCB0_ADDR_CYC_SHIFT	(16)

+/* ECC Control Register */
+#define NDECCCTRL_ECC_SPARE_MSK (0xFF << 7)
+#define NDECCCTRL_ECC_SPARE(x)  (((x) << 7) & NDECCCTRL_ECC_SPARE_MSK)
+#define NDECCCTRL_ECC_THR_MSK   (0x3F << 1)
+#define NDECCCTRL_ECC_THRESH(x) (((x) << 1) & NDECCCTRL_ECC_THR_MSK)
+#define NDECCCTRL_BCH_EN        (0x1)
+
 /* macros for registers read/write */
 #define nand_writel(info, off, val)	\
 	__raw_writel((val), (info)->mmio_base + (off))
@@ -120,6 +131,13 @@ enum {
 	STATE_IS_WRITE		= (1 << 7),
 };

+/* error code and state */
+enum {
+	ECC_NONE = 0,
+	ECC_HAMMIN,
+	ECC_BCH,
+};
+
 struct pxa3xx_nand_timing {
 	uint32_t	tCH;  /* Enable signal hold time */
 	uint32_t	tCS;  /* Enable signal setup time */
@@ -148,10 +166,11 @@ struct pxa3xx_nand_cmdset {
 struct pxa3xx_nand_flash {
 	char		*name;
 	uint32_t	chip_id;
-	uint16_t	page_per_block; /* Pages per block (PG_PER_BLK) */
-	uint16_t 	page_size;	/* Page size in bytes (PAGE_SZ) */
+	uint16_t	page_per_block; /* Pages per block */
+	uint16_t 	page_size;	/* Page size in bytes */
 	uint8_t		flash_width;	/* Width of Flash memory (DWIDTH_M) */
 	uint8_t 	dfc_width;	/* Width of flash controller(DWIDTH_C) */
+	uint8_t		ecc_type;	/* Which ECC is applied */
 	uint32_t	num_blocks;	/* Number of physical blocks in Flash */
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
@@ -246,16 +265,16 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 };

 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-	{ 		0,	0,   0,    0,  0,  0,    0, &timing[0], },
-	{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1], },
-	{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1], },
-	{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, 4096, &timing[1], },
-	{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1], },
-	{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2], },
-	{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2], },
-	{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2], },
-	{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2], },
-	{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3], },
+{ 		0,	0,   0,    0,  0,  0, ECC_NONE,      0, &timing[0], },
+{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, ECC_HAMMIN, 4096, &timing[1], },
+{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, ECC_HAMMIN, 2048, &timing[1], },
+{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, ECC_BCH,    4096, &timing[1], },
+{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, ECC_BCH,    8192, &timing[1], },
+{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, ECC_HAMMIN, 1024, &timing[2], },
+{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, ECC_HAMMIN, 1024, &timing[2], },
+{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, ECC_HAMMIN, 4096, &timing[2], },
+{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, ECC_HAMMIN, 4096, &timing[2], },
+{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, ECC_HAMMIN, 2048, &timing[3], },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
@@ -303,18 +322,43 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 	struct pxa3xx_nand *nand = info->nand_data;
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;

-	nand->data_size = info->page_size;
-	if (!oob_enable) {
-		nand->oob_size = 0;
-		return;
-	}
-	switch (info->page_size) {
-		case 2048:
-			nand->oob_size = (nand->use_ecc) ? 40 : 64;
+	if (info->page_size >= PAGE_CHUNK_SIZE) {
+		nand->data_size = PAGE_CHUNK_SIZE;
+		if (!oob_enable) {
+			nand->oob_size = 0;
+			return;
+		}
+
+		switch (nand->use_ecc) {
+		case ECC_HAMMIN:
+			nand->oob_size = 40;
+			break;
+		case ECC_BCH:
+			nand->oob_size = 32;
+			break;
+		default:
+			nand->oob_size = 64;
+			break;
+		}
+	} else {
+		nand->data_size = 512;
+		if (!oob_enable) {
+			nand->oob_size = 0;
+			return;
+		}
+
+		switch (nand->use_ecc) {
+		case ECC_HAMMIN:
+			nand->oob_size = 8;
 			break;
-		case 512:
-			nand->oob_size = (nand->use_ecc) ? 8 : 16;
+		case ECC_BCH:
+			printk("Don't support BCH on small page device!!!\n");
+			BUG();
 			break;
+		default:
+			nand->oob_size = 16;
+			break;
+		}
 	}
 }

@@ -327,16 +371,26 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 static void pxa3xx_nand_start(struct pxa3xx_nand *nand)
 {
 	struct pxa3xx_nand_info *info;
-	uint32_t ndcr;
+	uint32_t ndcr, ndeccctrl = 0;

 	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
-	ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
 	ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
 	ndcr |= NDCR_ND_RUN;

+	switch (nand->use_ecc) {
+	case ECC_BCH:
+		ndeccctrl |= NDECCCTRL_BCH_EN;
+		ndeccctrl |= NDECCCTRL_ECC_THRESH(BCH_THRESHOLD);
+	case ECC_HAMMIN:
+		ndcr |= NDCR_ECC_EN;
+	default:
+		break;
+	}
+
 	/* clear status bits and run */
 	nand_writel(nand, NDCR, 0);
+	nand_writel(nand, NDECCCTRL, ndeccctrl);
 	nand_writel(nand, NDSR, NDSR_MASK);
 	nand_writel(nand, NDCR, ndcr);
 }
@@ -449,6 +503,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	info            = nand->info[cs];

 	status = nand_readl(nand, NDSR);
+	nand->bad_count = (status & NDSR_ERR_CNT_MASK) >> 16;
 	if (status & NDSR_DBERR)
 		nand->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
@@ -782,6 +837,7 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	uint32_t ndcr = 0;

 	/* calculate flash information */
+	info->use_ecc = f->ecc_type;
 	info->page_size = f->page_size;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

@@ -804,7 +860,6 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */

 	info->reg_ndcr = ndcr;
-	info->use_ecc = 1;

 	pxa3xx_nand_set_timing(info, f->timing);
 	return 0;
@@ -814,6 +869,7 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)
 {
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
 	uint32_t ndcr = nand_readl(nand, NDCR);
+	uint32_t ndeccctrl = nand_readl(nand, NDECCCTRL);

 	if (nand->chip_select > 0) {
 		printk(KERN_ERR "We could not detect configure if two cs is supported!!\n");
@@ -822,6 +878,7 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)
 	info->reg_ndcr = ndcr & ~(NDCR_INT_MASK | NDCR_ECC_EN | NDCR_DMA_EN
| NDCR_ND_RUN);
 	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
+	info->use_ecc = (ndeccctrl & NDECCCTRL_BCH_EN) ? ECC_BCH : ECC_HAMMIN;

 	return 0;
 }
@@ -856,13 +913,16 @@ static int pxa3xx_nand_read_page_hwecc(struct
mtd_info *mtd,

 	if (nand->retcode == ERR_SBERR) {
 		switch (nand->use_ecc) {
-			case 1:
-				mtd->ecc_stats.corrected++;
-				break;
-
-			case 0:
-			default:
-				break;
+		case ECC_BCH:
+			if (nand->bad_count > BCH_THRESHOLD)
+				mtd->ecc_stats.corrected +=
+					(nand->bad_count - BCH_THRESHOLD);
+			break;
+		case ECC_HAMMIN:
+			mtd->ecc_stats.corrected ++;
+		case ECC_NONE:
+		default:
+			break;
 		}
 	} else if (nand->retcode == ERR_DBERR) {
 		int buf_blank;
@@ -1045,8 +1105,8 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	nand->mmio_phys = r->start;

 	/* initialize all interrupts to be disabled */
-	disable_int(nand, NDSR_MASK);
 	irq = platform_get_irq(pdev, 0);
+	disable_int(nand, NDCR_INT_MASK);
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		ret = -ENXIO;
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:35:02 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:35:02 +0800
Subject: [PATCH 12/25] pxa3xx_nand: add more attribute that platform could 
	choose from
Message-ID: <AANLkTikqQl2rmEJyee01f1Oq-oMf2C225cysCE53sykA@mail.gmail.com>


From leiwen at marvell.com  Sun Jun  6 10:02:08 2010
From: leiwen at marvell.com (Lei Wen)
Date: Sun, 6 Jun 2010 22:02:08 +0800
Subject: [PATCH 12/25] pxa3xx_nand: add more attribute that platform
Message-ID: <mailman.23.1276839432.27306.linux-mtd@lists.infradead.org>

could choose from

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c                 |    3 ++-
 arch/arm/mach-mmp/avengers_lite.c            |    3 ++-
 arch/arm/mach-pxa/cm-x300.c                  |    3 +--
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    3 +--
 arch/arm/mach-pxa/littleton.c                |    2 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    3 +--
 arch/arm/mach-pxa/raumfeld.c                 |    3 +--
 arch/arm/mach-pxa/zylonite.c                 |    2 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   23 +++++++++++++----------
 drivers/mtd/nand/pxa3xx_nand.c               |   11 +++++++----
 10 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 81ad58d..8d739d1 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -125,7 +125,8 @@ static struct mtd_partition aspenite_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
-	.enable_arbiter	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_NAKED_CMD_EN | PXA3XX_DMA_EN
+				| PXA3XX_ADV_TIME_TUNING | PXA3XX_TWO_CHIP_EN,
 	.parts[0]	= aspenite_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(aspenite_nand_partitions),
 };
diff --git a/arch/arm/mach-mmp/avengers_lite.c
b/arch/arm/mach-mmp/avengers_lite.c
index a828b1c..3a07613 100644
--- a/arch/arm/mach-mmp/avengers_lite.c
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -77,7 +77,8 @@ static void __init avengers_init_flash(void)
 	avengers_nand_info.nr_parts[0] = ARRAY_SIZE(avengers_nand_partitions_0);
 	avengers_nand_info.parts[1] = avengers_nand_partitions_1;
 	avengers_nand_info.nr_parts[1] = ARRAY_SIZE(avengers_nand_partitions_1);
-	avengers_nand_info.enable_arbiter = 1;
+	avengers_nand_info.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_NAKED_CMD_EN
+		| PXA3XX_DMA_EN | PXA3XX_ADV_TIME_TUNING | PXA3XX_TWO_CHIP_EN;
 	pxa168_add_nand(&avengers_nand_info);
 }

diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index ce1f6d3..9f0282b 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -417,8 +417,7 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= cm_x300_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(cm_x300_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c
b/arch/arm/mach-pxa/colibri-pxa3xx.c
index b33559c..627b289 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -186,8 +186,7 @@ static struct mtd_partition colibri_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data colibri_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= colibri_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(colibri_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 717cf92..e63451c 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -324,7 +324,7 @@ static struct mtd_partition littleton_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data littleton_nand_info = {
-	.enable_arbiter	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN,
 	.parts[0]	= littleton_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(littleton_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index 66c2086..baca736 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,8 +389,7 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= mxm_8x10_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(mxm_8x10_nand_partitions)
 };
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index df75d4d..8761775 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -348,8 +348,7 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= raumfeld_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(raumfeld_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 9e5c6cd..5cf3d10 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -355,7 +355,7 @@ static struct mtd_partition zylonite_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
-	.enable_arbiter	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN,
 	.parts[0]	= zylonite_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(zylonite_nand_partitions),
 };
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 56015bd..72bb70e 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -5,17 +5,20 @@
 #include <linux/mtd/partitions.h>

 #define NUM_CHIP_SELECT		(2)
+/* the data flash bus is shared between the Static Memory
+ * Controller and the Data Flash Controller,  the arbiter
+ * controls the ownership of the bus
+ */
+#define PXA3XX_ARBI_EN		(1)
+#define PXA3XX_NAKED_CMD_EN	(1 << 1)
+#define PXA3XX_TWO_CHIP_EN	(1 << 2)
+#define PXA3XX_DMA_EN		(1 << 3)
+/* for newer controller support more precise timing tuning, only
+ * enable such tuning for those platform which support it */
+#define PXA3XX_ADV_TIME_TUNING	(1 << 4)
+#define PXA3XX_KEEP_CONFIG	(1 << 5)
 struct pxa3xx_nand_platform_data {
-
-	/* the data flash bus is shared between the Static Memory
-	 * Controller and the Data Flash Controller,  the arbiter
-	 * controls the ownership of the bus
-	 */
-	int	enable_arbiter;
-
-	/* allow platform code to keep OBM/bootloader defined NFC config */
-	int	keep_config;
-
+	unsigned int				controller_attrs;
 	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
 	unsigned int				nr_parts[NUM_CHIP_SELECT];

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index c75bed6..8ec9172 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -849,7 +849,7 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	else
 		info->row_addr_cycles = 2;

-	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
+	ndcr |= (pdata->controller_attrs & PXA3XX_ARBI_EN) ? NDCR_ND_ARB_EN : 0;
 	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
 	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
@@ -975,7 +975,7 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret;

-	if (pdata->keep_config) {
+	if (pdata->controller_attrs & PXA3XX_KEEP_CONFIG) {
 		if (pxa3xx_nand_detect_config(nand) == 0)
 			goto KEEP_CONFIG;
 	}
@@ -1243,7 +1243,7 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 	struct mtd_info *mtd;
 	static const char *probes[] = { "cmdlinepart", NULL };
 	struct mtd_partition *parts;
-	int nr_parts, ret, cs, probe_success = 0;
+	int nr_parts, ret, cs, probe_success = 0, cs_to_scan;

 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1251,12 +1251,15 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 		return -ENODEV;
 	}

+	if (!(pdata->controller_attrs & PXA3XX_DMA_EN))
+		use_dma = 0;
 	ret = alloc_nand_resource(pdev);
 	if (ret)
 		return ret;

 	nand = platform_get_drvdata(pdev);
-	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+	cs_to_scan = (pdata->controller_attrs & PXA3XX_TWO_CHIP_EN)? 2 : 1;
+	for (cs = 0; cs < cs_to_scan; cs++) {
 		info = nand->info[cs];
 		mtd = get_mtd_by_info(info);
 		if (pxa3xx_nand_scan(mtd)) {
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:35:13 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:35:13 +0800
Subject: [PATCH 13/25] pxa3xx_nand: enable 4k page operation
Message-ID: <AANLkTik-MM98PEznLcu5YUO0GqValtpw-hTmSdr3GtAR@mail.gmail.com>


From leiwen at marvell.com  Sun Jun  6 10:05:06 2010
From: leiwen at marvell.com (Lei Wen)
Date: Sun, 6 Jun 2010 22:05:06 +0800
Subject: [PATCH 13/25] pxa3xx_nand: enable 4k page operation
Message-ID: <mailman.25.1276839446.27306.linux-mtd@lists.infradead.org>

For limitation of our controller, we only could do large page
nand chip by dividing the original page size into what we could
afford. We call one divide operation as chunk.

The divide operation need naked command support, which may not
be existed in so old version. You should check it first before
you want to use this feature.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  355 +++++++++++++++++++++++++++++++---------
 1 files changed, 280 insertions(+), 75 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 8ec9172..1e75df4 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -29,7 +29,10 @@
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
 #define NAND_STOP_DELAY		(2 * HZ/50)
 #define PAGE_CHUNK_SIZE		(2048)
+#define OOB_CHUNK_SIZE		(64)
 #define BCH_THRESHOLD           (8)
+#define CMD_POOL_SIZE           (5)
+#define READ_ID_BYTES		(4)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -39,33 +42,50 @@
 #define NDPCR		(0x18) /* Page Count Register */
 #define NDBDR0		(0x1C) /* Bad Block Register 0 */
 #define NDBDR1		(0x20) /* Bad Block Register 1 */
+#define NDREDEL		(0x24) /* Read Enable Return Delay Register */
 #define NDECCCTRL	(0x28) /* ECC Control Register */
+#define NDBZCNT		(0x2C) /* Timer for NDRnB0 and NDRnB1 */
 #define NDDB		(0x40) /* Data Buffer */
 #define NDCB0		(0x48) /* Command Buffer0 */
 #define NDCB1		(0x4C) /* Command Buffer1 */
 #define NDCB2		(0x50) /* Command Buffer2 */

 #define NDCR_SPARE_EN		(0x1 << 31)
-#define NDSR_ERR_CNT_MASK       (0x1F << 16)
-#define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
 #define NDCR_ECC_EN		(0x1 << 30)
 #define NDCR_DMA_EN		(0x1 << 29)
 #define NDCR_ND_RUN		(0x1 << 28)
 #define NDCR_DWIDTH_C		(0x1 << 27)
 #define NDCR_DWIDTH_M		(0x1 << 26)
-#define NDCR_PAGE_SZ		(0x1 << 24)
-#define NDCR_NCSX		(0x1 << 23)
-#define NDCR_ND_MODE		(0x3 << 21)
+#define NDCR_PAGE_SZ_MASK	(0x3 << 24)
+#define NDCR_PAGE_SZ(x)		(((x) << 24) & NDCR_PAGE_SZ_MASK)
+#define NDCR_SEQ_DIS		(0x1 << 23)
+#define NDCR_ND_STOP		(0x1 << 22)
+#define NDCR_FORCE_CSX		(0x1 << 21)
 #define NDCR_CLR_PG_CNT		(0x1 << 20)
 #define NDCR_STOP_ON_UNCOR	(0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK	(0x7 << 16)
 #define NDCR_RD_ID_CNT(x)	(((x) << 16) & NDCR_RD_ID_CNT_MASK)

 #define NDCR_RA_START		(0x1 << 15)
-#define NDCR_PG_PER_BLK		(0x1 << 14)
+#define NDCR_PG_PER_BLK_MASK	(0x3 << 13)
+#define NDCR_PG_PER_BLK(x)	(((x) << 13) & NDCR_PG_PER_BLK_MASK)
 #define NDCR_ND_ARB_EN		(0x1 << 12)
 #define NDCR_INT_MASK           (0xFFF)
+#define NDCR_RDYM               (0x1 << 11)
+#define NDCR_CS0_PAGEDM         (0x1 << 10)
+#define NDCR_CS1_PAGEDM         (0x1 << 9)
+#define NDCR_CS0_CMDDM          (0x1 << 8)
+#define NDCR_CS1_CMDDM          (0x1 << 7)
+#define NDCR_CS0_BBDM           (0x1 << 6)
+#define NDCR_CS1_BBDM           (0x1 << 5)
+#define NDCR_UNCERRM            (0x1 << 4)
+#define NDCR_CORERRM            (0x1 << 3)
+#define NDCR_WRDREQM            (0x1 << 2)
+#define NDCR_RDDREQM            (0x1 << 1)
+#define NDCR_WRCMDREQM          (0x1)

+#define NDSR_ERR_CNT_MASK       (0x1F << 16)
+#define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
 #define NDSR_MASK		(0xfff)
 #define NDSR_RDY                (0x1 << 12)
 #define NDSR_FLASH_RDY          (0x1 << 11)
@@ -81,6 +101,8 @@
 #define NDSR_RDDREQ		(0x1 << 1)
 #define NDSR_WRCMDREQ		(0x1)

+#define NDCB0_CMD_XTYPE_MASK    (0x7 << 29)
+#define NDCB0_CMD_XTYPE(x)      (((x) << 29) & NDCB0_CMD_XTYPE_MASK)
 #define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS		(0x1 << 25)
 #define NDCB0_CSEL		(0x1 << 24)
@@ -131,6 +153,7 @@ enum {
 	STATE_IS_WRITE		= (1 << 7),
 };

+#define STATE_MASK		(0x3f)
 /* error code and state */
 enum {
 	ECC_NONE = 0,
@@ -185,7 +208,6 @@ struct pxa3xx_nand_info {
 	/* calculated from pxa3xx_nand_flash data */
 	uint8_t			col_addr_cycles;
 	uint8_t			row_addr_cycles;
-	uint8_t			read_id_bytes;

 	/* cached register value */
 	uint32_t		reg_ndcr;
@@ -221,7 +243,8 @@ struct pxa3xx_nand {
 	unsigned char		*oob_buff;
 	uint32_t		buf_start;
 	uint32_t		buf_count;
-	uint8_t			total_cmds;
+	uint16_t		data_column;
+	uint16_t		oob_column;

 	/* relate to the command */
 	uint8_t			chip_select;
@@ -230,8 +253,11 @@ struct pxa3xx_nand {
 	int			use_dma;	/* use DMA ? */
 	int 			retcode;

-	/* generated NDCBx register values */
-	uint32_t		ndcb0;
+	/* cached register value */
+	uint8_t			cmd_seqs;
+	uint8_t			total_cmds;
+	uint8_t			wait_ready[CMD_POOL_SIZE];
+	uint32_t		ndcb0[CMD_POOL_SIZE];
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;
 };
@@ -274,6 +300,7 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 { "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, ECC_HAMMIN, 1024, &timing[2], },
 { "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, ECC_HAMMIN, 4096, &timing[2], },
 { "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, ECC_HAMMIN, 4096, &timing[2], },
+{ "1GiB 8-bit",    0x382c, 128, 4096,  8,  8, ECC_BCH,    2048, &timing[2], },
 { "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, ECC_HAMMIN, 2048, &timing[3], },
 };

@@ -430,41 +457,98 @@ static void disable_int(struct pxa3xx_nand
*nand, uint32_t int_mask)
 	nand_writel(nand, NDCR, ndcr | int_mask);
 }

+static void nand_error_dump(struct pxa3xx_nand *nand)
+{
+	int i;
+
+	printk(KERN_ERR "NAND controller state wrong!!!\n");
+	printk(KERN_ERR "command %x, state %x, current seqs %d, errcode %x,
bad count %d\n",
+			nand->command, nand->state, nand->cmd_seqs,
+			nand->retcode, nand->bad_count);
+	printk(KERN_ERR "Totally %d command for sending\n",
+			nand->total_cmds);
+	for (i = 0; i < nand->total_cmds; i ++)
+		printk(KERN_ERR "NDCB0:%d: %x\n",
+				i, nand->ndcb0[i]);
+	printk(KERN_ERR "NDCB1: %x; NDCB2 %x\n", nand->ndcb1, nand->ndcb2);
+
+	printk(KERN_ERR "\nRegister DUMPing ##############\n");
+	printk(KERN_ERR "NDCR %x\n"
+			"NDSR %x\n"
+			"NDCB0 %x\n"
+			"NDCB1 %x\n"
+			"NDCB2 %x\n"
+			"NDTR0CS0 %x\n"
+			"NDTR1CS0 %x\n"
+			"NDBDR0 %x\n"
+			"NDBDR1 %x\n"
+			"NDREDEL %x\n"
+			"NDECCCTRL %x\n"
+			"NDBZCNT %x\n\n",
+			nand_readl(nand, NDCR),
+			nand_readl(nand, NDSR),
+			nand_readl(nand, NDCB0),
+			nand_readl(nand, NDCB1),
+			nand_readl(nand, NDCB2),
+			nand_readl(nand, NDTR0CS0),
+			nand_readl(nand, NDTR1CS0),
+			nand_readl(nand, NDBDR0),
+			nand_readl(nand, NDBDR1),
+			nand_readl(nand, NDREDEL),
+			nand_readl(nand, NDECCCTRL),
+			nand_readl(nand, NDBZCNT));
+}
+
 static void handle_data_pio(struct pxa3xx_nand *nand)
 {
+	unsigned int data_size, oob_size;
+
+	data_size = DIV_ROUND_UP(nand->data_size, 4);
+	oob_size = DIV_ROUND_UP(nand->oob_size, 4);
 	if (nand->state & STATE_IS_WRITE) {
-		__raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
-				DIV_ROUND_UP(nand->data_size, 4));
+		__raw_writesl(nand->mmio_base + NDDB,
+				nand->data_buff + nand->data_column, data_size);
 		if (nand->oob_size > 0)
-			__raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
-					DIV_ROUND_UP(nand->oob_size, 4));
-
+			__raw_writesl(nand->mmio_base + NDDB,
+				nand->oob_buff + nand->oob_column, oob_size);
 	}
 	else {
-		__raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
-				DIV_ROUND_UP(nand->data_size, 4));
+		__raw_readsl(nand->mmio_base + NDDB,
+				nand->data_buff + nand->data_column, data_size);
 		if (nand->oob_size > 0)
-			__raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
-					DIV_ROUND_UP(nand->oob_size, 4));
+			__raw_readsl(nand->mmio_base + NDDB,
+				nand->oob_buff + nand->oob_column, oob_size);
 	}
+	nand->data_column += (data_size << 2);
+	nand->oob_column += (oob_size << 2);
 }

 static void start_data_dma(struct pxa3xx_nand *nand, int dir_out)
 {
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
 	struct pxa_dma_desc *desc = nand->data_desc;
-	int dma_len = ALIGN(nand->data_size + nand->oob_size, 32);
-
-	desc->ddadr = DDADR_STOP;
-	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
+	struct pxa_dma_desc *desc_oob = nand->data_desc + 1;
+	unsigned int data_len = ALIGN(nand->data_size, 32);
+	unsigned int oob_len = ALIGN(nand->oob_size, 32);

+	desc_oob->ddadr = desc->ddadr = DDADR_STOP;
+	desc_oob->dcmd = desc->dcmd = DCMD_WIDTH4 | DCMD_BURST32;
 	if (dir_out) {
-		desc->dsadr = nand->data_buff_phys;
+		desc->dsadr = nand->data_buff_phys + nand->data_column;
 		desc->dtadr = nand->mmio_phys + NDDB;
-		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
+		desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG |
(data_len + oob_len);
 	} else {
-		desc->dtadr = nand->data_buff_phys;
-		desc->dsadr = nand->mmio_phys + NDDB;
-		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+		if (nand->oob_size > 0) {
+			desc_oob->dtadr = nand->data_buff_phys
+					+ info->page_size + nand->oob_column;
+			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | oob_len;
+			desc->ddadr = nand->data_desc_addr + sizeof(struct pxa_dma_desc);
+			desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
+		}
+		else
+			desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
+		desc->dtadr = nand->data_buff_phys + nand->data_column;
+		desc_oob->dsadr = desc->dsadr = nand->mmio_phys + NDDB;
 	}

 	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
@@ -484,6 +568,8 @@ static void pxa3xx_nand_data_dma_irq(int channel,
void *data)
 		nand->retcode = ERR_DMABUSERR;
 	}

+	nand->data_column += nand->data_size;
+	nand->oob_column += nand->oob_size;
 	enable_int(nand, NDCR_INT_MASK);
 	nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }
@@ -492,7 +578,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand *nand = devid;
 	struct pxa3xx_nand_info *info;
-	unsigned int status, is_completed = 0, cs;
+	unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2;
 	unsigned int ready, cmd_done, page_done, badblock_detect;

 	cs		= nand->chip_select;
@@ -501,13 +587,14 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	page_done       = (cs) ? NDSR_CS1_PAGED : NDSR_CS0_PAGED;
 	badblock_detect = (cs) ? NDSR_CS1_BBD : NDSR_CS0_BBD;
 	info            = nand->info[cs];
+	cmd_seqs	= nand->cmd_seqs;

 	status = nand_readl(nand, NDSR);
 	nand->bad_count = (status & NDSR_ERR_CNT_MASK) >> 16;
-	if (status & NDSR_DBERR)
-		nand->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
 		nand->retcode = ERR_SBERR;
+	if (status & NDSR_DBERR)
+		nand->retcode = ERR_DBERR;
 	if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {

 		nand->state |= STATE_DATA_PROCESSING;
@@ -521,24 +608,51 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)

 		nand->state |= STATE_DATA_DONE;
 	}
+	if (status & page_done)
+		nand->state |= STATE_PAGE_DONE;
+	if (status & ready) {
+		nand->state |= STATE_READY;
+		if (nand->wait_ready[cmd_seqs]) {
+			enable_int(nand, NDCR_WRCMDREQM);
+			if (cmd_seqs == nand->total_cmds)
+				is_completed = 1;
+		}
+	}
 	if (status & cmd_done) {
 		nand->state |= STATE_CMD_DONE;
-		is_completed = 1;
+		if (cmd_seqs == nand->total_cmds && !nand->wait_ready[cmd_seqs])
+			is_completed = 1;
 	}
-	if (status & ready)
-		nand->state |= STATE_READY;
-	if (status & page_done)
-		nand->state |= STATE_PAGE_DONE;

 	if (status & NDSR_WRCMDREQ) {
-		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
 		status &= ~NDSR_WRCMDREQ;
-		nand->state |= STATE_CMD_WAIT_DONE;
-		nand_writel(nand, NDCB0, nand->ndcb0);
-		nand_writel(nand, NDCB0, nand->ndcb1);
-		nand_writel(nand, NDCB0, nand->ndcb2);
+		if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) {
+			disable_int(nand, NDCR_WRCMDREQM);
+			goto IRQ_FORCE_EXIT;
+		}
+
+		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
+		if (cmd_seqs < nand->total_cmds) {
+			nand->cmd_seqs ++;
+			if (cmd_seqs == 0) {
+				ndcb1 = nand->ndcb1;
+				ndcb2 = nand->ndcb2;
+			}
+			else {
+				ndcb1 = 0;
+				ndcb2 = 0;
+			}
+			nand->state &= ~STATE_MASK;
+			nand->state |= STATE_CMD_WAIT_DONE;
+			nand_writel(nand, NDCB0, nand->ndcb0[cmd_seqs]);
+			nand_writel(nand, NDCB0, ndcb1);
+			nand_writel(nand, NDCB0, ndcb2);
+		}
+		else
+			is_completed = 1;
 	}

+IRQ_FORCE_EXIT:
 	/* clear NDSR to let the controller exit the IRQ */
 	nand_writel(nand, NDSR, status);
 	if (is_completed)
@@ -559,7 +673,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
-	int addr_cycle, exec_cmd, ndcb0;
+	int addr_cycle, exec_cmd, ndcb0, i, chunks = 0;
 	struct mtd_info *mtd;
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];

@@ -569,14 +683,19 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	exec_cmd = 1;

 	/* reset data and oob column point to handle data */
+	nand->data_column	= 0;
+	nand->oob_column	= 0;
 	nand->buf_start		= 0;
 	nand->buf_count		= 0;
-	nand->ndcb0		= ndcb0;
+	nand->total_cmds	= 1;
+	nand->cmd_seqs		= 0;
 	nand->data_size		= 0;
 	nand->oob_size		= 0;
 	nand->use_ecc		= 0;
 	nand->use_dma		= 0;
 	nand->state		= 0;
+	nand->bad_count		= 0;
+	nand->retcode		= ERR_NONE;
 	nand->command		= command;

 	switch (command) {
@@ -587,6 +706,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		pxa3xx_set_datasize(info);
 		nand->oob_buff = nand->data_buff + nand->data_size;
 		nand->use_dma = use_dma;
+		chunks = info->page_size / nand->data_size;
 		break;
 	case NAND_CMD_SEQIN:
 		exec_cmd = 0;
@@ -597,6 +717,11 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		break;
 	}

+	/* clear the command buffer */
+	for (i = 0; i < CMD_POOL_SIZE; i ++) {
+		nand->ndcb0[i] = ndcb0;
+		nand->wait_ready[i] = 0;
+	}
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);

@@ -611,14 +736,37 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 			nand->buf_start = column;

 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
-		else
-			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
-					| NDCB0_DBC
-					| addr_cycle
-					| cmd;
+		else {
+			if (chunks == 1)
+				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
+						| NDCB0_DBC
+						| addr_cycle
+						| cmd;
+			else {
+				nand->total_cmds = chunks + 1;
+				nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
+						| NDCB0_CMD_TYPE(0)
+						| NDCB0_DBC
+						| NDCB0_NC
+						| addr_cycle
+						| cmd;
+
+				nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
+						| NDCB0_NC
+						| addr_cycle;
+
+				for (i = 2; i <= chunks; i ++)
+					nand->ndcb0[i] = nand->ndcb0[1];
+
+				nand->ndcb0[chunks] &= ~NDCB0_NC;
+				/* we should wait RnB go high again
+				 * before read out data*/
+				nand->wait_ready[1] = 1;
+			}
+		}

 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
@@ -651,18 +799,46 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 		cmd = cmdset.program;
 		nand->state |= STATE_IS_WRITE;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
-				| NDCB0_AUTO_RS
-				| NDCB0_ST_ROW_EN
-				| NDCB0_DBC
-				| cmd
-				| addr_cycle;
+		if (chunks == 1)
+			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0x1)
+					| NDCB0_AUTO_RS
+					| NDCB0_ST_ROW_EN
+					| NDCB0_DBC
+					| cmd
+					| addr_cycle;
+		else {
+			nand->total_cmds = chunks + 1;
+			nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x4)
+					| NDCB0_CMD_TYPE(0x1)
+					| NDCB0_NC
+					| NDCB0_AUTO_RS
+					| (cmd & NDCB0_CMD1_MASK)
+					| addr_cycle;
+
+			for (i = 1; i < chunks; i ++)
+				nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_CMD_TYPE(0x1)
+						| addr_cycle;
+
+			nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
+						| NDCB0_CMD_TYPE(0x1)
+						| NDCB0_ST_ROW_EN
+						| NDCB0_DBC
+						| (cmd & NDCB0_CMD2_MASK)
+						| NDCB0_CMD1_MASK
+						| addr_cycle;
+			/* we should wait for RnB goes high which
+			 * indicate the data has been written succesfully*/
+			nand->wait_ready[nand->total_cmds] = 1;
+		}
 		break;

 	case NAND_CMD_READID:
 		cmd = cmdset.read_id;
-		nand->buf_count = info->read_id_bytes;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(3)
+		nand->buf_count = READ_ID_BYTES;
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

@@ -672,7 +848,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	case NAND_CMD_STATUS:
 		cmd = cmdset.read_status;
 		nand->buf_count = 1;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(4)
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

@@ -681,7 +857,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,

 	case NAND_CMD_ERASE1:
 		cmd = cmdset.erase;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(2)
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
 				| NDCB0_DBC
@@ -692,7 +868,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		break;
 	case NAND_CMD_RESET:
 		cmd = cmdset.reset;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(5)
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(5)
 				| cmd;

 		break;
@@ -741,10 +917,10 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
 			dev_err(&nand->pdev->dev, "Wait time out!!!\n");
+			nand_error_dump(nand);
+			/* Stop State Machine for next command cycle */
+			pxa3xx_nand_stop(nand);
 		}
-		/* Stop State Machine for next command cycle */
-		pxa3xx_nand_stop(nand);
-		disable_int(nand, NDCR_INT_MASK);
 		nand->state &= ~STATE_CMD_PREPARED;
 	}
 }
@@ -828,7 +1004,7 @@ static int pxa3xx_nand_waitfunc(struct mtd_info
*mtd, struct nand_chip *this)
 	return 0;
 }

-static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
+static void pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 				    const struct pxa3xx_nand_flash *f)
 {
 	struct pxa3xx_nand *nand = info->nand_data;
@@ -836,13 +1012,18 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	uint32_t ndcr = 0;

+	if (f->page_size > PAGE_CHUNK_SIZE
+			&& !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
+		printk(KERN_ERR "Your controller don't support 4k or larger "
+			       "page NAND for don't support naked command\n");
+		BUG();
+	}
 	/* calculate flash information */
 	info->use_ecc = f->ecc_type;
 	info->page_size = f->page_size;
-	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

 	/* calculate addressing information */
-	info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+	info->col_addr_cycles = (f->page_size >= 2048) ? 2 : 1;

 	if (f->num_blocks * f->page_per_block > 65536)
 		info->row_addr_cycles = 3;
@@ -851,18 +1032,42 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,

 	ndcr |= (pdata->controller_attrs & PXA3XX_ARBI_EN) ? NDCR_ND_ARB_EN : 0;
 	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
-	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
-	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
 	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
 	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	switch (f->page_per_block) {
+		case 32:
+			ndcr |= NDCR_PG_PER_BLK(0x0);
+			break;
+		case 128:
+			ndcr |= NDCR_PG_PER_BLK(0x1);
+			break;
+		case 256:
+			ndcr |= NDCR_PG_PER_BLK(0x3);
+			break;
+		case 64:
+		default:
+			ndcr |= NDCR_PG_PER_BLK(0x2);
+			break;
+	}

-	ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
+	switch (f->page_size) {
+		case 512:
+			ndcr |= NDCR_PAGE_SZ(0x0);
+			break;
+		case 2048:
+		default:
+			ndcr |= NDCR_PAGE_SZ(0x1);
+			ndcr |= NDCR_FORCE_CSX;
+			break;
+
+	}
+
+	ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */

 	info->reg_ndcr = ndcr;

 	pxa3xx_nand_set_timing(info, f->timing);
-	return 0;
 }

 static int pxa3xx_nand_detect_config(struct pxa3xx_nand *nand)
@@ -883,11 +1088,10 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)
 	return 0;
 }

-/* the maximum possible buffer size for large page with OOB data
- * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
- * data buffer and the DMA descriptor
+/* the max buff size should be large than the largest size
+ * of page of NAND flash that currently controller support
  */
-#define MAX_BUFF_SIZE	PAGE_SIZE
+#define MAX_BUFF_SIZE	((PAGE_CHUNK_SIZE + OOB_CHUNK_SIZE) * 2) +
sizeof(struct pxa_dma_desc) * 2
 static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
 	struct pxa3xx_nand *nand;
@@ -975,6 +1179,7 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret;

+	nand->chip_select = info->chip_select;
 	if (pdata->controller_attrs & PXA3XX_KEEP_CONFIG) {
 		if (pxa3xx_nand_detect_config(nand) == 0)
 			goto KEEP_CONFIG;
@@ -1049,7 +1254,7 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	struct pxa3xx_nand *nand;
 	struct resource *r;
 	int ret, irq, cs;
-	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
+	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc) * 2;

 	nand = kzalloc(sizeof(struct pxa3xx_nand), GFP_KERNEL);
 	if (!nand) {
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:35:21 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:35:21 +0800
Subject: [PATCH 14/25] mmp: correct nand clock setting for pxa168 and pxa910
Message-ID: <AANLkTilfAX6_mEkeXCO9MYPzMYXTanvnCbRqjM4KIFxo@mail.gmail.com>


From leiwen at marvell.com  Thu Jun  3 03:46:50 2010
From: leiwen at marvell.com (Lei Wen)
Date: Thu, 3 Jun 2010 15:46:50 +0800
Subject: [PATCH 14/25] mmp: correct nand clock setting for pxa168 and pxa910
Message-ID: <mailman.27.1276839464.27306.linux-mtd@lists.infradead.org>

There is no clock setting at 208Mhz for nand on pxa168 and pxa910
platform. Set correct register and lock the clock at
156MHZ.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/pxa168.c |    2 +-
 arch/arm/mach-mmp/pxa910.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 652ae66..70d2231 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -78,7 +78,7 @@ static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
 static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
 static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);

-static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(nand, NAND, 0x19B, 156000000);

 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 46f2d69..96f2b61 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -110,7 +110,7 @@ static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
 static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
 static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);

-static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(nand, NAND, 0x19B, 156000000);

 /* device and clock bindings */
 static struct clk_lookup pxa910_clkregs[] = {
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:35:29 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:35:29 +0800
Subject: [PATCH 15/25] mmp: add nand support to mmp2
Message-ID: <AANLkTikzX_3shKAC16E7BKqZPFAw2a4b8_ToaYnSny6K@mail.gmail.com>


From leiwen at marvell.com  Thu Jun  3 04:21:04 2010
From: leiwen at marvell.com (Lei Wen)
Date: Thu, 3 Jun 2010 16:21:04 +0800
Subject: [PATCH 15/25] mmp: add nand support to mmp2
Message-ID: <mailman.29.1276839478.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/configs/mmp2_defconfig       |    4 +-
 arch/arm/mach-mmp/include/mach/mmp2.h |    6 ++++
 arch/arm/mach-mmp/jasper.c            |   52 +++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index 4b55dcb..e63dec3 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -469,7 +469,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
 #
 # User Modules And Translation Layers
 #
-# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
@@ -525,7 +525,7 @@ CONFIG_MTD_NAND=y
 # CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_PXA3xx is not set
+CONFIG_MTD_NAND_PXA3xx=y
 # CONFIG_MTD_NAND_NANDSIM is not set
 # CONFIG_MTD_NAND_PLATFORM is not set
 CONFIG_MTD_ONENAND=y
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h
b/arch/arm/mach-mmp/include/mach/mmp2.h
index fec220b..d68890b 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -4,6 +4,7 @@
 #include <linux/i2c.h>
 #include <mach/devices.h>
 #include <plat/i2c.h>
+#include <plat/pxa3xx_nand.h>

 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
@@ -15,6 +16,7 @@ extern struct pxa_device_desc mmp2_device_twsi3;
 extern struct pxa_device_desc mmp2_device_twsi4;
 extern struct pxa_device_desc mmp2_device_twsi5;
 extern struct pxa_device_desc mmp2_device_twsi6;
+extern struct pxa_device_desc mmp2_device_nand;

 static inline int mmp2_add_uart(int id)
 {
@@ -56,5 +58,9 @@ static inline int mmp2_add_twsi(int id, struct
i2c_pxa_platform_data *data,
 	return pxa_register_device(d, data, sizeof(*data));
 }

+static inline int mmp2_add_nand(struct pxa3xx_nand_platform_data *data)
+{
+	return pxa_register_device(&mmp2_device_nand, data, sizeof(*data));
+}
 #endif /* __ASM_MACH_MMP2_H */

diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index d77dd41..5d055f3 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -67,6 +67,57 @@ static unsigned long jasper_pin_config[] __initdata = {
 	PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
 };

+static struct mtd_partition jasper_nand_partitions[] = {
+	[0] = {
+		.name		= "Bootloader",
+		.offset		= 0,
+		.size		= 0x100000,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[1] = {
+		.name		= "Reserve",
+		.offset		= 0x100000,
+		.size		= 0x080000,
+	},
+	[2] = {
+		.name		= "Reserve",
+		.offset		= 0x180000,
+		.size		= 0x800000,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[3] = {
+		.name		= "Kernel",
+		.offset		= 0x980000,
+		.size		= 0x300000,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[4] = {
+		.name		= "system",
+		.offset		= 0x0c80000,
+		.size		= 0x7000000,
+	},
+	[5] = {
+		.name		= "userdata",
+		.offset		= 0x7c80000,
+		.size		= 0x7000000,
+	},
+	[6] = {
+		.name		= "filesystem",
+		.offset		= 0x0ec80000,
+		.size		= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct pxa3xx_nand_platform_data jasper_nand_info;
+static void __init jasper_init_flash(void)
+{
+	jasper_nand_info.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_NAKED_CMD_EN
+		| PXA3XX_DMA_EN | PXA3XX_ADV_TIME_TUNING | PXA3XX_TWO_CHIP_EN;
+	jasper_nand_info.parts[0] = jasper_nand_partitions;
+	jasper_nand_info.nr_parts[0] = ARRAY_SIZE(jasper_nand_partitions);
+	mmp2_add_nand(&jasper_nand_info);
+}
+
 static struct regulator_consumer_supply max8649_supply[] = {
 	REGULATOR_SUPPLY("vcc_core", NULL),
 };
@@ -128,6 +179,7 @@ static void __init jasper_init(void)
 	/* on-chip devices */
 	mmp2_add_uart(1);
 	mmp2_add_uart(3);
+	jasper_init_flash();
 	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(jasper_twsi1_info));

 	regulator_has_full_constraints();
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:35:36 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:35:36 +0800
Subject: [PATCH 16/25] pxa3xx_nand: update ns2cycle calculation method
Message-ID: <AANLkTilw9YwdJThmCo1l31kF2kSYaiNiFJ3B_sqzY1HX@mail.gmail.com>


From leiwen at marvell.com  Fri Jun  4 02:10:45 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 4 Jun 2010 14:10:45 +0800
Subject: [PATCH 16/25] pxa3xx_nand: update ns2cycle calculation method
Message-ID: <mailman.31.1276839491.27306.linux-mtd@lists.infradead.org>

For the original method change from plus 1 to minus 1,
this way make the default timing like tCS become 0 after calculation,
although we set the timing as 0xa...

Change the method to no plus and minus, and make the result
closer to what the timing specified in the NAND chip spec.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 1e75df4..bdcc881 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -318,7 +318,7 @@ static const char *mtd_names[] = {"pxa3xx_nand-0",
"pxa3xx_nand-1", NULL};
 #define NDTR1_tAR(c)	(min((c), 15) << 0)

 /* convert nano-seconds to nand flash controller clock cycles */
-#define ns2cycle(ns, clk)	(int)(((ns) * (clk / 1000000) / 1000) - 1)
+#define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
 {
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:37:05 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:37:05 +0800
Subject: [PATCH 17/25] pxa3xx_nand: use the buff passed from upper layer 
	directly if not use dma
Message-ID: <AANLkTimrtkwcaX8SF6w5D2acLa4tmo8gOr_DuuBsPaLX@mail.gmail.com>


From leiwen at marvell.com  Sun Jun  6 05:25:02 2010
From: leiwen at marvell.com (Lei Wen)
Date: Sun, 6 Jun 2010 17:25:02 +0800
Subject: [PATCH 17/25] pxa3xx_nand: use the buff passed from upper
Message-ID: <mailman.35.1276839538.27306.linux-mtd@lists.infradead.org>

layer directly if not use dma

For dma enabling case, we couldn't avoid the memcpy, for the buffer
in the upper layer may not be the physical consecutive.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  300 ++++++++++++++++++++++++----------------
 1 files changed, 182 insertions(+), 118 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index bdcc881..67acea4 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -201,6 +201,7 @@ struct pxa3xx_nand_flash {
 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;
 	/* page size of attached chip */
+	int			page_addr;
 	uint16_t		page_size;
 	uint8_t			chip_select;
 	uint8_t			use_ecc;
@@ -229,8 +230,8 @@ struct pxa3xx_nand {
 	int			drcmr_dat;
 	int			drcmr_cmd;
 	int 			data_dma_ch;
-	dma_addr_t 		data_buff_phys;
-	dma_addr_t 		data_desc_addr;
+	dma_addr_t 		dma_buff_phys;
+	dma_addr_t 		dma_desc_addr;
 	struct pxa_dma_desc	*data_desc;

 	struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
@@ -534,25 +535,25 @@ static void start_data_dma(struct pxa3xx_nand
*nand, int dir_out)
 	desc_oob->ddadr = desc->ddadr = DDADR_STOP;
 	desc_oob->dcmd = desc->dcmd = DCMD_WIDTH4 | DCMD_BURST32;
 	if (dir_out) {
-		desc->dsadr = nand->data_buff_phys + nand->data_column;
+		desc->dsadr = nand->dma_buff_phys + nand->data_column;
 		desc->dtadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG |
(data_len + oob_len);
 	} else {
 		if (nand->oob_size > 0) {
-			desc_oob->dtadr = nand->data_buff_phys
+			desc_oob->dtadr = nand->dma_buff_phys
 					+ info->page_size + nand->oob_column;
 			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | oob_len;
-			desc->ddadr = nand->data_desc_addr + sizeof(struct pxa_dma_desc);
+			desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc);
 			desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
 		}
 		else
 			desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
-		desc->dtadr = nand->data_buff_phys + nand->data_column;
+		desc->dtadr = nand->dma_buff_phys + nand->data_column;
 		desc_oob->dsadr = desc->dsadr = nand->mmio_phys + NDDB;
 	}

 	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
-	DDADR(nand->data_dma_ch) = nand->data_desc_addr;
+	DDADR(nand->data_dma_ch) = nand->dma_desc_addr;
 	DCSR(nand->data_dma_ch) |= DCSR_RUN;
 }

@@ -676,6 +677,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	int addr_cycle, exec_cmd, ndcb0, i, chunks = 0;
 	struct mtd_info *mtd;
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
+	struct platform_device *pdev = nand->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;

 	mtd = get_mtd_by_info(info);
 	ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;;
@@ -685,37 +688,33 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	/* reset data and oob column point to handle data */
 	nand->data_column	= 0;
 	nand->oob_column	= 0;
-	nand->buf_start		= 0;
-	nand->buf_count		= 0;
 	nand->total_cmds	= 1;
 	nand->cmd_seqs		= 0;
 	nand->data_size		= 0;
 	nand->oob_size		= 0;
-	nand->use_ecc		= 0;
 	nand->use_dma		= 0;
 	nand->state		= 0;
 	nand->bad_count		= 0;
 	nand->retcode		= ERR_NONE;
-	nand->command		= command;
+	nand->buf_start		= column;

 	switch (command) {
-	case NAND_CMD_READ0:
 	case NAND_CMD_PAGEPROG:
-		nand->use_ecc = info->use_ecc;
-	case NAND_CMD_READOOB:
+	case NAND_CMD_RNDOUT:
 		pxa3xx_set_datasize(info);
-		nand->oob_buff = nand->data_buff + nand->data_size;
 		nand->use_dma = use_dma;
 		chunks = info->page_size / nand->data_size;
 		break;
-	case NAND_CMD_SEQIN:
-		exec_cmd = 0;
-		break;
 	default:
 		nand->ndcb1 = 0;
 		nand->ndcb2 = 0;
+		nand->use_ecc = 0;
 		break;
 	}
+	if (nand->use_dma) {
+		nand->data_buff = nand->dma_buff;
+		nand->oob_buff = nand->dma_buff + mtd->writesize;
+	}

 	/* clear the command buffer */
 	for (i = 0; i < CMD_POOL_SIZE; i ++) {
@@ -726,68 +725,67 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 			+ info->col_addr_cycles);

 	switch (command) {
-	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-
-		cmd  = cmdset.read1;
-		if (command == NAND_CMD_READOOB)
-			nand->buf_start = mtd->writesize + column;
-		else
-			nand->buf_start = column;
-
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
-					| addr_cycle
-					| (cmd & NDCB0_CMD1_MASK);
-		else {
-			if (chunks == 1)
-				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
-						| NDCB0_DBC
-						| addr_cycle
-						| cmd;
-			else {
-				nand->total_cmds = chunks + 1;
-				nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
-						| NDCB0_CMD_TYPE(0)
-						| NDCB0_DBC
-						| NDCB0_NC
-						| addr_cycle
-						| cmd;
-
-				nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
-						| NDCB0_NC
-						| addr_cycle;
-
-				for (i = 2; i <= chunks; i ++)
-					nand->ndcb0[i] = nand->ndcb0[1];
-
-				nand->ndcb0[chunks] &= ~NDCB0_NC;
-				/* we should wait RnB go high again
-				 * before read out data*/
-				nand->wait_ready[1] = 1;
-			}
-		}
-
 	case NAND_CMD_SEQIN:
+		nand->use_ecc = info->use_ecc;
+	case NAND_CMD_READOOB:
+		memset(nand->data_buff, 0xff, column);
+		nand->buf_count = mtd->writesize + mtd->oobsize;
+		exec_cmd = 0;
+		info->page_addr = page_addr;
 		/* small page addr setting */
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
 			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
-
-			nand->ndcb2 = 0;
-		}
 		else {
 			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
 					| (column & 0xFFFF);

 			if (page_addr & 0xFF0000)
 				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
+		}
+		break;
+
+	case NAND_CMD_RNDOUT:
+		cmd = cmdset.read1;
+		if (nand->command == NAND_CMD_READOOB) {
+			nand->buf_start = mtd->writesize + column;
+			nand->buf_count = mtd->oobsize;
+		}
+
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)
+			|| !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
+			if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
+						| addr_cycle
+						| (cmd & NDCB0_CMD1_MASK);
 			else
-				nand->ndcb2 = 0;
+				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
+						| NDCB0_DBC
+						| addr_cycle
+						| cmd;
+			break;
 		}

-		nand->buf_count = mtd->writesize + mtd->oobsize;
-		memset(nand->data_buff, 0xFF, nand->buf_count);
+		nand->total_cmds = chunks + 1;
+		nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
+				| NDCB0_CMD_TYPE(0)
+				| NDCB0_DBC
+				| NDCB0_NC
+				| addr_cycle
+				| cmd;
+
+		nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
+				| NDCB0_NC
+				| addr_cycle;
+
+		for (i = 2; i <= chunks; i ++)
+			nand->ndcb0[i] = nand->ndcb0[1];
+
+		nand->ndcb0[chunks] &= ~NDCB0_NC;
+		/* we should wait RnB go high again
+		 * before read out data*/
+		nand->wait_ready[1] = 1;

 		break;

@@ -799,40 +797,42 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 		cmd = cmdset.program;
 		nand->state |= STATE_IS_WRITE;
-		if (chunks == 1)
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)
+			|| !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
 			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0x1)
 					| NDCB0_AUTO_RS
 					| NDCB0_ST_ROW_EN
 					| NDCB0_DBC
 					| cmd
 					| addr_cycle;
-		else {
-			nand->total_cmds = chunks + 1;
-			nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x4)
-					| NDCB0_CMD_TYPE(0x1)
+			break;
+		}
+
+		nand->total_cmds = chunks + 1;
+		nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x4)
+				| NDCB0_CMD_TYPE(0x1)
+				| NDCB0_NC
+				| NDCB0_AUTO_RS
+				| (cmd & NDCB0_CMD1_MASK)
+				| addr_cycle;
+
+		for (i = 1; i < chunks; i ++)
+			nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
 					| NDCB0_NC
 					| NDCB0_AUTO_RS
-					| (cmd & NDCB0_CMD1_MASK)
+					| NDCB0_CMD_TYPE(0x1)
 					| addr_cycle;

-			for (i = 1; i < chunks; i ++)
-				nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
-						| NDCB0_NC
-						| NDCB0_AUTO_RS
-						| NDCB0_CMD_TYPE(0x1)
-						| addr_cycle;
-
-			nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
-						| NDCB0_CMD_TYPE(0x1)
-						| NDCB0_ST_ROW_EN
-						| NDCB0_DBC
-						| (cmd & NDCB0_CMD2_MASK)
-						| NDCB0_CMD1_MASK
-						| addr_cycle;
-			/* we should wait for RnB goes high which
-			 * indicate the data has been written succesfully*/
-			nand->wait_ready[nand->total_cmds] = 1;
-		}
+		nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
+				| NDCB0_CMD_TYPE(0x1)
+				| NDCB0_ST_ROW_EN
+				| NDCB0_DBC
+				| (cmd & NDCB0_CMD2_MASK)
+				| NDCB0_CMD1_MASK
+				| addr_cycle;
+		/* we should wait for RnB goes high which
+		 * indicate the data has been written succesfully*/
+		nand->wait_ready[nand->total_cmds] = 1;
 		break;

 	case NAND_CMD_READID:
@@ -847,6 +847,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,

 	case NAND_CMD_STATUS:
 		cmd = cmdset.read_status;
+		nand->data_buff = nand->dma_buff;
 		nand->buf_count = 1;
 		nand->ndcb0[0] |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
@@ -883,6 +884,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		break;
 	}

+	nand->command = command;
 	return exec_cmd;
 }

@@ -1106,44 +1108,104 @@ static void free_cs_resource(struct
pxa3xx_nand_info *info, int cs)
 	nand->info[cs] = NULL;
 }

-static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
-		struct nand_chip *chip, uint8_t *buf, int page)
+static void pxa3xx_read_page(struct mtd_info *mtd, uint8_t *buf)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	struct pxa3xx_nand *nand = info->nand_data;
+	int buf_blank;

-	chip->read_buf(mtd, buf, mtd->writesize);
-	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-	if (nand->retcode == ERR_SBERR) {
+	nand->data_buff = buf;
+	nand->oob_buff = chip->oob_poi;
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RNDOUT, 0, info->page_addr);
+	switch (nand->retcode) {
+	case ERR_SBERR:
 		switch (nand->use_ecc) {
 		case ECC_BCH:
 			if (nand->bad_count > BCH_THRESHOLD)
 				mtd->ecc_stats.corrected +=
 					(nand->bad_count - BCH_THRESHOLD);
 			break;
+
 		case ECC_HAMMIN:
 			mtd->ecc_stats.corrected ++;
+			break;
+
 		case ECC_NONE:
 		default:
 			break;
 		}
-	} else if (nand->retcode == ERR_DBERR) {
-		int buf_blank;
-
-		buf_blank = is_buf_blank(buf, mtd->writesize);
+		break;
+	case ERR_DBERR:
+		buf_blank = is_buf_blank(nand->data_buff, mtd->writesize);
 		if (!buf_blank)
 			mtd->ecc_stats.failed++;
+		break;
+	case ERR_NONE:
+		break;
+	default:
+		mtd->ecc_stats.failed++;
+		break;
 	}
+}

+static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, uint8_t *buf, int page)
+{
+	pxa3xx_read_page(mtd, buf);
+	if (use_dma) {
+		chip->read_buf(mtd, buf, mtd->writesize);
+		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+	}
+	return 0;
+}
+
+static int pxa3xx_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+		int page, int sndcmd)
+{
+	if (sndcmd) {
+		pxa3xx_nand_cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+		pxa3xx_read_page(mtd, chip->oob_poi);
+	}
+	if (use_dma)
+		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 	return 0;
 }

 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 		struct nand_chip *chip, const uint8_t *buf)
 {
-	chip->write_buf(mtd, buf, mtd->writesize);
-	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
+	if (use_dma) {
+		chip->write_buf(mtd, buf, mtd->writesize);
+		chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	}
+	else {
+		nand->data_buff = (uint8_t *)buf;
+		nand->oob_buff = chip->oob_poi;
+	}
+}
+
+static int pxa3xx_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+			      int page)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
+	int status = 0;
+
+	nand->data_buff = nand->dma_buff;
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	if (use_dma)
+		chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	else
+		nand->oob_buff = chip->oob_poi;
+	/* Send command to program the OOB data */
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	status = chip->waitfunc(mtd, chip);
+
+	return status & NAND_STATUS_FAIL ? -EIO : 0;
 }

 static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
@@ -1191,8 +1253,8 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 		return -EINVAL;
 	}

+	nand->data_buff = (unsigned char *)&id;
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(nand->data_buff));
 	if (id != 0)
 		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id);
 	else {
@@ -1349,7 +1411,11 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		chip = (struct nand_chip *)(&mtd[1]);
 		chip->controller        = &nand->controller;
 		chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+		chip->ecc.read_page_raw = pxa3xx_nand_read_page_hwecc;
+		chip->ecc.read_oob      = pxa3xx_nand_read_oob;
 		chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+		chip->ecc.write_page_raw= pxa3xx_nand_write_page_hwecc;
+		chip->ecc.write_oob     = pxa3xx_nand_write_oob;
 		chip->waitfunc		= pxa3xx_nand_waitfunc;
 		chip->select_chip	= pxa3xx_nand_select_chip;
 		chip->cmdfunc		= pxa3xx_nand_cmdfunc;
@@ -1361,25 +1427,16 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		chip->erase_cmd		= pxa3xx_nand_erase_cmd;
 	}

-	if (use_dma == 0) {
-		nand->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
-		if (nand->data_buff == NULL) {
-			ret = -ENOMEM;
-			goto fail_free_buf;
-		}
-		goto success_exit;
-	}
-
-	nand->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
-			&nand->data_buff_phys, GFP_KERNEL);
-	if (nand->data_buff == NULL) {
+	nand->dma_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
+			&nand->dma_buff_phys, GFP_KERNEL);
+	if (nand->dma_buff == NULL) {
 		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
 		ret = -ENOMEM;
 		goto fail_free_buf;
 	}

-	nand->data_desc = (void *)nand->data_buff + data_desc_offset;
-	nand->data_desc_addr = nand->data_buff_phys + data_desc_offset;
+	nand->data_desc = (void *)nand->dma_buff + data_desc_offset;
+	nand->dma_desc_addr = nand->dma_buff_phys + data_desc_offset;
 	nand->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
 			pxa3xx_nand_data_dma_irq, nand);
 	if (nand->data_dma_ch < 0) {
@@ -1387,7 +1444,6 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		ret = -ENXIO;
 		goto fail_free_buf;
 	}
-success_exit:
 	return 0;

 fail_free_buf:
@@ -1437,6 +1493,14 @@ static int pxa3xx_nand_remove(struct
platform_device *pdev)
 		del_mtd_device(mtd);
 		free_cs_resource(info, cs);
 	}
+	if (nand->dma_buff_phys) {
+		if (nand->data_dma_ch >= 0)
+			pxa_free_dma(nand->data_dma_ch);
+		if (nand->dma_buff)
+			dma_free_coherent(&nand->pdev->dev, MAX_BUFF_SIZE,
+					nand->dma_buff, nand->dma_buff_phys);
+		nand->dma_buff_phys = 0;
+	}
 	return 0;
 }

-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:37:13 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:37:13 +0800
Subject: [PATCH 18/25] pxa3xx_nand: add ext id to distinguish different flash 
	with the same chip id
Message-ID: <AANLkTinf5DtfsXFrQagjrDFdBk3YnqD9kNJFlaPjJt9-@mail.gmail.com>


From leiwen at marvell.com  Sun Jun  6 21:24:11 2010
From: leiwen at marvell.com (Lei Wen)
Date: Mon, 7 Jun 2010 09:24:11 +0800
Subject: [PATCH 18/25] pxa3xx_nand: add ext id to distinguish
Message-ID: <mailman.37.1276839550.27306.linux-mtd@lists.infradead.org>

different flash with the same chip id

For K9LBG08U0M and K9LBG08UXD two nand chip, they have the same chip id as
0xd7ec. So we should use the ext id to distinguish them.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   35 ++++++++++++++++++-----------------
 1 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 67acea4..e4ccf7c 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -188,7 +188,8 @@ struct pxa3xx_nand_cmdset {

 struct pxa3xx_nand_flash {
 	char		*name;
-	uint32_t	chip_id;
+	uint16_t	chip_id;
+	uint16_t	ext_id;
 	uint16_t	page_per_block; /* Pages per block */
 	uint16_t 	page_size;	/* Page size in bytes */
 	uint8_t		flash_width;	/* Width of Flash memory (DWIDTH_M) */
@@ -292,17 +293,17 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 };

 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-{ 		0,	0,   0,    0,  0,  0, ECC_NONE,      0, &timing[0], },
-{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, ECC_HAMMIN, 4096, &timing[1], },
-{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, ECC_HAMMIN, 2048, &timing[1], },
-{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, ECC_BCH,    4096, &timing[1], },
-{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, ECC_BCH,    8192, &timing[1], },
-{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, ECC_HAMMIN, 1024, &timing[2], },
-{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, ECC_HAMMIN, 1024, &timing[2], },
-{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, ECC_HAMMIN, 4096, &timing[2], },
-{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, ECC_HAMMIN, 4096, &timing[2], },
-{ "1GiB 8-bit",    0x382c, 128, 4096,  8,  8, ECC_BCH,    2048, &timing[2], },
-{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, ECC_HAMMIN, 2048, &timing[3], },
+{ 		0,	0,	0,   0,	   0,  0,  0, ECC_NONE,      0, &timing[0], },
+{ "64MiB 16-bit",  0x46ec, 0xffff,  32,  512, 16, 16, ECC_HAMMIN,
4096, &timing[1], },
+{ "256MiB 8-bit",  0xdaec, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
2048, &timing[1], },
+{ "1GiB 8-bit",    0xd3ec, 0xffff, 128, 2048,  8,  8, ECC_BCH,
4096, &timing[1], },
+{ "4GiB 8-bit",    0xd7ec, 0x29d5, 128, 4096,  8,  8, ECC_BCH,
8192, &timing[1], },
+{ "128MiB 8-bit",  0xa12c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
1024, &timing[2], },
+{ "128MiB 16-bit", 0xb12c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
1024, &timing[2], },
+{ "512MiB 8-bit",  0xdc2c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
4096, &timing[2], },
+{ "512MiB 16-bit", 0xcc2c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
4096, &timing[2], },
+{ "1GiB 8-bit",    0x382c, 0xffff, 128, 4096,  8,  8, ECC_BCH,
2048, &timing[2], },
+{ "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
2048, &timing[3], },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
@@ -1237,7 +1238,7 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 	struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
-	uint32_t id = -1;
+	uint16_t id[2];
 	uint64_t chipsize;
 	int i, ret;

@@ -1253,10 +1254,10 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 		return -EINVAL;
 	}

-	nand->data_buff = (unsigned char *)&id;
+	nand->data_buff = (unsigned char *)id;
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	if (id != 0)
-		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id);
+	if (id[0] != 0)
+		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id[0]);
 	else {
 		dev_warn(&nand->pdev->dev, "Read out ID 0, potential timing set wrong!!\n");
 		free_cs_resource(info, nand->chip_select);
@@ -1270,7 +1271,7 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 			f = &builtin_flash_types[i - pdata->num_flash + 1];

 		/* find the chip in default list */
-		if (f->chip_id == id)
+		if ((f->chip_id == id[0]) && ((f->ext_id & id[1]) == id[1]))
 			break;
 	}

-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:37:20 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:37:20 +0800
Subject: [PATCH 19/25] pxa3xx_nand: support ecc requirement higher than 4bit 
	per 512 bytes
Message-ID: <AANLkTimSs22EFQRYNTEEOv4YSlwNRKaWReOfVHINJ2Vj@mail.gmail.com>


From leiwen at marvell.com  Mon Jun  7 03:13:50 2010
From: leiwen at marvell.com (Lei Wen)
Date: Mon, 7 Jun 2010 15:13:50 +0800
Subject: [PATCH 19/25] pxa3xx_nand: support ecc requirement higher
Message-ID: <mailman.38.1276839552.27306.linux-mtd@lists.infradead.org>

than 4bit per 512 bytes

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  118 ++++++++++++++++++++++++----------------
 1 files changed, 71 insertions(+), 47 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index e4ccf7c..04bf875 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -33,6 +33,8 @@
 #define BCH_THRESHOLD           (8)
 #define CMD_POOL_SIZE           (5)
 #define READ_ID_BYTES		(4)
+#define BCH_STRENGTH		(4)
+#define HAMMING_STRENGTH	(1)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -84,9 +86,9 @@
 #define NDCR_RDDREQM            (0x1 << 1)
 #define NDCR_WRCMDREQM          (0x1)

+#define NDSR_MASK		(0xffffffff)
 #define NDSR_ERR_CNT_MASK       (0x1F << 16)
 #define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
-#define NDSR_MASK		(0xfff)
 #define NDSR_RDY                (0x1 << 12)
 #define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED		(0x1 << 10)
@@ -103,6 +105,7 @@

 #define NDCB0_CMD_XTYPE_MASK    (0x7 << 29)
 #define NDCB0_CMD_XTYPE(x)      (((x) << 29) & NDCB0_CMD_XTYPE_MASK)
+#define NDCB0_LEN_OVRD		(0x1 << 28)
 #define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS		(0x1 << 25)
 #define NDCB0_CSEL		(0x1 << 24)
@@ -194,7 +197,7 @@ struct pxa3xx_nand_flash {
 	uint16_t 	page_size;	/* Page size in bytes */
 	uint8_t		flash_width;	/* Width of Flash memory (DWIDTH_M) */
 	uint8_t 	dfc_width;	/* Width of flash controller(DWIDTH_C) */
-	uint8_t		ecc_type;	/* Which ECC is applied */
+	uint8_t		ecc_strength;	/* How strong a ecc should be applied */
 	uint32_t	num_blocks;	/* Number of physical blocks in Flash */
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
@@ -205,7 +208,7 @@ struct pxa3xx_nand_info {
 	int			page_addr;
 	uint16_t		page_size;
 	uint8_t			chip_select;
-	uint8_t			use_ecc;
+	uint8_t			ecc_strength;

 	/* calculated from pxa3xx_nand_flash data */
 	uint8_t			col_addr_cycles;
@@ -250,8 +253,8 @@ struct pxa3xx_nand {

 	/* relate to the command */
 	uint8_t			chip_select;
+	uint8_t			ecc_strength;
 	unsigned int		state;
-	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
 	int 			retcode;

@@ -262,6 +265,7 @@ struct pxa3xx_nand {
 	uint32_t		ndcb0[CMD_POOL_SIZE];
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;
+	uint32_t		ndcb3[CMD_POOL_SIZE];
 };

 static int use_dma = 1;
@@ -293,17 +297,17 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 };

 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-{ 		0,	0,	0,   0,	   0,  0,  0, ECC_NONE,      0, &timing[0], },
-{ "64MiB 16-bit",  0x46ec, 0xffff,  32,  512, 16, 16, ECC_HAMMIN,
4096, &timing[1], },
-{ "256MiB 8-bit",  0xdaec, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
2048, &timing[1], },
-{ "1GiB 8-bit",    0xd3ec, 0xffff, 128, 2048,  8,  8, ECC_BCH,
4096, &timing[1], },
-{ "4GiB 8-bit",    0xd7ec, 0x29d5, 128, 4096,  8,  8, ECC_BCH,
8192, &timing[1], },
-{ "128MiB 8-bit",  0xa12c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
1024, &timing[2], },
-{ "128MiB 16-bit", 0xb12c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
1024, &timing[2], },
-{ "512MiB 8-bit",  0xdc2c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
4096, &timing[2], },
-{ "512MiB 16-bit", 0xcc2c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
4096, &timing[2], },
-{ "1GiB 8-bit",    0x382c, 0xffff, 128, 4096,  8,  8, ECC_BCH,
2048, &timing[2], },
-{ "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
2048, &timing[3], },
+{ 		0,	0,	0,   0,	   0,  0,  0, 0,    0, &timing[0], },
+{ "64MiB 16-bit",  0x46ec, 0xffff,  32,  512, 16, 16, 1, 4096, &timing[1], },
+{ "256MiB 8-bit",  0xdaec, 0xffff,  64, 2048,  8,  8, 1, 2048, &timing[1], },
+{ "1GiB 8-bit",    0xd3ec, 0xffff, 128, 2048,  8,  8, 4, 4096, &timing[1], },
+{ "4GiB 8-bit",    0xd7ec, 0x29d5, 128, 4096,  8,  8, 8, 8192, &timing[1], },
+{ "128MiB 8-bit",  0xa12c, 0xffff,  64, 2048,  8,  8, 1, 1024, &timing[2], },
+{ "128MiB 16-bit", 0xb12c, 0xffff,  64, 2048, 16, 16, 1, 1024, &timing[2], },
+{ "512MiB 8-bit",  0xdc2c, 0xffff,  64, 2048,  8,  8, 1, 4096, &timing[2], },
+{ "512MiB 16-bit", 0xcc2c, 0xffff,  64, 2048, 16, 16, 1, 4096, &timing[2], },
+{ "1GiB 8-bit",    0x382c, 0xffff, 128, 4096,  8,  8, 4, 2048, &timing[2], },
+{ "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, 1, 2048, &timing[3], },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
@@ -358,16 +362,15 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 			return;
 		}

-		switch (nand->use_ecc) {
-		case ECC_HAMMIN:
-			nand->oob_size = 40;
+		switch (nand->ecc_strength) {
+		case 0:
+			nand->oob_size = 64;
 			break;
-		case ECC_BCH:
-			nand->oob_size = 32;
+		case HAMMING_STRENGTH:
+			nand->oob_size = 40;
 			break;
 		default:
-			nand->oob_size = 64;
-			break;
+			nand->oob_size = 32;
 		}
 	} else {
 		nand->data_size = 512;
@@ -376,17 +379,16 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 			return;
 		}

-		switch (nand->use_ecc) {
-		case ECC_HAMMIN:
+		switch (nand->ecc_strength) {
+		case 0:
+			nand->oob_size = 16;
+			break;
+		case HAMMING_STRENGTH:
 			nand->oob_size = 8;
 			break;
-		case ECC_BCH:
+		default:
 			printk("Don't support BCH on small page device!!!\n");
 			BUG();
-			break;
-		default:
-			nand->oob_size = 16;
-			break;
 		}
 	}
 }
@@ -404,16 +406,16 @@ static void pxa3xx_nand_start(struct pxa3xx_nand *nand)

 	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
-	ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
+	ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
 	ndcr |= NDCR_ND_RUN;

-	switch (nand->use_ecc) {
-	case ECC_BCH:
+	switch (nand->ecc_strength) {
+	default:
 		ndeccctrl |= NDECCCTRL_BCH_EN;
 		ndeccctrl |= NDECCCTRL_ECC_THRESH(BCH_THRESHOLD);
-	case ECC_HAMMIN:
+	case HAMMING_STRENGTH:
 		ndcr |= NDCR_ECC_EN;
-	default:
+	case 0:
 		break;
 	}

@@ -649,6 +651,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 			nand_writel(nand, NDCB0, nand->ndcb0[cmd_seqs]);
 			nand_writel(nand, NDCB0, ndcb1);
 			nand_writel(nand, NDCB0, ndcb2);
+			if (nand->ndcb3[cmd_seqs])
+				nand_writel(nand, NDCB0, nand->ndcb3[cmd_seqs]);
 		}
 		else
 			is_completed = 1;
@@ -705,11 +709,23 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		pxa3xx_set_datasize(info);
 		nand->use_dma = use_dma;
 		chunks = info->page_size / nand->data_size;
+		if (info->ecc_strength > BCH_STRENGTH) {
+			i = info->ecc_strength / BCH_STRENGTH;
+			nand->data_size /= i;
+			ndcb0 |= NDCB0_LEN_OVRD;
+			chunks *= i;
+		}
 		break;
+	case NAND_CMD_READOOB:
+		if (info->ecc_strength > BCH_STRENGTH) {
+			printk(KERN_ERR "we don't support oob command if use"
+				     " 8bit per 512bytes ecc feature!!\n");
+			BUG();
+		}
 	default:
 		nand->ndcb1 = 0;
 		nand->ndcb2 = 0;
-		nand->use_ecc = 0;
+		nand->ecc_strength = 0;
 		break;
 	}
 	if (nand->use_dma) {
@@ -721,6 +737,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	for (i = 0; i < CMD_POOL_SIZE; i ++) {
 		nand->ndcb0[i] = ndcb0;
 		nand->wait_ready[i] = 0;
+		nand->ndcb3[i] = (ndcb0 & NDCB0_LEN_OVRD)? nand->data_size : 0;
 	}
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);
@@ -728,7 +745,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	switch (command) {
 	case NAND_CMD_READ0:
 	case NAND_CMD_SEQIN:
-		nand->use_ecc = info->use_ecc;
+		nand->ecc_strength = info->ecc_strength;
 	case NAND_CMD_READOOB:
 		memset(nand->data_buff, 0xff, column);
 		nand->buf_count = mtd->writesize + mtd->oobsize;
@@ -775,7 +792,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 				| NDCB0_NC
 				| addr_cycle
 				| cmd;
-
+		nand->ndcb0[0] &= ~NDCB0_LEN_OVRD;
+		nand->ndcb3[0] = 0;
 		nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
 				| NDCB0_NC
 				| addr_cycle;
@@ -831,6 +849,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 				| (cmd & NDCB0_CMD2_MASK)
 				| NDCB0_CMD1_MASK
 				| addr_cycle;
+		nand->ndcb0[chunks] &= ~NDCB0_LEN_OVRD;
+		nand->ndcb3[chunks] = 0;
 		/* we should wait for RnB goes high which
 		 * indicate the data has been written succesfully*/
 		nand->wait_ready[nand->total_cmds] = 1;
@@ -1022,7 +1042,12 @@ static void pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 		BUG();
 	}
 	/* calculate flash information */
-	info->use_ecc = f->ecc_type;
+	if (f->ecc_strength != 0 && f->ecc_strength != HAMMING_STRENGTH
+			&& (f->ecc_strength % BCH_STRENGTH != 0)) {
+		printk(KERN_ERR "ECC strength definition error, please recheck!!\n");
+		BUG();
+	}
+	info->ecc_strength = f->ecc_strength;
 	info->page_size = f->page_size;

 	/* calculate addressing information */
@@ -1066,7 +1091,9 @@ static void pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	}

 	ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
-	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
+	/* only enable spare area when ecc is lower than 8bits per 512 bytes */
+	if (f->ecc_strength <= BCH_STRENGTH)
+		ndcr |= NDCR_SPARE_EN;

 	info->reg_ndcr = ndcr;

@@ -1086,7 +1113,7 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)
 	info->reg_ndcr = ndcr & ~(NDCR_INT_MASK | NDCR_ECC_EN | NDCR_DMA_EN
| NDCR_ND_RUN);
 	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
-	info->use_ecc = (ndeccctrl & NDECCCTRL_BCH_EN) ? ECC_BCH : ECC_HAMMIN;
+	info->ecc_strength = (ndeccctrl & NDECCCTRL_BCH_EN) ? BCH_STRENGTH :
HAMMING_STRENGTH;

 	return 0;
 }
@@ -1121,19 +1148,16 @@ static void pxa3xx_read_page(struct mtd_info
*mtd, uint8_t *buf)
 	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RNDOUT, 0, info->page_addr);
 	switch (nand->retcode) {
 	case ERR_SBERR:
-		switch (nand->use_ecc) {
-		case ECC_BCH:
+		switch (nand->ecc_strength) {
+		default:
 			if (nand->bad_count > BCH_THRESHOLD)
 				mtd->ecc_stats.corrected +=
 					(nand->bad_count - BCH_THRESHOLD);
 			break;

-		case ECC_HAMMIN:
+		case HAMMING_STRENGTH:
 			mtd->ecc_stats.corrected ++;
-			break;
-
-		case ECC_NONE:
-		default:
+		case 0:
 			break;
 		}
 		break;
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:37:30 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:37:30 +0800
Subject: [PATCH 20/25] pxa3xx_nand: add advanced timing tuning feature
Message-ID: <AANLkTikeAtEbhzZa_T-pcvOb0vfYMXY1cYH7RMjHGAqm@mail.gmail.com>


From leiwen at marvell.com  Tue Jun  8 00:13:08 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 8 Jun 2010 12:13:08 +0800
Subject: [PATCH 20/25] pxa3xx_nand: add advanced timing tuning feature
Message-ID: <mailman.39.1276839554.27306.linux-mtd@lists.infradead.org>

For new controller, it has more power at more precise timing
tuning.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   93 ++++++++++++++++++++++++++++------------
 1 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 04bf875..834422d 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -165,6 +165,7 @@ enum {
 };

 struct pxa3xx_nand_timing {
+	uint32_t	tADL; /* Adress to Write Data delay */
 	uint32_t	tCH;  /* Enable signal hold time */
 	uint32_t	tCS;  /* Enable signal setup time */
 	uint32_t	tWH;  /* ND_nWE high duration */
@@ -172,6 +173,7 @@ struct pxa3xx_nand_timing {
 	uint32_t	tRH;  /* ND_nRE high duration */
 	uint32_t	tRP;  /* ND_nRE pulse width */
 	uint32_t	tR;   /* ND_nWE high to ND_nRE low for read */
+	uint32_t	tRHW; /* delay for next command issue */
 	uint32_t	tWHR; /* ND_nWE high to ND_nRE low for status read */
 	uint32_t	tAR;  /* ND_ALE low to ND_nRE low delay */
 };
@@ -287,13 +289,13 @@ const static struct pxa3xx_nand_cmdset cmdset = {

 static struct pxa3xx_nand_timing __devinitdata timing[] = {
 	/* common timing used to detect flash id */
-	{ 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
+	{   0, 40, 80, 60, 100, 80, 100, 90000,  0, 400, 40, },
 	/* Samsung NAND series */
-	{ 10,  0, 20,  40, 30,  40, 11123, 110, 10, },
+	{ 200, 10, 15, 20,  40, 30,  40, 11123, 20, 110, 10, },
 	/* Micron NAND series */
-	{ 10, 25, 15,  25, 15,  30, 25000,  60, 10, },
+	{   0, 10, 25, 15,  25, 15,  30, 25000,  0,  60, 10, },
 	/* ST NAND series */
-	{ 10, 35, 15,  25, 15,  25, 25000,  60, 10, },
+	{   0, 10, 35, 15,  25, 15,  25, 25000,  0,  60, 10, },
 };

 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
@@ -312,16 +314,20 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};

-#define NDTR0_tCH(c)	(min((c), 7) << 19)
-#define NDTR0_tCS(c)	(min((c), 7) << 16)
-#define NDTR0_tWH(c)	(min((c), 7) << 11)
-#define NDTR0_tWP(c)	(min((c), 7) << 8)
-#define NDTR0_tRH(c)	(min((c), 7) << 3)
-#define NDTR0_tRP(c)	(min((c), 7) << 0)
-
-#define NDTR1_tR(c)	(min((c), 65535) << 16)
-#define NDTR1_tWHR(c)	(min((c), 15) << 4)
-#define NDTR1_tAR(c)	(min((c), 15) << 0)
+#define NDTR0_tADL(c)		(min_t(uint32_t, (c), 31) << 27)
+#define NDTR0_tCH(c)		(min_t(uint32_t, (c), 7) << 19)
+#define NDTR0_tCS(c)		(min_t(uint32_t, (c), 7) << 16)
+#define NDTR0_tWH(c)		(min_t(uint32_t, (c), 7) << 11)
+#define NDTR0_tWP(c)		(min_t(uint32_t, (c), 7) << 8)
+#define NDTR0_ETRP		(0x1 << 6)
+#define NDTR0_tRH(c)		(min_t(uint32_t, (c), 7) << 3)
+#define NDTR0_tRP(c)		(min_t(uint32_t, (c), 7) << 0)
+
+#define NDTR1_tR(c)		(min_t(uint32_t, (c), 65535) << 16)
+#define NDTR1_PRESCALE		(0x1 << 14)
+#define NDTR1_tRHW(c)		(min_t(uint32_t, (c), 3) << 8)
+#define NDTR1_tWHR(c)		(min_t(uint32_t, (c), 15) << 4)
+#define NDTR1_tAR(c)		(min_t(uint32_t, (c), 15) << 0)

 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
@@ -329,20 +335,51 @@ static void pxa3xx_nand_set_timing(struct
pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
 {
 	struct pxa3xx_nand *nand = info->nand_data;
-	unsigned long nand_clk;
-	uint32_t ndtr0, ndtr1;
-
-	nand_clk = clk_get_rate(nand->clk);
-	ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
-		NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
-		NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
-		NDTR0_tWP(ns2cycle(t->tWP, nand_clk)) |
-		NDTR0_tRH(ns2cycle(t->tRH, nand_clk)) |
-		NDTR0_tRP(ns2cycle(t->tRP, nand_clk));
-
-	ndtr1 = NDTR1_tR(ns2cycle(t->tR, nand_clk)) |
-		NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
-		NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
+	struct platform_device *pdev = nand->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	unsigned long nand_clk = clk_get_rate(nand->clk);
+	uint32_t ndtr0, ndtr1, tRP, tR, tRHW, tADL;
+
+	tR = ns2cycle(t->tR, nand_clk);
+	tRP = ns2cycle(t->tRP, nand_clk);
+	tRHW = tADL = ndtr0 = ndtr1 = 0;
+	if (pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)
+		tR = 0;
+	if (pdata->controller_attrs & PXA3XX_ADV_TIME_TUNING) {
+		if (tRP > 0x7) {
+			ndtr0 |= NDTR0_ETRP;
+			tRP -= 0x7;
+		}
+		if (tR > 0xffff) {
+			ndtr1 |= NDTR1_PRESCALE;
+			tR /= 16;
+		}
+		if (t->tRHW > 0) {
+			tRHW = ns2cycle(t->tRHW, nand_clk);
+			if (tRHW < 16)
+				tRHW = 1;
+			else {
+				if (tRHW < 32)
+					tRHW = 2;
+				else
+					tRHW = 3;
+			}
+		}
+		tADL = ns2cycle(t->tADL, nand_clk);
+	}
+
+	ndtr0 |= NDTR0_tADL(tADL)
+		| NDTR0_tCH(ns2cycle(t->tCH, nand_clk))
+		| NDTR0_tCS(ns2cycle(t->tCS, nand_clk))
+		| NDTR0_tWH(ns2cycle(t->tWH, nand_clk))
+		| NDTR0_tWP(ns2cycle(t->tWP, nand_clk))
+		| NDTR0_tRH(ns2cycle(t->tRH, nand_clk))
+		| NDTR0_tRP(tRP);
+
+	ndtr1 |= NDTR1_tR(tR)
+		| NDTR1_tRHW(tRHW)
+		| NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk))
+		| NDTR1_tAR(ns2cycle(t->tAR, nand_clk));

 	info->ndtr0cs0 = ndtr0;
 	info->ndtr1cs0 = ndtr1;
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:37:37 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:37:37 +0800
Subject: [PATCH 21/25] pxa3xx_nand: add polling mode support
Message-ID: <AANLkTimyukBDuRU86Q8iegluZ5WsGKxqB0_5DuSBYGaC@mail.gmail.com>


From leiwen at marvell.com  Tue Jun  8 03:10:41 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 8 Jun 2010 15:10:41 +0800
Subject: [PATCH 21/25] pxa3xx_nand: add polling mode support
Message-ID: <mailman.41.1276839570.27306.linux-mtd@lists.infradead.org>

Add polling mode to facilitate debugging.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    1 +
 drivers/mtd/nand/pxa3xx_nand.c               |   55 +++++++++++++++++++++----
 2 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 72bb70e..ae63a5f 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -17,6 +17,7 @@
  * enable such tuning for those platform which support it */
 #define PXA3XX_ADV_TIME_TUNING	(1 << 4)
 #define PXA3XX_KEEP_CONFIG	(1 << 5)
+#define PXA3XX_POOLING_MODE	(1 << 6)
 struct pxa3xx_nand_platform_data {
 	unsigned int				controller_attrs;
 	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 834422d..7f8bae7 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -274,6 +274,10 @@ static int use_dma = 1;
 module_param(use_dma, bool, 0444);
 MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");

+static int use_polling = 0;
+module_param(use_polling, bool, 0444);
+MODULE_PARM_DESC(use_polling, "Use full polling mode");
+
 const static struct pxa3xx_nand_cmdset cmdset = {
 	.read1		= 0x3000,
 	.read2		= 0x0050,
@@ -444,6 +448,7 @@ static void pxa3xx_nand_start(struct pxa3xx_nand *nand)
 	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
 	ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
+	ndcr |= use_polling ? NDCR_INT_MASK : 0;
 	ndcr |= NDCR_ND_RUN;

 	switch (nand->ecc_strength) {
@@ -615,9 +620,8 @@ static void pxa3xx_nand_data_dma_irq(int channel,
void *data)
 	nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }

-static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
+static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand)
 {
-	struct pxa3xx_nand *nand = devid;
 	struct pxa3xx_nand_info *info;
 	unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2;
 	unsigned int ready, cmd_done, page_done, badblock_detect;
@@ -654,13 +658,20 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	if (status & ready) {
 		nand->state |= STATE_READY;
 		if (nand->wait_ready[cmd_seqs]) {
-			enable_int(nand, NDCR_WRCMDREQM);
+			if (!use_polling)
+				enable_int(nand, NDCR_WRCMDREQM | NDCR_CS0_CMDDM
+						| NDCR_CS1_CMDDM);
 			if (cmd_seqs == nand->total_cmds)
 				is_completed = 1;
 		}
 	}
 	if (status & cmd_done) {
 		nand->state |= STATE_CMD_DONE;
+		if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) {
+			status &= ~cmd_done;
+			if (!use_polling)
+				disable_int(nand, NDCR_CS0_CMDDM | NDCR_CS1_CMDDM);
+		}
 		if (cmd_seqs == nand->total_cmds && !nand->wait_ready[cmd_seqs])
 			is_completed = 1;
 	}
@@ -668,7 +679,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	if (status & NDSR_WRCMDREQ) {
 		status &= ~NDSR_WRCMDREQ;
 		if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) {
-			disable_int(nand, NDCR_WRCMDREQM);
+			if (!use_polling)
+				disable_int(nand, NDCR_WRCMDREQM);
 			goto IRQ_FORCE_EXIT;
 		}

@@ -698,12 +710,32 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 IRQ_FORCE_EXIT:
 	/* clear NDSR to let the controller exit the IRQ */
 	nand_writel(nand, NDSR, status);
-	if (is_completed)
-		complete(&nand->cmd_complete);
 NORMAL_IRQ_EXIT:
+	return is_completed;
+}
+
+static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
+{
+	struct pxa3xx_nand *nand = devid;
+	if (pxa3xx_nand_transaction(nand))
+		complete(&nand->cmd_complete);
 	return IRQ_HANDLED;
 }

+static int pxa3xx_nand_polling(struct pxa3xx_nand *nand, unsigned long timeout)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < timeout; i++) {
+		ret = pxa3xx_nand_transaction(nand);
+		if (ret)
+			break;
+		udelay(10);
+	}
+
+	return ret;
+}
+
 static inline int is_buf_blank(uint8_t *buf, size_t len)
 {
 	for (; len > 0; len--)
@@ -973,8 +1005,11 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		nand->state |= STATE_CMD_PREPARED;
 		pxa3xx_nand_start(nand);

-		ret = wait_for_completion_timeout(&nand->cmd_complete,
-				CHIP_DELAY_TIMEOUT);
+		if (!use_polling)
+			ret = wait_for_completion_timeout(&nand->cmd_complete,
+					CHIP_DELAY_TIMEOUT);
+		else
+			ret = pxa3xx_nand_polling(nand, CHIP_DELAY_TIMEOUT);
 		if (!ret) {
 			dev_err(&nand->pdev->dev, "Wait time out!!!\n");
 			nand_error_dump(nand);
@@ -1582,7 +1617,9 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 		return -ENODEV;
 	}

-	if (!(pdata->controller_attrs & PXA3XX_DMA_EN))
+	if (pdata->controller_attrs & PXA3XX_POOLING_MODE)
+		use_polling = 1;
+	if (!(pdata->controller_attrs & PXA3XX_DMA_EN) || use_polling)
 		use_dma = 0;
 	ret = alloc_nand_resource(pdev);
 	if (ret)
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:37:47 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:37:47 +0800
Subject: [PATCH 22/25] pxa3xx_nand: reimplement the read oob logic
Message-ID: <AANLkTikqS9j4uRQ_8nzKTPnbpnoHHH_LzTdi3CQTlC8U@mail.gmail.com>


From leiwen at marvell.com  Tue Jun  8 04:37:35 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 8 Jun 2010 16:37:35 +0800
Subject: [PATCH 22/25] pxa3xx_nand: reimplement the read oob logic
Message-ID: <mailman.43.1276839586.27306.linux-mtd@lists.infradead.org>

For readoob command only need the content of oob part, it certainly
don't need the controller transfer the data part, which greatly downgrade
the performance.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  182 +++++++++++++++++++++-------------------
 1 files changed, 96 insertions(+), 86 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 7f8bae7..e76264c 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -244,30 +244,28 @@ struct pxa3xx_nand {
 	uint32_t		command;
 	uint16_t		data_size;	/* data size in FIFO */
 	uint16_t		oob_size;
-	uint32_t		bad_count;
 	unsigned char		*dma_buff;
 	unsigned char		*data_buff;
 	unsigned char		*oob_buff;
+	uint8_t			chip_select;
+	uint8_t			total_cmds;
 	uint32_t		buf_start;
 	uint32_t		buf_count;
+
+	uint32_t		state;
+	uint32_t		bad_count;
 	uint16_t		data_column;
 	uint16_t		oob_column;
-
-	/* relate to the command */
-	uint8_t			chip_select;
-	uint8_t			ecc_strength;
-	unsigned int		state;
 	int			use_dma;	/* use DMA ? */
 	int 			retcode;
+	uint8_t			ecc_strength;

 	/* cached register value */
 	uint8_t			cmd_seqs;
-	uint8_t			total_cmds;
 	uint8_t			wait_ready[CMD_POOL_SIZE];
 	uint32_t		ndcb0[CMD_POOL_SIZE];
-	uint32_t		ndcb1;
+	uint32_t		ndcb1[CMD_POOL_SIZE];
 	uint32_t		ndcb2;
-	uint32_t		ndcb3[CMD_POOL_SIZE];
 };

 static int use_dma = 1;
@@ -396,8 +394,8 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 	struct pxa3xx_nand *nand = info->nand_data;
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;

-	if (info->page_size >= PAGE_CHUNK_SIZE) {
-		nand->data_size = PAGE_CHUNK_SIZE;
+	if (info->page_size < PAGE_CHUNK_SIZE) {
+		nand->data_size = 512;
 		if (!oob_enable) {
 			nand->oob_size = 0;
 			return;
@@ -405,32 +403,54 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)

 		switch (nand->ecc_strength) {
 		case 0:
-			nand->oob_size = 64;
+			nand->oob_size = 16;
 			break;
 		case HAMMING_STRENGTH:
-			nand->oob_size = 40;
+			nand->oob_size = 8;
 			break;
 		default:
-			nand->oob_size = 32;
-		}
-	} else {
-		nand->data_size = 512;
-		if (!oob_enable) {
-			nand->oob_size = 0;
-			return;
+			printk("Don't support BCH on small page device!!!\n");
+			BUG();
 		}
+		return;
+	}
+	nand->data_size = PAGE_CHUNK_SIZE;
+	if (!oob_enable) {
+		nand->oob_size = 0;
+		return;
+	}

-		switch (nand->ecc_strength) {
-		case 0:
-			nand->oob_size = 16;
-			break;
+	if (nand->command == NAND_CMD_READOOB) {
+		switch (info->ecc_strength) {
 		case HAMMING_STRENGTH:
-			nand->oob_size = 8;
+			nand->ndcb1[3] = 2 * PAGE_CHUNK_SIZE + OOB_CHUNK_SIZE;
+			nand->data_size = 40;
+			break;
+		case BCH_STRENGTH:
+			nand->ndcb1[3] = 2 * PAGE_CHUNK_SIZE + OOB_CHUNK_SIZE - 2;
+			nand->data_size = 32;
 			break;
 		default:
-			printk("Don't support BCH on small page device!!!\n");
 			BUG();
 		}
+		if (info->reg_ndcr & NDCR_DWIDTH_M) {
+			nand->ndcb1[1] = PAGE_CHUNK_SIZE / 2;
+			nand->ndcb1[3] /= 2;
+		}
+		else
+			nand->ndcb1[1] = PAGE_CHUNK_SIZE;
+		nand->oob_size = 0;
+		return;
+	}
+	switch (nand->ecc_strength) {
+	case 0:
+		nand->oob_size = 64;
+		break;
+	case HAMMING_STRENGTH:
+		nand->oob_size = 40;
+		break;
+	default:
+		nand->oob_size = 32;
 	}
 }

@@ -514,9 +534,8 @@ static void nand_error_dump(struct pxa3xx_nand *nand)
 	printk(KERN_ERR "Totally %d command for sending\n",
 			nand->total_cmds);
 	for (i = 0; i < nand->total_cmds; i ++)
-		printk(KERN_ERR "NDCB0:%d: %x\n",
-				i, nand->ndcb0[i]);
-	printk(KERN_ERR "NDCB1: %x; NDCB2 %x\n", nand->ndcb1, nand->ndcb2);
+		printk(KERN_ERR "%d::NDCB0: %x, NDCB1: %x, NDCB2: %x\n",
+			i, nand->ndcb0[i], nand->ndcb1[i], nand->ndcb2);

 	printk(KERN_ERR "\nRegister DUMPing ##############\n");
 	printk(KERN_ERR "NDCR %x\n"
@@ -623,8 +642,8 @@ static void pxa3xx_nand_data_dma_irq(int channel,
void *data)
 static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand)
 {
 	struct pxa3xx_nand_info *info;
-	unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2;
-	unsigned int ready, cmd_done, page_done, badblock_detect;
+	unsigned int status, is_completed = 0, cs, cmd_seqs;
+	unsigned int ready, cmd_done, page_done, badblock_detect, ndcb2;

 	cs		= nand->chip_select;
 	ready           = (cs) ? NDSR_RDY : NDSR_FLASH_RDY;
@@ -686,22 +705,19 @@ static int pxa3xx_nand_transaction(struct
pxa3xx_nand *nand)

 		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
 		if (cmd_seqs < nand->total_cmds) {
-			nand->cmd_seqs ++;
-			if (cmd_seqs == 0) {
-				ndcb1 = nand->ndcb1;
+			if (cmd_seqs == 0)
 				ndcb2 = nand->ndcb2;
-			}
-			else {
-				ndcb1 = 0;
+			else
 				ndcb2 = 0;
-			}
+			nand->cmd_seqs ++;
 			nand->state &= ~STATE_MASK;
 			nand->state |= STATE_CMD_WAIT_DONE;
 			nand_writel(nand, NDCB0, nand->ndcb0[cmd_seqs]);
-			nand_writel(nand, NDCB0, ndcb1);
+			nand_writel(nand, NDCB0, nand->ndcb1[cmd_seqs]);
 			nand_writel(nand, NDCB0, ndcb2);
-			if (nand->ndcb3[cmd_seqs])
-				nand_writel(nand, NDCB0, nand->ndcb3[cmd_seqs]);
+			if (nand->ndcb0[cmd_seqs] & NDCB0_LEN_OVRD)
+				nand_writel(nand, NDCB0, nand->data_size
+						+ nand->oob_size);
 		}
 		else
 			is_completed = 1;
@@ -760,24 +776,15 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	exec_cmd = 1;

 	/* reset data and oob column point to handle data */
-	nand->data_column	= 0;
-	nand->oob_column	= 0;
-	nand->total_cmds	= 1;
-	nand->cmd_seqs		= 0;
-	nand->data_size		= 0;
-	nand->oob_size		= 0;
-	nand->use_dma		= 0;
-	nand->state		= 0;
-	nand->bad_count		= 0;
-	nand->retcode		= ERR_NONE;
-	nand->buf_start		= column;
+	nand->total_cmds = 1;
+	nand->buf_start	= column;

 	switch (command) {
 	case NAND_CMD_PAGEPROG:
 	case NAND_CMD_RNDOUT:
 		pxa3xx_set_datasize(info);
 		nand->use_dma = use_dma;
-		chunks = info->page_size / nand->data_size;
+		chunks = info->page_size / PAGE_CHUNK_SIZE;
 		if (info->ecc_strength > BCH_STRENGTH) {
 			i = info->ecc_strength / BCH_STRENGTH;
 			nand->data_size /= i;
@@ -792,9 +799,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 			BUG();
 		}
 	default:
-		nand->ndcb1 = 0;
-		nand->ndcb2 = 0;
-		nand->ecc_strength = 0;
+		i = (uint32_t)(&nand->state) - (uint32_t)nand;
+		memset(&nand->state, 0, sizeof(struct pxa3xx_nand) - i);
 		break;
 	}
 	if (nand->use_dma) {
@@ -803,11 +809,8 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	}

 	/* clear the command buffer */
-	for (i = 0; i < CMD_POOL_SIZE; i ++) {
+	for (i = 0; i < CMD_POOL_SIZE; i ++)
 		nand->ndcb0[i] = ndcb0;
-		nand->wait_ready[i] = 0;
-		nand->ndcb3[i] = (ndcb0 & NDCB0_LEN_OVRD)? nand->data_size : 0;
-	}
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);

@@ -822,10 +825,10 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		info->page_addr = page_addr;
 		/* small page addr setting */
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+			nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
 		else {
-			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
+			nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16)
 					| (column & 0xFFFF);

 			if (page_addr & 0xFF0000)
@@ -835,11 +838,6 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 	case NAND_CMD_RNDOUT:
 		cmd = cmdset.read1;
-		if (nand->command == NAND_CMD_READOOB) {
-			nand->buf_start = mtd->writesize + column;
-			nand->buf_count = mtd->oobsize;
-		}
-
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)
 			|| !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
 			if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
@@ -851,10 +849,18 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 						| NDCB0_DBC
 						| addr_cycle
 						| cmd;
+			if (nand->command == NAND_CMD_READOOB) {
+				nand->buf_start = mtd->writesize + column;
+				nand->buf_count = mtd->oobsize;
+			}
 			break;
 		}

-		nand->total_cmds = chunks + 1;
+		if (nand->command == NAND_CMD_READOOB)
+			nand->total_cmds = 2 * chunks + 1;
+		else
+			nand->total_cmds = chunks + 1;
+
 		nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
 				| NDCB0_CMD_TYPE(0)
 				| NDCB0_DBC
@@ -862,15 +868,23 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 				| addr_cycle
 				| cmd;
 		nand->ndcb0[0] &= ~NDCB0_LEN_OVRD;
-		nand->ndcb3[0] = 0;
-		nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
-				| NDCB0_NC
-				| addr_cycle;

-		for (i = 2; i <= chunks; i ++)
-			nand->ndcb0[i] = nand->ndcb0[1];
+		for (i = 1; i <= nand->total_cmds - 1;) {
+			if (nand->command == NAND_CMD_READOOB) {
+				nand->ndcb0[i ++] |= NDCB0_CMD_XTYPE(0x6)
+						| NDCB0_CMD_TYPE(0)
+						| NDCB0_ADDR_CYC(info->col_addr_cycles)
+						| NDCB0_DBC
+						| NDCB0_NC
+						| (NAND_CMD_RNDOUTSTART << 8)
+						| NAND_CMD_RNDOUT;
+				nand->ndcb0[i] |= NDCB0_LEN_OVRD;
+			}
+			nand->ndcb0[i ++] |= NDCB0_CMD_XTYPE(0x5)
+					| NDCB0_NC;
+		}

-		nand->ndcb0[chunks] &= ~NDCB0_NC;
+		nand->ndcb0[nand->total_cmds - 1] &= ~NDCB0_NC;
 		/* we should wait RnB go high again
 		 * before read out data*/
 		nand->wait_ready[1] = 1;
@@ -908,18 +922,15 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 			nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
 					| NDCB0_NC
 					| NDCB0_AUTO_RS
-					| NDCB0_CMD_TYPE(0x1)
-					| addr_cycle;
+					| NDCB0_CMD_TYPE(0x1);

 		nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
-				| NDCB0_CMD_TYPE(0x1)
-				| NDCB0_ST_ROW_EN
-				| NDCB0_DBC
-				| (cmd & NDCB0_CMD2_MASK)
-				| NDCB0_CMD1_MASK
-				| addr_cycle;
+					| NDCB0_CMD_TYPE(0x1)
+					| NDCB0_ST_ROW_EN
+					| NDCB0_DBC
+					| (cmd & NDCB0_CMD2_MASK)
+					| NDCB0_CMD1_MASK;
 		nand->ndcb0[chunks] &= ~NDCB0_LEN_OVRD;
-		nand->ndcb3[chunks] = 0;
 		/* we should wait for RnB goes high which
 		 * indicate the data has been written succesfully*/
 		nand->wait_ready[nand->total_cmds] = 1;
@@ -953,8 +964,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 				| NDCB0_ADDR_CYC(3)
 				| NDCB0_DBC
 				| cmd;
-		nand->ndcb1 = page_addr;
-		nand->ndcb2 = 0;
+		nand->ndcb1[0] = page_addr;

 		break;
 	case NAND_CMD_RESET:
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:37:56 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:37:56 +0800
Subject: [PATCH 23/25] pxa3xx_nand: fix reset timeout on mmp2
Message-ID: <AANLkTil4P4BuMuCXWwALcgxqUgPFB1wlb3rnzEdiC_On@mail.gmail.com>


From leiwen at marvell.com  Tue Jun  8 21:53:18 2010
From: leiwen at marvell.com (Lei Wen)
Date: Wed, 9 Jun 2010 09:53:18 +0800
Subject: [PATCH 23/25] pxa3xx_nand: fix reset timeout on mmp2
Message-ID: <mailman.47.1276839609.27306.linux-mtd@lists.infradead.org>

For mmp2 board, reset command would always have timeout when enable
the IRQ processing. The command done would comes after exit the IRQ
processing whatever the timeout value is set.

Change reset command use polling mode fix the issue.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index e76264c..99f4088 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -968,6 +968,10 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 		break;
 	case NAND_CMD_RESET:
+		/* on some platform, it is stranger that when issue reset command,
+		 * cmd done would not come till timeout cause irq exit.
+		 * Force polling mode for reset command*/
+		use_polling = 1;
 		cmd = cmdset.reset;
 		nand->ndcb0[0] |= NDCB0_CMD_TYPE(5)
 				| cmd;
@@ -993,7 +997,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
 	struct pxa3xx_nand *nand = info->nand_data;
-	int ret, exec_cmd;
+	int ret, exec_cmd, polling_mode;

 	/* if this is a x16 device ,then convert the input
 	 * "byte" address into a "word" address appropriate
@@ -1009,6 +1013,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
 	}

+	polling_mode = use_polling;
 	exec_cmd = prepare_command_pool(nand, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&nand->cmd_complete);
@@ -1028,6 +1033,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		}
 		nand->state &= ~STATE_CMD_PREPARED;
 	}
+	use_polling = polling_mode;
 }

 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:38:03 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:38:03 +0800
Subject: [PATCH 24/25] pxa3xx_nand: fix write oob bug
Message-ID: <AANLkTikhoddXubBcuRw1K1u9GFNCp710rArmE4L7K43-@mail.gmail.com>


From leiwen at marvell.com  Wed Jun  9 04:55:14 2010
From: leiwen at marvell.com (Lei Wen)
Date: Wed, 9 Jun 2010 16:55:14 +0800
Subject: [PATCH 24/25] pxa3xx_nand: fix write oob bug
Message-ID: <mailman.49.1276839619.27306.linux-mtd@lists.infradead.org>

For column addressing is only used to subpage and oob operation,
and the fact that our controller is performing poor at such two
operations, disable the column addressing in writing the ndcb1.

If not add this patch, write_oob function would fail.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   42 +++++++++++++++++++++++++++++++--------
 1 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 99f4088..96b46e1 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -314,6 +314,20 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 { "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, 1, 2048, &timing[3], },
 };

+static struct nand_ecclayout nand_oob_128_BCH = {
+	.eccbytes = 64,
+	.eccpos = {
+		64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+		76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+		88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+		100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+		110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127},
+	.oobfree = {
+		{.offset = 2,
+		.length = 62}}
+};
+
 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};

 #define NDTR0_tADL(c)		(min_t(uint32_t, (c), 31) << 27)
@@ -599,13 +613,19 @@ static void start_data_dma(struct pxa3xx_nand
*nand, int dir_out)
 	desc_oob->ddadr = desc->ddadr = DDADR_STOP;
 	desc_oob->dcmd = desc->dcmd = DCMD_WIDTH4 | DCMD_BURST32;
 	if (dir_out) {
+		if (nand->oob_size > 0) {
+			desc_oob->dsadr = nand->dma_buff_phys + info->page_size + nand->oob_column;
+			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG | oob_len;
+			desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc);
+			desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG | data_len;
+		}
+		else
+			desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG | data_len;
 		desc->dsadr = nand->dma_buff_phys + nand->data_column;
-		desc->dtadr = nand->mmio_phys + NDDB;
-		desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG |
(data_len + oob_len);
+		desc_oob->dtadr = desc->dtadr = nand->mmio_phys + NDDB;
 	} else {
 		if (nand->oob_size > 0) {
-			desc_oob->dtadr = nand->dma_buff_phys
-					+ info->page_size + nand->oob_column;
+			desc_oob->dtadr = nand->dma_buff_phys + info->page_size + nand->oob_column;
 			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | oob_len;
 			desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc);
 			desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
@@ -766,11 +786,13 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	uint16_t cmd;
 	int addr_cycle, exec_cmd, ndcb0, i, chunks = 0;
 	struct mtd_info *mtd;
+	struct nand_chip *chip;
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
 	struct platform_device *pdev = nand->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;

 	mtd = get_mtd_by_info(info);
+	chip = mtd->priv;
 	ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;;
 	addr_cycle = 0;
 	exec_cmd = 1;
@@ -825,11 +847,9 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		info->page_addr = page_addr;
 		/* small page addr setting */
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8)
-					| (column & 0xFF);
+			nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8);
 		else {
-			nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16)
-					| (column & 0xFFFF);
+			nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16);

 			if (page_addr & 0xFF0000)
 				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
@@ -892,7 +912,9 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		break;

 	case NAND_CMD_PAGEPROG:
-		if (is_buf_blank(nand->data_buff, (mtd->writesize + mtd->oobsize))) {
+		if (is_buf_blank(nand->data_buff, mtd->writesize) &&
+		    is_buf_blank(nand->oob_buff + chip->ecc.layout->oobfree[0].offset,
+			    chip->ecc.layout->oobfree[0].length)) {
 			exec_cmd = 0;
 			break;
 		}
@@ -1394,6 +1416,8 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 	}

 	pxa3xx_nand_config_flash(info, f);
+	if (f->page_size == 4096 && f->ecc_strength == 4)
+		chip->ecc.layout = &nand_oob_128_BCH;
 	pxa3xx_flash_ids[0].name = f->name;
 	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
-- 
1.7.0.4


From haojian.zhuang at gmail.com  Fri Jun 18 01:38:11 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 18 Jun 2010 13:38:11 +0800
Subject: [PATCH 25/25] pxa3xx_nand: fix power management support
Message-ID: <AANLkTilYSzvQfpHtdIVv1w4yMyMZhk_FW59wgkPEXU_X@mail.gmail.com>


From leiwen at marvell.com  Wed Jun 16 21:43:24 2010
From: leiwen at marvell.com (Lei Wen)
Date: Thu, 17 Jun 2010 09:43:24 +0800
Subject: [PATCH 25/25] pxa3xx_nand: fix power management support
Message-ID: <mailman.51.1276839624.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   48 +++++++++++++++++++++++++++++++--------
 1 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 96b46e1..e4de69c 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1695,26 +1695,54 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev,
pm_message_t state)
 {
-	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand *nand= platform_get_drvdata(pdev);
+	struct pxa3xx_nand_info *info;
+	struct mtd_info *mtd;
+	int ret = 0;
+	uint8_t cs;

-	if (info->state & STATE_CMD_PREPARED) {
-		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
+	if (nand->state & STATE_CMD_PREPARED) {
+		dev_err(&pdev->dev, "driver busy, state = %d\n", nand->state);
 		return -EAGAIN;
 	}

-	return 0;
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs ++) {
+		info = nand->info[cs];
+		if (!info)
+			continue;
+		mtd = get_mtd_by_info(info);
+		ret = mtd->suspend(mtd);
+	}
+
+	return ret;
 }

 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand *nand= platform_get_drvdata(pdev);
+	struct pxa3xx_nand_info *info;
+	struct mtd_info *mtd;
+	uint8_t cs;

-	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
-	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
-	clk_enable(info->clk);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs ++) {
+		info = nand->info[cs];
+		if (!info)
+			continue;
+		nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
+		nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
+		nand->chip_select = cs;
+		/* Sometimes nand chip would raise a ready interrupt
+		 * when resume, reset the by start and stop to prevent
+		 * it damage driver's state machine */
+		pxa3xx_nand_start(nand);
+		pxa3xx_nand_stop(nand);
+		mtd = get_mtd_by_info(info);
+		mtd->resume(mtd);
+	}

+	/* set the controller cs to a invalid num to let driver
+	 * reconfigure the timing when it call the cmdfunc */
+	nand->chip_select = 0xff;
 	return 0;
 }
 #else
-- 
1.7.0.4


From eric.y.miao at gmail.com  Fri Jun 18 02:23:02 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:23:02 +0800
Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
In-Reply-To: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com>
References: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com>
Message-ID: <AANLkTinOsQ8AcH-As91CRqrEQVnXdsm_CmFQgyj7gI1_@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:32 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From 76684334fbf214ab164ed07791b02535a3f04779 Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Sat, 20 Mar 2010 19:01:23 +0800
> Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
>
> Adding a new flash definition would need less code.
> Keep the platform passing flash defition method.
                                  ^^^^^^^^ definition?
> If one flash is both defined in platform data and builtin table,
> driver would select the one from platform data first.

This makes sense. I thin the CONFIG_MTD_NAND_PXA3xx_BUILTIN is introduced
as an optimization so to reduce the code size if platform flash definition
is provided, instead of an option to remove built-in definitions.

>
> By this way, platform could select the timing most suit for itself,
                                                     ^^^^ suitable
> not need to follow the common settings.
>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>

// there are some line wrapped though, maybe it's my gmail fault.

> ---
> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 37 ----
> ?drivers/mtd/nand/Kconfig ? ? ? ? ? ? ? ? ? ? | ? ?7 -
> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?241 +++++++-------------------
> ?3 files changed, 66 insertions(+), 219 deletions(-)
>
> diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> index 3478eae..7e5a28f 100644
> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> @@ -4,43 +4,6 @@
> ?#include <linux/mtd/mtd.h>
> ?#include <linux/mtd/partitions.h>
>
> -struct pxa3xx_nand_timing {
> - ? ? ? unsigned int ? ?tCH; ?/* Enable signal hold time */
> - ? ? ? unsigned int ? ?tCS; ?/* Enable signal setup time */
> - ? ? ? unsigned int ? ?tWH; ?/* ND_nWE high duration */
> - ? ? ? unsigned int ? ?tWP; ?/* ND_nWE pulse time */
> - ? ? ? unsigned int ? ?tRH; ?/* ND_nRE high duration */
> - ? ? ? unsigned int ? ?tRP; ?/* ND_nRE pulse width */
> - ? ? ? unsigned int ? ?tR; ? /* ND_nWE high to ND_nRE low for read */
> - ? ? ? unsigned int ? ?tWHR; /* ND_nWE high to ND_nRE low for status read */
> - ? ? ? unsigned int ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */
> -};
> -
> -struct pxa3xx_nand_cmdset {
> - ? ? ? uint16_t ? ? ? ?read1;
> - ? ? ? uint16_t ? ? ? ?read2;
> - ? ? ? uint16_t ? ? ? ?program;
> - ? ? ? uint16_t ? ? ? ?read_status;
> - ? ? ? uint16_t ? ? ? ?read_id;
> - ? ? ? uint16_t ? ? ? ?erase;
> - ? ? ? uint16_t ? ? ? ?reset;
> - ? ? ? uint16_t ? ? ? ?lock;
> - ? ? ? uint16_t ? ? ? ?unlock;
> - ? ? ? uint16_t ? ? ? ?lock_status;
> -};
> -
> -struct pxa3xx_nand_flash {
> - ? ? ? const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset;
> -
> - ? ? ? uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
> - ? ? ? uint32_t page_size; ? ? /* Page size in bytes (PAGE_SZ) */
> - ? ? ? uint32_t flash_width; ? /* Width of Flash memory (DWIDTH_M) */
> - ? ? ? uint32_t dfc_width; ? ? /* Width of flash controller(DWIDTH_C) */
> - ? ? ? uint32_t num_blocks; ? ?/* Number of physical blocks in Flash */
> - ? ? ? uint32_t chip_id;
> -};
> -

So does this prevent board code from defining their own timing and etc?

> ?struct pxa3xx_nand_platform_data {
>
> ? ? ? ?/* the data flash bus is shared between the Static Memory
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 98a04b3..9a35d92 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -399,13 +399,6 @@ config MTD_NAND_PXA3xx
> ? ? ? ? ?This enables the driver for the NAND flash device found on
> ? ? ? ? ?PXA3xx processors
>
> -config MTD_NAND_PXA3xx_BUILTIN
> - ? ? ? bool "Use builtin definitions for some NAND chips (deprecated)"
> - ? ? ? depends on MTD_NAND_PXA3xx
> - ? ? ? help
> - ? ? ? ? This enables builtin definitions for some NAND chips. This
> - ? ? ? ? is deprecated in favor of platform specific data.
> -
> ?config MTD_NAND_CM_X270
> ? ? ? ?tristate "Support for NAND Flash on CM-X270 modules"
> ? ? ? ?depends on MTD_NAND && MACH_ARMCORE
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index e02fa4f..013e075 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c

... snipped ...

> ?static struct pxa3xx_nand_timing default_timing;
> ?static struct pxa3xx_nand_flash default_flash;
>
> -static struct pxa3xx_nand_cmdset smallpage_cmdset = {
> - ? ? ? .read1 ? ? ? ? ?= 0x0000,
> - ? ? ? .read2 ? ? ? ? ?= 0x0050,
> - ? ? ? .program ? ? ? ?= 0x1080,
> - ? ? ? .read_status ? ?= 0x0070,
> - ? ? ? .read_id ? ? ? ?= 0x0090,
> - ? ? ? .erase ? ? ? ? ?= 0xD060,
> - ? ? ? .reset ? ? ? ? ?= 0x00FF,
> - ? ? ? .lock ? ? ? ? ? = 0x002A,
> - ? ? ? .unlock ? ? ? ? = 0x2423,
> - ? ? ? .lock_status ? ?= 0x007A,
> -};
> -
> -static struct pxa3xx_nand_cmdset largepage_cmdset = {
> +const static struct pxa3xx_nand_cmdset cmdset = {

So how to handle the difference of command set between smallpage and
largepage?

> ? ? ? ?.read1 ? ? ? ? ?= 0x3000,
> ? ? ? ?.read2 ? ? ? ? ?= 0x0050,
> ? ? ? ?.program ? ? ? ?= 0x1080,
> @@ -203,143 +225,26 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = {
> ? ? ? ?.lock_status ? ?= 0x007A,
> ?};
>
> -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN
> -static struct pxa3xx_nand_timing samsung512MbX16_timing = {
> - ? ? ? .tCH ? ?= 10,
> - ? ? ? .tCS ? ?= 0,
> - ? ? ? .tWH ? ?= 20,
> - ? ? ? .tWP ? ?= 40,

...

> +static struct pxa3xx_nand_timing __devinitdata timing[] = {

Better with some comment columns like below:

  /*	    tCH tCS tWH tWP ... */
> + ? ? ? /* Samsung NAND series */
> + ? ? ? { 10, ?0, 20, 40, 30, 40, 11123, 110, 10, },
> + ? ? ? /* Micron NAND series */
> + ? ? ? { 10, 25, 15, 25, 15, 30, 25000, ?60, 10, },
> + ? ? ? /* ST NAND series */
> + ? ? ? { 10, 35, 15, 25, 15, 25, 25000, ?60, 10, },

Now define something like

#define NAND_TIMING_SAMSUNG	(&timing[0])
#define NAND_TIMING_MICRON	(&timing[1])
#define NAND_TIMING_ST		(&timing[2])

> ?};
>
> -static struct pxa3xx_nand_flash samsung32GbX8 = {
> - ? ? ? .timing ? ? ? ? = &samsung512MbX16_timing,
> - ? ? ? .cmdset ? ? ? ? = &smallpage_cmdset,
> - ? ? ? .page_per_block = 128,
> - ? ? ? .page_size ? ? ?= 4096,
> - ? ? ? .flash_width ? ?= 8,
> - ? ? ? .dfc_width ? ? ?= 8,
> - ? ? ? .num_blocks ? ? = 8192,
> - ? ? ? .chip_id ? ? ? ?= 0xd7ec,
> +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {

/*	  Chip ID, page per block, page size, flash width, .... */

> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[0], },
> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[0], },
> + ? ? ? { 0xd7ec, 128, 4096, ?8, ?8, 8192, &timing[0], },
> + ? ? ? { 0xa12c, ?64, 2048, ?8, ?8, 1024, &timing[1], },
> + ? ? ? { 0xb12c, ?64, 2048, 16, 16, 1024, &timing[1], },
> + ? ? ? { 0xdc2c, ?64, 2048, ?8, ?8, 4096, &timing[1], },
> + ? ? ? { 0xcc2c, ?64, 2048, 16, 16, 4096, &timing[1], },
> + ? ? ? { 0xba20, ?64, 2048, 16, 16, 2048, &timing[2], },
> ?};

BTW, I like the array above very much.

>
> -static struct pxa3xx_nand_timing micron_timing = {
> - ? ? ? .tCH ? ?= 10,
> - ? ? ? .tCS ? ?= 25,
> - ? ? ? .tWH ? ?= 15,
> - ? ? ? .tWP ? ?= 25,
> - ? ? ? .tRH ? ?= 15,
> - ? ? ? .tRP ? ?= 30,
> - ? ? ? .tR ? ? = 25000,

... snipped ...

> -};
> -#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */
> -
> ?#define NDTR0_tCH(c) ? (min((c), 7) << 19)
> ?#define NDTR0_tCS(c) ? (min((c), 7) << 16)
> ?#define NDTR0_tWH(c) ? (min((c), 7) << 11)
> @@ -412,7 +317,6 @@ static int prepare_read_prog_cmd(struct
> pxa3xx_nand_info *info,
> ? ? ? ? ? ? ? ? ? ? ? ?uint16_t cmd, int column, int page_addr)
> ?{
> ? ? ? ?const struct pxa3xx_nand_flash *f = info->flash_info;
> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;

I think it's better to keep a local pointer. Reference within a function
to a global structure is always a bad idea, one day you will find you've
to modify all these references again when you add a new cmdset.

And most of the modifications below can thus be removed and patch simplified.


From eric.y.miao at gmail.com  Fri Jun 18 02:33:59 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:33:59 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce read
	id times
In-Reply-To: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com>
References: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com>
Message-ID: <AANLkTil6QDRdh3s63J9Mm-B1qjMcnYjEEm-W5lC1NXVb@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:33 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From 832379d0da4d772e45872de365053f9a15733967 Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Wed, 2 Jun 2010 21:50:25 +0800
> Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce
> read id times
>
> We certainly don't need to send read id command times by times, since
> we already know what the id is after the first read id...
>
> So create a common timing which could ensure it would successfully read id
> out all supported chip. Then follow the build-in table to reconfigure
> the timing.

This is clever trick we'd like to have. And I'd prefer to call this a
'loose timing'
or a 'default safe timing' instead of 'common timing'.

>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ? 72 ++++++++++++++++-----------------------
> ?1 files changed, 30 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 013e075..f939083 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -226,23 +226,26 @@ const static struct pxa3xx_nand_cmdset cmdset = {
> ?};
>
> ?static struct pxa3xx_nand_timing __devinitdata timing[] = {
> + ? ? ? /* common timing used to detect flash id */
> + ? ? ? { 40, 80, 60, 100, 80, 100, 90000, 400, 40, },

Make sure this is the loose and safe enough timing.

> ? ? ? ?/* Samsung NAND series */
> - ? ? ? { 10, ?0, 20, 40, 30, 40, 11123, 110, 10, },
> + ? ? ? { 10, ?0, 20, ?40, 30, ?40, 11123, 110, 10, },
> ? ? ? ?/* Micron NAND series */
> - ? ? ? { 10, 25, 15, 25, 15, 30, 25000, ?60, 10, },
> + ? ? ? { 10, 25, 15, ?25, 15, ?30, 25000, ?60, 10, },
> ? ? ? ?/* ST NAND series */
> - ? ? ? { 10, 35, 15, 25, 15, 25, 25000, ?60, 10, },
> + ? ? ? { 10, 35, 15, ?25, 15, ?25, 25000, ?60, 10, },
> ?};
>
> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
> - ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[0], },
> - ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[0], },
> - ? ? ? { 0xd7ec, 128, 4096, ?8, ?8, 8192, &timing[0], },
> - ? ? ? { 0xa12c, ?64, 2048, ?8, ?8, 1024, &timing[1], },
> - ? ? ? { 0xb12c, ?64, 2048, 16, 16, 1024, &timing[1], },
> - ? ? ? { 0xdc2c, ?64, 2048, ?8, ?8, 4096, &timing[1], },
> - ? ? ? { 0xcc2c, ?64, 2048, 16, 16, 4096, &timing[1], },
> - ? ? ? { 0xba20, ?64, 2048, 16, 16, 2048, &timing[2], },
> + ? ? ? { ? ? ?0, ? 0, ? ?0, ?0, ?0, ? ?0, &timing[0], },
> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },
> + ? ? ? { 0xd7ec, 128, 4096, ?8, ?8, 8192, &timing[1], },
> + ? ? ? { 0xa12c, ?64, 2048, ?8, ?8, 1024, &timing[2], },
> + ? ? ? { 0xb12c, ?64, 2048, 16, 16, 1024, &timing[2], },
> + ? ? ? { 0xdc2c, ?64, 2048, ?8, ?8, 4096, &timing[2], },
> + ? ? ? { 0xcc2c, ?64, 2048, 16, 16, 4096, &timing[2], },
> + ? ? ? { 0xba20, ?64, 2048, 16, 16, 2048, &timing[3], },
> ?};
>
> ?#define NDTR0_tCH(c) ? (min((c), 7) << 19)
> @@ -859,12 +862,6 @@ static int pxa3xx_nand_config_flash(struct
> pxa3xx_nand_info *info,
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> ? ? ? ?uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
>
> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
> - ? ? ? ? ? ? ? return -EINVAL;
> -
> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
> - ? ? ? ? ? ? ? return -EINVAL;
> -

I do think these are sanity check, that's useful to prevent incorrectly defined
data (esp. coming from board code). Can we define the loose flash type as:

> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
> + ? ? ? { ?0x0000, ? 0, ? ?512, ?8, ?8, ? ?0, &timing[0], },
> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },

with a comment of /* default flash type to detect ID */?

My understanding is the minimum requirement to detect the NAND ID is a
loose timing and 512 small page, 8-bit wide bus, so with a chip_id being
0x0000, that should be enough to tell it's a special flash type to detect ID.

> ? ? ? ?/* calculate flash information */
> ? ? ? ?info->oob_size = (f->page_size == 2048) ? 64 : 16;
> ? ? ? ?info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
> @@ -976,36 +973,27 @@ static int pxa3xx_nand_detect_flash(struct
> pxa3xx_nand_info *info,
> ? ? ? ? ? ? ? ?if (pxa3xx_nand_detect_config(info) == 0)
> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>
> - ? ? ? for (i = 0; i<pdata->num_flash; ++i) {
> - ? ? ? ? ? ? ? f = pdata->flash + i;
> -
> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> -
> - ? ? ? ? ? ? ? if (__readid(info, &id))
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> -
> - ? ? ? ? ? ? ? if (id == f->chip_id)
> - ? ? ? ? ? ? ? ? ? ? ? return 0;
> - ? ? ? }
> -
> - ? ? ? for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
> -
> - ? ? ? ? ? ? ? f = &builtin_flash_types[i];
> -
> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> -
> - ? ? ? ? ? ? ? if (__readid(info, &id))
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> -
> - ? ? ? ? ? ? ? if (id == f->chip_id)
> + ? ? ? f = &builtin_flash_types[0];
> + ? ? ? pxa3xx_nand_config_flash(info, f);
> + ? ? ? if (__readid(info, &id))
> + ? ? ? ? ? ? ? goto fail_detect;
> +
> + ? ? ? for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
> + ? ? ? ? ? ? ? if (i < pdata->num_flash)
> + ? ? ? ? ? ? ? ? ? ? ? f = pdata->flash + i;
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? f = &builtin_flash_types[i - pdata->num_flash + 1];

This looks a bit tricky and difficult to read, can you improve the
readability here?

> + ? ? ? ? ? ? ? if (f->chip_id == id) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f);
> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
> + ? ? ? ? ? ? ? }
> ? ? ? ?}
>
> ? ? ? ?dev_warn(&info->pdev->dev,
> - ? ? ? ? ? ? ? ?"failed to detect configured nand flash; found %04x instead of\n",
> + ? ? ? ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found %04x instead of\n",
> ? ? ? ? ? ? ? ? id);
> +fail_detect:
> ? ? ? ?return -ENODEV;
> ?}
>

I'm generally OK with the idea.


From eric.y.miao at gmail.com  Fri Jun 18 02:40:17 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:40:17 +0800
Subject: [PATCH 03/25] pxa3xx_nand: remove the flash info in driver 
	structure
In-Reply-To: <AANLkTimbCSM3Kk-Mq3MhRDyhHAaERR-dXhtuplauB3ki@mail.gmail.com>
References: <AANLkTimbCSM3Kk-Mq3MhRDyhHAaERR-dXhtuplauB3ki@mail.gmail.com>
Message-ID: <AANLkTilnlE7hl4FKo5qRJ4PeTCuxA3Mfm13eedGPehrk@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:33 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From 643765e6ae0f37902321f31e14b565896217dd3a Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Wed, 2 Jun 2010 21:54:33 +0800
> Subject: [PATCH 03/25] pxa3xx_nand: remove the flash info in driver structure
>
> After probe, all info already transfer to driver structure.
> There is no need to keep the original flash info.
> So that we could safely free the flash info in memory, which may grows
> larger when more flash is suported.
>

Some of the changes should be separated from my POV? Like the
change to oob_size, and pxa3xx_nand_resume?


From eric.y.miao at gmail.com  Fri Jun 18 02:43:08 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:43:08 +0800
Subject: [PATCH 04/25] pxa3xx_nand: make scan procedure more clear
In-Reply-To: <AANLkTiliVtvBEmJPgkha444k9XGB_dNm0lQ9TCif8AAj@mail.gmail.com>
References: <AANLkTiliVtvBEmJPgkha444k9XGB_dNm0lQ9TCif8AAj@mail.gmail.com>
Message-ID: <AANLkTikKNw7purkGZoYMN7rWuHwkLdILSoDAaIzpugYe@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:33 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From 9023ee9b020ebda0c6ee299807a7fd2eb8fae53d Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Sun, 16 May 2010 17:03:52 +0800
> Subject: [PATCH 04/25] pxa3xx_nand: make scan procedure more clear
>

Looks like a good cleanup to me. The git diff, though, seems to generate poor
differences here.

> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ? 88 ++++++++++++++++++++++-----------------
> ?1 files changed, 50 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 291610a..1f52701 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -160,6 +160,7 @@ struct pxa3xx_nand_info {
> ? ? ? ?unsigned int ? ? ? ? ? ?buf_start;
> ? ? ? ?unsigned int ? ? ? ? ? ?buf_count;
>
> + ? ? ? struct mtd_info ? ? ? ? *mtd;
> ? ? ? ?/* DMA information */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_dat;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_cmd;
> @@ -1105,21 +1106,13 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
> ? ? ? ?this->chip_delay = 25;
> ?}
>
> -static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
> +static int alloc_nand_resource(struct platform_device *pdev)
> ?{
> - ? ? ? struct pxa3xx_nand_platform_data *pdata;
> + ? ? ? struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> ? ? ? ?struct pxa3xx_nand_info *info;
> - ? ? ? struct nand_chip *this;
> ? ? ? ?struct mtd_info *mtd;
> ? ? ? ?struct resource *r;
> - ? ? ? int ret = 0, irq;
> -
> - ? ? ? pdata = pdev->dev.platform_data;
> -
> - ? ? ? if (!pdata) {
> - ? ? ? ? ? ? ? dev_err(&pdev->dev, "no platform data defined\n");
> - ? ? ? ? ? ? ? return -ENODEV;
> - ? ? ? }
> + ? ? ? int ret, irq;
>
> ? ? ? ?mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
> ? ? ? ? ? ? ? ? ? ? ? ?GFP_KERNEL);
> @@ -1131,8 +1124,8 @@ static int __devinit pxa3xx_nand_probe(struct
> platform_device *pdev)
> ? ? ? ?info = (struct pxa3xx_nand_info *)(&mtd[1]);
> ? ? ? ?info->pdev = pdev;
>
> - ? ? ? this = &info->nand_chip;
> ? ? ? ?mtd->priv = info;
> + ? ? ? info->mtd = mtd;
> ? ? ? ?mtd->owner = THIS_MODULE;
>
> ? ? ? ?info->clk = clk_get(&pdev->dev, NULL);
> @@ -1210,27 +1203,9 @@ static int __devinit pxa3xx_nand_probe(struct
> platform_device *pdev)
> ? ? ? ?}
>
> ? ? ? ?pxa3xx_nand_init_mtd(mtd, info);
> + ? ? ? platform_set_drvdata(pdev, info);
>
> - ? ? ? platform_set_drvdata(pdev, mtd);
> -
> - ? ? ? if (nand_scan(mtd, 1)) {
> - ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n");
> - ? ? ? ? ? ? ? ret = -ENXIO;
> - ? ? ? ? ? ? ? goto fail_free_irq;
> - ? ? ? }
> -
> - ? ? ? if (mtd_has_cmdlinepart()) {
> - ? ? ? ? ? ? ? static const char *probes[] = { "cmdlinepart", NULL };
> - ? ? ? ? ? ? ? struct mtd_partition *parts;
> - ? ? ? ? ? ? ? int nr_parts;
> -
> - ? ? ? ? ? ? ? nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
> -
> - ? ? ? ? ? ? ? if (nr_parts)
> - ? ? ? ? ? ? ? ? ? ? ? return add_mtd_partitions(mtd, parts, nr_parts);
> - ? ? ? }
> -
> - ? ? ? return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
> + ? ? ? return 0;
>
> ?fail_free_irq:
> ? ? ? ?free_irq(irq, info);
> @@ -1255,8 +1230,8 @@ fail_free_mtd:
>
> ?static int pxa3xx_nand_remove(struct platform_device *pdev)
> ?{
> - ? ? ? struct mtd_info *mtd = platform_get_drvdata(pdev);
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
> + ? ? ? struct mtd_info *mtd = info->mtd;
> ? ? ? ?struct resource *r;
> ? ? ? ?int irq;
>
> @@ -1285,11 +1260,48 @@ static int pxa3xx_nand_remove(struct
> platform_device *pdev)
> ? ? ? ?return 0;
> ?}
>
> +static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
> +{
> + ? ? ? struct pxa3xx_nand_platform_data *pdata;
> + ? ? ? struct pxa3xx_nand_info *info;
> + ? ? ? int ret;
> +
> + ? ? ? pdata = pdev->dev.platform_data;
> + ? ? ? if (!pdata) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "no platform data defined\n");
> + ? ? ? ? ? ? ? return -ENODEV;
> + ? ? ? }
> +
> + ? ? ? ret = alloc_nand_resource(pdev);
> + ? ? ? if (ret)
> + ? ? ? ? ? ? ? return ret;
> +
> + ? ? ? info = platform_get_drvdata(pdev);
> + ? ? ? if (nand_scan(info->mtd, 1)) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n");
> + ? ? ? ? ? ? ? pxa3xx_nand_remove(pdev);
> + ? ? ? ? ? ? ? return -ENODEV;
> + ? ? ? }
> +
> + ? ? ? if (mtd_has_cmdlinepart()) {
> + ? ? ? ? ? ? ? static const char *probes[] = { "cmdlinepart", NULL };
> + ? ? ? ? ? ? ? struct mtd_partition *parts;
> + ? ? ? ? ? ? ? int nr_parts;
> +
> + ? ? ? ? ? ? ? nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
> +
> + ? ? ? ? ? ? ? if (nr_parts)
> + ? ? ? ? ? ? ? ? ? ? ? return add_mtd_partitions(mtd, parts, nr_parts);
> + ? ? ? }
> +
> + ? ? ? return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
> +}
> +
> ?#ifdef CONFIG_PM
> ?static int pxa3xx_nand_suspend(struct platform_device *pdev,
> pm_message_t state)
> ?{
> - ? ? ? struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
> + ? ? ? struct mtd_info *mtd = info->mtd;
>
> ? ? ? ?if (info->state != STATE_READY) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
> @@ -1301,8 +1313,8 @@ static int pxa3xx_nand_suspend(struct
> platform_device *pdev, pm_message_t state)
>
> ?static int pxa3xx_nand_resume(struct platform_device *pdev)
> ?{
> - ? ? ? struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
> + ? ? ? struct mtd_info *mtd = info->mtd;
>
> ? ? ? ?nand_writel(info, NDTR0CS0, info->ndtr0cs0);
> ? ? ? ?nand_writel(info, NDTR1CS0, info->ndtr1cs0);
> --
> 1.7.0.4
>


From eric.y.miao at gmail.com  Fri Jun 18 02:50:37 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:50:37 +0800
Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
In-Reply-To: <AANLkTimvhEWIDupsj3Ty8vB9ualwU9RsaIxa0CDgWgYQ@mail.gmail.com>
References: <AANLkTimvhEWIDupsj3Ty8vB9ualwU9RsaIxa0CDgWgYQ@mail.gmail.com>
Message-ID: <AANLkTikTzNY2hI0JDTOOZpGeOPc_MU79jVJ_1L9XxA_e@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From 18d589a078871a09dec0862241fedd2d1d07be85 Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Mon, 31 May 2010 14:05:46 +0800
> Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
>
> Enable all irq when we start the nand controller, and
> put all the transaction logic in the pxa3xx_nand_irq.
>

Didn't look into the change too much, but the idea sounds to me like
chaining all the logic with different IRQ events, which was my original
reason of having different states. And considering the page read/write
is actually to an internal SRAM within the controller, I guess it's quick
enough. (though I'd suggest to do some experiments of time profiling
to see if it's going to increase the interrupt latency)

> By doing this way, we could dramatically increase the
> performance by avoid unnecessary delay.
>

The removal of __read_id() doesn't look to be part of this patch, no?

> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ?382 +++++++++++++++-------------------------
> ?1 files changed, 140 insertions(+), 242 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 1f52701..753346f 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -27,6 +27,7 @@
> ?#include <plat/pxa3xx_nand.h>
>
> ?#define ? ? ? ?CHIP_DELAY_TIMEOUT ? ? ?(2 * HZ/10)
> +#define NAND_STOP_DELAY ? ? ? ? ? ? ? ?(2 * HZ/50)
>
> ?/* registers and bit definitions */
> ?#define NDCR ? ? ? ? ? (0x00) /* Control register */
> @@ -49,6 +50,7 @@
> ?#define NDCR_DWIDTH_M ? ? ? ? ?(0x1 << 26)
> ?#define NDCR_PAGE_SZ ? ? ? ? ? (0x1 << 24)
> ?#define NDCR_NCSX ? ? ? ? ? ? ?(0x1 << 23)
> +#define NDCR_STOP_ON_UNCOR ? ? (0x1 << 22)
> ?#define NDCR_ND_MODE ? ? ? ? ? (0x3 << 21)
> ?#define NDCR_NAND_MODE ? ? ? ? (0x0)
> ?#define NDCR_CLR_PG_CNT ? ? ? ? ? ? ? ?(0x1 << 20)
> @@ -59,9 +61,11 @@
> ?#define NDCR_RA_START ? ? ? ? ?(0x1 << 15)
> ?#define NDCR_PG_PER_BLK ? ? ? ? ? ? ? ?(0x1 << 14)
> ?#define NDCR_ND_ARB_EN ? ? ? ? (0x1 << 12)
> +#define NDCR_INT_MASK ? ? ? ? ? (0xFFF)
>
> ?#define NDSR_MASK ? ? ? ? ? ? ?(0xfff)
> -#define NDSR_RDY ? ? ? ? ? ? ? (0x1 << 11)
> +#define NDSR_RDY ? ? ? ? ? ? ? ?(0x1 << 12)
> +#define NDSR_FLASH_RDY ? ? ? ? ?(0x1 << 11)
> ?#define NDSR_CS0_PAGED ? ? ? ? (0x1 << 10)
> ?#define NDSR_CS1_PAGED ? ? ? ? (0x1 << 9)
> ?#define NDSR_CS0_CMDD ? ? ? ? ?(0x1 << 8)
> @@ -104,13 +108,14 @@ enum {
> ?};
>
> ?enum {
> - ? ? ? STATE_READY ? ? = 0,
> - ? ? ? STATE_CMD_HANDLE,
> - ? ? ? STATE_DMA_READING,
> - ? ? ? STATE_DMA_WRITING,
> - ? ? ? STATE_DMA_DONE,
> - ? ? ? STATE_PIO_READING,
> - ? ? ? STATE_PIO_WRITING,
> + ? ? ? STATE_CMD_WAIT_DONE ? ? = 1,
> + ? ? ? STATE_DATA_PROCESSING ? = (1 << 1),
> + ? ? ? STATE_DATA_DONE ? ? ? ? = (1 << 2),
> + ? ? ? STATE_PAGE_DONE ? ? ? ? = (1 << 3),
> + ? ? ? STATE_CMD_DONE ? ? ? ? ?= (1 << 4),
> + ? ? ? STATE_READY ? ? ? ? ? ? = (1 << 5),
> + ? ? ? STATE_CMD_PREPARED ? ? ?= (1 << 6),
> + ? ? ? STATE_IS_WRITE ? ? ? ? ?= (1 << 7),
> ?};
>
> ?struct pxa3xx_nand_timing {
> @@ -305,25 +310,6 @@ static void pxa3xx_nand_set_timing(struct
> pxa3xx_nand_info *info,
> ? ? ? ?nand_writel(info, NDTR1CS0, ndtr1);
> ?}
>
> -#define WAIT_EVENT_TIMEOUT ? ? 10
> -
> -static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
> -{
> - ? ? ? int timeout = WAIT_EVENT_TIMEOUT;
> - ? ? ? uint32_t ndsr;
> -
> - ? ? ? while (timeout--) {
> - ? ? ? ? ? ? ? ndsr = nand_readl(info, NDSR) & NDSR_MASK;
> - ? ? ? ? ? ? ? if (ndsr & event) {
> - ? ? ? ? ? ? ? ? ? ? ? nand_writel(info, NDSR, ndsr);
> - ? ? ? ? ? ? ? ? ? ? ? return 0;
> - ? ? ? ? ? ? ? }
> - ? ? ? ? ? ? ? udelay(10);
> - ? ? ? }
> -
> - ? ? ? return -ETIMEDOUT;
> -}
> -
> ?static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
> ?{
> ? ? ? ?int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
> @@ -343,7 +329,47 @@ static void pxa3xx_set_datasize(struct
> pxa3xx_nand_info *info)
> ? ? ? ?}
> ?}
>
> -static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
> +/**
> + * NOTE: it is a must to set ND_RUN firstly, then write
> + * command buffer, otherwise, it does not work.
> + * We enable all the interrupt at the same time, and
> + * let pxa3xx_nand_irq to handle all logic.
> + */
> +static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
> +{
> + ? ? ? uint32_t ndcr;
> +
> + ? ? ? ndcr = info->reg_ndcr;
> + ? ? ? ndcr |= NDCR_ECC_EN;
> + ? ? ? ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
> + ? ? ? ndcr |= NDCR_ND_RUN;
> +
> + ? ? ? /* clear status bits and run */
> + ? ? ? nand_writel(info, NDCR, 0);
> + ? ? ? nand_writel(info, NDSR, NDSR_MASK);
> + ? ? ? nand_writel(info, NDCR, ndcr);
> +}
> +
> +static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
> +{
> + ? ? ? uint32_t ndcr;
> + ? ? ? int timeout = NAND_STOP_DELAY;
> +
> + ? ? ? /* wait RUN bit in NDCR become 0 */
> + ? ? ? do {
> + ? ? ? ? ? ? ? /* clear status bits */
> + ? ? ? ? ? ? ? nand_writel(info, NDSR, NDSR_MASK);
> + ? ? ? ? ? ? ? ndcr = nand_readl(info, NDCR);
> + ? ? ? ? ? ? ? udelay(1);
> + ? ? ? } while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0));
> +
> + ? ? ? if (timeout <= 0) {
> + ? ? ? ? ? ? ? ndcr &= ~(NDCR_ND_RUN);
> + ? ? ? ? ? ? ? nand_writel(info, NDCR, ndcr);
> + ? ? ? }
> +}
> +
> +static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
> ? ? ? ? ? ? ? ?uint16_t cmd, int column, int page_addr)
> ?{
> ? ? ? ?pxa3xx_set_datasize(info);
> @@ -369,21 +395,18 @@ static int prepare_read_prog_cmd(struct
> pxa3xx_nand_info *info,
>
> ? ? ? ?if (cmd == cmdset.program)
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
> -
> - ? ? ? return 0;
> ?}
>
> -static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
> +static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
> ? ? ? ? ? ? ? ? ? ? ? ?uint16_t cmd, int page_addr)
> ?{
> ? ? ? ?info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
> ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
> ? ? ? ?info->ndcb1 = page_addr;
> ? ? ? ?info->ndcb2 = 0;
> - ? ? ? return 0;
> ?}
>
> -static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
> +static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
> ?{
> ? ? ? ?info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
> ? ? ? ?info->ndcb1 = 0;
> @@ -398,10 +421,7 @@ static int prepare_other_cmd(struct
> pxa3xx_nand_info *info, uint16_t cmd)
> ? ? ? ?} else if (cmd == cmdset.reset || cmd == cmdset.lock ||
> ? ? ? ? ? ? ? ? ? cmd == cmdset.unlock) {
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(5);
> - ? ? ? } else
> - ? ? ? ? ? ? ? return -EINVAL;
> -
> - ? ? ? return 0;
> + ? ? ? }
> ?}
>
> ?static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
> @@ -420,71 +440,23 @@ static void disable_int(struct pxa3xx_nand_info
> *info, uint32_t int_mask)
> ? ? ? ?nand_writel(info, NDCR, ndcr | int_mask);
> ?}
>
> -/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
> - * otherwise, it does not work
> - */
> -static int write_cmd(struct pxa3xx_nand_info *info)
> -{
> - ? ? ? uint32_t ndcr;
> -
> - ? ? ? /* clear status bits and run */
> - ? ? ? nand_writel(info, NDSR, NDSR_MASK);
> -
> - ? ? ? ndcr = info->reg_ndcr;
> -
> - ? ? ? ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
> - ? ? ? ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
> - ? ? ? ndcr |= NDCR_ND_RUN;
> -
> - ? ? ? nand_writel(info, NDCR, ndcr);
> -
> - ? ? ? if (wait_for_event(info, NDSR_WRCMDREQ)) {
> - ? ? ? ? ? ? ? printk(KERN_ERR "timed out writing command\n");
> - ? ? ? ? ? ? ? return -ETIMEDOUT;
> - ? ? ? }
> -
> - ? ? ? nand_writel(info, NDCB0, info->ndcb0);
> - ? ? ? nand_writel(info, NDCB0, info->ndcb1);
> - ? ? ? nand_writel(info, NDCB0, info->ndcb2);
> - ? ? ? return 0;
> -}
> -
> -static int handle_data_pio(struct pxa3xx_nand_info *info)
> +static void handle_data_pio(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? int ret, timeout = CHIP_DELAY_TIMEOUT;
> -
> - ? ? ? switch (info->state) {
> - ? ? ? case STATE_PIO_WRITING:
> + ? ? ? if (info->state & STATE_IS_WRITE) {
> ? ? ? ? ? ? ? ?__raw_writesl(info->mmio_base + NDDB, info->data_buff,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->data_size, 4));
> ? ? ? ? ? ? ? ?if (info->oob_size > 0)
> ? ? ? ? ? ? ? ? ? ? ? ?__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->oob_size, 4));
>
> - ? ? ? ? ? ? ? enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
> -
> - ? ? ? ? ? ? ? ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
> - ? ? ? ? ? ? ? if (!ret) {
> - ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "program command time out\n");
> - ? ? ? ? ? ? ? ? ? ? ? return -1;
> - ? ? ? ? ? ? ? }
> - ? ? ? ? ? ? ? break;
> - ? ? ? case STATE_PIO_READING:
> + ? ? ? }
> + ? ? ? else {
> ? ? ? ? ? ? ? ?__raw_readsl(info->mmio_base + NDDB, info->data_buff,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->data_size, 4));
> ? ? ? ? ? ? ? ?if (info->oob_size > 0)
> ? ? ? ? ? ? ? ? ? ? ? ?__raw_readsl(info->mmio_base + NDDB, info->oob_buff,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->oob_size, 4));
> -
> - ? ? ? ? ? ? ? break;
> - ? ? ? default:
> - ? ? ? ? ? ? ? printk(KERN_ERR "%s: invalid state %d\n", __func__,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
> - ? ? ? ? ? ? ? return -EINVAL;
> ? ? ? ?}
> -
> - ? ? ? info->state = STATE_READY;
> - ? ? ? return 0;
> ?}
>
> ?static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
> @@ -520,93 +492,59 @@ static void pxa3xx_nand_data_dma_irq(int
> channel, void *data)
>
> ? ? ? ?if (dcsr & DCSR_BUSERR) {
> ? ? ? ? ? ? ? ?info->retcode = ERR_DMABUSERR;
> - ? ? ? ? ? ? ? complete(&info->cmd_complete);
> ? ? ? ?}
>
> - ? ? ? if (info->state == STATE_DMA_WRITING) {
> - ? ? ? ? ? ? ? info->state = STATE_DMA_DONE;
> - ? ? ? ? ? ? ? enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
> - ? ? ? } else {
> - ? ? ? ? ? ? ? info->state = STATE_READY;
> - ? ? ? ? ? ? ? complete(&info->cmd_complete);
> - ? ? ? }
> + ? ? ? enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
> ?}
>
> ?static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = devid;
> - ? ? ? unsigned int status;
> + ? ? ? unsigned int status, is_completed = 0;
>
> ? ? ? ?status = nand_readl(info, NDSR);
>
> - ? ? ? if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) {
> - ? ? ? ? ? ? ? if (status & NDSR_DBERR)
> - ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_DBERR;
> - ? ? ? ? ? ? ? else if (status & NDSR_SBERR)
> - ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_SBERR;
> -
> - ? ? ? ? ? ? ? disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
> + ? ? ? if (status & NDSR_DBERR)
> + ? ? ? ? ? ? ? info->retcode = ERR_DBERR;
> + ? ? ? if (status & NDSR_SBERR)
> + ? ? ? ? ? ? ? info->retcode = ERR_SBERR;
> + ? ? ? if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
>
> + ? ? ? ? ? ? ? info->state |= STATE_DATA_PROCESSING;
> + ? ? ? ? ? ? ? /* whether use dma to transfer data */
> ? ? ? ? ? ? ? ?if (info->use_dma) {
> - ? ? ? ? ? ? ? ? ? ? ? info->state = STATE_DMA_READING;
> + ? ? ? ? ? ? ? ? ? ? ? disable_int(info, NDSR_WRDREQ);
> ? ? ? ? ? ? ? ? ? ? ? ?start_data_dma(info, 0);
> - ? ? ? ? ? ? ? } else {
> - ? ? ? ? ? ? ? ? ? ? ? info->state = STATE_PIO_READING;
> - ? ? ? ? ? ? ? ? ? ? ? complete(&info->cmd_complete);
> - ? ? ? ? ? ? ? }
> - ? ? ? } else if (status & NDSR_WRDREQ) {
> - ? ? ? ? ? ? ? disable_int(info, NDSR_WRDREQ);
> - ? ? ? ? ? ? ? if (info->use_dma) {
> - ? ? ? ? ? ? ? ? ? ? ? info->state = STATE_DMA_WRITING;
> - ? ? ? ? ? ? ? ? ? ? ? start_data_dma(info, 1);
> - ? ? ? ? ? ? ? } else {
> - ? ? ? ? ? ? ? ? ? ? ? info->state = STATE_PIO_WRITING;
> - ? ? ? ? ? ? ? ? ? ? ? complete(&info->cmd_complete);
> - ? ? ? ? ? ? ? }
> - ? ? ? } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
> - ? ? ? ? ? ? ? if (status & NDSR_CS0_BBD)
> - ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_BBERR;
> + ? ? ? ? ? ? ? ? ? ? ? goto NORMAL_IRQ_EXIT;
> + ? ? ? ? ? ? ? } else
> + ? ? ? ? ? ? ? ? ? ? ? handle_data_pio(info);
>
> - ? ? ? ? ? ? ? disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
> - ? ? ? ? ? ? ? info->state = STATE_READY;
> - ? ? ? ? ? ? ? complete(&info->cmd_complete);
> + ? ? ? ? ? ? ? info->state |= STATE_DATA_DONE;
> ? ? ? ?}
> - ? ? ? nand_writel(info, NDSR, status);
> - ? ? ? return IRQ_HANDLED;
> -}
> -
> -static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
> -{
> - ? ? ? uint32_t ndcr;
> - ? ? ? int ret, timeout = CHIP_DELAY_TIMEOUT;
> -
> - ? ? ? if (write_cmd(info)) {
> - ? ? ? ? ? ? ? info->retcode = ERR_SENDCMD;
> - ? ? ? ? ? ? ? goto fail_stop;
> + ? ? ? if (status & NDSR_CS0_CMDD) {
> + ? ? ? ? ? ? ? info->state |= STATE_CMD_DONE;
> + ? ? ? ? ? ? ? is_completed = 1;
> ? ? ? ?}
> -
> - ? ? ? info->state = STATE_CMD_HANDLE;
> -
> - ? ? ? enable_int(info, event);
> -
> - ? ? ? ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
> - ? ? ? if (!ret) {
> - ? ? ? ? ? ? ? printk(KERN_ERR "command execution timed out\n");
> - ? ? ? ? ? ? ? info->retcode = ERR_SENDCMD;
> - ? ? ? ? ? ? ? goto fail_stop;
> + ? ? ? if (status & NDSR_FLASH_RDY)
> + ? ? ? ? ? ? ? info->state |= STATE_READY;
> + ? ? ? if (status & NDSR_CS0_PAGED)
> + ? ? ? ? ? ? ? info->state |= STATE_PAGE_DONE;
> +
> + ? ? ? if (status & NDSR_WRCMDREQ) {
> + ? ? ? ? ? ? ? nand_writel(info, NDSR, NDSR_WRCMDREQ);
> + ? ? ? ? ? ? ? status &= ~NDSR_WRCMDREQ;
> + ? ? ? ? ? ? ? info->state |= STATE_CMD_WAIT_DONE;
> + ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb0);
> + ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb1);
> + ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb2);
> ? ? ? ?}
>
> - ? ? ? if (info->use_dma == 0 && info->data_size > 0)
> - ? ? ? ? ? ? ? if (handle_data_pio(info))
> - ? ? ? ? ? ? ? ? ? ? ? goto fail_stop;
> -
> - ? ? ? return 0;
> -
> -fail_stop:
> - ? ? ? ndcr = nand_readl(info, NDCR);
> - ? ? ? nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
> - ? ? ? udelay(10);
> - ? ? ? return -ETIMEDOUT;
> + ? ? ? /* clear NDSR to let the controller exit the IRQ */
> + ? ? ? nand_writel(info, NDSR, status);
> + ? ? ? if (is_completed)
> + ? ? ? ? ? ? ? complete(&info->cmd_complete);
> +NORMAL_IRQ_EXIT:
> + ? ? ? return IRQ_HANDLED;
> ?}
>
> ?static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
> @@ -627,14 +565,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
> *mtd, unsigned command,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int column, int page_addr)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
> - ? ? ? int ret;
> + ? ? ? int ret, exec_cmd = 0;
>
> ? ? ? ?info->use_dma = (use_dma) ? 1 : 0;
> ? ? ? ?info->use_ecc = 0;
> ? ? ? ?info->data_size = 0;
> - ? ? ? info->state = STATE_READY;
> -
> - ? ? ? init_completion(&info->cmd_complete);
> + ? ? ? info->state = 0;
>
> ? ? ? ?switch (command) {
> ? ? ? ?case NAND_CMD_READOOB:
> @@ -643,14 +579,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
> *mtd, unsigned command,
> ? ? ? ? ? ? ? ?info->buf_start = mtd->writesize + column;
> ? ? ? ? ? ? ? ?memset(info->data_buff, 0xFF, info->buf_count);
>
> - ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr))
> - ? ? ? ? ? ? ? ? ? ? ? break;
> -
> - ? ? ? ? ? ? ? pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
> + ? ? ? ? ? ? ? prepare_read_prog_cmd(info, cmdset.read1, column, page_addr);
>
> ? ? ? ? ? ? ? ?/* We only are OOB, so if the data has error, does not matter */
> ? ? ? ? ? ? ? ?if (info->retcode == ERR_DBERR)
> ? ? ? ? ? ? ? ? ? ? ? ?info->retcode = ERR_NONE;
> +
> + ? ? ? ? ? ? ? exec_cmd = 1;
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case NAND_CMD_READ0:
> @@ -660,11 +595,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
> *mtd, unsigned command,
> ? ? ? ? ? ? ? ?info->buf_count = mtd->writesize + mtd->oobsize;
> ? ? ? ? ? ? ? ?memset(info->data_buff, 0xFF, info->buf_count);
>
> - ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr))
> - ? ? ? ? ? ? ? ? ? ? ? break;
> -
> - ? ? ? ? ? ? ? pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
> -
> + ? ? ? ? ? ? ? prepare_read_prog_cmd(info, cmdset.read1, column, page_addr);
> ? ? ? ? ? ? ? ?if (info->retcode == ERR_DBERR) {
> ? ? ? ? ? ? ? ? ? ? ? ?/* for blank page (all 0xff), HW will calculate its ECC as
> ? ? ? ? ? ? ? ? ? ? ? ? * 0, which is different from the ECC information within
> @@ -673,6 +604,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
> *mtd, unsigned command,
> ? ? ? ? ? ? ? ? ? ? ? ?if (is_buf_blank(info->data_buff, mtd->writesize))
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->retcode = ERR_NONE;
> ? ? ? ? ? ? ? ?}
> +
> + ? ? ? ? ? ? ? exec_cmd = 1;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_SEQIN:
> ? ? ? ? ? ? ? ?info->buf_start = column;
> @@ -686,18 +619,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
> *mtd, unsigned command,
> ? ? ? ?case NAND_CMD_PAGEPROG:
> ? ? ? ? ? ? ? ?info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
>
> - ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset.program,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->seqin_column, info->seqin_page_addr))
> - ? ? ? ? ? ? ? ? ? ? ? break;
> -
> - ? ? ? ? ? ? ? pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
> + ? ? ? ? ? ? ? prepare_read_prog_cmd(info, cmdset.program,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->seqin_column, info->seqin_page_addr);
> + ? ? ? ? ? ? ? info->state |= STATE_IS_WRITE;
> + ? ? ? ? ? ? ? exec_cmd = 1;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_ERASE1:
> - ? ? ? ? ? ? ? if (prepare_erase_cmd(info, cmdset.erase, page_addr))
> - ? ? ? ? ? ? ? ? ? ? ? break;
> -
> - ? ? ? ? ? ? ? pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
> - ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? prepare_erase_cmd(info, cmdset.erase, page_addr);
> + ? ? ? ? ? ? ? exec_cmd = 1;
> ? ? ? ?case NAND_CMD_ERASE2:
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_READID:
> @@ -707,39 +636,37 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
> *mtd, unsigned command,
> ? ? ? ? ? ? ? ?info->buf_count = (command == NAND_CMD_READID) ?
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->read_id_bytes : 1;
>
> - ? ? ? ? ? ? ? if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cmdset.read_id : cmdset.read_status))
> - ? ? ? ? ? ? ? ? ? ? ? break;
> -
> - ? ? ? ? ? ? ? pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
> + ? ? ? ? ? ? ? prepare_other_cmd(info, (command == NAND_CMD_READID) ?
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cmdset.read_id : cmdset.read_status);
> + ? ? ? ? ? ? ? exec_cmd = 1;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_RESET:
> - ? ? ? ? ? ? ? if (prepare_other_cmd(info, cmdset.reset))
> - ? ? ? ? ? ? ? ? ? ? ? break;
> -
> - ? ? ? ? ? ? ? ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
> - ? ? ? ? ? ? ? if (ret == 0) {
> - ? ? ? ? ? ? ? ? ? ? ? int timeout = 2;
> - ? ? ? ? ? ? ? ? ? ? ? uint32_t ndcr;
> -
> - ? ? ? ? ? ? ? ? ? ? ? while (timeout--) {
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (nand_readl(info, NDSR) & NDSR_RDY)
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? msleep(10);
> - ? ? ? ? ? ? ? ? ? ? ? }
> -
> - ? ? ? ? ? ? ? ? ? ? ? ndcr = nand_readl(info, NDCR);
> - ? ? ? ? ? ? ? ? ? ? ? nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
> - ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? prepare_other_cmd(info, cmdset.reset);
> + ? ? ? ? ? ? ? exec_cmd = 1;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?printk(KERN_ERR "non-supported command.\n");
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
>
> - ? ? ? if (info->retcode == ERR_DBERR) {
> - ? ? ? ? ? ? ? printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
> - ? ? ? ? ? ? ? info->retcode = ERR_NONE;
> + ? ? ? if (exec_cmd) {
> + ? ? ? ? ? ? ? init_completion(&info->cmd_complete);
> + ? ? ? ? ? ? ? info->state |= STATE_CMD_PREPARED;
> + ? ? ? ? ? ? ? pxa3xx_nand_start(info);
> +
> + ? ? ? ? ? ? ? ret = wait_for_completion_timeout(&info->cmd_complete,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CHIP_DELAY_TIMEOUT);
> + ? ? ? ? ? ? ? if (!ret) {
> + ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "Wait time out!!!\n");
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? /* Stop State Machine for next command cycle */
> + ? ? ? ? ? ? ? pxa3xx_nand_stop(info);
> + ? ? ? ? ? ? ? disable_int(info, NDCR_INT_MASK);
> + ? ? ? ? ? ? ? info->state &= ~STATE_CMD_PREPARED;
> + ? ? ? ? ? ? ? if (info->retcode == ERR_DBERR) {
> + ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
> + ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
> + ? ? ? ? ? ? ? }
> ? ? ? ?}
> ?}
>
> @@ -848,41 +775,12 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
> ? ? ? ?return 0;
> ?}
>
> -static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
> -{
> - ? ? ? uint32_t ndcr;
> - ? ? ? uint8_t ?id_buff[8];
> -
> - ? ? ? if (prepare_other_cmd(info, cmdset.read_id)) {
> - ? ? ? ? ? ? ? printk(KERN_ERR "failed to prepare command\n");
> - ? ? ? ? ? ? ? return -EINVAL;
> - ? ? ? }
> -
> - ? ? ? /* Send command */
> - ? ? ? if (write_cmd(info))
> - ? ? ? ? ? ? ? goto fail_timeout;
> -
> - ? ? ? /* Wait for CMDDM(command done successfully) */
> - ? ? ? if (wait_for_event(info, NDSR_RDDREQ))
> - ? ? ? ? ? ? ? goto fail_timeout;
> -
> - ? ? ? __raw_readsl(info->mmio_base + NDDB, id_buff, 2);
> - ? ? ? *id = id_buff[0] | (id_buff[1] << 8);
> - ? ? ? return 0;
> -
> -fail_timeout:
> - ? ? ? ndcr = nand_readl(info, NDCR);
> - ? ? ? nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
> - ? ? ? udelay(10);
> - ? ? ? return -ETIMEDOUT;
> -}
> -
> ?static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const struct pxa3xx_nand_flash *f)
> ?{
> ? ? ? ?struct platform_device *pdev = info->pdev;
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> - ? ? ? uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
> + ? ? ? uint32_t ndcr = 0;
>
> ? ? ? ?/* calculate flash information */
> ? ? ? ?info->page_size = f->page_size;
> @@ -949,8 +847,9 @@ static int pxa3xx_nand_detect_config(struct
> pxa3xx_nand_info *info)
> ? ? ? ?info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2;
> ? ? ? ?info->reg_ndcr = ndcr;
>
> - ? ? ? if (__readid(info, &id))
> - ? ? ? ? ? ? ? return -ENODEV;
> +
> + ? ? ? pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
> + ? ? ? id = *((uint16_t *)(info->data_buff));
>
> ? ? ? ?/* Lookup the flash id */
> ? ? ? ?id = (id >> 8) & 0xff; ? ? ? ? ?/* device id is byte 2 */
> @@ -997,8 +896,8 @@ static int pxa3xx_nand_detect_flash(struct
> pxa3xx_nand_info *info,
>
> ? ? ? ?f = &builtin_flash_types[0];
> ? ? ? ?pxa3xx_nand_config_flash(info, f);
> - ? ? ? if (__readid(info, &id))
> - ? ? ? ? ? ? ? goto fail_detect;
> + ? ? ? pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
> + ? ? ? id = *((uint16_t *)(info->data_buff));
>
> ? ? ? ?for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
> ? ? ? ? ? ? ? ?if (i < pdata->num_flash)
> @@ -1015,7 +914,6 @@ static int pxa3xx_nand_detect_flash(struct
> pxa3xx_nand_info *info,
> ? ? ? ?dev_warn(&info->pdev->dev,
> ? ? ? ? ? ? ? ? ? ? ? ?"failed to detect configured nand flash; found %04x instead of\n",
> ? ? ? ? ? ? ? ? id);
> -fail_detect:
> ? ? ? ?return -ENODEV;
> ?}
>
> @@ -1303,7 +1201,7 @@ static int pxa3xx_nand_suspend(struct
> platform_device *pdev, pm_message_t state)
> ? ? ? ?struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
> ? ? ? ?struct mtd_info *mtd = info->mtd;
>
> - ? ? ? if (info->state != STATE_READY) {
> + ? ? ? if (info->state & STATE_CMD_PREPARED) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
> ? ? ? ? ? ? ? ?return -EAGAIN;
> ? ? ? ?}
> --
> 1.7.0.4
>

From eric.y.miao at gmail.com  Fri Jun 18 02:52:34 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:52:34 +0800
Subject: [PATCH 06/25] pxa3xx_nand: unify prepare command
In-Reply-To: <AANLkTilhattkx7AiyG-R4zbWSZ3-qkPIM6VhyFW4lk4D@mail.gmail.com>
References: <AANLkTilhattkx7AiyG-R4zbWSZ3-qkPIM6VhyFW4lk4D@mail.gmail.com>
Message-ID: <AANLkTinNqtnL3LRFsPuUQXcTnRda0_B059bRLGlJuzlh@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From ac05ddc3c13d2b80b243e91cba9922572841f34a Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Mon, 22 Mar 2010 12:04:22 +0800
> Subject: [PATCH 06/25] pxa3xx_nand: unify prepare command
>
> Make the interface simpler which could make both debug
> and enhancement easier.

What is the benefit of combining them into one big several pages lengthy
function? I dislike lengthy function :-/

>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ?256 +++++++++++++++++++++-------------------
> ?1 files changed, 136 insertions(+), 120 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 753346f..9ab292b 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -28,6 +28,7 @@
>
> ?#define ? ? ? ?CHIP_DELAY_TIMEOUT ? ? ?(2 * HZ/10)
> ?#define NAND_STOP_DELAY ? ? ? ? ? ? ? ?(2 * HZ/50)
> +#define PAGE_CHUNK_SIZE ? ? ? ? ? ? ? ?(2048)
>
> ?/* registers and bit definitions */
> ?#define NDCR ? ? ? ? ? (0x00) /* Control register */
> @@ -78,6 +79,7 @@
> ?#define NDSR_RDDREQ ? ? ? ? ? ?(0x1 << 1)
> ?#define NDSR_WRCMDREQ ? ? ? ? ?(0x1)
>
> +#define NDCB0_ST_ROW_EN ? ? ? ? (0x1 << 26)
> ?#define NDCB0_AUTO_RS ? ? ? ? ?(0x1 << 25)
> ?#define NDCB0_CSEL ? ? ? ? ? ? (0x1 << 24)
> ?#define NDCB0_CMD_TYPE_MASK ? ?(0x7 << 21)
> @@ -340,7 +342,7 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
> ? ? ? ?uint32_t ndcr;
>
> ? ? ? ?ndcr = info->reg_ndcr;
> - ? ? ? ndcr |= NDCR_ECC_EN;
> + ? ? ? ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
> ? ? ? ?ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
> ? ? ? ?ndcr |= NDCR_ND_RUN;
>
> @@ -369,61 +371,6 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
> ? ? ? ?}
> ?}
>
> -static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
> - ? ? ? ? ? ? ? uint16_t cmd, int column, int page_addr)
> -{
> - ? ? ? pxa3xx_set_datasize(info);
> -
> - ? ? ? /* generate values for NDCBx registers */
> - ? ? ? info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
> - ? ? ? info->ndcb1 = 0;
> - ? ? ? info->ndcb2 = 0;
> - ? ? ? info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
> -
> - ? ? ? if (info->col_addr_cycles == 2) {
> - ? ? ? ? ? ? ? /* large block, 2 cycles for column address
> - ? ? ? ? ? ? ? ?* row address starts from 3rd cycle
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? info->ndcb1 |= page_addr << 16;
> - ? ? ? ? ? ? ? if (info->row_addr_cycles == 3)
> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = (page_addr >> 16) & 0xff;
> - ? ? ? } else
> - ? ? ? ? ? ? ? /* small block, 1 cycles for column address
> - ? ? ? ? ? ? ? ?* row address starts from 2nd cycle
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? info->ndcb1 = page_addr << 8;
> -
> - ? ? ? if (cmd == cmdset.program)
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
> -}
> -
> -static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
> - ? ? ? ? ? ? ? ? ? ? ? uint16_t cmd, int page_addr)
> -{
> - ? ? ? info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
> - ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
> - ? ? ? info->ndcb1 = page_addr;
> - ? ? ? info->ndcb2 = 0;
> -}
> -
> -static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
> -{
> - ? ? ? info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
> - ? ? ? info->ndcb1 = 0;
> - ? ? ? info->ndcb2 = 0;
> -
> - ? ? ? if (cmd == cmdset.read_id) {
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(3);
> - ? ? ? ? ? ? ? info->data_size = 8;
> - ? ? ? } else if (cmd == cmdset.read_status) {
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(4);
> - ? ? ? ? ? ? ? info->data_size = 8;
> - ? ? ? } else if (cmd == cmdset.reset || cmd == cmdset.lock ||
> - ? ? ? ? ? ? ? ? ?cmd == cmdset.unlock) {
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(5);
> - ? ? ? }
> -}
> -
> ?static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
> ?{
> ? ? ? ?uint32_t ndcr;
> @@ -561,94 +508,167 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
> ? ? ? ?return 1;
> ?}
>
> -static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int column, int page_addr)
> +static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> + ? ? ? ? ? ? ? uint16_t column, int page_addr)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> - ? ? ? int ret, exec_cmd = 0;
> + ? ? ? uint16_t cmd;
> + ? ? ? int addr_cycle, exec_cmd, ndcb0;
> + ? ? ? struct mtd_info *mtd = info->mtd;
>
> - ? ? ? info->use_dma = (use_dma) ? 1 : 0;
> - ? ? ? info->use_ecc = 0;
> - ? ? ? info->data_size = 0;
> - ? ? ? info->state = 0;
> + ? ? ? ndcb0 = 0;
> + ? ? ? addr_cycle = 0;
> + ? ? ? exec_cmd = 1;
> +
> + ? ? ? /* reset data and oob column point to handle data */
> + ? ? ? info->buf_start ? ? ? ? = 0;
> + ? ? ? info->buf_count ? ? ? ? = 0;
> + ? ? ? info->oob_size ? ? ? ? ?= 0;
> + ? ? ? info->use_ecc ? ? ? ? ? = 0;
>
> ? ? ? ?switch (command) {
> + ? ? ? case NAND_CMD_READ0:
> + ? ? ? case NAND_CMD_PAGEPROG:
> + ? ? ? ? ? ? ? info->use_ecc = 1;
> ? ? ? ?case NAND_CMD_READOOB:
> - ? ? ? ? ? ? ? /* disable HW ECC to get all the OOB data */
> - ? ? ? ? ? ? ? info->buf_count = mtd->writesize + mtd->oobsize;
> - ? ? ? ? ? ? ? info->buf_start = mtd->writesize + column;
> - ? ? ? ? ? ? ? memset(info->data_buff, 0xFF, info->buf_count);
> + ? ? ? ? ? ? ? pxa3xx_set_datasize(info);
> + ? ? ? ? ? ? ? break;
> + ? ? ? case NAND_CMD_SEQIN:
> + ? ? ? ? ? ? ? exec_cmd = 0;
> + ? ? ? ? ? ? ? break;
> + ? ? ? default:
> + ? ? ? ? ? ? ? info->ndcb1 = 0;
> + ? ? ? ? ? ? ? info->ndcb2 = 0;
> + ? ? ? ? ? ? ? break;
> + ? ? ? }
>
> - ? ? ? ? ? ? ? prepare_read_prog_cmd(info, cmdset.read1, column, page_addr);
> + ? ? ? info->ndcb0 = ndcb0;
> + ? ? ? addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
> + ? ? ? ? ? ? ? ? ? ? ? + info->col_addr_cycles);
>
> - ? ? ? ? ? ? ? /* We only are OOB, so if the data has error, does not matter */
> - ? ? ? ? ? ? ? if (info->retcode == ERR_DBERR)
> - ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
> + ? ? ? switch (command) {
> + ? ? ? case NAND_CMD_READOOB:
> + ? ? ? case NAND_CMD_READ0:
>
> - ? ? ? ? ? ? ? exec_cmd = 1;
> - ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? cmd ?= cmdset.read1;
> + ? ? ? ? ? ? ? if (command == NAND_CMD_READOOB)
> + ? ? ? ? ? ? ? ? ? ? ? info->buf_start = mtd->writesize + column;
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? info->buf_start = column;
>
> - ? ? ? case NAND_CMD_READ0:
> - ? ? ? ? ? ? ? info->use_ecc = 1;
> - ? ? ? ? ? ? ? info->retcode = ERR_NONE;
> - ? ? ? ? ? ? ? info->buf_start = column;
> - ? ? ? ? ? ? ? info->buf_count = mtd->writesize + mtd->oobsize;
> - ? ? ? ? ? ? ? memset(info->data_buff, 0xFF, info->buf_count);
> + ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
> + ? ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | addr_cycle
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (cmd & NDCB0_CMD1_MASK);
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_DBC
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | addr_cycle
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
>
> - ? ? ? ? ? ? ? prepare_read_prog_cmd(info, cmdset.read1, column, page_addr);
> - ? ? ? ? ? ? ? if (info->retcode == ERR_DBERR) {
> - ? ? ? ? ? ? ? ? ? ? ? /* for blank page (all 0xff), HW will calculate its ECC as
> - ? ? ? ? ? ? ? ? ? ? ? ?* 0, which is different from the ECC information within
> - ? ? ? ? ? ? ? ? ? ? ? ?* OOB, ignore such double bit errors
> - ? ? ? ? ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? ? ? ? ? if (is_buf_blank(info->data_buff, mtd->writesize))
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
> + ? ? ? case NAND_CMD_SEQIN:
> + ? ? ? ? ? ? ? /* small page addr setting */
> + ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
> + ? ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (column & 0xFF);
> +
> + ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? else {
> + ? ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFF) << 16)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (column & 0xFFFF);
> +
> + ? ? ? ? ? ? ? ? ? ? ? if (page_addr & 0xFF0000)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = (page_addr & 0xFF0000) >> 16;
> + ? ? ? ? ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
> ? ? ? ? ? ? ? ?}
>
> - ? ? ? ? ? ? ? exec_cmd = 1;
> - ? ? ? ? ? ? ? break;
> - ? ? ? case NAND_CMD_SEQIN:
> - ? ? ? ? ? ? ? info->buf_start = column;
> ? ? ? ? ? ? ? ?info->buf_count = mtd->writesize + mtd->oobsize;
> - ? ? ? ? ? ? ? memset(info->data_buff, 0xff, info->buf_count);
> + ? ? ? ? ? ? ? memset(info->data_buff, 0xFF, info->buf_count);
>
> - ? ? ? ? ? ? ? /* save column/page_addr for next CMD_PAGEPROG */
> - ? ? ? ? ? ? ? info->seqin_column = column;
> - ? ? ? ? ? ? ? info->seqin_page_addr = page_addr;
> ? ? ? ? ? ? ? ?break;
> +
> ? ? ? ?case NAND_CMD_PAGEPROG:
> - ? ? ? ? ? ? ? info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
> + ? ? ? ? ? ? ? if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) {
> + ? ? ? ? ? ? ? ? ? ? ? exec_cmd = 0;
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
>
> - ? ? ? ? ? ? ? prepare_read_prog_cmd(info, cmdset.program,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->seqin_column, info->seqin_page_addr);
> + ? ? ? ? ? ? ? cmd = cmdset.program;
> ? ? ? ? ? ? ? ?info->state |= STATE_IS_WRITE;
> - ? ? ? ? ? ? ? exec_cmd = 1;
> - ? ? ? ? ? ? ? break;
> - ? ? ? case NAND_CMD_ERASE1:
> - ? ? ? ? ? ? ? prepare_erase_cmd(info, cmdset.erase, page_addr);
> - ? ? ? ? ? ? ? exec_cmd = 1;
> - ? ? ? case NAND_CMD_ERASE2:
> + ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_AUTO_RS
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ST_ROW_EN
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_DBC
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | addr_cycle;
> ? ? ? ? ? ? ? ?break;
> +
> ? ? ? ?case NAND_CMD_READID:
> + ? ? ? ? ? ? ? cmd = cmdset.read_id;
> + ? ? ? ? ? ? ? info->buf_count = info->read_id_bytes;
> + ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(3)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ADDR_CYC(1)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
> +
> + ? ? ? ? ? ? ? info->data_size = 8;
> + ? ? ? ? ? ? ? break;
> +
> ? ? ? ?case NAND_CMD_STATUS:
> - ? ? ? ? ? ? ? info->use_dma = 0; ? ? ?/* force PIO read */
> - ? ? ? ? ? ? ? info->buf_start = 0;
> - ? ? ? ? ? ? ? info->buf_count = (command == NAND_CMD_READID) ?
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->read_id_bytes : 1;
> -
> - ? ? ? ? ? ? ? prepare_other_cmd(info, (command == NAND_CMD_READID) ?
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cmdset.read_id : cmdset.read_status);
> - ? ? ? ? ? ? ? exec_cmd = 1;
> + ? ? ? ? ? ? ? cmd = cmdset.read_status;
> + ? ? ? ? ? ? ? info->buf_count = 1;
> + ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(4)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ADDR_CYC(1)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
> +
> + ? ? ? ? ? ? ? info->data_size = 8;
> + ? ? ? ? ? ? ? break;
> +
> + ? ? ? case NAND_CMD_ERASE1:
> + ? ? ? ? ? ? ? cmd = cmdset.erase;
> + ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(2)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_AUTO_RS
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ADDR_CYC(3)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_DBC
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
> + ? ? ? ? ? ? ? info->ndcb1 = page_addr;
> + ? ? ? ? ? ? ? info->ndcb2 = 0;
> +
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_RESET:
> - ? ? ? ? ? ? ? prepare_other_cmd(info, cmdset.reset);
> - ? ? ? ? ? ? ? exec_cmd = 1;
> + ? ? ? ? ? ? ? cmd = cmdset.reset;
> + ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(5)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
> +
> ? ? ? ? ? ? ? ?break;
> +
> + ? ? ? case NAND_CMD_ERASE2:
> + ? ? ? ? ? ? ? exec_cmd = 0;
> + ? ? ? ? ? ? ? break;
> +
> ? ? ? ?default:
> - ? ? ? ? ? ? ? printk(KERN_ERR "non-supported command.\n");
> + ? ? ? ? ? ? ? exec_cmd = 0;
> + ? ? ? ? ? ? ? printk(KERN_ERR "pxa3xx-nand: non-supported command %x\n", command);
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
>
> + ? ? ? return exec_cmd;
> +}
> +
> +static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int column, int page_addr)
> +{
> + ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? int ret, exec_cmd;
> +
> + ? ? ? /* if this is a x16 device ,then convert the input
> + ? ? ? ?* "byte" address into a "word" address appropriate
> + ? ? ? ?* for indexing a word-oriented device
> + ? ? ? ?*/
> + ? ? ? if (info->reg_ndcr & NDCR_DWIDTH_M)
> + ? ? ? ? ? ? ? column /= 2;
> +
> + ? ? ? exec_cmd = prepare_command_pool(info, command, column, page_addr);
> ? ? ? ?if (exec_cmd) {
> ? ? ? ? ? ? ? ?init_completion(&info->cmd_complete);
> ? ? ? ? ? ? ? ?info->state |= STATE_CMD_PREPARED;
> @@ -663,10 +683,6 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
> *mtd, unsigned command,
> ? ? ? ? ? ? ? ?pxa3xx_nand_stop(info);
> ? ? ? ? ? ? ? ?disable_int(info, NDCR_INT_MASK);
> ? ? ? ? ? ? ? ?info->state &= ~STATE_CMD_PREPARED;
> - ? ? ? ? ? ? ? if (info->retcode == ERR_DBERR) {
> - ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
> - ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
> - ? ? ? ? ? ? ? }
> ? ? ? ?}
> ?}
>
> --
> 1.7.0.4
>

From eric.y.miao at gmail.com  Fri Jun 18 02:58:47 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:58:47 +0800
Subject: [PATCH 07/25] pxa3xx_nand: mtd scan id process could be defined 
	by driver itself
In-Reply-To: <AANLkTilY1gnS_jwZ_xPKhchTLR5cWj7FEla1V76OuMVK@mail.gmail.com>
References: <AANLkTilY1gnS_jwZ_xPKhchTLR5cWj7FEla1V76OuMVK@mail.gmail.com>
Message-ID: <AANLkTimnaBO_Zb0UvPZYzmQNmqJafTv1gWV8KQm_LwC3@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From d2958ecbec5d0b7f7aee311fd3e87ed1a858864d Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Wed, 2 Jun 2010 21:55:51 +0800
> Subject: [PATCH 07/25] pxa3xx_nand: mtd scan id process could be
> defined by driver itself
>
> Different NAND driver may require its unique detection. For pxa3xx_nand,
> it use its self id database to get the necessary info.

I believe I get the central point of this patch: to have a specific
pxa3xx_nand_scan()
instead of using the generic nand_scan(). This point is good, yet I
found it extremely
difficult to read the patch. Like those chip->xxxx assignment, is that
also part of this
patch, I strongly recommend to remove irrelevant changes into separate patches.

>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ?255 ++++++++++++++++++++++++++--------------
> ?1 files changed, 165 insertions(+), 90 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 9ab292b..481cb25 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -158,6 +158,7 @@ struct pxa3xx_nand_flash {
> ?struct pxa3xx_nand_info {
> ? ? ? ?struct nand_chip ? ? ? ?nand_chip;
>
> + ? ? ? struct nand_hw_control ?controller;
> ? ? ? ?struct platform_device ? *pdev;
>
> ? ? ? ?struct clk ? ? ? ? ? ? ?*clk;
> @@ -261,6 +262,8 @@ static struct pxa3xx_nand_flash __devinitdata
> builtin_flash_types[] = {
> ? ? ? ?{ 0xba20, ?64, 2048, 16, 16, 2048, &timing[3], },
> ?};
>
> +static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
> +
> ?#define NDTR0_tCH(c) ? (min((c), 7) << 19)
> ?#define NDTR0_tCS(c) ? (min((c), 7) << 16)
> ?#define NDTR0_tWH(c) ? (min((c), 7) << 11)
> @@ -899,40 +902,6 @@ static int pxa3xx_nand_detect_config(struct
> pxa3xx_nand_info *info)
> ? ? ? ?return 0;
> ?}
>
> -static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const struct pxa3xx_nand_platform_data *pdata)
> -{
> - ? ? ? const struct pxa3xx_nand_flash *f;
> - ? ? ? uint32_t id = -1;
> - ? ? ? int i;
> -
> - ? ? ? if (pdata->keep_config)
> - ? ? ? ? ? ? ? if (pxa3xx_nand_detect_config(info) == 0)
> - ? ? ? ? ? ? ? ? ? ? ? return 0;
> -
> - ? ? ? f = &builtin_flash_types[0];
> - ? ? ? pxa3xx_nand_config_flash(info, f);
> - ? ? ? pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
> - ? ? ? id = *((uint16_t *)(info->data_buff));
> -
> - ? ? ? for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
> - ? ? ? ? ? ? ? if (i < pdata->num_flash)
> - ? ? ? ? ? ? ? ? ? ? ? f = pdata->flash + i;
> - ? ? ? ? ? ? ? else
> - ? ? ? ? ? ? ? ? ? ? ? f = &builtin_flash_types[i - pdata->num_flash + 1];
> - ? ? ? ? ? ? ? if (f->chip_id == id) {
> - ? ? ? ? ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
> - ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f);
> - ? ? ? ? ? ? ? ? ? ? ? return 0;
> - ? ? ? ? ? ? ? }
> - ? ? ? }
> -
> - ? ? ? dev_warn(&info->pdev->dev,
> - ? ? ? ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found %04x instead of\n",
> - ? ? ? ? ? ? ? ?id);
> - ? ? ? return -ENODEV;
> -}
> -
> ?/* the maximum possible buffer size for large page with OOB data
> ?* is: 2048 + 64 = 2112 bytes, allocate a page here for both the
> ?* data buffer and the DMA descriptor
> @@ -974,56 +943,153 @@ static int pxa3xx_nand_init_buff(struct
> pxa3xx_nand_info *info)
> ? ? ? ?return 0;
> ?}
>
> -static struct nand_ecclayout hw_smallpage_ecclayout = {
> - ? ? ? .eccbytes = 6,
> - ? ? ? .eccpos = {8, 9, 10, 11, 12, 13 },
> - ? ? ? .oobfree = { {2, 6} }
> -};
> +static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
> + ? ? ? ? ? ? ? struct nand_chip *chip, uint8_t *buf, int page)
> +{
> + ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
>
> -static struct nand_ecclayout hw_largepage_ecclayout = {
> - ? ? ? .eccbytes = 24,
> - ? ? ? .eccpos = {
> - ? ? ? ? ? ? ? 40, 41, 42, 43, 44, 45, 46, 47,
> - ? ? ? ? ? ? ? 48, 49, 50, 51, 52, 53, 54, 55,
> - ? ? ? ? ? ? ? 56, 57, 58, 59, 60, 61, 62, 63},
> - ? ? ? .oobfree = { {2, 38} }
> -};
> + ? ? ? chip->read_buf(mtd, buf, mtd->writesize);
> + ? ? ? chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
> +
> + ? ? ? if (info->retcode == ERR_SBERR) {
> + ? ? ? ? ? ? ? switch (info->use_ecc) {
> + ? ? ? ? ? ? ? ? ? ? ? case 1:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mtd->ecc_stats.corrected ++;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> +
> + ? ? ? ? ? ? ? ? ? ? ? case 0:
> + ? ? ? ? ? ? ? ? ? ? ? default:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> + ? ? ? else if (info->retcode == ERR_DBERR) {
> + ? ? ? ? ? ? ? int buf_blank;
> +
> + ? ? ? ? ? ? ? buf_blank = is_buf_blank(buf, mtd->writesize);
> + ? ? ? ? ? ? ? if (!buf_blank)
> + ? ? ? ? ? ? ? ? ? ? ? mtd->ecc_stats.failed++;
> + ? ? ? }
> +
> + ? ? ? return 0;
> +}
> +
> +static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
> + ? ? ? ? ? ? ? struct nand_chip *chip, const uint8_t *buf)
> +{
> + ? ? ? chip->write_buf(mtd, buf, mtd->writesize);
> + ? ? ? chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
> +}
> +
> +static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
> +{
> + ? ? ? struct nand_chip *chip = mtd->priv;
> + ? ? ? /* Send commands to erase a block */
> + ? ? ? chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
> +}
>
> -static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct pxa3xx_nand_info *info)
> +static int __devinit pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? struct nand_chip *this = &info->nand_chip;
> -
> - ? ? ? this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
> -
> - ? ? ? this->waitfunc ? ? ? ? ?= pxa3xx_nand_waitfunc;
> - ? ? ? this->select_chip ? ? ? = pxa3xx_nand_select_chip;
> - ? ? ? this->dev_ready ? ? ? ? = pxa3xx_nand_dev_ready;
> - ? ? ? this->cmdfunc ? ? ? ? ? = pxa3xx_nand_cmdfunc;
> - ? ? ? this->read_word ? ? ? ? = pxa3xx_nand_read_word;
> - ? ? ? this->read_byte ? ? ? ? = pxa3xx_nand_read_byte;
> - ? ? ? this->read_buf ? ? ? ? ?= pxa3xx_nand_read_buf;
> - ? ? ? this->write_buf ? ? ? ? = pxa3xx_nand_write_buf;
> - ? ? ? this->verify_buf ? ? ? ?= pxa3xx_nand_verify_buf;
> -
> - ? ? ? this->ecc.mode ? ? ? ? ?= NAND_ECC_HW;
> - ? ? ? this->ecc.hwctl ? ? ? ? = pxa3xx_nand_ecc_hwctl;
> - ? ? ? this->ecc.calculate ? ? = pxa3xx_nand_ecc_calculate;
> - ? ? ? this->ecc.correct ? ? ? = pxa3xx_nand_ecc_correct;
> - ? ? ? this->ecc.size ? ? ? ? ?= info->page_size;
> -
> - ? ? ? if (info->page_size == 2048)
> - ? ? ? ? ? ? ? this->ecc.layout = &hw_largepage_ecclayout;
> + ? ? ? struct mtd_info *mtd = info->mtd;
> + ? ? ? struct nand_chip *chip = mtd->priv;
> +
> + ? ? ? /* use the common timing to make a try */
> + ? ? ? pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
> + ? ? ? chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
> + ? ? ? if (info->state & STATE_READY)
> + ? ? ? ? ? ? ? return 1;
> ? ? ? ?else
> - ? ? ? ? ? ? ? this->ecc.layout = &hw_smallpage_ecclayout;
> + ? ? ? ? ? ? ? return 0;
> +}
> +
> +static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
> +{
> + ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct platform_device *pdev = info->pdev;
> + ? ? ? struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> + ? ? ? const struct pxa3xx_nand_flash *f = NULL;
> + ? ? ? struct nand_chip *chip = mtd->priv;
> + ? ? ? uint32_t id = -1;
> + ? ? ? int i, ret;
> +
> + ? ? ? if (pdata->keep_config)
> + ? ? ? ? ? ? ? if (pxa3xx_nand_detect_config(info) == 0)
> + ? ? ? ? ? ? ? ? ? ? ? return 0;
> +
> + ? ? ? ret = pxa3xx_nand_sensing(info);
> + ? ? ? if (!ret) {
> + ? ? ? ? ? ? ? kfree(mtd);
> + ? ? ? ? ? ? ? info->mtd = NULL;
> + ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs 0!\n");
>
> - ? ? ? this->chip_delay = 25;
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? }
> +
> + ? ? ? chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
> + ? ? ? id = *((uint16_t *)(info->data_buff));
> + ? ? ? if (id != 0)
> + ? ? ? ? ? ? ? printk(KERN_INFO "Detect a flash id %x\n", id);
> + ? ? ? else {
> + ? ? ? ? ? ? ? kfree(mtd);
> + ? ? ? ? ? ? ? info->mtd = NULL;
> + ? ? ? ? ? ? ? printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
> +
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? }
> +
> + ? ? ? for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
> + ? ? ? ? ? ? ? if (i < pdata->num_flash)
> + ? ? ? ? ? ? ? ? ? ? ? f = pdata->flash + i;
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? f = &builtin_flash_types[i - pdata->num_flash + 1];
> +
> + ? ? ? ? ? ? ? /* find the chip in default list */
> + ? ? ? ? ? ? ? if (f->chip_id == id) {
> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f);
> + ? ? ? ? ? ? ? ? ? ? ? mtd->writesize = f->page_size;
> + ? ? ? ? ? ? ? ? ? ? ? mtd->writesize_shift = ffs(mtd->writesize) - 1;
> + ? ? ? ? ? ? ? ? ? ? ? mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
> + ? ? ? ? ? ? ? ? ? ? ? mtd->oobsize = mtd->writesize / 32;
> + ? ? ? ? ? ? ? ? ? ? ? mtd->erasesize = f->page_size * f->page_per_block;
> + ? ? ? ? ? ? ? ? ? ? ? mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
> + ? ? ? ? ? ? ? ? ? ? ? mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
> +
> + ? ? ? ? ? ? ? ? ? ? ? mtd->name = mtd_names[0];
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ? if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
> + ? ? ? ? ? ? ? kfree(mtd);
> + ? ? ? ? ? ? ? info->mtd = NULL;
> + ? ? ? ? ? ? ? printk(KERN_ERR "ERROR!! flash not defined!!!\n");
> +
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? }
> +
> + ? ? ? chip->ecc.mode = NAND_ECC_HW;
> + ? ? ? chip->ecc.size = f->page_size;
> + ? ? ? chip->chipsize ?= (uint64_t)f->num_blocks * f->page_per_block
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * f->page_size;
> + ? ? ? mtd->size = chip->chipsize;
> +
> + ? ? ? /* Calculate the address shift from the page size */
> + ? ? ? chip->page_shift = ffs(mtd->writesize) - 1;
> + ? ? ? chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
> + ? ? ? chip->numchips = 1;
> + ? ? ? chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
> +
> + ? ? ? chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
> + ? ? ? chip->options |= NAND_NO_AUTOINCR;
> + ? ? ? chip->options |= NAND_NO_READRDY;
> + ? ? ? chip->options |= NAND_USE_FLASH_BBT;
> +
> + ? ? ? return nand_scan_tail(mtd);
> ?}
>
> ?static int alloc_nand_resource(struct platform_device *pdev)
> ?{
> - ? ? ? struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> ? ? ? ?struct pxa3xx_nand_info *info;
> + ? ? ? struct nand_chip *chip;
> ? ? ? ?struct mtd_info *mtd;
> ? ? ? ?struct resource *r;
> ? ? ? ?int ret, irq;
> @@ -1036,12 +1102,31 @@ static int alloc_nand_resource(struct
> platform_device *pdev)
> ? ? ? ?}
>
> ? ? ? ?info = (struct pxa3xx_nand_info *)(&mtd[1]);
> + ? ? ? chip = (struct nand_chip *)(&mtd[1]);
> ? ? ? ?info->pdev = pdev;
> -
> - ? ? ? mtd->priv = info;
> ? ? ? ?info->mtd = mtd;
> + ? ? ? mtd->priv = info;
> ? ? ? ?mtd->owner = THIS_MODULE;
>
> + ? ? ? chip->ecc.read_page ? ? = pxa3xx_nand_read_page_hwecc;
> + ? ? ? chip->ecc.write_page ? ?= pxa3xx_nand_write_page_hwecc;
> + ? ? ? chip->ecc.hwctl ? ? ? ? = pxa3xx_nand_ecc_hwctl;
> + ? ? ? chip->ecc.calculate ? ? = pxa3xx_nand_ecc_calculate;
> + ? ? ? chip->ecc.correct ? ? ? = pxa3xx_nand_ecc_correct;
> + ? ? ? chip->controller ? ? ? ?= &info->controller;
> + ? ? ? chip->waitfunc ? ? ? ? ?= pxa3xx_nand_waitfunc;
> + ? ? ? chip->select_chip ? ? ? = pxa3xx_nand_select_chip;
> + ? ? ? chip->dev_ready ? ? ? ? = pxa3xx_nand_dev_ready;
> + ? ? ? chip->cmdfunc ? ? ? ? ? = pxa3xx_nand_cmdfunc;
> + ? ? ? chip->read_word ? ? ? ? = pxa3xx_nand_read_word;
> + ? ? ? chip->read_byte ? ? ? ? = pxa3xx_nand_read_byte;
> + ? ? ? chip->read_buf ? ? ? ? ?= pxa3xx_nand_read_buf;
> + ? ? ? chip->write_buf ? ? ? ? = pxa3xx_nand_write_buf;
> + ? ? ? chip->verify_buf ? ? ? ?= pxa3xx_nand_verify_buf;
> + ? ? ? chip->erase_cmd ? ? ? ? = pxa3xx_nand_erase_cmd;
> +
> + ? ? ? spin_lock_init(&chip->controller->lock);
> + ? ? ? init_waitqueue_head(&chip->controller->wq);
> ? ? ? ?info->clk = clk_get(&pdev->dev, NULL);
> ? ? ? ?if (IS_ERR(info->clk)) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to get nand clock\n");
> @@ -1109,21 +1194,11 @@ static int alloc_nand_resource(struct
> platform_device *pdev)
> ? ? ? ? ? ? ? ?goto fail_free_buf;
> ? ? ? ?}
>
> - ? ? ? ret = pxa3xx_nand_detect_flash(info, pdata);
> - ? ? ? if (ret) {
> - ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to detect flash\n");
> - ? ? ? ? ? ? ? ret = -ENODEV;
> - ? ? ? ? ? ? ? goto fail_free_irq;
> - ? ? ? }
> -
> - ? ? ? pxa3xx_nand_init_mtd(mtd, info);
> ? ? ? ?platform_set_drvdata(pdev, info);
> -
> ? ? ? ?return 0;
>
> -fail_free_irq:
> - ? ? ? free_irq(irq, info);
> ?fail_free_buf:
> + ? ? ? free_irq(irq, info);
> ? ? ? ?if (use_dma) {
> ? ? ? ? ? ? ? ?pxa_free_dma(info->data_dma_ch);
> ? ? ? ? ? ? ? ?dma_free_coherent(&pdev->dev, info->data_buff_size,
> @@ -1191,7 +1266,7 @@ static int __devinit pxa3xx_nand_probe(struct
> platform_device *pdev)
> ? ? ? ? ? ? ? ?return ret;
>
> ? ? ? ?info = platform_get_drvdata(pdev);
> - ? ? ? if (nand_scan(info->mtd, 1)) {
> + ? ? ? if (pxa3xx_nand_scan(info->mtd)) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to scan nand\n");
> ? ? ? ? ? ? ? ?pxa3xx_nand_remove(pdev);
> ? ? ? ? ? ? ? ?return -ENODEV;
> @@ -1202,10 +1277,10 @@ static int __devinit pxa3xx_nand_probe(struct
> platform_device *pdev)
> ? ? ? ? ? ? ? ?struct mtd_partition *parts;
> ? ? ? ? ? ? ? ?int nr_parts;
>
> - ? ? ? ? ? ? ? nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
> + ? ? ? ? ? ? ? nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
>
> ? ? ? ? ? ? ? ?if (nr_parts)
> - ? ? ? ? ? ? ? ? ? ? ? return add_mtd_partitions(mtd, parts, nr_parts);
> + ? ? ? ? ? ? ? ? ? ? ? return add_mtd_partitions(info->mtd, parts, nr_parts);
> ? ? ? ?}
>
> ? ? ? ?return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
> --
> 1.7.0.4
>

From eric.y.miao at gmail.com  Fri Jun 18 02:59:46 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 14:59:46 +0800
Subject: [PATCH 08/25] mmp: add nand support to pxa168
In-Reply-To: <AANLkTinxMQjZIG4G1d9WVOiUX8-zHjTuTc1eRuInDRGW@mail.gmail.com>
References: <AANLkTinxMQjZIG4G1d9WVOiUX8-zHjTuTc1eRuInDRGW@mail.gmail.com>
Message-ID: <AANLkTilOIds0GEPmTWgi_y7UzJT4g9qx6iAtDJDgVxWu@mail.gmail.com>

On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
<haojian.zhuang at gmail.com> wrote:
> From 55adf11cb4ba8ba0b88148c9bce0cc08f94b97bd Mon Sep 17 00:00:00 2001
> From: Lei Wen <leiwen at marvell.com>
> Date: Mon, 31 May 2010 14:57:49 +0800
> Subject: [PATCH 08/25] mmp: add nand support to pxa168
>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> ---
> ?arch/arm/configs/pxa168_defconfig | ? ?9 ++++++++-
> ?drivers/mtd/nand/Kconfig ? ? ? ? ?| ? ?2 +-
> ?2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/configs/pxa168_defconfig
> b/arch/arm/configs/pxa168_defconfig
> index 113511f..a01ea99 100644
> --- a/arch/arm/configs/pxa168_defconfig
> +++ b/arch/arm/configs/pxa168_defconfig
> @@ -438,7 +438,14 @@ CONFIG_EXTRA_FIRMWARE=""
> ?# CONFIG_DEBUG_DEVRES is not set
> ?# CONFIG_SYS_HYPERVISOR is not set
> ?# CONFIG_CONNECTOR is not set
> -# CONFIG_MTD is not set
> +CONFIG_MTD=y
> +CONFIG_MTD_PARTITIONS=y
> +CONFIG_MTD_CMDLINE_PARTS=y
> +CONFIG_MTD_CHAR=y
> +CONFIG_MTD_BLKDEVS=y
> +CONFIG_MTD_BLOCK=y
> +CONFIG_MTD_NAND=y
> +CONFIG_MTD_NAND_PXA3xx=y
> ?# CONFIG_PARPORT is not set
> ?# CONFIG_BLK_DEV is not set
> ?# CONFIG_MISC_DEVICES is not set
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 9a35d92..0d29b5d 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -394,7 +394,7 @@ endchoice
>
> ?config MTD_NAND_PXA3xx
> ? ? ? ?tristate "Support for NAND flash devices on PXA3xx"
> - ? ? ? depends on MTD_NAND && (PXA3xx || ARCH_MMP)
> + ? ? ? depends on MTD_NAND && PLAT_PXA

I'd prefer this not being changed, as pxa3xx_nand isn't applicable to
pxa25x/pxa27x.

> ? ? ? ?help
> ? ? ? ? ?This enables the driver for the NAND flash device found on
> ? ? ? ? ?PXA3xx processors
> --
> 1.7.0.4
>


From adrian.wenl at gmail.com  Fri Jun 18 03:55:21 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 15:55:21 +0800
Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
In-Reply-To: <AANLkTinOsQ8AcH-As91CRqrEQVnXdsm_CmFQgyj7gI1_@mail.gmail.com>
References: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com>
	<AANLkTinOsQ8AcH-As91CRqrEQVnXdsm_CmFQgyj7gI1_@mail.gmail.com>
Message-ID: <AANLkTim9O5kuGzvQoB65fWDr3Bi9siiVBMCPx6heqZjd@mail.gmail.com>

On Fri, Jun 18, 2010 at 2:23 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 1:32 PM, Haojian Zhuang
> <haojian.zhuang at gmail.com> wrote:
>> From 76684334fbf214ab164ed07791b02535a3f04779 Mon Sep 17 00:00:00 2001
>> From: Lei Wen <leiwen at marvell.com>
>> Date: Sat, 20 Mar 2010 19:01:23 +0800
>> Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
>>
>> Adding a new flash definition would need less code.
>> Keep the platform passing flash defition method.
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^^^^^^^^ definition?
Oops... Typo...
>> If one flash is both defined in platform data and builtin table,
>> driver would select the one from platform data first.
>
> This makes sense. I thin the CONFIG_MTD_NAND_PXA3xx_BUILTIN is introduced
> as an optimization so to reduce the code size if platform flash definition
> is provided, instead of an option to remove built-in definitions.

Em... I agree...
>
>>
>> By this way, platform could select the timing most suit for itself,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^^^^ suitable
>> not need to follow the common settings.
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
>
> // there are some line wrapped though, maybe it's my gmail fault.
>
>> ---
>> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 37 ----
>> ?drivers/mtd/nand/Kconfig ? ? ? ? ? ? ? ? ? ? | ? ?7 -
>> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?241 +++++++-------------------
>> ?3 files changed, 66 insertions(+), 219 deletions(-)
>>
>> diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>> b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>> index 3478eae..7e5a28f 100644
>> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>> @@ -4,43 +4,6 @@
>> ?#include <linux/mtd/mtd.h>
>> ?#include <linux/mtd/partitions.h>
>>
>> -struct pxa3xx_nand_timing {
>> - ? ? ? unsigned int ? ?tCH; ?/* Enable signal hold time */
>> - ? ? ? unsigned int ? ?tCS; ?/* Enable signal setup time */
>> - ? ? ? unsigned int ? ?tWH; ?/* ND_nWE high duration */
>> - ? ? ? unsigned int ? ?tWP; ?/* ND_nWE pulse time */
>> - ? ? ? unsigned int ? ?tRH; ?/* ND_nRE high duration */
>> - ? ? ? unsigned int ? ?tRP; ?/* ND_nRE pulse width */
>> - ? ? ? unsigned int ? ?tR; ? /* ND_nWE high to ND_nRE low for read */
>> - ? ? ? unsigned int ? ?tWHR; /* ND_nWE high to ND_nRE low for status read */
>> - ? ? ? unsigned int ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */
>> -};
>> -
>> -struct pxa3xx_nand_cmdset {
>> - ? ? ? uint16_t ? ? ? ?read1;
>> - ? ? ? uint16_t ? ? ? ?read2;
>> - ? ? ? uint16_t ? ? ? ?program;
>> - ? ? ? uint16_t ? ? ? ?read_status;
>> - ? ? ? uint16_t ? ? ? ?read_id;
>> - ? ? ? uint16_t ? ? ? ?erase;
>> - ? ? ? uint16_t ? ? ? ?reset;
>> - ? ? ? uint16_t ? ? ? ?lock;
>> - ? ? ? uint16_t ? ? ? ?unlock;
>> - ? ? ? uint16_t ? ? ? ?lock_status;
>> -};
>> -
>> -struct pxa3xx_nand_flash {
>> - ? ? ? const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
>> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset;
>> -
>> - ? ? ? uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
>> - ? ? ? uint32_t page_size; ? ? /* Page size in bytes (PAGE_SZ) */
>> - ? ? ? uint32_t flash_width; ? /* Width of Flash memory (DWIDTH_M) */
>> - ? ? ? uint32_t dfc_width; ? ? /* Width of flash controller(DWIDTH_C) */
>> - ? ? ? uint32_t num_blocks; ? ?/* Number of physical blocks in Flash */
>> - ? ? ? uint32_t chip_id;
>> -};
>> -
>
> So does this prevent board code from defining their own timing and etc?

No, platform could define its own timing. If there is definition for
the same chip,
driver would choose the one from platform definition first.

>
>> ?struct pxa3xx_nand_platform_data {
>>
>> ? ? ? ?/* the data flash bus is shared between the Static Memory
>> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
>> index 98a04b3..9a35d92 100644
>> --- a/drivers/mtd/nand/Kconfig
>> +++ b/drivers/mtd/nand/Kconfig
>> @@ -399,13 +399,6 @@ config MTD_NAND_PXA3xx
>> ? ? ? ? ?This enables the driver for the NAND flash device found on
>> ? ? ? ? ?PXA3xx processors
>>
>> -config MTD_NAND_PXA3xx_BUILTIN
>> - ? ? ? bool "Use builtin definitions for some NAND chips (deprecated)"
>> - ? ? ? depends on MTD_NAND_PXA3xx
>> - ? ? ? help
>> - ? ? ? ? This enables builtin definitions for some NAND chips. This
>> - ? ? ? ? is deprecated in favor of platform specific data.
>> -
>> ?config MTD_NAND_CM_X270
>> ? ? ? ?tristate "Support for NAND Flash on CM-X270 modules"
>> ? ? ? ?depends on MTD_NAND && MACH_ARMCORE
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>> index e02fa4f..013e075 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>
> ... snipped ...
>
>> ?static struct pxa3xx_nand_timing default_timing;
>> ?static struct pxa3xx_nand_flash default_flash;
>>
>> -static struct pxa3xx_nand_cmdset smallpage_cmdset = {
>> - ? ? ? .read1 ? ? ? ? ?= 0x0000,
>> - ? ? ? .read2 ? ? ? ? ?= 0x0050,
>> - ? ? ? .program ? ? ? ?= 0x1080,
>> - ? ? ? .read_status ? ?= 0x0070,
>> - ? ? ? .read_id ? ? ? ?= 0x0090,
>> - ? ? ? .erase ? ? ? ? ?= 0xD060,
>> - ? ? ? .reset ? ? ? ? ?= 0x00FF,
>> - ? ? ? .lock ? ? ? ? ? = 0x002A,
>> - ? ? ? .unlock ? ? ? ? = 0x2423,
>> - ? ? ? .lock_status ? ?= 0x007A,
>> -};
>> -
>> -static struct pxa3xx_nand_cmdset largepage_cmdset = {
>> +const static struct pxa3xx_nand_cmdset cmdset = {
>
> So how to handle the difference of command set between smallpage and
> largepage?

The only difference of cmdsetbetween the small page and large page is
at the read command.
While large page is 0x3000, small page is 0x0.
This handle is not address in this patch, but put to latter patch of
0006 in this seris patch set.
For whole patch set chnage is so large, that it is not easy to make it
very clear at each patch...



>
>> ? ? ? ?.read1 ? ? ? ? ?= 0x3000,
>> ? ? ? ?.read2 ? ? ? ? ?= 0x0050,
>> ? ? ? ?.program ? ? ? ?= 0x1080,
>> @@ -203,143 +225,26 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = {
>> ? ? ? ?.lock_status ? ?= 0x007A,
>> ?};
>>
>> -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN
>> -static struct pxa3xx_nand_timing samsung512MbX16_timing = {
>> - ? ? ? .tCH ? ?= 10,
>> - ? ? ? .tCS ? ?= 0,
>> - ? ? ? .tWH ? ?= 20,
>> - ? ? ? .tWP ? ?= 40,
>
> ...
>
>> +static struct pxa3xx_nand_timing __devinitdata timing[] = {
>
> Better with some comment columns like below:
>
> ?/* ? ? ? ?tCH tCS tWH tWP ... */
>> + ? ? ? /* Samsung NAND series */
>> + ? ? ? { 10, ?0, 20, 40, 30, 40, 11123, 110, 10, },
>> + ? ? ? /* Micron NAND series */
>> + ? ? ? { 10, 25, 15, 25, 15, 30, 25000, ?60, 10, },
>> + ? ? ? /* ST NAND series */
>> + ? ? ? { 10, 35, 15, 25, 15, 25, 25000, ?60, 10, },
>
> Now define something like
>
> #define NAND_TIMING_SAMSUNG ? ? (&timing[0])
> #define NAND_TIMING_MICRON ? ? ?(&timing[1])
> #define NAND_TIMING_ST ? ? ? ? ?(&timing[2])
>
>> ?};
>>
>> -static struct pxa3xx_nand_flash samsung32GbX8 = {
>> - ? ? ? .timing ? ? ? ? = &samsung512MbX16_timing,
>> - ? ? ? .cmdset ? ? ? ? = &smallpage_cmdset,
>> - ? ? ? .page_per_block = 128,
>> - ? ? ? .page_size ? ? ?= 4096,
>> - ? ? ? .flash_width ? ?= 8,
>> - ? ? ? .dfc_width ? ? ?= 8,
>> - ? ? ? .num_blocks ? ? = 8192,
>> - ? ? ? .chip_id ? ? ? ?= 0xd7ec,
>> +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
>
> /* ? ? ? ?Chip ID, page per block, page size, flash width, .... */
Agree.

>
>> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[0], },
>> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[0], },
>> + ? ? ? { 0xd7ec, 128, 4096, ?8, ?8, 8192, &timing[0], },
>> + ? ? ? { 0xa12c, ?64, 2048, ?8, ?8, 1024, &timing[1], },
>> + ? ? ? { 0xb12c, ?64, 2048, 16, 16, 1024, &timing[1], },
>> + ? ? ? { 0xdc2c, ?64, 2048, ?8, ?8, 4096, &timing[1], },
>> + ? ? ? { 0xcc2c, ?64, 2048, 16, 16, 4096, &timing[1], },
>> + ? ? ? { 0xba20, ?64, 2048, 16, 16, 2048, &timing[2], },
>> ?};
>
> BTW, I like the array above very much.
>
>>
>> -static struct pxa3xx_nand_timing micron_timing = {
>> - ? ? ? .tCH ? ?= 10,
>> - ? ? ? .tCS ? ?= 25,
>> - ? ? ? .tWH ? ?= 15,
>> - ? ? ? .tWP ? ?= 25,
>> - ? ? ? .tRH ? ?= 15,
>> - ? ? ? .tRP ? ?= 30,
>> - ? ? ? .tR ? ? = 25000,
>
> ... snipped ...
>
>> -};
>> -#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */
>> -
>> ?#define NDTR0_tCH(c) ? (min((c), 7) << 19)
>> ?#define NDTR0_tCS(c) ? (min((c), 7) << 16)
>> ?#define NDTR0_tWH(c) ? (min((c), 7) << 11)
>> @@ -412,7 +317,6 @@ static int prepare_read_prog_cmd(struct
>> pxa3xx_nand_info *info,
>> ? ? ? ? ? ? ? ? ? ? ? ?uint16_t cmd, int column, int page_addr)
>> ?{
>> ? ? ? ?const struct pxa3xx_nand_flash *f = info->flash_info;
>> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
>
> I think it's better to keep a local pointer. Reference within a function
> to a global structure is always a bad idea, one day you will find you've
> to modify all these references again when you add a new cmdset.
>
> And most of the modifications below can thus be removed and patch simplified.

My original thinking is for the cmdset is almost standardized, so make
such change for global structure.
Well, the suggestion also make sense. I would revert this change.

Best regards,
Lei


From eric.y.miao at gmail.com  Fri Jun 18 04:00:59 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 16:00:59 +0800
Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
In-Reply-To: <AANLkTim9O5kuGzvQoB65fWDr3Bi9siiVBMCPx6heqZjd@mail.gmail.com>
References: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com> 
	<AANLkTinOsQ8AcH-As91CRqrEQVnXdsm_CmFQgyj7gI1_@mail.gmail.com> 
	<AANLkTim9O5kuGzvQoB65fWDr3Bi9siiVBMCPx6heqZjd@mail.gmail.com>
Message-ID: <AANLkTimGzVtuJuuxipim-f6UhdK287EjF41UlhdKCWRM@mail.gmail.com>

>>> -struct pxa3xx_nand_timing {
>>> - ? ? ? unsigned int ? ?tCH; ?/* Enable signal hold time */
>>> - ? ? ? unsigned int ? ?tCS; ?/* Enable signal setup time */
>>> - ? ? ? unsigned int ? ?tWH; ?/* ND_nWE high duration */
>>> - ? ? ? unsigned int ? ?tWP; ?/* ND_nWE pulse time */
>>> - ? ? ? unsigned int ? ?tRH; ?/* ND_nRE high duration */
>>> - ? ? ? unsigned int ? ?tRP; ?/* ND_nRE pulse width */
>>> - ? ? ? unsigned int ? ?tR; ? /* ND_nWE high to ND_nRE low for read */
>>> - ? ? ? unsigned int ? ?tWHR; /* ND_nWE high to ND_nRE low for status read */
>>> - ? ? ? unsigned int ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */
>>> -};
>>> -
>>> -struct pxa3xx_nand_cmdset {
>>> - ? ? ? uint16_t ? ? ? ?read1;
>>> - ? ? ? uint16_t ? ? ? ?read2;
>>> - ? ? ? uint16_t ? ? ? ?program;
>>> - ? ? ? uint16_t ? ? ? ?read_status;
>>> - ? ? ? uint16_t ? ? ? ?read_id;
>>> - ? ? ? uint16_t ? ? ? ?erase;
>>> - ? ? ? uint16_t ? ? ? ?reset;
>>> - ? ? ? uint16_t ? ? ? ?lock;
>>> - ? ? ? uint16_t ? ? ? ?unlock;
>>> - ? ? ? uint16_t ? ? ? ?lock_status;
>>> -};
>>> -
>>> -struct pxa3xx_nand_flash {
>>> - ? ? ? const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
>>> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset;
>>> -
>>> - ? ? ? uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
>>> - ? ? ? uint32_t page_size; ? ? /* Page size in bytes (PAGE_SZ) */
>>> - ? ? ? uint32_t flash_width; ? /* Width of Flash memory (DWIDTH_M) */
>>> - ? ? ? uint32_t dfc_width; ? ? /* Width of flash controller(DWIDTH_C) */
>>> - ? ? ? uint32_t num_blocks; ? ?/* Number of physical blocks in Flash */
>>> - ? ? ? uint32_t chip_id;
>>> -};
>>> -
>>
>> So does this prevent board code from defining their own timing and etc?
>
> No, platform could define its own timing. If there is definition for
> the same chip,
> driver would choose the one from platform definition first.
>

I'm seeing pxa3xx_nand_flash being referenced in pxa3xx_nand_platform_data
below, though?

struct pxa3xx_nand_platform_data {

      ......

	const struct pxa3xx_nand_flash * 	flash;
	size_t					num_flash;
};


From stanley.miao at windriver.com  Fri Jun 18 04:16:37 2010
From: stanley.miao at windriver.com (stanley.miao)
Date: Fri, 18 Jun 2010 16:16:37 +0800
Subject: Fix mtd-utils bugs
In-Reply-To: <1276424048.19028.217.camel@localhost>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	
	<1276422718.19028.211.camel@localhost>
	<1276424048.19028.217.camel@localhost>
Message-ID: <4C1B2B65.3090606@windriver.com>

Artem Bityutskiy wrote:
> On Sun, 2010-06-13 at 12:51 +0300, Artem Bityutskiy wrote:
>   
>> On Fri, 2010-06-11 at 17:36 +0800, Stanley.Miao wrote:
>>     
>>> <snip>
>>>       
>> Please, make sure your submissions have proper version. I have limited
>> amount of time and do not want to spend it figuring out which patch is
>> the latest. Use the best kernel practices and apply prefix your stuff
>> with [PATCHv3] or something like that.
>>
>> Could you please re-submit your latest version?
>>     
>
> Also, it is nice to put a short changelog, but I can live without it.
>   

Is the subject of every emails is the short changelog you wanted ?

Stanley.




From adrian.wenl at gmail.com  Fri Jun 18 04:08:13 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 16:08:13 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce read
	id times
In-Reply-To: <AANLkTil6QDRdh3s63J9Mm-B1qjMcnYjEEm-W5lC1NXVb@mail.gmail.com>
References: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com>
	<AANLkTil6QDRdh3s63J9Mm-B1qjMcnYjEEm-W5lC1NXVb@mail.gmail.com>
Message-ID: <AANLkTikbzXgwMvnNVRkcOO-9El9hmAXhKZK_dFgStbwY@mail.gmail.com>

On Fri, Jun 18, 2010 at 2:33 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 1:33 PM, Haojian Zhuang
> <haojian.zhuang at gmail.com> wrote:
>> From 832379d0da4d772e45872de365053f9a15733967 Mon Sep 17 00:00:00 2001
>> From: Lei Wen <leiwen at marvell.com>
>> Date: Wed, 2 Jun 2010 21:50:25 +0800
>> Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce
>> read id times
>>
>> We certainly don't need to send read id command times by times, since
>> we already know what the id is after the first read id...
>>
>> So create a common timing which could ensure it would successfully read id
>> out all supported chip. Then follow the build-in table to reconfigure
>> the timing.
>
> This is clever trick we'd like to have. And I'd prefer to call this a
> 'loose timing'
> or a 'default safe timing' instead of 'common timing'.
>
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
>> ---
>> ?drivers/mtd/nand/pxa3xx_nand.c | ? 72 ++++++++++++++++-----------------------
>> ?1 files changed, 30 insertions(+), 42 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>> index 013e075..f939083 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -226,23 +226,26 @@ const static struct pxa3xx_nand_cmdset cmdset = {
>> ?};
>>
>> ?static struct pxa3xx_nand_timing __devinitdata timing[] = {
>> + ? ? ? /* common timing used to detect flash id */
>> + ? ? ? { 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
>
> Make sure this is the loose and safe enough timing.
>
>> ? ? ? ?/* Samsung NAND series */
>> - ? ? ? { 10, ?0, 20, 40, 30, 40, 11123, 110, 10, },
>> + ? ? ? { 10, ?0, 20, ?40, 30, ?40, 11123, 110, 10, },
>> ? ? ? ?/* Micron NAND series */
>> - ? ? ? { 10, 25, 15, 25, 15, 30, 25000, ?60, 10, },
>> + ? ? ? { 10, 25, 15, ?25, 15, ?30, 25000, ?60, 10, },
>> ? ? ? ?/* ST NAND series */
>> - ? ? ? { 10, 35, 15, 25, 15, 25, 25000, ?60, 10, },
>> + ? ? ? { 10, 35, 15, ?25, 15, ?25, 25000, ?60, 10, },
>> ?};
>>
>> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
>> - ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[0], },
>> - ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[0], },
>> - ? ? ? { 0xd7ec, 128, 4096, ?8, ?8, 8192, &timing[0], },
>> - ? ? ? { 0xa12c, ?64, 2048, ?8, ?8, 1024, &timing[1], },
>> - ? ? ? { 0xb12c, ?64, 2048, 16, 16, 1024, &timing[1], },
>> - ? ? ? { 0xdc2c, ?64, 2048, ?8, ?8, 4096, &timing[1], },
>> - ? ? ? { 0xcc2c, ?64, 2048, 16, 16, 4096, &timing[1], },
>> - ? ? ? { 0xba20, ?64, 2048, 16, 16, 2048, &timing[2], },
>> + ? ? ? { ? ? ?0, ? 0, ? ?0, ?0, ?0, ? ?0, &timing[0], },
>> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
>> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },
>> + ? ? ? { 0xd7ec, 128, 4096, ?8, ?8, 8192, &timing[1], },
>> + ? ? ? { 0xa12c, ?64, 2048, ?8, ?8, 1024, &timing[2], },
>> + ? ? ? { 0xb12c, ?64, 2048, 16, 16, 1024, &timing[2], },
>> + ? ? ? { 0xdc2c, ?64, 2048, ?8, ?8, 4096, &timing[2], },
>> + ? ? ? { 0xcc2c, ?64, 2048, 16, 16, 4096, &timing[2], },
>> + ? ? ? { 0xba20, ?64, 2048, 16, 16, 2048, &timing[3], },
>> ?};
>>
>> ?#define NDTR0_tCH(c) ? (min((c), 7) << 19)
>> @@ -859,12 +862,6 @@ static int pxa3xx_nand_config_flash(struct
>> pxa3xx_nand_info *info,
>> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
>> ? ? ? ?uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
>>
>> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
>> - ? ? ? ? ? ? ? return -EINVAL;
>> -
>> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
>> - ? ? ? ? ? ? ? return -EINVAL;
>> -
>
> I do think these are sanity check, that's useful to prevent incorrectly defined
> data (esp. coming from board code). Can we define the loose flash type as:
>
>> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
>> + ? ? ? { ?0x0000, ? 0, ? ?512, ?8, ?8, ? ?0, &timing[0], },
>> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
>> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },
>
> with a comment of /* default flash type to detect ID */?
>
> My understanding is the minimum requirement to detect the NAND ID is a
> loose timing and 512 small page, 8-bit wide bus, so with a chip_id being
> 0x0000, that should be enough to tell it's a special flash type to detect ID.

There is no need to add the flash page size and bus width for the
common timing, or loose timing...
For the chip identification only need reset and read id command, and
reset and read id command only care
for the first command in NDCB0 and the timing setting in NDTR0CS0 and
NDTR1CS0, the page size is not useful
here and could make confussion if give such definition...
>
>> ? ? ? ?/* calculate flash information */
>> ? ? ? ?info->oob_size = (f->page_size == 2048) ? 64 : 16;
>> ? ? ? ?info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
>> @@ -976,36 +973,27 @@ static int pxa3xx_nand_detect_flash(struct
>> pxa3xx_nand_info *info,
>> ? ? ? ? ? ? ? ?if (pxa3xx_nand_detect_config(info) == 0)
>> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>>
>> - ? ? ? for (i = 0; i<pdata->num_flash; ++i) {
>> - ? ? ? ? ? ? ? f = pdata->flash + i;
>> -
>> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>> -
>> - ? ? ? ? ? ? ? if (__readid(info, &id))
>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>> -
>> - ? ? ? ? ? ? ? if (id == f->chip_id)
>> - ? ? ? ? ? ? ? ? ? ? ? return 0;
>> - ? ? ? }
>> -
>> - ? ? ? for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
>> -
>> - ? ? ? ? ? ? ? f = &builtin_flash_types[i];
>> -
>> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>> -
>> - ? ? ? ? ? ? ? if (__readid(info, &id))
>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>> -
>> - ? ? ? ? ? ? ? if (id == f->chip_id)
>> + ? ? ? f = &builtin_flash_types[0];
>> + ? ? ? pxa3xx_nand_config_flash(info, f);
>> + ? ? ? if (__readid(info, &id))
>> + ? ? ? ? ? ? ? goto fail_detect;
>> +
>> + ? ? ? for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
>> + ? ? ? ? ? ? ? if (i < pdata->num_flash)
>> + ? ? ? ? ? ? ? ? ? ? ? f = pdata->flash + i;
>> + ? ? ? ? ? ? ? else
>> + ? ? ? ? ? ? ? ? ? ? ? f = &builtin_flash_types[i - pdata->num_flash + 1];
>
> This looks a bit tricky and difficult to read, can you improve the
> readability here?

The chip id identification logic here is changed in latter patch in
this patch set...
If from the last patch of view, does this part looks better?

>
>> + ? ? ? ? ? ? ? if (f->chip_id == id) {
>> + ? ? ? ? ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
>> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f);
>> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>> + ? ? ? ? ? ? ? }
>> ? ? ? ?}
>>
>> ? ? ? ?dev_warn(&info->pdev->dev,
>> - ? ? ? ? ? ? ? ?"failed to detect configured nand flash; found %04x instead of\n",
>> + ? ? ? ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found %04x instead of\n",
>> ? ? ? ? ? ? ? ? id);
>> +fail_detect:
>> ? ? ? ?return -ENODEV;
>> ?}
>>
>
> I'm generally OK with the idea.
>
Best regards,
Lei


From adrian.wenl at gmail.com  Fri Jun 18 04:10:51 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 16:10:51 +0800
Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
In-Reply-To: <AANLkTimGzVtuJuuxipim-f6UhdK287EjF41UlhdKCWRM@mail.gmail.com>
References: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com>
	<AANLkTinOsQ8AcH-As91CRqrEQVnXdsm_CmFQgyj7gI1_@mail.gmail.com>
	<AANLkTim9O5kuGzvQoB65fWDr3Bi9siiVBMCPx6heqZjd@mail.gmail.com>
	<AANLkTimGzVtuJuuxipim-f6UhdK287EjF41UlhdKCWRM@mail.gmail.com>
Message-ID: <AANLkTindDgsvPK-ZZsyB2cdsrh0IyykBuhgStuwvyIdg@mail.gmail.com>

On Fri, Jun 18, 2010 at 4:00 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>>>> -struct pxa3xx_nand_timing {
>>>> - ? ? ? unsigned int ? ?tCH; ?/* Enable signal hold time */
>>>> - ? ? ? unsigned int ? ?tCS; ?/* Enable signal setup time */
>>>> - ? ? ? unsigned int ? ?tWH; ?/* ND_nWE high duration */
>>>> - ? ? ? unsigned int ? ?tWP; ?/* ND_nWE pulse time */
>>>> - ? ? ? unsigned int ? ?tRH; ?/* ND_nRE high duration */
>>>> - ? ? ? unsigned int ? ?tRP; ?/* ND_nRE pulse width */
>>>> - ? ? ? unsigned int ? ?tR; ? /* ND_nWE high to ND_nRE low for read */
>>>> - ? ? ? unsigned int ? ?tWHR; /* ND_nWE high to ND_nRE low for status read */
>>>> - ? ? ? unsigned int ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */
>>>> -};
>>>> -
>>>> -struct pxa3xx_nand_cmdset {
>>>> - ? ? ? uint16_t ? ? ? ?read1;
>>>> - ? ? ? uint16_t ? ? ? ?read2;
>>>> - ? ? ? uint16_t ? ? ? ?program;
>>>> - ? ? ? uint16_t ? ? ? ?read_status;
>>>> - ? ? ? uint16_t ? ? ? ?read_id;
>>>> - ? ? ? uint16_t ? ? ? ?erase;
>>>> - ? ? ? uint16_t ? ? ? ?reset;
>>>> - ? ? ? uint16_t ? ? ? ?lock;
>>>> - ? ? ? uint16_t ? ? ? ?unlock;
>>>> - ? ? ? uint16_t ? ? ? ?lock_status;
>>>> -};
>>>> -
>>>> -struct pxa3xx_nand_flash {
>>>> - ? ? ? const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
>>>> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset;
>>>> -
>>>> - ? ? ? uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
>>>> - ? ? ? uint32_t page_size; ? ? /* Page size in bytes (PAGE_SZ) */
>>>> - ? ? ? uint32_t flash_width; ? /* Width of Flash memory (DWIDTH_M) */
>>>> - ? ? ? uint32_t dfc_width; ? ? /* Width of flash controller(DWIDTH_C) */
>>>> - ? ? ? uint32_t num_blocks; ? ?/* Number of physical blocks in Flash */
>>>> - ? ? ? uint32_t chip_id;
>>>> -};
>>>> -
>>>
>>> So does this prevent board code from defining their own timing and etc?
>>
>> No, platform could define its own timing. If there is definition for
>> the same chip,
>> driver would choose the one from platform definition first.
>>
>
> I'm seeing pxa3xx_nand_flash being referenced in pxa3xx_nand_platform_data
> below, though?
>
> struct pxa3xx_nand_platform_data {
>
> ? ? ?......
>
> ? ? ? ?const struct pxa3xx_nand_flash * ? ? ? ?flash;
> ? ? ? ?size_t ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?num_flash;
> };
>

Yes, platform could define its own pxa3xx_nand_flash structure in its
own code, and pass the structure to let driver know.


From eric.y.miao at gmail.com  Fri Jun 18 04:12:41 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 16:12:41 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce read
	id times
In-Reply-To: <AANLkTikbzXgwMvnNVRkcOO-9El9hmAXhKZK_dFgStbwY@mail.gmail.com>
References: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com> 
	<AANLkTil6QDRdh3s63J9Mm-B1qjMcnYjEEm-W5lC1NXVb@mail.gmail.com> 
	<AANLkTikbzXgwMvnNVRkcOO-9El9hmAXhKZK_dFgStbwY@mail.gmail.com>
Message-ID: <AANLkTikDDFYY65l5YYGW3a0O2bWDyKRO6VRb15aaFtF7@mail.gmail.com>

>>> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
>>> - ? ? ? ? ? ? ? return -EINVAL;
>>> -
>>> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
>>> - ? ? ? ? ? ? ? return -EINVAL;
>>> -
>>
>> I do think these are sanity check, that's useful to prevent incorrectly defined
>> data (esp. coming from board code). Can we define the loose flash type as:
>>
>>> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
>>> + ? ? ? { ?0x0000, ? 0, ? ?512, ?8, ?8, ? ?0, &timing[0], },
>>> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
>>> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },
>>
>> with a comment of /* default flash type to detect ID */?
>>
>> My understanding is the minimum requirement to detect the NAND ID is a
>> loose timing and 512 small page, 8-bit wide bus, so with a chip_id being
>> 0x0000, that should be enough to tell it's a special flash type to detect ID.
>
> There is no need to add the flash page size and bus width for the
> common timing, or loose timing...
> For the chip identification only need reset and read id command, and
> reset and read id command only care
> for the first command in NDCB0 and the timing setting in NDTR0CS0 and
> NDTR1CS0, the page size is not useful
> here and could make confussion if give such definition...

I know, but I'd like to keep the checking of page_size, and flash_width,
if you take a look into the rest of the code how much it is assumed that
page_size being either 2048 or 512, flash_width being 8 or 16, you'll
know why such an error checking here is mandatory actually.

>>
>>> ? ? ? ?/* calculate flash information */
>>> ? ? ? ?info->oob_size = (f->page_size == 2048) ? 64 : 16;
>>> ? ? ? ?info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
>>> @@ -976,36 +973,27 @@ static int pxa3xx_nand_detect_flash(struct
>>> pxa3xx_nand_info *info,
>>> ? ? ? ? ? ? ? ?if (pxa3xx_nand_detect_config(info) == 0)
>>> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>>>
>>> - ? ? ? for (i = 0; i<pdata->num_flash; ++i) {
>>> - ? ? ? ? ? ? ? f = pdata->flash + i;
>>> -
>>> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>> -
>>> - ? ? ? ? ? ? ? if (__readid(info, &id))
>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>> -
>>> - ? ? ? ? ? ? ? if (id == f->chip_id)
>>> - ? ? ? ? ? ? ? ? ? ? ? return 0;
>>> - ? ? ? }
>>> -
>>> - ? ? ? for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
>>> -
>>> - ? ? ? ? ? ? ? f = &builtin_flash_types[i];
>>> -
>>> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>> -
>>> - ? ? ? ? ? ? ? if (__readid(info, &id))
>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>> -
>>> - ? ? ? ? ? ? ? if (id == f->chip_id)
>>> + ? ? ? f = &builtin_flash_types[0];
>>> + ? ? ? pxa3xx_nand_config_flash(info, f);
>>> + ? ? ? if (__readid(info, &id))
>>> + ? ? ? ? ? ? ? goto fail_detect;
>>> +
>>> + ? ? ? for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
>>> + ? ? ? ? ? ? ? if (i < pdata->num_flash)
>>> + ? ? ? ? ? ? ? ? ? ? ? f = pdata->flash + i;
>>> + ? ? ? ? ? ? ? else
>>> + ? ? ? ? ? ? ? ? ? ? ? f = &builtin_flash_types[i - pdata->num_flash + 1];
>>
>> This looks a bit tricky and difficult to read, can you improve the
>> readability here?
>
> The chip id identification logic here is changed in latter patch in
> this patch set...
> If from the last patch of view, does this part looks better?
>

Not sure, I'd rather this being separated into two loops if that helps
readability.

>>
>>> + ? ? ? ? ? ? ? if (f->chip_id == id) {
>>> + ? ? ? ? ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
>>> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f);
>>> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>>> + ? ? ? ? ? ? ? }
>>> ? ? ? ?}
>>>
>>> ? ? ? ?dev_warn(&info->pdev->dev,
>>> - ? ? ? ? ? ? ? ?"failed to detect configured nand flash; found %04x instead of\n",
>>> + ? ? ? ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found %04x instead of\n",
>>> ? ? ? ? ? ? ? ? id);
>>> +fail_detect:
>>> ? ? ? ?return -ENODEV;
>>> ?}
>>>
>>
>> I'm generally OK with the idea.
>>
> Best regards,
> Lei
>


From eric.y.miao at gmail.com  Fri Jun 18 04:14:53 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 16:14:53 +0800
Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
In-Reply-To: <AANLkTindDgsvPK-ZZsyB2cdsrh0IyykBuhgStuwvyIdg@mail.gmail.com>
References: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com> 
	<AANLkTinOsQ8AcH-As91CRqrEQVnXdsm_CmFQgyj7gI1_@mail.gmail.com> 
	<AANLkTim9O5kuGzvQoB65fWDr3Bi9siiVBMCPx6heqZjd@mail.gmail.com> 
	<AANLkTimGzVtuJuuxipim-f6UhdK287EjF41UlhdKCWRM@mail.gmail.com> 
	<AANLkTindDgsvPK-ZZsyB2cdsrh0IyykBuhgStuwvyIdg@mail.gmail.com>
Message-ID: <AANLkTinwlsrxvjHyEs1IAwaw-8GXYN2lVrUOtYp0C52n@mail.gmail.com>

On Fri, Jun 18, 2010 at 4:10 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 4:00 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>>>>> -struct pxa3xx_nand_timing {
>>>>> - ? ? ? unsigned int ? ?tCH; ?/* Enable signal hold time */
>>>>> - ? ? ? unsigned int ? ?tCS; ?/* Enable signal setup time */
>>>>> - ? ? ? unsigned int ? ?tWH; ?/* ND_nWE high duration */
>>>>> - ? ? ? unsigned int ? ?tWP; ?/* ND_nWE pulse time */
>>>>> - ? ? ? unsigned int ? ?tRH; ?/* ND_nRE high duration */
>>>>> - ? ? ? unsigned int ? ?tRP; ?/* ND_nRE pulse width */
>>>>> - ? ? ? unsigned int ? ?tR; ? /* ND_nWE high to ND_nRE low for read */
>>>>> - ? ? ? unsigned int ? ?tWHR; /* ND_nWE high to ND_nRE low for status read */
>>>>> - ? ? ? unsigned int ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */
>>>>> -};
>>>>> -
>>>>> -struct pxa3xx_nand_cmdset {
>>>>> - ? ? ? uint16_t ? ? ? ?read1;
>>>>> - ? ? ? uint16_t ? ? ? ?read2;
>>>>> - ? ? ? uint16_t ? ? ? ?program;
>>>>> - ? ? ? uint16_t ? ? ? ?read_status;
>>>>> - ? ? ? uint16_t ? ? ? ?read_id;
>>>>> - ? ? ? uint16_t ? ? ? ?erase;
>>>>> - ? ? ? uint16_t ? ? ? ?reset;
>>>>> - ? ? ? uint16_t ? ? ? ?lock;
>>>>> - ? ? ? uint16_t ? ? ? ?unlock;
>>>>> - ? ? ? uint16_t ? ? ? ?lock_status;
>>>>> -};
>>>>> -
>>>>> -struct pxa3xx_nand_flash {
>>>>> - ? ? ? const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
>>>>> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset;
>>>>> -
>>>>> - ? ? ? uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
>>>>> - ? ? ? uint32_t page_size; ? ? /* Page size in bytes (PAGE_SZ) */
>>>>> - ? ? ? uint32_t flash_width; ? /* Width of Flash memory (DWIDTH_M) */
>>>>> - ? ? ? uint32_t dfc_width; ? ? /* Width of flash controller(DWIDTH_C) */
>>>>> - ? ? ? uint32_t num_blocks; ? ?/* Number of physical blocks in Flash */
>>>>> - ? ? ? uint32_t chip_id;
>>>>> -};
>>>>> -
>>>>
>>>> So does this prevent board code from defining their own timing and etc?
>>>
>>> No, platform could define its own timing. If there is definition for
>>> the same chip,
>>> driver would choose the one from platform definition first.
>>>
>>
>> I'm seeing pxa3xx_nand_flash being referenced in pxa3xx_nand_platform_data
>> below, though?
>>
>> struct pxa3xx_nand_platform_data {
>>
>> ? ? ?......
>>
>> ? ? ? ?const struct pxa3xx_nand_flash * ? ? ? ?flash;
>> ? ? ? ?size_t ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?num_flash;
>> };
>>
>
> Yes, platform could define its own pxa3xx_nand_flash structure in its
> own code, and pass the structure to let driver know.
>

I'm actually quite confused here. Did you ever try build a kernel with
platform defined flash info?


From adrian.wenl at gmail.com  Fri Jun 18 04:16:26 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 16:16:26 +0800
Subject: [PATCH 03/25] pxa3xx_nand: remove the flash info in driver 
	structure
In-Reply-To: <AANLkTilnlE7hl4FKo5qRJ4PeTCuxA3Mfm13eedGPehrk@mail.gmail.com>
References: <AANLkTimbCSM3Kk-Mq3MhRDyhHAaERR-dXhtuplauB3ki@mail.gmail.com>
	<AANLkTilnlE7hl4FKo5qRJ4PeTCuxA3Mfm13eedGPehrk@mail.gmail.com>
Message-ID: <AANLkTikT1hzTe4nEKj5n0cay0Q_277GlygXftYOlHI0q@mail.gmail.com>

On Fri, Jun 18, 2010 at 2:40 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 1:33 PM, Haojian Zhuang
> <haojian.zhuang at gmail.com> wrote:
>> From 643765e6ae0f37902321f31e14b565896217dd3a Mon Sep 17 00:00:00 2001
>> From: Lei Wen <leiwen at marvell.com>
>> Date: Wed, 2 Jun 2010 21:54:33 +0800
>> Subject: [PATCH 03/25] pxa3xx_nand: remove the flash info in driver structure
>>
>> After probe, all info already transfer to driver structure.
>> There is no need to keep the original flash info.
>> So that we could safely free the flash info in memory, which may grows
>> larger when more flash is suported.
>>
>
> Some of the changes should be separated from my POV? Like the
> change to oob_size, and pxa3xx_nand_resume?
>

This patch is only servered as the prepraration of latter patch
seris... So hard to seperate them...


From adrian.wenl at gmail.com  Fri Jun 18 04:44:43 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 16:44:43 +0800
Subject: [PATCH 01/25] pxa3xx_nand: condense the flash definition
In-Reply-To: <AANLkTinwlsrxvjHyEs1IAwaw-8GXYN2lVrUOtYp0C52n@mail.gmail.com>
References: <AANLkTil1FnPkGS7l6W0HWeXyOxXzWbZkvFWY4jJF_I_A@mail.gmail.com>
	<AANLkTinOsQ8AcH-As91CRqrEQVnXdsm_CmFQgyj7gI1_@mail.gmail.com>
	<AANLkTim9O5kuGzvQoB65fWDr3Bi9siiVBMCPx6heqZjd@mail.gmail.com>
	<AANLkTimGzVtuJuuxipim-f6UhdK287EjF41UlhdKCWRM@mail.gmail.com>
	<AANLkTindDgsvPK-ZZsyB2cdsrh0IyykBuhgStuwvyIdg@mail.gmail.com>
	<AANLkTinwlsrxvjHyEs1IAwaw-8GXYN2lVrUOtYp0C52n@mail.gmail.com>
Message-ID: <AANLkTikDXl0XwO_08T87l8jY-Lf_uNZDfOjrMfsnuCto@mail.gmail.com>

On Fri, Jun 18, 2010 at 4:14 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 4:10 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
>> On Fri, Jun 18, 2010 at 4:00 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>>>>>> -struct pxa3xx_nand_timing {
>>>>>> - ? ? ? unsigned int ? ?tCH; ?/* Enable signal hold time */
>>>>>> - ? ? ? unsigned int ? ?tCS; ?/* Enable signal setup time */
>>>>>> - ? ? ? unsigned int ? ?tWH; ?/* ND_nWE high duration */
>>>>>> - ? ? ? unsigned int ? ?tWP; ?/* ND_nWE pulse time */
>>>>>> - ? ? ? unsigned int ? ?tRH; ?/* ND_nRE high duration */
>>>>>> - ? ? ? unsigned int ? ?tRP; ?/* ND_nRE pulse width */
>>>>>> - ? ? ? unsigned int ? ?tR; ? /* ND_nWE high to ND_nRE low for read */
>>>>>> - ? ? ? unsigned int ? ?tWHR; /* ND_nWE high to ND_nRE low for status read */
>>>>>> - ? ? ? unsigned int ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */
>>>>>> -};
>>>>>> -
>>>>>> -struct pxa3xx_nand_cmdset {
>>>>>> - ? ? ? uint16_t ? ? ? ?read1;
>>>>>> - ? ? ? uint16_t ? ? ? ?read2;
>>>>>> - ? ? ? uint16_t ? ? ? ?program;
>>>>>> - ? ? ? uint16_t ? ? ? ?read_status;
>>>>>> - ? ? ? uint16_t ? ? ? ?read_id;
>>>>>> - ? ? ? uint16_t ? ? ? ?erase;
>>>>>> - ? ? ? uint16_t ? ? ? ?reset;
>>>>>> - ? ? ? uint16_t ? ? ? ?lock;
>>>>>> - ? ? ? uint16_t ? ? ? ?unlock;
>>>>>> - ? ? ? uint16_t ? ? ? ?lock_status;
>>>>>> -};
>>>>>> -
>>>>>> -struct pxa3xx_nand_flash {
>>>>>> - ? ? ? const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
>>>>>> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset;
>>>>>> -
>>>>>> - ? ? ? uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
>>>>>> - ? ? ? uint32_t page_size; ? ? /* Page size in bytes (PAGE_SZ) */
>>>>>> - ? ? ? uint32_t flash_width; ? /* Width of Flash memory (DWIDTH_M) */
>>>>>> - ? ? ? uint32_t dfc_width; ? ? /* Width of flash controller(DWIDTH_C) */
>>>>>> - ? ? ? uint32_t num_blocks; ? ?/* Number of physical blocks in Flash */
>>>>>> - ? ? ? uint32_t chip_id;
>>>>>> -};
>>>>>> -
>>>>>
>>>>> So does this prevent board code from defining their own timing and etc?
>>>>
>>>> No, platform could define its own timing. If there is definition for
>>>> the same chip,
>>>> driver would choose the one from platform definition first.
>>>>
>>>
>>> I'm seeing pxa3xx_nand_flash being referenced in pxa3xx_nand_platform_data
>>> below, though?
>>>
>>> struct pxa3xx_nand_platform_data {
>>>
>>> ? ? ?......
>>>
>>> ? ? ? ?const struct pxa3xx_nand_flash * ? ? ? ?flash;
>>> ? ? ? ?size_t ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?num_flash;
>>> };
>>>
>>
>> Yes, platform could define its own pxa3xx_nand_flash structure in its
>> own code, and pass the structure to let driver know.
>>
>
> I'm actually quite confused here. Did you ever try build a kernel with
> platform defined flash info?
>

I haven't tried to build one platform code with flash definition
yet... My fault...
I would correct this error in .h file.


From adrian.wenl at gmail.com  Fri Jun 18 04:51:30 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 16:51:30 +0800
Subject: [PATCH 06/25] pxa3xx_nand: unify prepare command
In-Reply-To: <AANLkTinNqtnL3LRFsPuUQXcTnRda0_B059bRLGlJuzlh@mail.gmail.com>
References: <AANLkTilhattkx7AiyG-R4zbWSZ3-qkPIM6VhyFW4lk4D@mail.gmail.com>
	<AANLkTinNqtnL3LRFsPuUQXcTnRda0_B059bRLGlJuzlh@mail.gmail.com>
Message-ID: <AANLkTikqhHK2snjdEb1jDURueQm5WclZ3xnGNsgew08X@mail.gmail.com>

On Fri, Jun 18, 2010 at 2:52 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
> <haojian.zhuang at gmail.com> wrote:
>> From ac05ddc3c13d2b80b243e91cba9922572841f34a Mon Sep 17 00:00:00 2001
>> From: Lei Wen <leiwen at marvell.com>
>> Date: Mon, 22 Mar 2010 12:04:22 +0800
>> Subject: [PATCH 06/25] pxa3xx_nand: unify prepare command
>>
>> Make the interface simpler which could make both debug
>> and enhancement easier.
>
> What is the benefit of combining them into one big several pages lengthy
> function? I dislike lengthy function :-/

The reason why I combine those function is to make a common patch for
all command to quick
identify error during driver development and make code more robust...
Another reason is to share some common setting for different command,
and make code more concise.


From adrian.wenl at gmail.com  Fri Jun 18 04:56:24 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 16:56:24 +0800
Subject: [PATCH 08/25] mmp: add nand support to pxa168
In-Reply-To: <AANLkTilOIds0GEPmTWgi_y7UzJT4g9qx6iAtDJDgVxWu@mail.gmail.com>
References: <AANLkTinxMQjZIG4G1d9WVOiUX8-zHjTuTc1eRuInDRGW@mail.gmail.com>
	<AANLkTilOIds0GEPmTWgi_y7UzJT4g9qx6iAtDJDgVxWu@mail.gmail.com>
Message-ID: <AANLkTimzn6YyOX8CuCJ2UbchRtHjrrhWxkAL_s4gZovG@mail.gmail.com>

On Fri, Jun 18, 2010 at 2:59 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
> <haojian.zhuang at gmail.com> wrote:
>> From 55adf11cb4ba8ba0b88148c9bce0cc08f94b97bd Mon Sep 17 00:00:00 2001
>> From: Lei Wen <leiwen at marvell.com>
>> Date: Mon, 31 May 2010 14:57:49 +0800
>> Subject: [PATCH 08/25] mmp: add nand support to pxa168
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> ---
>> ?arch/arm/configs/pxa168_defconfig | ? ?9 ++++++++-
>> ?drivers/mtd/nand/Kconfig ? ? ? ? ?| ? ?2 +-
>> ?2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/configs/pxa168_defconfig
>> b/arch/arm/configs/pxa168_defconfig
>> index 113511f..a01ea99 100644
>> --- a/arch/arm/configs/pxa168_defconfig
>> +++ b/arch/arm/configs/pxa168_defconfig
>> @@ -438,7 +438,14 @@ CONFIG_EXTRA_FIRMWARE=""
>> ?# CONFIG_DEBUG_DEVRES is not set
>> ?# CONFIG_SYS_HYPERVISOR is not set
>> ?# CONFIG_CONNECTOR is not set
>> -# CONFIG_MTD is not set
>> +CONFIG_MTD=y
>> +CONFIG_MTD_PARTITIONS=y
>> +CONFIG_MTD_CMDLINE_PARTS=y
>> +CONFIG_MTD_CHAR=y
>> +CONFIG_MTD_BLKDEVS=y
>> +CONFIG_MTD_BLOCK=y
>> +CONFIG_MTD_NAND=y
>> +CONFIG_MTD_NAND_PXA3xx=y
>> ?# CONFIG_PARPORT is not set
>> ?# CONFIG_BLK_DEV is not set
>> ?# CONFIG_MISC_DEVICES is not set
>> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
>> index 9a35d92..0d29b5d 100644
>> --- a/drivers/mtd/nand/Kconfig
>> +++ b/drivers/mtd/nand/Kconfig
>> @@ -394,7 +394,7 @@ endchoice
>>
>> ?config MTD_NAND_PXA3xx
>> ? ? ? ?tristate "Support for NAND flash devices on PXA3xx"
>> - ? ? ? depends on MTD_NAND && (PXA3xx || ARCH_MMP)
>> + ? ? ? depends on MTD_NAND && PLAT_PXA
>
> I'd prefer this not being changed, as pxa3xx_nand isn't applicable to
> pxa25x/pxa27x.
>

I see... I would remove that change


From adrian.wenl at gmail.com  Fri Jun 18 05:15:20 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 17:15:20 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce read
	id times
In-Reply-To: <AANLkTikDDFYY65l5YYGW3a0O2bWDyKRO6VRb15aaFtF7@mail.gmail.com>
References: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com>
	<AANLkTil6QDRdh3s63J9Mm-B1qjMcnYjEEm-W5lC1NXVb@mail.gmail.com>
	<AANLkTikbzXgwMvnNVRkcOO-9El9hmAXhKZK_dFgStbwY@mail.gmail.com>
	<AANLkTikDDFYY65l5YYGW3a0O2bWDyKRO6VRb15aaFtF7@mail.gmail.com>
Message-ID: <AANLkTil6D3Cijy1JZ3aQLBGBfi99zOGDy5Xl8OmY_T_8@mail.gmail.com>

On Fri, Jun 18, 2010 at 4:12 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>>>> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
>>>> - ? ? ? ? ? ? ? return -EINVAL;
>>>> -
>>>> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
>>>> - ? ? ? ? ? ? ? return -EINVAL;
>>>> -
>>>
>>> I do think these are sanity check, that's useful to prevent incorrectly defined
>>> data (esp. coming from board code). Can we define the loose flash type as:
>>>
>>>> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
>>>> + ? ? ? { ?0x0000, ? 0, ? ?512, ?8, ?8, ? ?0, &timing[0], },
>>>> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
>>>> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },
>>>
>>> with a comment of /* default flash type to detect ID */?
>>>
>>> My understanding is the minimum requirement to detect the NAND ID is a
>>> loose timing and 512 small page, 8-bit wide bus, so with a chip_id being
>>> 0x0000, that should be enough to tell it's a special flash type to detect ID.
>>
>> There is no need to add the flash page size and bus width for the
>> common timing, or loose timing...
>> For the chip identification only need reset and read id command, and
>> reset and read id command only care
>> for the first command in NDCB0 and the timing setting in NDTR0CS0 and
>> NDTR1CS0, the page size is not useful
>> here and could make confussion if give such definition...
>
> I know, but I'd like to keep the checking of page_size, and flash_width,
> if you take a look into the rest of the code how much it is assumed that
> page_size being either 2048 or 512, flash_width being 8 or 16, you'll
> know why such an error checking here is mandatory actually.

I know that the configure_flash function need to check page_size &
flash_width to set the
ndcr. But what the setting would not affect the reset/read id result anyway...
For there is some chip has the same bytes in the first two bytes, I
choose to always read out
4 bytes data when send read id command in latter patch of this patch set...

>
>>>
>>>> ? ? ? ?/* calculate flash information */
>>>> ? ? ? ?info->oob_size = (f->page_size == 2048) ? 64 : 16;
>>>> ? ? ? ?info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
>>>> @@ -976,36 +973,27 @@ static int pxa3xx_nand_detect_flash(struct
>>>> pxa3xx_nand_info *info,
>>>> ? ? ? ? ? ? ? ?if (pxa3xx_nand_detect_config(info) == 0)
>>>> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>>>>
>>>> - ? ? ? for (i = 0; i<pdata->num_flash; ++i) {
>>>> - ? ? ? ? ? ? ? f = pdata->flash + i;
>>>> -
>>>> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
>>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>>> -
>>>> - ? ? ? ? ? ? ? if (__readid(info, &id))
>>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>>> -
>>>> - ? ? ? ? ? ? ? if (id == f->chip_id)
>>>> - ? ? ? ? ? ? ? ? ? ? ? return 0;
>>>> - ? ? ? }
>>>> -
>>>> - ? ? ? for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
>>>> -
>>>> - ? ? ? ? ? ? ? f = &builtin_flash_types[i];
>>>> -
>>>> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f))
>>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>>> -
>>>> - ? ? ? ? ? ? ? if (__readid(info, &id))
>>>> - ? ? ? ? ? ? ? ? ? ? ? continue;
>>>> -
>>>> - ? ? ? ? ? ? ? if (id == f->chip_id)
>>>> + ? ? ? f = &builtin_flash_types[0];
>>>> + ? ? ? pxa3xx_nand_config_flash(info, f);
>>>> + ? ? ? if (__readid(info, &id))
>>>> + ? ? ? ? ? ? ? goto fail_detect;
>>>> +
>>>> + ? ? ? for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
>>>> + ? ? ? ? ? ? ? if (i < pdata->num_flash)
>>>> + ? ? ? ? ? ? ? ? ? ? ? f = pdata->flash + i;
>>>> + ? ? ? ? ? ? ? else
>>>> + ? ? ? ? ? ? ? ? ? ? ? f = &builtin_flash_types[i - pdata->num_flash + 1];
>>>
>>> This looks a bit tricky and difficult to read, can you improve the
>>> readability here?
>>
>> The chip id identification logic here is changed in latter patch in
>> this patch set...
>> If from the last patch of view, does this part looks better?
>>
>
> Not sure, I'd rather this being separated into two loops if that helps
> readability.
>
>>>
>>>> + ? ? ? ? ? ? ? if (f->chip_id == id) {
>>>> + ? ? ? ? ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
>>>> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f);
>>>> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>>>> + ? ? ? ? ? ? ? }
>>>> ? ? ? ?}
>>>>
>>>> ? ? ? ?dev_warn(&info->pdev->dev,
>>>> - ? ? ? ? ? ? ? ?"failed to detect configured nand flash; found %04x instead of\n",
>>>> + ? ? ? ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found %04x instead of\n",
>>>> ? ? ? ? ? ? ? ? id);
>>>> +fail_detect:
>>>> ? ? ? ?return -ENODEV;
>>>> ?}
>>>>
>>>
>>> I'm generally OK with the idea.
>>>
>> Best regards,
>> Lei
>>
>


From eric.y.miao at gmail.com  Fri Jun 18 05:19:59 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Fri, 18 Jun 2010 17:19:59 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce read
	id times
In-Reply-To: <AANLkTil6D3Cijy1JZ3aQLBGBfi99zOGDy5Xl8OmY_T_8@mail.gmail.com>
References: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com> 
	<AANLkTil6QDRdh3s63J9Mm-B1qjMcnYjEEm-W5lC1NXVb@mail.gmail.com> 
	<AANLkTikbzXgwMvnNVRkcOO-9El9hmAXhKZK_dFgStbwY@mail.gmail.com> 
	<AANLkTikDDFYY65l5YYGW3a0O2bWDyKRO6VRb15aaFtF7@mail.gmail.com> 
	<AANLkTil6D3Cijy1JZ3aQLBGBfi99zOGDy5Xl8OmY_T_8@mail.gmail.com>
Message-ID: <AANLkTimeJYwret1ZlEHaX_-T14qB3WteQwpn9y7_1Zo9@mail.gmail.com>

On Fri, Jun 18, 2010 at 5:15 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 4:12 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>>>>> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
>>>>> - ? ? ? ? ? ? ? return -EINVAL;
>>>>> -
>>>>> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
>>>>> - ? ? ? ? ? ? ? return -EINVAL;
>>>>> -
>>>>
>>>> I do think these are sanity check, that's useful to prevent incorrectly defined
>>>> data (esp. coming from board code). Can we define the loose flash type as:
>>>>
>>>>> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
>>>>> + ? ? ? { ?0x0000, ? 0, ? ?512, ?8, ?8, ? ?0, &timing[0], },
>>>>> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
>>>>> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },
>>>>
>>>> with a comment of /* default flash type to detect ID */?
>>>>
>>>> My understanding is the minimum requirement to detect the NAND ID is a
>>>> loose timing and 512 small page, 8-bit wide bus, so with a chip_id being
>>>> 0x0000, that should be enough to tell it's a special flash type to detect ID.
>>>
>>> There is no need to add the flash page size and bus width for the
>>> common timing, or loose timing...
>>> For the chip identification only need reset and read id command, and
>>> reset and read id command only care
>>> for the first command in NDCB0 and the timing setting in NDTR0CS0 and
>>> NDTR1CS0, the page size is not useful
>>> here and could make confussion if give such definition...
>>
>> I know, but I'd like to keep the checking of page_size, and flash_width,
>> if you take a look into the rest of the code how much it is assumed that
>> page_size being either 2048 or 512, flash_width being 8 or 16, you'll
>> know why such an error checking here is mandatory actually.
>
> I know that the configure_flash function need to check page_size &
> flash_width to set the
> ndcr. But what the setting would not affect the reset/read id result anyway...
> For there is some chip has the same bytes in the first two bytes, I
> choose to always read out
> 4 bytes data when send read id command in latter patch of this patch set...
>

My understanding is that NAND READID will at least work with the assumption
of 512bytes/page and 8-bit wide bus, no matter how the NAND chips are
connected. (unless some one comes up with a insane design of using multiple
interlaced NAND chips of different types).

Again, assume the NAND controller is not initialized (register values being
garbage or all zero-ed), do you still think you can read out the ID without
letting it know the page size, bus width and etc?


From egorkat at gmail.com  Fri Jun 18 05:20:55 2010
From: egorkat at gmail.com (Egorkat)
Date: Fri, 18 Jun 2010 09:20:55 +0000 (UTC)
Subject: prepare DiskOnChip
Message-ID: <loom.20100618T111420-702@post.gmane.org>

Good day, All!

Could you please advise me a correct way to prepare DoC MD2201-D72 for use under
Linux?

I can format it under DOS with dformat utility in different ways, even like a
floppy. But when I try modprobe nftl after successfully modprobe diskonchip, it
fails or hungs with different errors. 
I've read and old how-to's, based on 2.4 kernel and old doc2000 driver, and new
ones. Kernel is compiled to support new MTD modules.
What do I do wrong...

Please enlighten me, I'm now out of ideas. Any logs, tests, configs and dumps
will be provided immediately.

Regards!



From dedekind1 at gmail.com  Fri Jun 18 05:28:38 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 18 Jun 2010 12:28:38 +0300
Subject: UBIFS performance measurements
In-Reply-To: <AANLkTikVqjmLiBDq6bdtTcHKwZxlxAVCBg3-WGXMzbmF@mail.gmail.com>
References: <AANLkTikVqjmLiBDq6bdtTcHKwZxlxAVCBg3-WGXMzbmF@mail.gmail.com>
Message-ID: <1276853318.19028.442.camel@localhost>

Hi,

On Thu, 2010-06-17 at 10:42 +0200, Leo Barnes wrote:
> I have a few questions regarding sequential write speeds in UBIFS and
> how to measure them.

Measurements are always tricky... :-) But I'm happy to help answering
specific UBIFS questions, of course.

> 1. If I want to measure sequential (and later on, random) write speed
> in UBIFS, should I do the writes using the O_SYNC flag or just do a
> fsync after writing? I worry that using the O_SYNC flag will reduce
> the write performance since the file system is meant to be used
> asynchronously and I want my measurements to be as close as possible
> to how the file system is meant to be used.

With O_SYNC you will get a guarantee that when your 'write()' call
returns, every single byte of your buffer will be on the flash media.
Yes, this is slow. This is un-optimal, because UBIFS will waste a lot of
space flushing the write-buffer every time.

With out O_SYNC you will do your writes to the page cache, then when you
call fsync(), UBIFS will flush this all, but this should be faster
because UBIFS will waste less space and pack data nodes nicely to the
write buffer.

It makes sense to measure both. But yes, write all / fsync is closer to
real life.

> 2. If I do not use O_SYNC, will using fflush and fsync guarantee that
> all written data has been written to flash when they return?

Yes.

> 3. If I do not use fflush before fsync, I assume, after reading the
> FAQ, that I am not guaranteed that all data has been written. Is this
> correct?

Yes, because some amount of data is cached in usre-space somewhere in
libc, and was not even sent to the kernel yet. fsync() will just call
the syscall without flushing that buffered data.

> 4. Does the commandline sync command do the same thing as fflush/fsync?

It syncs all (kernel) dirty pages, for all files. fsync synchronize only
one file.

> 5. Does sync/fsync force garbage collection?

No, they do minimum stuff to make sure all data is on the media and
would not lost if you had a power cut just after sync/fsync is done.

>  In other words, if I have
> deleted lots of files from an UBIFS volume, will I be ensured that
> their corresponding eraseblocks will actually be freed if I do a sync?

No. You are guaranteed that these files will never come back only. But
on physical flash level, corresponding PEBs will not necessarily be
erased.

> Any other tips regarding how to perform valid write performance
> measurements on UBIFS would be welcome.

Well, not from me, although I am of course interested to see people
using UBIFS :-) FS testing is always tricky, and the best testing is
using the FS with real-life applications. E.g., if you have some apps
with back-end data-bases, or you have some apps doing intensive I/O,
installing removing packages, etc.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From adrian.wenl at gmail.com  Fri Jun 18 06:01:02 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 18 Jun 2010 18:01:02 +0800
Subject: [PATCH 02/25] pxa3xx_nand: introduce common timing to reduce read
	id times
In-Reply-To: <AANLkTimeJYwret1ZlEHaX_-T14qB3WteQwpn9y7_1Zo9@mail.gmail.com>
References: <AANLkTim1qcVoqSS7T8bE0Vsu6phC2iY_Ok671WYHcD0z@mail.gmail.com>
	<AANLkTil6QDRdh3s63J9Mm-B1qjMcnYjEEm-W5lC1NXVb@mail.gmail.com>
	<AANLkTikbzXgwMvnNVRkcOO-9El9hmAXhKZK_dFgStbwY@mail.gmail.com>
	<AANLkTikDDFYY65l5YYGW3a0O2bWDyKRO6VRb15aaFtF7@mail.gmail.com>
	<AANLkTil6D3Cijy1JZ3aQLBGBfi99zOGDy5Xl8OmY_T_8@mail.gmail.com>
	<AANLkTimeJYwret1ZlEHaX_-T14qB3WteQwpn9y7_1Zo9@mail.gmail.com>
Message-ID: <AANLkTimU35i4hpzwb34lbqYrP0ijoWw6KH3q_ntb2fHh@mail.gmail.com>

On Fri, Jun 18, 2010 at 5:19 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 5:15 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
>> On Fri, Jun 18, 2010 at 4:12 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>>>>>> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
>>>>>> - ? ? ? ? ? ? ? return -EINVAL;
>>>>>> -
>>>>>> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
>>>>>> - ? ? ? ? ? ? ? return -EINVAL;
>>>>>> -
>>>>>
>>>>> I do think these are sanity check, that's useful to prevent incorrectly defined
>>>>> data (esp. coming from board code). Can we define the loose flash type as:
>>>>>
>>>>>> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
>>>>>> + ? ? ? { ?0x0000, ? 0, ? ?512, ?8, ?8, ? ?0, &timing[0], },
>>>>>> + ? ? ? { 0x46ec, ?32, ?512, 16, 16, 4096, &timing[1], },
>>>>>> + ? ? ? { 0xdaec, ?64, 2048, ?8, ?8, 2048, &timing[1], },
>>>>>
>>>>> with a comment of /* default flash type to detect ID */?
>>>>>
>>>>> My understanding is the minimum requirement to detect the NAND ID is a
>>>>> loose timing and 512 small page, 8-bit wide bus, so with a chip_id being
>>>>> 0x0000, that should be enough to tell it's a special flash type to detect ID.
>>>>
>>>> There is no need to add the flash page size and bus width for the
>>>> common timing, or loose timing...
>>>> For the chip identification only need reset and read id command, and
>>>> reset and read id command only care
>>>> for the first command in NDCB0 and the timing setting in NDTR0CS0 and
>>>> NDTR1CS0, the page size is not useful
>>>> here and could make confussion if give such definition...
>>>
>>> I know, but I'd like to keep the checking of page_size, and flash_width,
>>> if you take a look into the rest of the code how much it is assumed that
>>> page_size being either 2048 or 512, flash_width being 8 or 16, you'll
>>> know why such an error checking here is mandatory actually.
>>
>> I know that the configure_flash function need to check page_size &
>> flash_width to set the
>> ndcr. But what the setting would not affect the reset/read id result anyway...
>> For there is some chip has the same bytes in the first two bytes, I
>> choose to always read out
>> 4 bytes data when send read id command in latter patch of this patch set...
>>
>
> My understanding is that NAND READID will at least work with the assumption
> of 512bytes/page and 8-bit wide bus, no matter how the NAND chips are
> connected. (unless some one comes up with a insane design of using multiple
> interlaced NAND chips of different types).
>
> Again, assume the NAND controller is not initialized (register values being
> garbage or all zero-ed), do you still think you can read out the ID without
> letting it know the page size, bus width and etc?
>

Well... I understand it is good to reserve the page size and width
judgement in configuration.
I would make this part revert back to its original state...
For read id, it would not care for the page size and width setting in NDCR...


From roman.tereshonkov at nokia.com  Fri Jun 18 06:08:27 2010
From: roman.tereshonkov at nokia.com (Roman Tereshonkov)
Date: Fri, 18 Jun 2010 13:08:27 +0300
Subject: [PATCH 0/4] mtd: add mtd repartition ioctl
Message-ID: <1276855711-18570-1-git-send-email-roman.tereshonkov@nokia.com>

Adding mtd master device after all partitions should provide
minimum effect on the created partition enumeration.

The master mtd device can be repartitioned in runtime through
the mtd ioctl MTDREPARTITION. The ioctl passed argument is
the set of the new partitions defined by the structures:
struct mtd_partitions and struct mtd_partition_user.

All at once partition configuration is used and caused by
the all at once partition removing. Only unused partitions are deleted.
If any of the partitions for given mtd device is used then user gets error.
The care should be taken to close all applications which access
the partitions.

Roman Tereshonkov (4):
  mtd: add new ioctl structures to be used for repartitioning
  mtd: add the possibility to modify partitions in runtime
  mtd: add MTDREPARTITION ioctl
  mtd: create the mtd master device for given set of partitions

 drivers/mtd/mtdchar.c          |  110 +++++++++++++++++++++++++++++++++++++++-
 drivers/mtd/mtdpart.c          |   45 ++++++++++++++--
 drivers/mtd/onenand/omap2.c    |    8 ++-
 include/linux/mtd/partitions.h |    2 +
 include/mtd/mtd-abi.h          |   15 ++++++
 5 files changed, 170 insertions(+), 10 deletions(-)



From roman.tereshonkov at nokia.com  Fri Jun 18 06:08:30 2010
From: roman.tereshonkov at nokia.com (Roman Tereshonkov)
Date: Fri, 18 Jun 2010 13:08:30 +0300
Subject: [PATCH 3/4] mtd: add MTDREPARTITION ioctl
In-Reply-To: <1276855711-18570-3-git-send-email-roman.tereshonkov@nokia.com>
References: <1276855711-18570-1-git-send-email-roman.tereshonkov@nokia.com>
	<1276855711-18570-2-git-send-email-roman.tereshonkov@nokia.com>
	<1276855711-18570-3-git-send-email-roman.tereshonkov@nokia.com>
Message-ID: <1276855711-18570-4-git-send-email-roman.tereshonkov@nokia.com>

Add MTDREPARTITION ioctl to modify all partitions for given mtd
master device. The partitions having the same master are modified
all at once: all previous are deleted and the new set is created.

Signed-off-by: Roman Tereshonkov <roman.tereshonkov at nokia.com>
---
 drivers/mtd/mtdchar.c |  110 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 109 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 91c8013..ccdccad 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -19,7 +19,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/compatmac.h>
-
+#include <linux/mtd/partitions.h>
 #include <asm/uaccess.h>
 
 #define MTD_INODE_FS_MAGIC 0x11307854
@@ -463,6 +463,65 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
 	return ret;
 }
 
+#ifdef CONFIG_MTD_PARTITIONS
+static int mtd_do_repartition(struct file *file, struct mtd_info *mtd,
+				uint32_t nparts, void __user *ptr)
+{
+	struct mtd_partition *parts;
+	struct mtd_partition_user *up;
+	int size, i, ret = -ENOMEM;
+
+	if (!(file->f_mode & FMODE_WRITE))
+		return -EPERM;
+
+	size = nparts * sizeof(struct mtd_partition_user);
+	if (!size)
+		return -EINVAL;
+
+	if (!access_ok(VERIFY_READ, ptr, size))
+		return -EFAULT;
+
+	up = kmalloc(size, GFP_KERNEL);
+	if (!up)
+		return -ENOMEM;
+
+	if (copy_from_user(up, ptr, size)) {
+		ret = -EFAULT;
+		goto err_free_up;
+	}
+
+	size = nparts * sizeof(struct mtd_partition);
+	parts = kzalloc(size, GFP_KERNEL);
+	if (!parts)
+		goto err_free_up;
+
+	for (i = 0; i < nparts; i++) {
+		parts[i].offset = up[i].offset;
+		parts[i].size = up[i].size;
+		parts[i].mask_flags = up[i].mask_flags;
+
+		parts[i].name = kstrndup(up[i].name, MTD_MAX_PARTITION_NAME_LEN,
+					 GFP_KERNEL);
+		if (!parts[i].name)
+			goto err_free;
+	}
+
+	ret = del_mtd_partitions(mtd);
+	if (!ret)
+		ret = add_mtd_partitions(mtd, parts, nparts);
+
+ err_free:
+	for (i = 0; i < nparts; i++)
+		kfree(parts[i].name);
+	kfree(parts);
+ err_free_up:
+	kfree(up);
+
+	return ret;
+}
+#endif
+
+
 static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 {
 	struct mtd_file_info *mfi = file->private_data;
@@ -826,7 +885,25 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 		file->f_pos = 0;
 		break;
 	}
+#ifdef CONFIG_MTD_PARTITIONS
+	case MTDREPARTITION:
+	{
+		struct mtd_partitions p;
+		struct mtd_info *master;
+
+		/* only root (no assigned master) device can be accessed */
+		master = part_get_mtd_master(mtd);
+		if (master)
+			return -EACCES;
+
+		if (copy_from_user(&p, argp, sizeof(p)))
+			return -EFAULT;
+
+		ret = mtd_do_repartition(file, mtd, p.nparts, p.parts);
 
+		break;
+	}
+#endif
 	default:
 		ret = -ENOTTY;
 	}
@@ -856,6 +933,15 @@ struct mtd_oob_buf32 {
 #define MEMWRITEOOB32		_IOWR('M', 3, struct mtd_oob_buf32)
 #define MEMREADOOB32		_IOWR('M', 4, struct mtd_oob_buf32)
 
+#ifdef CONFIG_MTD_PARTITIONS
+struct mtd_partitions32 {
+	uint32_t nparts;
+	compat_caddr_t ptr;
+};
+
+#define MTDREPARTITION32	_IOW('M', 23, struct mtd_partitions32)
+#endif
+
 static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
@@ -895,6 +981,28 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
 				&buf_user->start);
 		break;
 	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	case MTDREPARTITION32:
+	{
+		struct mtd_partitions32 p;
+		struct mtd_info *master;
+
+		/* only root (no assigned master) device can be accessed */
+		master = part_get_mtd_master(mtd);
+		if (!master) {
+			if (copy_from_user(&p, argp, sizeof(p)))
+				ret = -EFAULT;
+			else
+				ret = mtd_do_repartition(file, mtd, p.nparts,
+							 compat_ptr(p.ptr));
+		} else {
+			ret = -EACCES;
+		}
+
+		break;
+	}
+#endif
 	default:
 		ret = mtd_ioctl(file, cmd, (unsigned long)argp);
 	}
-- 
1.6.2.4



From roman.tereshonkov at nokia.com  Fri Jun 18 06:08:31 2010
From: roman.tereshonkov at nokia.com (Roman Tereshonkov)
Date: Fri, 18 Jun 2010 13:08:31 +0300
Subject: [PATCH 4/4] mtd: create the mtd master device for given set of
	partitions
In-Reply-To: <1276855711-18570-4-git-send-email-roman.tereshonkov@nokia.com>
References: <1276855711-18570-1-git-send-email-roman.tereshonkov@nokia.com>
	<1276855711-18570-2-git-send-email-roman.tereshonkov@nokia.com>
	<1276855711-18570-3-git-send-email-roman.tereshonkov@nokia.com>
	<1276855711-18570-4-git-send-email-roman.tereshonkov@nokia.com>
Message-ID: <1276855711-18570-5-git-send-email-roman.tereshonkov@nokia.com>

The master device is needed for repartioning to be done.

Signed-off-by: Roman Tereshonkov <roman.tereshonkov at nokia.com>
---
 drivers/mtd/onenand/omap2.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 9f322f1..f9bdad8 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -724,12 +724,14 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	}
 
 #ifdef CONFIG_MTD_PARTITIONS
-	if (pdata->parts != NULL)
+	if (pdata->parts != NULL) {
 		r = add_mtd_partitions(&c->mtd, pdata->parts,
 				       pdata->nr_parts);
-	else
+		if (r < 0)
+			goto err_release_onenand;
+	}
 #endif
-		r = add_mtd_device(&c->mtd);
+	r = add_mtd_device(&c->mtd);
 	if (r < 0)
 		goto err_release_onenand;
 
-- 
1.6.2.4



From roman.tereshonkov at nokia.com  Fri Jun 18 06:08:28 2010
From: roman.tereshonkov at nokia.com (Roman Tereshonkov)
Date: Fri, 18 Jun 2010 13:08:28 +0300
Subject: [PATCH 1/4] mtd: add new ioctl structures to be used for
	repartitioning
In-Reply-To: <1276855711-18570-1-git-send-email-roman.tereshonkov@nokia.com>
References: <1276855711-18570-1-git-send-email-roman.tereshonkov@nokia.com>
Message-ID: <1276855711-18570-2-git-send-email-roman.tereshonkov@nokia.com>

Signed-off-by: Roman Tereshonkov <roman.tereshonkov at nokia.com>
---
 include/mtd/mtd-abi.h |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index be51ae2..c2c6b41 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -88,6 +88,20 @@ struct otp_info {
 	__u32 locked;
 };
 
+#define MTD_MAX_PARTITION_NAME_LEN	64
+struct mtd_partition_user {
+	__u64 size;
+	__u64 offset;
+	__u32 mask_flags;
+	char name[MTD_MAX_PARTITION_NAME_LEN];
+	__u8 padding[128];	/* reserved for future, must be zero! */
+};
+
+struct mtd_partitions {
+	__u32 nparts;
+	struct mtd_partition_user __user *parts;
+};
+
 #define MEMGETINFO		_IOR('M', 1, struct mtd_info_user)
 #define MEMERASE		_IOW('M', 2, struct erase_info_user)
 #define MEMWRITEOOB		_IOWR('M', 3, struct mtd_oob_buf)
@@ -110,6 +124,7 @@ struct otp_info {
 #define MEMERASE64		_IOW('M', 20, struct erase_info_user64)
 #define MEMWRITEOOB64		_IOWR('M', 21, struct mtd_oob_buf64)
 #define MEMREADOOB64		_IOWR('M', 22, struct mtd_oob_buf64)
+#define MTDREPARTITION		_IOW('M', 23, struct mtd_partitions)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
-- 
1.6.2.4



From roman.tereshonkov at nokia.com  Fri Jun 18 06:08:29 2010
From: roman.tereshonkov at nokia.com (Roman Tereshonkov)
Date: Fri, 18 Jun 2010 13:08:29 +0300
Subject: [PATCH 2/4] mtd: add the possibility to modify partitions in runtime
In-Reply-To: <1276855711-18570-2-git-send-email-roman.tereshonkov@nokia.com>
References: <1276855711-18570-1-git-send-email-roman.tereshonkov@nokia.com>
	<1276855711-18570-2-git-send-email-roman.tereshonkov@nokia.com>
Message-ID: <1276855711-18570-3-git-send-email-roman.tereshonkov@nokia.com>

This includes adding locks, appropriate memory handling and function
to get the master device for given partition.

Signed-off-by: Roman Tereshonkov <roman.tereshonkov at nokia.com>
---
 drivers/mtd/mtdpart.c          |   45 ++++++++++++++++++++++++++++++++++-----
 include/linux/mtd/partitions.h |    2 +
 2 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index b8043a9..595d270 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -21,6 +21,7 @@
 
 /* Our partition linked list */
 static LIST_HEAD(mtd_partitions);
+static DEFINE_MUTEX(mtd_partitions_mutex);
 
 /* Our partition node structure */
 struct mtd_part {
@@ -309,21 +310,30 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
 /*
  * This function unregisters and destroy all slave MTD objects which are
- * attached to the given master MTD object.
+ * attached to the given master MTD object and which are possible to be
+ * deleted (usercount==0).
  */
 
 int del_mtd_partitions(struct mtd_info *master)
 {
 	struct mtd_part *slave, *next;
+	int ret, err = 0;
 
+	mutex_lock(&mtd_partitions_mutex);
 	list_for_each_entry_safe(slave, next, &mtd_partitions, list)
 		if (slave->master == master) {
+			ret = del_mtd_device(&slave->mtd);
+			if (ret < 0) {
+				err = ret;
+				continue;
+			}
 			list_del(&slave->list);
-			del_mtd_device(&slave->mtd);
+			kfree(slave->mtd.name);
 			kfree(slave);
 		}
+	mutex_unlock(&mtd_partitions_mutex);
 
-	return 0;
+	return err;
 }
 EXPORT_SYMBOL(del_mtd_partitions);
 
@@ -332,16 +342,19 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 		uint64_t cur_offset)
 {
 	struct mtd_part *slave;
+	char *name;
 
 	/* allocate the partition structure */
 	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
-	if (!slave) {
+	name = kstrdup(part->name, GFP_KERNEL);
+	if (!name || !slave) {
 		printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
 			master->name);
 		del_mtd_partitions(master);
+		kfree(name);
+		kfree(slave);
 		return NULL;
 	}
-	list_add(&slave->list, &mtd_partitions);
 
 	/* set up the MTD object for this partition */
 	slave->mtd.type = master->type;
@@ -352,7 +365,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 	slave->mtd.oobavail = master->oobavail;
 	slave->mtd.subpage_sft = master->subpage_sft;
 
-	slave->mtd.name = part->name;
+	slave->mtd.name = name;
 	slave->mtd.owner = master->owner;
 	slave->mtd.backing_dev_info = master->backing_dev_info;
 
@@ -497,6 +510,9 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 	}
 
 out_register:
+	mutex_lock(&mtd_partitions_mutex);
+	list_add(&slave->list, &mtd_partitions);
+	mutex_unlock(&mtd_partitions_mutex);
 	/* register our partition */
 	add_mtd_device(&slave->mtd);
 
@@ -597,3 +613,20 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
 	return ret;
 }
 EXPORT_SYMBOL_GPL(parse_mtd_partitions);
+
+struct mtd_info *part_get_mtd_master(struct mtd_info *mtd)
+{
+	struct mtd_part *part;
+	struct mtd_info *master = NULL;
+
+	mutex_lock(&mtd_partitions_mutex);
+	list_for_each_entry(part, &mtd_partitions, list)
+		if (&part->mtd == mtd) {
+			master = part->master;
+			break;
+		}
+	mutex_unlock(&mtd_partitions_mutex);
+
+	return master;
+}
+EXPORT_SYMBOL(part_get_mtd_master);
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 274b619..942c425 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -89,4 +89,6 @@ static inline int mtd_has_cmdlinepart(void) { return 1; }
 static inline int mtd_has_cmdlinepart(void) { return 0; }
 #endif
 
+struct mtd_info *part_get_mtd_master(struct mtd_info *mtd);
+
 #endif
-- 
1.6.2.4



From stanley.miao at windriver.com  Fri Jun 18 06:32:50 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 18 Jun 2010 18:32:50 +0800
Subject: [PATCH v3] Fix mtd-utils bugs
Message-ID: <1276857173-10848-1-git-send-email-stanley.miao@windriver.com>

Changes from V2:
1, Get the linux version via uname() according to Joakim Tjernlund.
2, Set the default version the latest version according to Joakim Tjernlund.

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up. 


Stanley.


From dedekind1 at gmail.com  Fri Jun 18 06:24:23 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 18 Jun 2010 13:24:23 +0300
Subject: Fix mtd-utils bugs
In-Reply-To: <4C1B2B65.3090606@windriver.com>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>
	<1276422718.19028.211.camel@localhost>
	<1276424048.19028.217.camel@localhost> <4C1B2B65.3090606@windriver.com>
Message-ID: <1276856663.19028.447.camel@localhost>

On Fri, 2010-06-18 at 16:16 +0800, stanley.miao wrote:
> Artem Bityutskiy wrote:
> > On Sun, 2010-06-13 at 12:51 +0300, Artem Bityutskiy wrote:
> >   
> >> On Fri, 2010-06-11 at 17:36 +0800, Stanley.Miao wrote:
> >>     
> >>> <snip>
> >>>       
> >> Please, make sure your submissions have proper version. I have limited
> >> amount of time and do not want to spend it figuring out which patch is
> >> the latest. Use the best kernel practices and apply prefix your stuff
> >> with [PATCHv3] or something like that.
> >>
> >> Could you please re-submit your latest version?
> >>     
> >
> > Also, it is nice to put a short changelog, but I can live without it.
> >   
> 
> Is the subject of every emails is the short changelog you wanted ?

Hi,

Sorry, I do not understand the question. I do not need changelogs. I
just noted that there are best practices, and people use changelogs. You
can take a look at lkml archives at patch series from good kernel
hackers for example.

If you asked whether the changelog should be in each patch - no, just in
the "0" patch, and just short.

Anyway, I just want you to re-send your up-to-date patches as a separate
series with a v2 prefix.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From cbouatmailru at gmail.com  Fri Jun 18 09:32:12 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Fri, 18 Jun 2010 17:32:12 +0400
Subject: [PATCH 1/2] mtd: m25p80: Rework probing/JEDEC code
In-Reply-To: <AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru>
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
Message-ID: <20100618133212.GA5276@oksana.dev.rtsoft.ru>

On Sat, Jun 12, 2010 at 02:27:12PM +0800, Barry Song wrote:
> On Wed, Aug 19, 2009 at 5:46 AM, Anton Vorontsov
> <avorontsov at ru.mvista.com> wrote:
> >
> > Previosly the driver always tried JEDEC probing, assuming that non-JEDEC
> > chips will return '0'. But truly non-JEDEC chips (like CAT25) won't do
> > that, their behaviour on RDID command is undefined, so the driver should
> > not call jedec_probe() for these chips.
> >
> > Also, be less strict on error conditions, don't fail to probe if JEDEC
> > found a chip that is different from what platform code told, instead
> > just print some warnings and use an information obtained via JEDEC. In
> This patch caused a problem:
> even though the external flash doesn't exist, it will still pass the
> probe() and be registerred into kernel and given the partition table.
> You may refer to this bug report:
> http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=5975&start=0

Thanks for the report.

There's little we can do about it. Platform code asked us
to register the device, and JEDEC probing of M25Pxx chips isn't
reliable (thanks to various vendors that make these JEDEC and
non-JEDEC variants), so the best thing we can do is to register
the chip anyway.

OTOH, if the board pulls MISO line up, then the following patch
should help.

If this won't work, we'll have to add some flag to the platform
data, i.e. to force JEDEC probing, and not trust platform data.

Not-yet-Signed-off-by: Anton Vorontsov <cbouatmailru at gmail.com>
---

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 81e49a9..a307929 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
@@ -723,7 +724,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 	if (tmp < 0) {
 		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
 			dev_name(&spi->dev), tmp);
-		return NULL;
+		return ERR_PTR(tmp);
 	}
 	jedec = id[0];
 	jedec = jedec << 8;
@@ -737,7 +738,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 	 * exist for non-JEDEC chips, but for compatibility they return ID 0.
 	 */
 	if (jedec == 0)
-		return NULL;
+		return ERR_PTR(-EEXIST);
 
 	ext_jedec = id[3] << 8 | id[4];
 
@@ -749,7 +750,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 			return &m25p_ids[tmp];
 		}
 	}
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 
 
@@ -794,9 +795,11 @@ static int __devinit m25p_probe(struct spi_device *spi)
 		const struct spi_device_id *jid;
 
 		jid = jedec_probe(spi);
-		if (!jid) {
+		if (IS_ERR(jid) && PTR_ERR(jid) == -EEXIST) {
 			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
 				 id->name);
+		} else if (IS_ERR(jid)) {
+			return PTR_ERR(jid);
 		} else if (jid != id) {
 			/*
 			 * JEDEC knows better, so overwrite platform ID. We


From dedekind1 at gmail.com  Fri Jun 18 14:02:41 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 18 Jun 2010 21:02:41 +0300
Subject: CRC error when mounting UBIFS
In-Reply-To: <AANLkTinzLo7e5sHOn7sFKRAZNZHWoi3TMMG-FslG-CVv@mail.gmail.com>
References: <AANLkTilGg81TGnkS2VwF6xdFCvsB_AF_8rLYVqTr-81g@mail.gmail.com>
	<1275575118.9729.2.camel@localhost.localdomain>
	<AANLkTim4K_-kJc4x7mlgyXG3DPgcWUR5-nb46SEpn3pG@mail.gmail.com>
	<1275579127.9729.6.camel@localhost.localdomain>
	<AANLkTinzLo7e5sHOn7sFKRAZNZHWoi3TMMG-FslG-CVv@mail.gmail.com>
Message-ID: <1276884161.2503.1.camel@localhost.localdomain>

On Fri, 2010-06-04 at 18:18 +0200, Leo Barnes wrote:
> Question:
> Would it be possible to make all buffers that are sent to mtd->read()
> DMA-friendly?

But of course if you just want to experiment, you may replace all
vmalloc()'s with kmallocs()' in both UBI and UBIFS, which can be good
enough to start playing with UBIFS.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From lars at metafoo.de  Sat Jun 19 01:08:05 2010
From: lars at metafoo.de (Lars-Peter Clausen)
Date: Sat, 19 Jun 2010 07:08:05 +0200
Subject: [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip
Message-ID: <1276924111-11158-1-git-send-email-lars@metafoo.de>

Foreword:
Ralf suggested that it might be a good idea in order to allow for reasonable
testing and to avoid build failures due to two-way dependencies in different
parts of the kernel, that he applies all the patches once they have been acked
by their respective maintainers, feeds them into -next and eventually sends the
whole series to Linus. One exception will be the ASoC patches which will, due to
major changes in the ASoC subsystem, go through the ASoC tree.
So if you are a maintainer for one of the subsystem touched by this series and
would rather see the patch going through your tree (given the patch is ok)
please tell.


This patch series adds support for the Ingenic JZ4740 System-on-a-Chip.

The JZ4740 has a mostly MIPS32 compatible core (no on cpu timers) and many on
chip peripherals like RTC, NAND, MMC, OHCI, UDC, ADC, I2C, SPI, AC97, I2S, I2S
Codec, UART and LCD controller.

The JZ4740 is mostly used in eBooks, PMPs and hand-held consoles.
This series contains patches for the Qi Ben NanoNote clamshell device as the
inital supported device.

Changes since v1:
There have been some minor changes since v1, mostly code cleanup and some
functional changes. One bigger change is that there is now a MFD driver for
the ADC core which does IRQ demultiplexing for the ADC unit and synchronizes
access to shared registers between the different users of the ADC core.
The patch adding a defconfig for the Qi LB60 has been dropped.
A detailed list of changes is present in each patch.

- Lars

Cc: Alessandro Zummo <a.zummo at towertech.it>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Anton Vorontsov <cbouatmailru at gmail.com>
Cc: David Brownell <dbrownell at users.sourceforge.net>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Greg Kroah-Hartman <gregkh at suse.de>
Cc: Liam Girdwood <lrg at slimlogic.co.uk>
Cc: Mark Brown <broonie at opensource.wolfsonmicro.com>
Cc: Paul Gortmaker <p_gortmaker at yahoo.com>
Cc: Samuel Ortiz <sameo at linux.intel.com>
Cc: alsa-devel at alsa-project.org
Cc: linux-fbdev at vger.kernel.org
Cc: linux-mmc at vger.kernel.org
Cc: linux-mtd at lists.infradead.org
Cc: linux-usb at vger.kernel.org
Cc: lm-sensors at lm-sensors.org
Cc: rtc-linux at googlegroups.com

Lars-Peter Clausen (26):
  MIPS: Add base support for Ingenic JZ4740 System-on-a-Chip
  MIPS: jz4740: Add IRQ handler code
  MIPS: JZ4740: Add clock API support.
  MIPS: JZ4740: Add timer support
  MIPS: JZ4740: Add clocksource/clockevent support.
  MIPS: JZ4740: Add power-management and system reset support
  MIPS: JZ4740: Add setup code
  MIPS: JZ4740: Add gpio support
  MIPS: JZ4740: Add DMA support.
  MIPS: JZ4740: Add PWM support
  MIPS: JZ4740: Add serial support
  MIPS: JZ4740: Add prom support
  MIPS: JZ4740: Add platform devices
  MIPS: JZ4740: Add Kbuild files
  RTC: Add JZ4740 RTC driver
  fbdev: Add JZ4740 framebuffer driver
  MTD: Nand: Add JZ4740 NAND driver
  MMC: Add JZ4740 mmc driver
  USB: Add JZ4740 ohci support
  alsa: ASoC: Add JZ4740 codec driver
  alsa: ASoC: Add JZ4740 ASoC support
  MFD: Add JZ4740 ADC driver
  hwmon: Add JZ4740 ADC driver
  power: Add JZ4740 battery driver.
  MIPS: JZ4740: Add qi_lb60 board support
  alsa: ASoC: JZ4740: Add qi_lb60 board driver

 arch/mips/Kbuild.platforms                   |    1 +
 arch/mips/Kconfig                            |   13 +
 arch/mips/include/asm/bootinfo.h             |    6 +
 arch/mips/include/asm/cpu.h                  |    9 +-
 arch/mips/include/asm/mach-jz4740/base.h     |   26 +
 arch/mips/include/asm/mach-jz4740/clock.h    |   28 +
 arch/mips/include/asm/mach-jz4740/dma.h      |   90 +++
 arch/mips/include/asm/mach-jz4740/gpio.h     |  398 +++++++++++
 arch/mips/include/asm/mach-jz4740/irq.h      |   57 ++
 arch/mips/include/asm/mach-jz4740/platform.h |   36 +
 arch/mips/include/asm/mach-jz4740/timer.h    |   22 +
 arch/mips/include/asm/mach-jz4740/war.h      |   25 +
 arch/mips/jz4740/Kconfig                     |   12 +
 arch/mips/jz4740/Makefile                    |   20 +
 arch/mips/jz4740/Platform                    |    5 +
 arch/mips/jz4740/board-qi_lb60.c             |  483 +++++++++++++
 arch/mips/jz4740/clock-debugfs.c             |  109 +++
 arch/mips/jz4740/clock.c                     |  920 ++++++++++++++++++++++++
 arch/mips/jz4740/clock.h                     |   76 ++
 arch/mips/jz4740/dma.c                       |  289 ++++++++
 arch/mips/jz4740/gpio.c                      |  601 ++++++++++++++++
 arch/mips/jz4740/irq.c                       |  169 +++++
 arch/mips/jz4740/irq.h                       |   21 +
 arch/mips/jz4740/platform.c                  |  284 ++++++++
 arch/mips/jz4740/pm.c                        |   56 ++
 arch/mips/jz4740/prom.c                      |   68 ++
 arch/mips/jz4740/pwm.c                       |  169 +++++
 arch/mips/jz4740/reset.c                     |   79 ++
 arch/mips/jz4740/reset.h                     |    7 +
 arch/mips/jz4740/serial.c                    |   33 +
 arch/mips/jz4740/serial.h                    |   21 +
 arch/mips/jz4740/setup.c                     |   29 +
 arch/mips/jz4740/time.c                      |  144 ++++
 arch/mips/jz4740/timer.c                     |   48 ++
 arch/mips/jz4740/timer.h                     |  136 ++++
 arch/mips/kernel/cpu-probe.c                 |   20 +
 arch/mips/mm/tlbex.c                         |    5 +
 drivers/hwmon/Kconfig                        |   11 +
 drivers/hwmon/Makefile                       |    1 +
 drivers/hwmon/jz4740-hwmon.c                 |  206 ++++++
 drivers/mfd/Kconfig                          |    8 +
 drivers/mfd/Makefile                         |    1 +
 drivers/mfd/jz4740-adc.c                     |  392 ++++++++++
 drivers/mmc/host/Kconfig                     |    8 +
 drivers/mmc/host/Makefile                    |    1 +
 drivers/mmc/host/jz4740_mmc.c                |  993 ++++++++++++++++++++++++++
 drivers/mtd/nand/Kconfig                     |    6 +
 drivers/mtd/nand/Makefile                    |    1 +
 drivers/mtd/nand/jz4740_nand.c               |  474 ++++++++++++
 drivers/power/Kconfig                        |   11 +
 drivers/power/Makefile                       |    1 +
 drivers/power/jz4740-battery.c               |  445 ++++++++++++
 drivers/rtc/Kconfig                          |   11 +
 drivers/rtc/Makefile                         |    1 +
 drivers/rtc/rtc-jz4740.c                     |  341 +++++++++
 drivers/usb/Kconfig                          |    1 +
 drivers/usb/host/ohci-hcd.c                  |    5 +
 drivers/usb/host/ohci-jz4740.c               |  276 +++++++
 drivers/video/Kconfig                        |    9 +
 drivers/video/Makefile                       |    1 +
 drivers/video/jz4740_fb.c                    |  817 +++++++++++++++++++++
 include/linux/jz4740-adc.h                   |   32 +
 include/linux/jz4740_fb.h                    |   58 ++
 include/linux/mmc/jz4740_mmc.h               |   15 +
 include/linux/mtd/jz4740_nand.h              |   34 +
 include/linux/power/jz4740-battery.h         |   24 +
 sound/soc/Kconfig                            |    1 +
 sound/soc/Makefile                           |    1 +
 sound/soc/codecs/Kconfig                     |    4 +
 sound/soc/codecs/Makefile                    |    2 +
 sound/soc/codecs/jz4740-codec.c              |  514 +++++++++++++
 sound/soc/codecs/jz4740-codec.h              |   20 +
 sound/soc/jz4740/Kconfig                     |   23 +
 sound/soc/jz4740/Makefile                    |   13 +
 sound/soc/jz4740/jz4740-i2s.c                |  540 ++++++++++++++
 sound/soc/jz4740/jz4740-i2s.h                |   18 +
 sound/soc/jz4740/jz4740-pcm.c                |  373 ++++++++++
 sound/soc/jz4740/jz4740-pcm.h                |   22 +
 sound/soc/jz4740/qi_lb60.c                   |  167 +++++
 79 files changed, 10396 insertions(+), 1 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/base.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/clock.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/dma.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/gpio.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/irq.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/platform.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/timer.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/war.h
 create mode 100644 arch/mips/jz4740/Kconfig
 create mode 100644 arch/mips/jz4740/Makefile
 create mode 100644 arch/mips/jz4740/Platform
 create mode 100644 arch/mips/jz4740/board-qi_lb60.c
 create mode 100644 arch/mips/jz4740/clock-debugfs.c
 create mode 100644 arch/mips/jz4740/clock.c
 create mode 100644 arch/mips/jz4740/clock.h
 create mode 100644 arch/mips/jz4740/dma.c
 create mode 100644 arch/mips/jz4740/gpio.c
 create mode 100644 arch/mips/jz4740/irq.c
 create mode 100644 arch/mips/jz4740/irq.h
 create mode 100644 arch/mips/jz4740/platform.c
 create mode 100644 arch/mips/jz4740/pm.c
 create mode 100644 arch/mips/jz4740/prom.c
 create mode 100644 arch/mips/jz4740/pwm.c
 create mode 100644 arch/mips/jz4740/reset.c
 create mode 100644 arch/mips/jz4740/reset.h
 create mode 100644 arch/mips/jz4740/serial.c
 create mode 100644 arch/mips/jz4740/serial.h
 create mode 100644 arch/mips/jz4740/setup.c
 create mode 100644 arch/mips/jz4740/time.c
 create mode 100644 arch/mips/jz4740/timer.c
 create mode 100644 arch/mips/jz4740/timer.h
 create mode 100644 drivers/hwmon/jz4740-hwmon.c
 create mode 100644 drivers/mfd/jz4740-adc.c
 create mode 100644 drivers/mmc/host/jz4740_mmc.c
 create mode 100644 drivers/mtd/nand/jz4740_nand.c
 create mode 100644 drivers/power/jz4740-battery.c
 create mode 100644 drivers/rtc/rtc-jz4740.c
 create mode 100644 drivers/usb/host/ohci-jz4740.c
 create mode 100644 drivers/video/jz4740_fb.c
 create mode 100644 include/linux/jz4740-adc.h
 create mode 100644 include/linux/jz4740_fb.h
 create mode 100644 include/linux/mmc/jz4740_mmc.h
 create mode 100644 include/linux/mtd/jz4740_nand.h
 create mode 100644 include/linux/power/jz4740-battery.h
 create mode 100644 sound/soc/codecs/jz4740-codec.c
 create mode 100644 sound/soc/codecs/jz4740-codec.h
 create mode 100644 sound/soc/jz4740/Kconfig
 create mode 100644 sound/soc/jz4740/Makefile
 create mode 100644 sound/soc/jz4740/jz4740-i2s.c
 create mode 100644 sound/soc/jz4740/jz4740-i2s.h
 create mode 100644 sound/soc/jz4740/jz4740-pcm.c
 create mode 100644 sound/soc/jz4740/jz4740-pcm.h
 create mode 100644 sound/soc/jz4740/qi_lb60.c



From lars at metafoo.de  Sat Jun 19 01:08:22 2010
From: lars at metafoo.de (Lars-Peter Clausen)
Date: Sat, 19 Jun 2010 07:08:22 +0200
Subject: [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver
In-Reply-To: <1276924111-11158-1-git-send-email-lars@metafoo.de>
References: <1276924111-11158-1-git-send-email-lars@metafoo.de>
Message-ID: <1276924111-11158-18-git-send-email-lars@metafoo.de>

This patch adds support for the NAND controller on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars at metafoo.de>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: linux-mtd at lists.infradead.org

---
Changes since v1
- JZ4740: Remove debug macro
- Fix platform driver remove callback
- Add custom nand read/write callback since we need to support more then 64 ecc
  bytes
---
 drivers/mtd/nand/Kconfig        |    6 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/jz4740_nand.c  |  474 +++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/jz4740_nand.h |   34 +++
 4 files changed, 515 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/jz4740_nand.c
 create mode 100644 include/linux/mtd/jz4740_nand.h

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ffc3720..362d177 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -526,4 +526,10 @@ config MTD_NAND_NUC900
 	  This enables the driver for the NAND Flash on evaluation board based
 	  on w90p910 / NUC9xx.
 
+config MTD_NAND_JZ4740
+	tristate "Support for JZ4740 SoC NAND controller"
+	depends on MACH_JZ4740
+	help
+		Enables support for NAND Flash on JZ4740 SoC based boards.
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index e8ab884..ac83dcd 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -46,5 +46,6 @@ obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
+obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
new file mode 100644
index 0000000..8c55f8a
--- /dev/null
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -0,0 +1,474 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars at metafoo.de>
+ *  JZ4740 SoC NAND controller driver
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/gpio.h>
+
+#define JZ_REG_NAND_CTRL	0x50
+#define JZ_REG_NAND_ECC_CTRL	0x100
+#define JZ_REG_NAND_DATA	0x104
+#define JZ_REG_NAND_PAR0	0x108
+#define JZ_REG_NAND_PAR1	0x10C
+#define JZ_REG_NAND_PAR2	0x110
+#define JZ_REG_NAND_IRQ_STAT	0x114
+#define JZ_REG_NAND_IRQ_CTRL	0x118
+#define JZ_REG_NAND_ERR(x)	(0x11C + (x << 2))
+
+#define JZ_NAND_ECC_CTRL_PAR_READY	BIT(4)
+#define JZ_NAND_ECC_CTRL_ENCODING	BIT(3)
+#define JZ_NAND_ECC_CTRL_RS		BIT(2)
+#define JZ_NAND_ECC_CTRL_RESET		BIT(1)
+#define JZ_NAND_ECC_CTRL_ENABLE		BIT(0)
+
+#define JZ_NAND_STATUS_ERR_COUNT	(BIT(31) | BIT(30) | BIT(29))
+#define JZ_NAND_STATUS_PAD_FINISH	BIT(4)
+#define JZ_NAND_STATUS_DEC_FINISH	BIT(3)
+#define JZ_NAND_STATUS_ENC_FINISH	BIT(2)
+#define JZ_NAND_STATUS_UNCOR_ERROR	BIT(1)
+#define JZ_NAND_STATUS_ERROR		BIT(0)
+
+#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT(x << 1)
+#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT((x << 1) + 1)
+
+#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
+#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
+#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
+
+struct jz_nand {
+	struct mtd_info mtd;
+	struct nand_chip chip;
+	void __iomem *base;
+	struct resource *mem;
+
+	struct jz_nand_platform_data *pdata;
+	bool is_reading;
+};
+
+static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
+{
+	return container_of(mtd, struct jz_nand, mtd);
+}
+
+static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	struct nand_chip *chip = mtd->priv;
+	uint32_t reg;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
+		if (ctrl & NAND_ALE)
+			chip->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
+		else if (ctrl & NAND_CLE)
+			chip->IO_ADDR_W = JZ_NAND_CMD_ADDR;
+		else
+			chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+		reg = readl(nand->base + JZ_REG_NAND_CTRL);
+		if (ctrl & NAND_NCE)
+			reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
+		else
+			reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
+		writel(reg, nand->base + JZ_REG_NAND_CTRL);
+	}
+	if (dat != NAND_CMD_NONE)
+		writeb(dat, chip->IO_ADDR_W);
+}
+
+static int jz_nand_dev_ready(struct mtd_info *mtd)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	return gpio_get_value_cansleep(nand->pdata->busy_gpio);
+}
+
+static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	uint32_t reg;
+
+	writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	reg |= JZ_NAND_ECC_CTRL_RESET;
+	reg |= JZ_NAND_ECC_CTRL_ENABLE;
+	reg |= JZ_NAND_ECC_CTRL_RS;
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
+		nand->is_reading = true;
+		break;
+	case NAND_ECC_WRITE:
+		reg |= JZ_NAND_ECC_CTRL_ENCODING;
+		nand->is_reading = false;
+		break;
+	default:
+		break;
+	}
+
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+}
+
+static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat,
+	uint8_t *ecc_code)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	uint32_t reg, status;
+	int i;
+	static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4,
+						0x8b, 0xff, 0xb7, 0x6f};
+
+	if (nand->is_reading)
+		return 0;
+
+	do {
+		status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+	} while (!(status & JZ_NAND_STATUS_ENC_FINISH));
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	for (i = 0; i < 9; ++i)
+		ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i);
+
+	/* If the written data is completly 0xff, we also want to write 0xff as
+	 * ecc, otherwise we will get in trouble when doing subpage writes. */
+	if (memcmp(ecc_code, empty_block_ecc, 9) == 0)
+		memset(ecc_code, 0xff, 9);
+
+	return 0;
+}
+
+static void correct_data(uint8_t *dat, int index, int mask)
+{
+	int offset = index & 0x7;
+	uint16_t data;
+
+	index += (index >> 3);
+
+	data = dat[index];
+	data |= dat[index+1] << 8;
+
+	mask ^= (data >> offset) & 0x1ff;
+	data &= ~(0x1ff << offset);
+	data |= (mask << offset);
+
+	dat[index] = data & 0xff;
+	dat[index+1] = (data >> 8) & 0xff;
+}
+
+static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
+	uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	int i, error_count, index;
+	uint32_t reg, status, error;
+	uint32_t t;
+
+	t = read_ecc[0];
+
+	if (t == 0xff) {
+		for (i = 1; i < 9; ++i)
+			t &= read_ecc[i];
+
+		t &= dat[0];
+		t &= dat[nand->chip.ecc.size / 2];
+		t &= dat[nand->chip.ecc.size - 1];
+
+		if (t == 0xff) {
+			for (i = 1; i < nand->chip.ecc.size - 1; ++i)
+				t &= dat[i];
+			if (t == 0xff)
+				return 0;
+		}
+	}
+
+	for (i = 0; i < 9; ++i)
+		writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg |= JZ_NAND_ECC_CTRL_PAR_READY;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	do {
+		status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+	} while (!(status & JZ_NAND_STATUS_DEC_FINISH));
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	if (status & JZ_NAND_STATUS_ERROR) {
+		if (status & JZ_NAND_STATUS_UNCOR_ERROR)
+			return -1;
+
+		error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
+
+		for (i = 0; i < error_count; ++i) {
+			error = readl(nand->base + JZ_REG_NAND_ERR(i));
+			index = ((error >> 16) & 0x1ff) - 1;
+			if (index >= 0 && index < 512)
+				correct_data(dat, index, error & 0x1ff);
+		}
+
+		return error_count;
+	}
+
+	return 0;
+}
+
+
+/* Copy paste of nand_read_page_hwecc_oob_first except for different eccpos
+ * handling. The ecc area is for 4k chips 72 bytes long and thus does not fit
+ * into the eccpos array. */
+static int jz_nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
+	struct nand_chip *chip, uint8_t *buf, int page)
+{
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	unsigned int ecc_offset = chip->page_shift;
+
+	/* Read the OOB area first */
+	chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+	for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		int stat;
+
+		chip->ecc.hwctl(mtd, NAND_ECC_READ);
+		chip->read_buf(mtd, p, eccsize);
+
+		stat = chip->ecc.correct(mtd, p, &chip->oob_poi[i], NULL);
+		if (stat < 0)
+			mtd->ecc_stats.failed++;
+		else
+			mtd->ecc_stats.corrected += stat;
+	}
+	return 0;
+}
+
+/* Copy-and-paste of nand_write_page_hwecc with different eccpos handling. */
+static void jz_nand_write_page_hwecc(struct mtd_info *mtd,
+	struct nand_chip *chip, const uint8_t *buf)
+{
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	const uint8_t *p = buf;
+	unsigned int ecc_offset = chip->page_shift;
+
+	for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+		chip->write_buf(mtd, p, eccsize);
+		chip->ecc.calculate(mtd, p, &chip->oob_poi[i]);
+	}
+
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+static const char *part_probes[] = {"cmdline", NULL};
+#endif
+
+static int __devinit jz_nand_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jz_nand *nand;
+	struct nand_chip *chip;
+	struct mtd_info *mtd;
+	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *partition_info;
+	int num_partitions = 0;
+#endif
+
+	nand = kzalloc(sizeof(*nand), GFP_KERNEL);
+	if (!nand) {
+		dev_err(&pdev->dev, "Failed to allocate device structure.\n");
+		return -ENOMEM;
+	}
+
+	nand->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!nand->mem) {
+		dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
+		ret = -ENOENT;
+		goto err_free;
+	}
+
+	nand->mem = request_mem_region(nand->mem->start,
+					resource_size(nand->mem), pdev->name);
+	if (!nand->mem) {
+		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	nand->base = ioremap(nand->mem->start, resource_size(nand->mem));
+	if (!nand->base) {
+		dev_err(&pdev->dev, "Failed to ioremap mmio memory region\n");
+		ret = -EBUSY;
+		goto err_release_mem;
+	}
+
+	if (pdata && gpio_is_valid(pdata->busy_gpio)) {
+		ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to request busy gpio %d: %d\n",
+				pdata->busy_gpio, ret);
+			goto err_iounmap;
+		}
+	}
+
+	mtd		= &nand->mtd;
+	chip		= &nand->chip;
+	mtd->priv	= chip;
+	mtd->owner	= THIS_MODULE;
+	mtd->name	= "jz4740-nand";
+
+	chip->ecc.hwctl		= jz_nand_hwctl;
+	chip->ecc.calculate	= jz_nand_calculate_ecc_rs;
+	chip->ecc.correct	= jz_nand_correct_ecc_rs;
+	chip->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
+	chip->ecc.size		= 512;
+	chip->ecc.bytes		= 9;
+
+	chip->ecc.read_page	= jz_nand_read_page_hwecc_oob_first;
+	chip->ecc.write_page	= jz_nand_write_page_hwecc;
+
+	if (pdata)
+		chip->ecc.layout = pdata->ecc_layout;
+
+	chip->chip_delay = 50;
+	chip->cmd_ctrl = jz_nand_cmd_ctrl;
+
+	if (pdata && gpio_is_valid(pdata->busy_gpio))
+		chip->dev_ready = jz_nand_dev_ready;
+
+	chip->IO_ADDR_R = JZ_NAND_DATA_ADDR;
+	chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+	nand->pdata = pdata;
+	platform_set_drvdata(pdev, nand);
+
+	ret = nand_scan_ident(mtd, 1, NULL);
+	if (ret) {
+		dev_err(&pdev->dev,  "Failed to scan nand\n");
+		goto err_gpio_free;
+	}
+
+	if (pdata && pdata->ident_callback) {
+		pdata->ident_callback(pdev, chip, &pdata->partitions,
+					&pdata->num_partitions);
+	}
+
+	ret = nand_scan_tail(mtd);
+	if (ret) {
+		dev_err(&pdev->dev,  "Failed to scan nand\n");
+		goto err_gpio_free;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+	num_partitions = parse_mtd_partitions(mtd, part_probes,
+						&partition_info, 0);
+#endif
+	if (num_partitions <= 0 && pdata) {
+		num_partitions = pdata->num_partitions;
+		partition_info = pdata->partitions;
+	}
+
+	if (num_partitions > 0)
+		ret = add_mtd_partitions(mtd, partition_info, num_partitions);
+	else
+#endif
+	ret = add_mtd_device(mtd);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add mtd device\n");
+		goto err_nand_release;
+	}
+
+	dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
+
+	return 0;
+err_nand_release:
+	nand_release(&nand->mtd);
+err_gpio_free:
+	platform_set_drvdata(pdev, NULL);
+	gpio_free(pdata->busy_gpio);
+err_iounmap:
+	iounmap(nand->base);
+err_release_mem:
+	release_mem_region(nand->mem->start, resource_size(nand->mem));
+err_free:
+	kfree(nand);
+	return ret;
+}
+
+static int __devexit jz_nand_remove(struct platform_device *pdev)
+{
+	struct jz_nand *nand = platform_get_drvdata(pdev);
+
+	nand_release(&nand->mtd);
+
+	iounmap(nand->base);
+	release_mem_region(nand->mem->start, resource_size(nand->mem));
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(nand);
+
+	return 0;
+}
+
+struct platform_driver jz_nand_driver = {
+	.probe = jz_nand_probe,
+	.remove = __devexit_p(jz_nand_remove),
+	.driver = {
+		.name = "jz4740-nand",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init jz_nand_init(void)
+{
+	return platform_driver_register(&jz_nand_driver);
+}
+module_init(jz_nand_init);
+
+static void __exit jz_nand_exit(void)
+{
+	platform_driver_unregister(&jz_nand_driver);
+}
+module_exit(jz_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars at metafoo.de>");
+MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC");
+MODULE_ALIAS("platform:jz4740-nand");
diff --git a/include/linux/mtd/jz4740_nand.h b/include/linux/mtd/jz4740_nand.h
new file mode 100644
index 0000000..379f9b6
--- /dev/null
+++ b/include/linux/mtd/jz4740_nand.h
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars at metafoo.de>
+ *  JZ4740 SoC NAND controller driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __JZ_NAND_H__
+#define __JZ_NAND_H__
+
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+struct jz_nand_platform_data {
+	int			num_partitions;
+	struct mtd_partition	*partitions;
+
+	struct nand_ecclayout	*ecc_layout;
+
+	unsigned int busy_gpio;
+
+	void (*ident_callback)(struct platform_device *, struct nand_chip *,
+				struct mtd_partition **, int *num_partitions);
+};
+
+#endif
-- 
1.5.6.5



From schor.dong at gmail.com  Sun Jun 20 00:51:28 2010
From: schor.dong at gmail.com (schorn dong)
Date: Sun, 20 Jun 2010 12:51:28 +0800
Subject: a question about mtd partition information
Message-ID: <AANLkTim7PFSDEQT0H_s3LvGNGpPHxhr1uuXBE6csGlpj@mail.gmail.com>

Hi all
I have a question about MTD partition.
My NAND controller is PCI device, so MTD driver need use pci register
interrface.
I want to add mtd partition features in my MTD driver. But I don't
want to list the
mtd_partition structure in MTD driver. Since I think this is the
platform relevant.
Different platform with the same NAND controller may have different partitions.

Here is my question: If I don't list mtd_partition structure in MTD
driver, which file
is the best one for me to list this structure?


From nealb001 at gmail.com  Sun Jun 20 04:01:54 2010
From: nealb001 at gmail.com (Neal Buckendahl)
Date: Sun, 20 Jun 2010 03:01:54 -0500
Subject: [PATCH] Mtd: fixed coding style issues in afs.c ar7part.c
	cmdlinepart.c inftlcore.c This is a patch to the files afs.c
	ar7part.c cmdlinepart.c inftlcore.c that fixes up warnings
	found by the checkpatch.pl tool Signed-off-by: Neal Buckendahl
	<nealb001@gmail.com>
Message-ID: <1277020914-10984-1-git-send-email-nealb001@gmail.com>

From: Neal Buckendahl <nealb at tbcnet.com>

---
 drivers/mtd/afs.c         |    9 ++-
 drivers/mtd/ar7part.c     |    2 +-
 drivers/mtd/cmdlinepart.c |  167 ++++++++++++++++++++-------------------------
 drivers/mtd/inftlcore.c   |   47 ++++++++-----
 4 files changed, 109 insertions(+), 116 deletions(-)

diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c
index cec7ab9..d127171 100644
--- a/drivers/mtd/afs.c
+++ b/drivers/mtd/afs.c
@@ -162,8 +162,8 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
 }
 
 static int parse_afs_partitions(struct mtd_info *mtd,
-                         struct mtd_partition **pparts,
-                         unsigned long origin)
+			struct mtd_partition **pparts,
+			unsigned long origin)
 {
 	struct mtd_partition *parts;
 	u_int mask, off, idx, sz;
@@ -235,11 +235,12 @@ static int parse_afs_partitions(struct mtd_info *mtd,
 		strcpy(str, iis.name);
 
 		parts[idx].name		= str;
-		parts[idx].size		= (iis.length + mtd->erasesize - 1) & ~(mtd->erasesize - 1);
+		parts[idx].size		= (iis.length + mtd->erasesize - 1)&
+						~(mtd->erasesize - 1);
 		parts[idx].offset	= img_ptr;
 		parts[idx].mask_flags	= 0;
 
-		printk("  mtd%d: at 0x%08x, %5lluKiB, %8u, %s\n",
+		printk(KERN_INFO "  mtd%d: at 0x%08x, %5lluKiB, %8u, %s\n",
 			idx, img_ptr, parts[idx].size / 1024,
 			iis.imageNumber, str);
 
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
index 6697a1e..7ccfdca 100644
--- a/drivers/mtd/ar7part.c
+++ b/drivers/mtd/ar7part.c
@@ -148,6 +148,6 @@ static int __init ar7_parser_init(void)
 module_init(ar7_parser_init);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR(	"Felix Fietkau <nbd at openwrt.org>, "
+MODULE_AUTHOR("Felix Fietkau <nbd at openwrt.org>, "
 		"Eugene Konev <ejka at openwrt.org>");
 MODULE_DESCRIPTION("MTD partitioning for TI AR7");
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index 1479da6..ef5ea7e 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -34,7 +34,8 @@
 
 /* debug macro */
 #if 0
-#define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
+#define dbg(x) do { printk(KERN_DEBUG "DEBUG-CMDLINE-PART: "); printk x;
+		} while (0)
 #else
 #define dbg(x)
 #endif
@@ -56,7 +57,7 @@ static struct cmdline_mtd_partition *partitions;
 
 /* the command line passed to mtdpart_setupd() */
 static char *cmdline;
-static int cmdline_parsed = 0;
+static int cmdline_parsed = 1;
 
 /*
  * Parse one partition definition for an MTD. Since there can be many
@@ -66,12 +67,12 @@ static int cmdline_parsed = 0;
  * is allocated upon the last definition being found. At that point the
  * syntax has been verified ok.
  */
-static struct mtd_partition * newpart(char *s,
-                                      char **retptr,
-                                      int *num_parts,
-                                      int this_part,
-                                      unsigned char **extra_mem_ptr,
-                                      int extra_mem_size)
+static struct mtd_partition *newpart(char *s,
+					char **retptr,
+					int *num_parts,
+					int this_part,
+					unsigned char **extra_mem_ptr,
+					int extra_mem_size)
 {
 	struct mtd_partition *parts;
 	unsigned long size;
@@ -83,17 +84,15 @@ static struct mtd_partition * newpart(char *s,
 	unsigned int mask_flags;
 
 	/* fetch the partition size */
-	if (*s == '-')
-	{	/* assign all remaining space to this partition */
+	if (*s == '-') {
+		/* assign all remaining space to this partition */
 		size = SIZE_REMAINING;
 		s++;
-	}
-	else
-	{
+	} else {
 		size = memparse(s, &s);
-		if (size < PAGE_SIZE)
-		{
-			printk(KERN_ERR ERRP "partition size too small (%lx)\n", size);
+		if (size < PAGE_SIZE) {
+			printk(KERN_ERR ERRP "partition size too small (%lx)\n"
+			, size);
 			return NULL;
 		}
 	}
@@ -101,61 +100,51 @@ static struct mtd_partition * newpart(char *s,
 	/* fetch partition name and flags */
 	mask_flags = 0; /* this is going to be a regular partition */
 	delim = 0;
-        /* check for offset */
-        if (*s == '@')
-	{
-                s++;
-                offset = memparse(s, &s);
-        }
-        /* now look for name */
+	/* check for offset */
+	if (*s == '@') {
+		s++;
+		offset = memparse(s, &s);
+	}
+	/* now look for name */
 	if (*s == '(')
-	{
 		delim = ')';
-	}
 
-	if (delim)
-	{
+	if (delim) {
 		char *p;
-
-	    	name = ++s;
+		name = ++s;
 		p = strchr(name, delim);
-		if (!p)
-		{
-			printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
+		if (!p) {
+			printk(KERN_ERR ERRP
+			"no closing %c found in partition name\n", delim);
 			return NULL;
 		}
 		name_len = p - name;
 		s = p + 1;
-	}
-	else
-	{
-	    	name = NULL;
+	} else {
+		name = NULL;
 		name_len = 13; /* Partition_000 */
 	}
 
 	/* record name length for memory allocation later */
 	extra_mem_size += name_len + 1;
 
-        /* test for options */
-        if (strncmp(s, "ro", 2) == 0)
-	{
+	/* test for options */
+	if (strncmp(s, "ro", 2) == 0) {
 		mask_flags |= MTD_WRITEABLE;
 		s += 2;
-        }
+	}
 
-        /* if lk is found do NOT unlock the MTD partition*/
-        if (strncmp(s, "lk", 2) == 0)
-	{
+	/* if lk is found do NOT unlock the MTD partition*/
+	if (strncmp(s, "lk", 2) == 0) {
 		mask_flags |= MTD_POWERUP_LOCK;
 		s += 2;
-        }
+	}
 
 	/* test if more partitions are following */
-	if (*s == ',')
-	{
-		if (size == SIZE_REMAINING)
-		{
-			printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
+	if (*s == ',') {
+		if (size == SIZE_REMAINING) {
+			printk(KERN_ERR ERRP
+			"no partitions allowed after a fill-up partition\n");
 			return NULL;
 		}
 		/* more partitions follow, parse them */
@@ -163,34 +152,29 @@ static struct mtd_partition * newpart(char *s,
 				&extra_mem, extra_mem_size);
 		if (!parts)
 			return NULL;
-	}
-	else
-	{	/* this is the last partition: allocate space for all */
+	} else {
+		/* this is the last partition: allocate space for all */
 		int alloc_size;
 
 		*num_parts = this_part + 1;
 		alloc_size = *num_parts * sizeof(struct mtd_partition) +
 			     extra_mem_size;
 		parts = kzalloc(alloc_size, GFP_KERNEL);
-		if (!parts)
-		{
+		if (!parts) {
 			printk(KERN_ERR ERRP "out of memory\n");
 			return NULL;
 		}
 		extra_mem = (unsigned char *)(parts + *num_parts);
 	}
-	/* enter this partition (offset will be calculated later if it is zero at this point) */
+	/* enter this partition (offset will be calculated later if it is zero
+	   at this point) */
 	parts[this_part].size = size;
 	parts[this_part].offset = offset;
 	parts[this_part].mask_flags = mask_flags;
 	if (name)
-	{
 		strlcpy(extra_mem, name, name_len + 1);
-	}
 	else
-	{
 		sprintf(extra_mem, "Partition_%03d", this_part);
-	}
 	parts[this_part].name = extra_mem;
 	extra_mem += name_len + 1;
 
@@ -203,7 +187,7 @@ static struct mtd_partition * newpart(char *s,
 
 	/* return (updated) pointer to extra_mem memory */
 	if (extra_mem_ptr)
-	  *extra_mem_ptr = extra_mem;
+		*extra_mem_ptr = extra_mem;
 
 	/* return (updated) pointer command line string */
 	*retptr = s;
@@ -217,20 +201,19 @@ static struct mtd_partition * newpart(char *s,
  */
 static int mtdpart_setup_real(char *s)
 {
-	cmdline_parsed = 1;
+	cmdline_parsed = 0;
 
-	for( ; s != NULL; )
-	{
+	for ( ; s != NULL; ) {
 		struct cmdline_mtd_partition *this_mtd;
 		struct mtd_partition *parts;
-	    	int mtd_id_len;
+		int mtd_id_len;
 		int num_parts;
 		char *p, *mtd_id;
 
-	    	mtd_id = s;
+		mtd_id = s;
 		/* fetch <mtd-id> */
-		if (!(p = strchr(s, ':')))
-		{
+		p = strchr(s, ':');
+		if (!p) {
 			printk(KERN_ERR ERRP "no mtd-id\n");
 			return 0;
 		}
@@ -246,11 +229,11 @@ static int mtdpart_setup_real(char *s)
 				&s,		/* out: updated cmdline ptr */
 				&num_parts,	/* out: number of parts */
 				0,		/* first partition */
-				(unsigned char**)&this_mtd, /* out: extra mem */
+				(unsigned char **)&this_mtd,/*out: extra mem */
 				mtd_id_len + 1 + sizeof(*this_mtd) +
-				sizeof(void*)-1 /*alignment*/);
-		if(!parts)
-		{
+				sizeof(void *)-1 /*alignment*/);
+		if (!parts) {
+
 			/*
 			 * An error occurred. We're either:
 			 * a) out of memory, or
@@ -259,15 +242,15 @@ static int mtdpart_setup_real(char *s)
 			 * unlikely to succeed in parsing any more
 			 */
 			 return 0;
-		 }
+		}
 
 		/* align this_mtd */
 		this_mtd = (struct cmdline_mtd_partition *)
-			ALIGN((unsigned long)this_mtd, sizeof(void*));
+		ALIGN((unsigned long)this_mtd, sizeof(void *));
 		/* enter results */
 		this_mtd->parts = parts;
 		this_mtd->num_parts = num_parts;
-		this_mtd->mtd_id = (char*)(this_mtd + 1);
+		this_mtd->mtd_id = (char *)(this_mtd + 1);
 		strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1);
 
 		/* link into chain */
@@ -283,9 +266,9 @@ static int mtdpart_setup_real(char *s)
 			break;
 
 		/* does another spec follow? */
-		if (*s != ';')
-		{
-			printk(KERN_ERR ERRP "bad character after partition (%c)\n", *s);
+		if (*s != ';') {
+			printk(KERN_ERR ERRP
+			"bad character after partition (%c)\n", *s);
 			return 0;
 		}
 		s++;
@@ -301,8 +284,8 @@ static int mtdpart_setup_real(char *s)
  * the first one in the chain if a NULL mtd_id is passed in.
  */
 static int parse_cmdline_partitions(struct mtd_info *master,
-                             struct mtd_partition **pparts,
-                             unsigned long origin)
+				struct mtd_partition **pparts,
+				unsigned long origin)
 {
 	unsigned long offset;
 	int i;
@@ -310,27 +293,27 @@ static int parse_cmdline_partitions(struct mtd_info *master,
 	const char *mtd_id = master->name;
 
 	/* parse command line */
-	if (!cmdline_parsed)
+	if (cmdline_parsed)
 		mtdpart_setup_real(cmdline);
 
-	for(part = partitions; part; part = part->next)
-	{
-		if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id)))
-		{
-			for(i = 0, offset = 0; i < part->num_parts; i++)
-			{
+	for (part = partitions; part; part = part->next) {
+		if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) {
+			for (i = 0, offset = 0; i < part->num_parts; i++) {
 				if (part->parts[i].offset == OFFSET_CONTINUOUS)
-				  part->parts[i].offset = offset;
+					part->parts[i].offset = offset;
 				else
 				  offset = part->parts[i].offset;
 				if (part->parts[i].size == SIZE_REMAINING)
-				  part->parts[i].size = master->size - offset;
-				if (offset + part->parts[i].size > master->size)
-				{
+					part->parts[i].size = master->size -
+					offset;
+				if (offset + part->parts[i].size
+				  > master->size) {
 					printk(KERN_WARNING ERRP
-					       "%s: partitioning exceeds flash size, truncating\n",
+					       "%s: partitioning exceeds \
+					       flash size, truncating\n",
 					       part->mtd_id);
-					part->parts[i].size = master->size - offset;
+					part->parts[i].size = master->size -
+					offset;
 					part->num_parts = i;
 				}
 				offset += part->parts[i].size;
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 015a7fe..1634694 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -34,9 +34,9 @@
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/inftl.h>
 #include <linux/mtd/nand.h>
-#include <asm/uaccess.h>
-#include <asm/errno.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/io.h>
 
 /*
  * Maximum number of loops while examining next block, to have a
@@ -103,7 +103,8 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 		}
 	}
 
-	if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) {
+	if (inftl->mbd.size != inftl->heads * inftl->cylinders *
+	    inftl->sectors) {
 		/*
 		  Oh no we don't have
 		   mbd.size == heads * cylinders * sectors
@@ -114,7 +115,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 			"(== 0x%lx sects)\n",
 			inftl->cylinders, inftl->heads , inftl->sectors,
 			(long)inftl->cylinders * (long)inftl->heads *
-			(long)inftl->sectors );
+			(long)inftl->sectors);
 	}
 
 	if (add_mtd_blktrans_dev(&inftl->mbd)) {
@@ -248,7 +249,8 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate)
 	return BLOCK_NIL;
 }
 
-static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned pendingblock)
+static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC,
+			   unsigned pendingblock)
 {
 	u16 BlockMap[MAX_SECTORS_PER_UNIT];
 	unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT];
@@ -279,7 +281,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
 	 */
 	silly = MAX_LOOPS;
 	while (thisEUN < inftl->nb_blocks) {
-		for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) {
+		for (block = 0; block < inftl->EraseSize/SECTORSIZE; block++) {
 			if ((BlockMap[block] != BLOCK_NIL) ||
 			    BlockDeleted[block])
 				continue;
@@ -291,7 +293,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
 			else
 				status = oob.b.Status | oob.b.Status1;
 
-			switch(status) {
+			switch (status) {
 			case SECTOR_FREE:
 			case SECTOR_IGNORE:
 				break;
@@ -341,7 +343,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
 
 		/*
 		 * Copy only in non free block (free blocks can only
-                 * happen in case of media errors or deleted blocks).
+		 * happen in case of media errors or deleted blocks).
 		 */
 		if (BlockMap[block] == BLOCK_NIL)
 			continue;
@@ -476,7 +478,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
 {
 	unsigned int thisVUC = block / (inftl->EraseSize / SECTORSIZE);
 	unsigned int thisEUN, writeEUN, prev_block, status;
-	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize -1);
+	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
 	struct mtd_info *mtd = inftl->mbd.mtd;
 	struct inftl_oob oob;
 	struct inftl_bci bci;
@@ -504,7 +506,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
 			DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
 				"EUN %d is %x\n", block , writeEUN, status);
 
-			switch(status) {
+			switch (status) {
 			case SECTOR_FREE:
 				writeEUN = thisEUN;
 				break;
@@ -677,7 +679,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 			else
 				status = bci.Status | bci.Status1;
 
-			switch(status) {
+			switch (status) {
 			case SECTOR_FREE:
 			case SECTOR_IGNORE:
 				break;
@@ -719,7 +721,8 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 
 		/* If the chain is all gone already, we're done */
 		if (thisEUN == BLOCK_NIL) {
-			DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
+			DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d \
+			for deletion was already absent\n", thisEUN);
 			return;
 		}
 
@@ -759,7 +762,8 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 
 static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
 {
-	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
+	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize /
+				SECTORSIZE)];
 	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
 	struct mtd_info *mtd = inftl->mbd.mtd;
 	unsigned int status;
@@ -811,7 +815,8 @@ foundit:
 		bci.Status = bci.Status1 = SECTOR_DELETED;
 		if (inftl_write_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
 			return -EIO;
-		INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE));
+		INFTL_trydeletechain(inftl, block / (inftl->EraseSize /
+		SECTORSIZE));
 	}
 	return 0;
 }
@@ -868,7 +873,8 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
 			   char *buffer)
 {
 	struct INFTLrecord *inftl = (void *)mbd;
-	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
+	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize /
+				SECTORSIZE)];
 	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
 	struct mtd_info *mtd = inftl->mbd.mtd;
 	unsigned int status;
@@ -943,7 +949,7 @@ static struct mtd_blktrans_ops inftl_tr = {
 	.name		= "inftl",
 	.major		= INFTL_MAJOR,
 	.part_bits	= INFTL_PARTN_BITS,
-	.blksize 	= 512,
+	.blksize	= 512,
 	.getgeo		= inftl_getgeo,
 	.readsect	= inftl_readblock,
 	.writesect	= inftl_writeblock,
@@ -966,5 +972,8 @@ module_init(init_inftl);
 module_exit(cleanup_inftl);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Greg Ungerer <gerg at snapgear.com>, David Woodhouse <dwmw2 at infradead.org>, Fabrice Bellard <fabrice.bellard at netgem.com> et al.");
-MODULE_DESCRIPTION("Support code for Inverse Flash Translation Layer, used on M-Systems DiskOnChip 2000, Millennium and Millennium Plus");
+MODULE_AUTHOR("Greg Ungerer <gerg at snapgear.com>, \
+	      David Woodhouse <dwmw2 at infradead.org>, \
+	      Fabrice Bellard <fabrice.bellard at netgem.com> et al.");
+MODULE_DESCRIPTION("Support code for Inverse Flash Translation Layer, used on \
+		    M-Systems DiskOnChip 2000, Millennium and Millennium Plus");
-- 
1.7.1



From tsbogend at alpha.franken.de  Sun Jun 20 05:26:10 2010
From: tsbogend at alpha.franken.de (Thomas Bogendoerfer)
Date: Sun, 20 Jun 2010 11:26:10 +0200
Subject: [PATCH v2 00/26] Add support for the Ingenic JZ4740
	System-on-a-Chip
In-Reply-To: <1276924111-11158-1-git-send-email-lars@metafoo.de>
References: <1276924111-11158-1-git-send-email-lars@metafoo.de>
Message-ID: <20100620092610.GA4950@alpha.franken.de>

On Sat, Jun 19, 2010 at 07:08:05AM +0200, Lars-Peter Clausen wrote:
> This patch series adds support for the Ingenic JZ4740 System-on-a-Chip.

great stuff. I have a JZ4730 based netbook, for which I started magling
the provided sources quite some time ago, but I didn't reach the
point of submitting patches... there are a lot of common stuff between
JZ4730 and JZ4740 so IMHO it would be a good thing not to nail
everthing to JZ4740 namewise. It might also a good idea to select
something like arch/mips/jzrisc as base directory, put the
factored out code there and add JZ4730/JZ4740 in either seperate
files or directories.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea.                                                [ RFC1925, 2.3 ]


From stanley.miao at windriver.com  Sun Jun 20 08:21:37 2010
From: stanley.miao at windriver.com (stanley.miao)
Date: Sun, 20 Jun 2010 20:21:37 +0800
Subject: Fix mtd-utils bugs
In-Reply-To: <1276856663.19028.447.camel@localhost>
References: <1276248975-1822-1-git-send-email-stanley.miao@windriver.com>	
	<1276422718.19028.211.camel@localhost>	
	<1276424048.19028.217.camel@localhost>
	<4C1B2B65.3090606@windriver.com>
	<1276856663.19028.447.camel@localhost>
Message-ID: <4C1E07D1.4090703@windriver.com>

Artem Bityutskiy wrote:
> On Fri, 2010-06-18 at 16:16 +0800, stanley.miao wrote:
>   
>> Artem Bityutskiy wrote:
>>     
>>> On Sun, 2010-06-13 at 12:51 +0300, Artem Bityutskiy wrote:
>>>   
>>>       
>>>> On Fri, 2010-06-11 at 17:36 +0800, Stanley.Miao wrote:
>>>>     
>>>>         
>>>>> <snip>
>>>>>       
>>>>>           
>>>> Please, make sure your submissions have proper version. I have limited
>>>> amount of time and do not want to spend it figuring out which patch is
>>>> the latest. Use the best kernel practices and apply prefix your stuff
>>>> with [PATCHv3] or something like that.
>>>>
>>>> Could you please re-submit your latest version?
>>>>     
>>>>         
>>> Also, it is nice to put a short changelog, but I can live without it.
>>>   
>>>       
>> Is the subject of every emails is the short changelog you wanted ?
>>     
>
> Hi,
>
> Sorry, I do not understand the question. I do not need changelogs. I
> just noted that there are best practices, and people use changelogs. You
> can take a look at lkml archives at patch series from good kernel
> hackers for example.
>
> If you asked whether the changelog should be in each patch - no, just in
> the "0" patch, and just short.
>   

Oh, Got it. I misunderstood the "short changelog" previously.
I have sent the V3.

Thanks
Stanley.
> Anyway, I just want you to re-send your up-to-date patches as a separate
> series with a v2 prefix.
>
>   



From stanley.miao at windriver.com  Sun Jun 20 08:22:57 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Sun, 20 Jun 2010 20:22:57 +0800
Subject: [PATCH v3] Fix mtd-utils bugs
Message-ID: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>

Changes from V2:
1, Get the linux version via uname() according to Joakim Tjernlund.
2, Set the default version the latest version according to Joakim Tjernlund.

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up. 


Stanley.


From stanley.miao at windriver.com  Sun Jun 20 08:22:58 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Sun, 20 Jun 2010 20:22:58 +0800
Subject: [PATCHv3 1/3] clean up the legacy interfaces in nandwrite.c
In-Reply-To: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
References: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
Message-ID: <1277036580-3501-2-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 nandwrite.c |  224 +++++++++++++++--------------------------------------------
 1 files changed, 57 insertions(+), 167 deletions(-)

diff --git a/nandwrite.c b/nandwrite.c
index 1b4ca3d..eadca54 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <getopt.h>
 
 #include <asm/types.h>
@@ -45,26 +46,7 @@
 #define MAX_PAGE_SIZE	4096
 #define MAX_OOB_SIZE	128
 
-// oob layouts to pass into the kernel as default
-static struct nand_oobinfo none_oobinfo = {
-	.useecc = MTD_NANDECC_OFF,
-};
-
-static struct nand_oobinfo jffs2_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 0, 1, 2, 3, 6, 7 }
-};
-
-static struct nand_oobinfo yaffs_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_oobinfo autoplace_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE
-};
+#define LINUX_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
 
 static void display_help (void)
 {
@@ -72,13 +54,7 @@ static void display_help (void)
 "Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
 "Writes to the specified MTD device.\n"
 "\n"
-"  -a, --autoplace         Use auto oob layout\n"
-"  -j, --jffs2             Force jffs2 oob layout (legacy support)\n"
-"  -y, --yaffs             Force yaffs oob layout (legacy support)\n"
-"  -f, --forcelegacy       Force legacy support on autoplacement-enabled mtd\n"
-"                          device\n"
 "  -m, --markbad           Mark blocks bad if write fails\n"
-"  -n, --noecc             Write without ecc\n"
 "  -o, --oob               Image contains oob data\n"
 "  -r, --raw               Image contains the raw oob data dumped by nanddump\n"
 "  -s addr, --start=addr   Set start address (default is 0)\n"
@@ -112,37 +88,49 @@ static int		mtdoffset = 0;
 static bool		quiet = false;
 static bool		writeoob = false;
 static bool		rawoob = false;
-static bool		autoplace = false;
 static bool		markbad = false;
-static bool		forcejffs2 = false;
-static bool		forceyaffs = false;
-static bool		forcelegacy = false;
-static bool		noecc = false;
 static bool		pad = false;
 static int		blockalign = 1; /*default to using 16K block size */
 
+static int get_linux_version(void)
+{
+	int a, b, c, ret, err = 0;
+	struct utsname buf;
+
+	ret = uname(&buf);
+	if (ret == 0) {
+		ret = sscanf(buf.release, "%d.%d.%d", &a, &b, &c);
+		if (ret != 3)
+			err = 1;
+	} else
+		err = 1;
+
+	if (err) {
+		a = b = c = 0xff;
+		fprintf(stderr, "Warning: Can't get linux kernel version."
+				"Set the default version to the latest version.\n");
+	}
+
+	return LINUX_VERSION(a, b, c);
+}
+
 static void process_options (int argc, char * const argv[])
 {
 	int error = 0;
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "ab:fjmnopqrs:y";
+		static const char *short_options = "b:mopqrs:";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
-			{"autoplace", no_argument, 0, 'a'},
 			{"blockalign", required_argument, 0, 'b'},
-			{"forcelegacy", no_argument, 0, 'f'},
-			{"jffs2", no_argument, 0, 'j'},
 			{"markbad", no_argument, 0, 'm'},
-			{"noecc", no_argument, 0, 'n'},
 			{"oob", no_argument, 0, 'o'},
 			{"pad", no_argument, 0, 'p'},
 			{"quiet", no_argument, 0, 'q'},
 			{"raw", no_argument, 0, 'r'},
 			{"start", required_argument, 0, 's'},
-			{"yaffs", no_argument, 0, 'y'},
 			{0, 0, 0, 0},
 		};
 
@@ -166,21 +154,6 @@ static void process_options (int argc, char * const argv[])
 			case 'q':
 				quiet = true;
 				break;
-			case 'a':
-				autoplace = true;
-				break;
-			case 'j':
-				forcejffs2 = true;
-				break;
-			case 'y':
-				forceyaffs = true;
-				break;
-			case 'f':
-				forcelegacy = true;
-				break;
-			case 'n':
-				noecc = true;
-				break;
 			case 'm':
 				markbad = true;
 				break;
@@ -258,8 +231,7 @@ int main(int argc, char * const argv[])
 	struct mtd_oob_buf oob;
 	loff_t offs;
 	int ret;
-	int oobinfochanged = 0;
-	struct nand_oobinfo old_oobinfo;
+	struct nand_ecclayout ecclayout;
 	bool failed = true;
 	// contains all the data read from the file so far for the current eraseblock
 	unsigned char *filebuf = NULL;
@@ -316,86 +288,30 @@ int main(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (autoplace) {
-		/* Read the current oob info */
-		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMGETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-
-		// autoplace ECC ?
-		if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
-
-			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
-				perror ("MEMSETOOBSEL");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-			oobinfochanged = 1;
-		}
-	}
-
-	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
-		if (ret == 0) {
-			oobinfochanged = 2;
-		} else {
-			switch (errno) {
-			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				oobinfochanged = 1;
-				break;
-			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-		}
-	}
-
-	/*
-	 * force oob layout for jffs2 or yaffs ?
-	 * Legacy support
-	 */
-	if (forcejffs2 || forceyaffs) {
-		struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
 
-		if (autoplace) {
-			fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n");
-			goto restoreoob;
-		}
-		if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) {
-			fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n");
-			goto restoreoob;
-		}
-		if (meminfo.oobsize == 8) {
-			if (forceyaffs) {
-				fprintf (stderr, "YAFSS cannot operate on 256 Byte page size");
-				goto restoreoob;
-			}
-			/* Adjust number of ecc bytes */
-			jffs2_oobinfo.eccbytes = 3;
+	oob.length = meminfo.oobsize;
+	oob.ptr =  oobbuf;
+
+	memset(&ecclayout, 0, sizeof(ecclayout));
+	if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+		if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+			perror("ECCGETLAYOUT");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
+	} else {
+		struct nand_oobinfo oi;
 
-		if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) {
-			perror ("MEMSETOOBSEL");
-			goto restoreoob;
+		if (ioctl(fd, MEMGETOOBSEL, &oi) != 0) {
+			perror("MEMGETOOBSEL");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
+		memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+		memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+		ecclayout.eccbytes = oi.eccbytes;
 	}
 
-	oob.length = meminfo.oobsize;
-	oob.ptr = noecc ? oobreadbuf : oobbuf;
-
 	/* Determine if we are reading from standard input or from a file. */
 	if (strcmp(img, standard_input) == 0) {
 		ifd = STDIN_FILENO;
@@ -559,6 +475,8 @@ int main(int argc, char * const argv[])
 		}
 
 		if (writeoob) {
+			int i, start, len;
+			int tags_pos = 0;
 			oobreadbuf = writebuf + meminfo.writesize;
 
 			// Read more data for the OOB from the input if there isn't enough in the buffer
@@ -595,40 +513,19 @@ int main(int argc, char * const argv[])
 				}
 			}
 
-			if (noecc) {
-				oob.ptr = oobreadbuf;
-			} else {
-				int i, start, len;
-				int tags_pos = 0;
-				/*
-				 *  We use autoplacement and have the oobinfo with the autoplacement
-				 * information from the kernel available
-				 *
-				 * Modified to support out of order oobfree segments,
-				 * such as the layout used by diskonchip.c
-				 */
-				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
-					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
-						/* Set the reserved bytes to 0xff */
-						start = old_oobinfo.oobfree[i][0];
-						len = old_oobinfo.oobfree[i][1];
-						if (rawoob)
-							memcpy(oobbuf + start,
-									oobreadbuf + start, len);
-						else
-							memcpy(oobbuf + start,
-									oobreadbuf + tags_pos, len);
-						tags_pos += len;
-					}
-				} else {
-					/* Set at least the ecc byte positions to 0xff */
-					start = old_oobinfo.eccbytes;
-					len = meminfo.oobsize - start;
+			for (i = 0; ecclayout.oobfree[i].length; i++) {
+				/* Set the reserved bytes to 0xff */
+				start = ecclayout.oobfree[i].offset;
+				len = ecclayout.oobfree[i].length;
+				if (rawoob)
 					memcpy(oobbuf + start,
-							oobreadbuf + start,
-							len);
-				}
+							oobreadbuf + start, len);
+				else
+					memcpy(oobbuf + start,
+							oobreadbuf + tags_pos, len);
+				tags_pos += len;
 			}
+
 			/* Write OOB data first, as ecc will be placed in there*/
 			oob.start = mtdoffset;
 			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
@@ -687,13 +584,6 @@ closeall:
 	close(ifd);
 
 restoreoob:
-	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-	}
 
 	close(fd);
 
-- 
1.5.4.3



From stanley.miao at windriver.com  Sun Jun 20 08:22:59 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Sun, 20 Jun 2010 20:22:59 +0800
Subject: [PATCHv3 2/3] Discard the legacy interface MEMGETOOBSEL in
	flash_eraseall
In-Reply-To: <1277036580-3501-2-git-send-email-stanley.miao@windriver.com>
References: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
	<1277036580-3501-2-git-send-email-stanley.miao@windriver.com>
Message-ID: <1277036580-3501-3-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
to keep compatible with the old linux kernel, a linux version detection
function is added.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   79 ++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index a22fc49..b8068c0 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -35,6 +35,7 @@
 #include <getopt.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
+#include <sys/utsname.h>
 #include "crc32.h"
 
 #include <mtd/mtd-user.h>
@@ -43,6 +44,8 @@
 #define PROGRAM "flash_eraseall"
 #define VERSION "$Revision: 1.22 $"
 
+#define LINUX_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
+
 static const char *exe_name;
 static const char *mtd_device;
 static int quiet;		/* true -- don't output progress */
@@ -55,6 +58,28 @@ static void display_version (void);
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
 
+static int get_linux_version(void)
+{
+	int a, b, c, ret, err = 0;
+	struct utsname buf;
+
+	ret = uname(&buf);
+	if (ret == 0) {
+		ret = sscanf(buf.release, "%d.%d.%d", &a, &b, &c);
+		if (ret != 3)
+			err = 1;
+	} else
+		err = 1;
+
+	if (err) {
+		a = b = c = 0xff;
+		fprintf(stderr, "Warning: Can't get linux kernel version."
+				"Set the default version to the latest version.\n");
+	}
+
+	return LINUX_VERSION(a, b, c);
+}
+
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
@@ -84,41 +109,37 @@ int main (int argc, char *argv[])
 		if (!isNAND)
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
 		else {
-			struct nand_oobinfo oobinfo;
-
-			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
-				fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", exe_name, mtd_device);
-				return 1;
-			}
+			struct nand_ecclayout ecclayout;
 
-			/* Check for autoplacement */
-			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
-				/* Get the position of the free bytes */
-				if (!oobinfo.oobfree[0][1]) {
-					fprintf (stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+			memset(&ecclayout, 0, sizeof(ecclayout));
+			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+					fprintf(stderr,	"%s: %s: unable to get NAND oob layout\n", \
+							exe_name, mtd_device);
 					return 1;
 				}
-				clmpos = oobinfo.oobfree[0][0];
-				clmlen = oobinfo.oobfree[0][1];
-				if (clmlen > 8)
-					clmlen = 8;
 			} else {
-				/* Legacy mode */
-				switch (meminfo.oobsize) {
-					case 8:
-						clmpos = 6;
-						clmlen = 2;
-						break;
-					case 16:
-						clmpos = 8;
-						clmlen = 8;
-						break;
-					case 64:
-						clmpos = 16;
-						clmlen = 8;
-						break;
+				struct nand_oobinfo oi;
+
+				if (ioctl(fd, MEMGETOOBSEL, &oi) != 0) {
+					fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", \
+							exe_name, mtd_device);
+					return 1;
 				}
+				memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+				ecclayout.eccbytes = oi.eccbytes;
+			}
+
+			/* Get the position of the free bytes */
+			if (!ecclayout.oobfree[0].length) {
+				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+				return 1;
 			}
+			clmpos = ecclayout.oobfree[0].offset;
+			clmlen = ecclayout.oobfree[0].length;
+			if (clmlen > 8)
+				clmlen = 8;
 			cleanmarker.totlen = cpu_to_je32(8);
 		}
 		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
-- 
1.5.4.3



From stanley.miao at windriver.com  Sun Jun 20 08:23:00 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Sun, 20 Jun 2010 20:23:00 +0800
Subject: [PATCHv3 3/3] Place the cleanmarker in OOB area according to the mode
	MTD_OOB_AUTO
In-Reply-To: <1277036580-3501-3-git-send-email-stanley.miao@windriver.com>
References: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
	<1277036580-3501-2-git-send-email-stanley.miao@windriver.com>
	<1277036580-3501-3-git-send-email-stanley.miao@windriver.com>
Message-ID: <1277036580-3501-4-git-send-email-stanley.miao@windriver.com>

The jffs2 filesystem writes the cleanmarker according to the mode
MTD_OOB_AUTO, so flash_eraseall should arrange the layout of the
cleanmarker according to the mode MTD_OOB_AUTO too.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   40 ++++++++++++++++++++++------------------
 1 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index b8068c0..374edd7 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -34,7 +34,7 @@
 #include <time.h>
 #include <getopt.h>
 #include <sys/ioctl.h>
-#include <sys/mount.h>
+#include <sys/param.h>
 #include <sys/utsname.h>
 #include "crc32.h"
 
@@ -83,9 +83,11 @@ static int get_linux_version(void)
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
-	int fd, clmpos = 0, clmlen = 8;
+	int fd;
 	erase_info_t erase;
 	int isNAND, bbtest = 1;
+	unsigned char oobbuf[128];
+	memset(oobbuf, 0xFF, 128);
 
 	process_options(argc, argv);
 
@@ -106,11 +108,18 @@ int main (int argc, char *argv[])
 	if (jffs2) {
 		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
 		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-		if (!isNAND)
+		if (!isNAND) {
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
-		else {
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+		} else {
+			int already_read, num, i, start;
 			struct nand_ecclayout ecclayout;
 
+			cleanmarker.totlen = cpu_to_je32(8);
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+
 			memset(&ecclayout, 0, sizeof(ecclayout));
 			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
 				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
@@ -130,19 +139,14 @@ int main (int argc, char *argv[])
 				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
 				ecclayout.eccbytes = oi.eccbytes;
 			}
-
-			/* Get the position of the free bytes */
-			if (!ecclayout.oobfree[0].length) {
-				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
-				return 1;
+			already_read = 0;
+			for (i = 0; (already_read < 8) && ecclayout.oobfree[i].length; i++) {
+				num = MIN(8 - already_read, ecclayout.oobfree[i].length);
+				start = ecclayout.oobfree[i].offset;
+				memcpy(oobbuf + start, (unsigned char *)&cleanmarker + already_read, num);
+				already_read += num;
 			}
-			clmpos = ecclayout.oobfree[0].offset;
-			clmlen = ecclayout.oobfree[0].length;
-			if (clmlen > 8)
-				clmlen = 8;
-			cleanmarker.totlen = cpu_to_je32(8);
 		}
-		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
 	}
 
 	for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) {
@@ -182,9 +186,9 @@ int main (int argc, char *argv[])
 		/* write cleanmarker */
 		if (isNAND) {
 			struct mtd_oob_buf oob;
-			oob.ptr = (unsigned char *) &cleanmarker;
-			oob.start = erase.start + clmpos;
-			oob.length = clmlen;
+			oob.ptr = oobbuf;
+			oob.start = erase.start;
+			oob.length = meminfo.oobsize;
 			if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
 				fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
 				continue;
-- 
1.5.4.3



From Barry.Song at analog.com  Sun Jun 20 22:42:21 2010
From: Barry.Song at analog.com (Song, Barry)
Date: Mon, 21 Jun 2010 10:42:21 +0800
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: Reworkprobing/JEDEC
	code
In-Reply-To: <20100618133212.GA5276@oksana.dev.rtsoft.ru>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru><20090818214622.GA22651@oksana.dev.rtsoft.ru><AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
Message-ID: <0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>

 

>-----Original Message-----
>From: uclinux-dist-devel-bounces at blackfin.uclinux.org 
>[mailto:uclinux-dist-devel-bounces at blackfin.uclinux.org] On 
>Behalf Of Anton Vorontsov
>Sent: Friday, June 18, 2010 9:32 PM
>To: Barry Song
>Cc: David Brownell; Artem Bityutskiy; 
>linux-kernel at vger.kernel.org; linuxppc-dev at ozlabs.org; 
>linux-mtd at lists.infradead.org; 
>uclinux-dist-devel at blackfin.uclinux.org; Andrew Morton
>Subject: Re: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: 
>Reworkprobing/JEDEC code
>
>On Sat, Jun 12, 2010 at 02:27:12PM +0800, Barry Song wrote:
>> On Wed, Aug 19, 2009 at 5:46 AM, Anton Vorontsov
>> <avorontsov at ru.mvista.com> wrote:
>> >
>> > Previosly the driver always tried JEDEC probing, assuming 
>that non-JEDEC
>> > chips will return '0'. But truly non-JEDEC chips (like 
>CAT25) won't do
>> > that, their behaviour on RDID command is undefined, so the 
>driver should
>> > not call jedec_probe() for these chips.
>> >
>> > Also, be less strict on error conditions, don't fail to 
>probe if JEDEC
>> > found a chip that is different from what platform code 
>told, instead
>> > just print some warnings and use an information obtained 
>via JEDEC. In
>> This patch caused a problem:
>> even though the external flash doesn't exist, it will still pass the
>> probe() and be registerred into kernel and given the partition table.
>> You may refer to this bug report:
>> 
>http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?ac
>tion=TrackerItemEdit&tracker_item_id=5975&start=0
>
>Thanks for the report.
>
>There's little we can do about it. Platform code asked us
>to register the device, and JEDEC probing of M25Pxx chips isn't
>reliable (thanks to various vendors that make these JEDEC and
>non-JEDEC variants), so the best thing we can do is to register
>the chip anyway.
>
>OTOH, if the board pulls MISO line up, then the following patch
>should help.
Make sense with pullup to keep the value high while external device
doesn't exist.
>
>If this won't work, we'll have to add some flag to the platform
>data, i.e. to force JEDEC probing, and not trust platform data.

How about we add a non_jedec flag in platform_data, if the flag is 1, we
let the detection pass even though the ID is 0? Otherwise, we need a
valid ID?

>
>Not-yet-Signed-off-by: Anton Vorontsov <cbouatmailru at gmail.com>
>---
>
>diff --git a/drivers/mtd/devices/m25p80.c 
>b/drivers/mtd/devices/m25p80.c
>index 81e49a9..a307929 100644
>--- a/drivers/mtd/devices/m25p80.c
>+++ b/drivers/mtd/devices/m25p80.c
>@@ -16,6 +16,7 @@
>  */
> 
> #include <linux/init.h>
>+#include <linux/errno.h>
> #include <linux/module.h>
> #include <linux/device.h>
> #include <linux/interrupt.h>
>@@ -723,7 +724,7 @@ static const struct spi_device_id 
>*__devinit jedec_probe(struct spi_device *spi)
> 	if (tmp < 0) {
> 		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading 
>JEDEC ID\n",
> 			dev_name(&spi->dev), tmp);
>-		return NULL;
>+		return ERR_PTR(tmp);
> 	}
> 	jedec = id[0];
> 	jedec = jedec << 8;
>@@ -737,7 +738,7 @@ static const struct spi_device_id 
>*__devinit jedec_probe(struct spi_device *spi)
> 	 * exist for non-JEDEC chips, but for compatibility 
>they return ID 0.
> 	 */
> 	if (jedec == 0)
>-		return NULL;
>+		return ERR_PTR(-EEXIST);
> 
> 	ext_jedec = id[3] << 8 | id[4];
> 
>@@ -749,7 +750,7 @@ static const struct spi_device_id 
>*__devinit jedec_probe(struct spi_device *spi)
> 			return &m25p_ids[tmp];
> 		}
> 	}
>-	return NULL;
>+	return ERR_PTR(-ENODEV);
> }
> 
> 
>@@ -794,9 +795,11 @@ static int __devinit m25p_probe(struct 
>spi_device *spi)
> 		const struct spi_device_id *jid;
> 
> 		jid = jedec_probe(spi);
>-		if (!jid) {
>+		if (IS_ERR(jid) && PTR_ERR(jid) == -EEXIST) {
> 			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> 				 id->name);
>+		} else if (IS_ERR(jid)) {
>+			return PTR_ERR(jid);
> 		} else if (jid != id) {
> 			/*
> 			 * JEDEC knows better, so overwrite 
>platform ID. We
>_______________________________________________
>Uclinux-dist-devel mailing list
>Uclinux-dist-devel at blackfin.uclinux.org
>https://blackfin.uclinux.org/mailman/listinfo/uclinux-dist-devel
>


From xiangfu.z at gmail.com  Sun Jun 20 22:56:10 2010
From: xiangfu.z at gmail.com (Xiangfu Liu)
Date: Mon, 21 Jun 2010 10:56:10 +0800
Subject: [PATCH v2 00/26] Add support for the Ingenic JZ4740
	System-on-a-Chip
In-Reply-To: <20100620092610.GA4950@alpha.franken.de>
References: <1276924111-11158-1-git-send-email-lars@metafoo.de>
	<20100620092610.GA4950@alpha.franken.de>
Message-ID: <4C1ED4CA.9030906@gmail.com>

On 06/20/2010 05:26 PM, Thomas Bogendoerfer wrote:
> great stuff. I have a JZ4730 based netbook, for which I started magling
> the provided sources quite some time ago, but I didn't reach the
> point of submitting patches... there are a lot of common stuff between
> JZ4730 and JZ4740 so IMHO it would be a good thing not to nail
> everthing to JZ4740 namewise. It might also a good idea to select
> something like arch/mips/jzrisc as base directory, put the

Hi Thomas

I would advice "xburst" instead jzrisc. because the Ingenic call
their cpu "XBurst" series. like: XBurst JZ4740, XBurst JZ4750 ...


> factored out code there and add JZ4730/JZ4740 in either seperate
> files or directories.


-- 
Best Regards
Xiangfu Liu
http://www.openmobilefree.net


From 21cnbao at gmail.com  Sun Jun 20 23:27:31 2010
From: 21cnbao at gmail.com (Barry Song)
Date: Mon, 21 Jun 2010 11:27:31 +0800
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: Reworkprobing/JEDEC
	code
In-Reply-To: <0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru> 
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com> 
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
Message-ID: <AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com>

On Mon, Jun 21, 2010 at 10:42 AM, Song, Barry <Barry.Song at analog.com> wrote:
>
>
>>-----Original Message-----
>>From: uclinux-dist-devel-bounces at blackfin.uclinux.org
>>[mailto:uclinux-dist-devel-bounces at blackfin.uclinux.org] On
>>Behalf Of Anton Vorontsov
>>Sent: Friday, June 18, 2010 9:32 PM
>>To: Barry Song
>>Cc: David Brownell; Artem Bityutskiy;
>>linux-kernel at vger.kernel.org; linuxppc-dev at ozlabs.org;
>>linux-mtd at lists.infradead.org;
>>uclinux-dist-devel at blackfin.uclinux.org; Andrew Morton
>>Subject: Re: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80:
>>Reworkprobing/JEDEC code
>>
>>On Sat, Jun 12, 2010 at 02:27:12PM +0800, Barry Song wrote:
>>> On Wed, Aug 19, 2009 at 5:46 AM, Anton Vorontsov
>>> <avorontsov at ru.mvista.com> wrote:
>>> >
>>> > Previosly the driver always tried JEDEC probing, assuming
>>that non-JEDEC
>>> > chips will return '0'. But truly non-JEDEC chips (like
>>CAT25) won't do
>>> > that, their behaviour on RDID command is undefined, so the
>>driver should
>>> > not call jedec_probe() for these chips.
>>> >
>>> > Also, be less strict on error conditions, don't fail to
>>probe if JEDEC
>>> > found a chip that is different from what platform code
>>told, instead
>>> > just print some warnings and use an information obtained
>>via JEDEC. In
>>> This patch caused a problem:
>>> even though the external flash doesn't exist, it will still pass the
>>> probe() and be registerred into kernel and given the partition table.
>>> You may refer to this bug report:
>>>
>>http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?ac
>>tion=TrackerItemEdit&tracker_item_id=5975&start=0
>>
>>Thanks for the report.
>>
>>There's little we can do about it. Platform code asked us
>>to register the device, and JEDEC probing of M25Pxx chips isn't
>>reliable (thanks to various vendors that make these JEDEC and
>>non-JEDEC variants), so the best thing we can do is to register
>>the chip anyway.
>>
>>OTOH, if the board pulls MISO line up, then the following patch
>>should help.
> Make sense with pullup to keep the value high while external device
> doesn't exist.
>>
>>If this won't work, we'll have to add some flag to the platform
>>data, i.e. to force JEDEC probing, and not trust platform data.
>
> How about we add a non_jedec flag in platform_data, if the flag is 1, we
> let the detection pass even though the ID is 0? Otherwise, we need a
> valid ID?
Here i mean:
Index: drivers/mtd/devices/m25p80.c
===================================================================
--- drivers/mtd/devices/m25p80.c	(revision 8927)
+++ drivers/mtd/devices/m25p80.c	(revision 8929)
@@ -795,8 +795,13 @@

 		jid = jedec_probe(spi);
 		if (!jid) {
-			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
-				 id->name);
+			if (!data->non_jedec) {
+				dev_err(&spi->dev, "fail to detect%s\n",
+						id->name);
+				return -ENODEV;
+			} else
+				dev_info(&spi->dev, "non-JEDEC variant of %s\n",
+						id->name);
 		} else if (jid != id) {
 			/*
 			 * JEDEC knows better, so overwrite platform ID. We
Index: include/linux/spi/flash.h
===================================================================
--- include/linux/spi/flash.h	(revision 8927)
+++ include/linux/spi/flash.h	(revision 8929)
@@ -25,6 +25,11 @@

 	char		*type;

+	/*
+	 * For non-JEDEC, id will be 0. In this case, we can't be sure
+	 * whether the flash exists with runtime probing.
+	 */
+	int             non_jedec;
 	/* we'll likely add more ... use JEDEC IDs, etc */
 };

>
>>
>>Not-yet-Signed-off-by: Anton Vorontsov <cbouatmailru at gmail.com>
>>---
>>
>>diff --git a/drivers/mtd/devices/m25p80.c
>>b/drivers/mtd/devices/m25p80.c
>>index 81e49a9..a307929 100644
>>--- a/drivers/mtd/devices/m25p80.c
>>+++ b/drivers/mtd/devices/m25p80.c
>>@@ -16,6 +16,7 @@
>> ?*/
>>
>> #include <linux/init.h>
>>+#include <linux/errno.h>
>> #include <linux/module.h>
>> #include <linux/device.h>
>> #include <linux/interrupt.h>
>>@@ -723,7 +724,7 @@ static const struct spi_device_id
>>*__devinit jedec_probe(struct spi_device *spi)
>> ? ? ? if (tmp < 0) {
>> ? ? ? ? ? ? ? DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading
>>JEDEC ID\n",
>> ? ? ? ? ? ? ? ? ? ? ? dev_name(&spi->dev), tmp);
>>- ? ? ? ? ? ? ?return NULL;
>>+ ? ? ? ? ? ? ?return ERR_PTR(tmp);
>> ? ? ? }
>> ? ? ? jedec = id[0];
>> ? ? ? jedec = jedec << 8;
>>@@ -737,7 +738,7 @@ static const struct spi_device_id
>>*__devinit jedec_probe(struct spi_device *spi)
>> ? ? ? ?* exist for non-JEDEC chips, but for compatibility
>>they return ID 0.
>> ? ? ? ?*/
>> ? ? ? if (jedec == 0)
>>- ? ? ? ? ? ? ?return NULL;
>>+ ? ? ? ? ? ? ?return ERR_PTR(-EEXIST);
>>
>> ? ? ? ext_jedec = id[3] << 8 | id[4];
>>
>>@@ -749,7 +750,7 @@ static const struct spi_device_id
>>*__devinit jedec_probe(struct spi_device *spi)
>> ? ? ? ? ? ? ? ? ? ? ? return &m25p_ids[tmp];
>> ? ? ? ? ? ? ? }
>> ? ? ? }
>>- ? ? ?return NULL;
>>+ ? ? ?return ERR_PTR(-ENODEV);
>> }
>>
>>
>>@@ -794,9 +795,11 @@ static int __devinit m25p_probe(struct
>>spi_device *spi)
>> ? ? ? ? ? ? ? const struct spi_device_id *jid;
>>
>> ? ? ? ? ? ? ? jid = jedec_probe(spi);
>>- ? ? ? ? ? ? ?if (!jid) {
>>+ ? ? ? ? ? ? ?if (IS_ERR(jid) && PTR_ERR(jid) == -EEXIST) {
>> ? ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?id->name);
>>+ ? ? ? ? ? ? ?} else if (IS_ERR(jid)) {
>>+ ? ? ? ? ? ? ? ? ? ? ?return PTR_ERR(jid);
>> ? ? ? ? ? ? ? } else if (jid != id) {
>> ? ? ? ? ? ? ? ? ? ? ? /*
>> ? ? ? ? ? ? ? ? ? ? ? ?* JEDEC knows better, so overwrite
>>platform ID. We
>>_______________________________________________
>>Uclinux-dist-devel mailing list
>>Uclinux-dist-devel at blackfin.uclinux.org
>>https://blackfin.uclinux.org/mailman/listinfo/uclinux-dist-devel
>>
>


From cbouatmailru at gmail.com  Mon Jun 21 03:15:51 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Mon, 21 Jun 2010 11:15:51 +0400
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80:
	Reworkprobing/JEDEC code
In-Reply-To: <AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru>
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com>
Message-ID: <20100621071551.GA16109@oksana.dev.rtsoft.ru>

On Mon, Jun 21, 2010 at 11:27:31AM +0800, Barry Song wrote:
[...]
> > How about we add a non_jedec flag in platform_data, if the flag is 1, we
> > let the detection pass even though the ID is 0? Otherwise, we need a
> > valid ID?
> Here i mean:

This will break at least OF-enabled platforms (e.g. PowerPC),
they assume that the driver will success for non-JEDEC flashes.
OF platforms don't pass platform data, and even if they did,
device tree doesn't specify if the flash is JEDEC or non-JEDEC.

Which is why I think that, by default, the driver should
successfully register the flash even if JEDEC probe fails. So,
instead of checking for "!non_jedec", I would recommend
"force_jedec" check.

> Index: drivers/mtd/devices/m25p80.c
> ===================================================================
> --- drivers/mtd/devices/m25p80.c	(revision 8927)
> +++ drivers/mtd/devices/m25p80.c	(revision 8929)
> @@ -795,8 +795,13 @@
> 
>  		jid = jedec_probe(spi);
>  		if (!jid) {
> -			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> -				 id->name);
> +			if (!data->non_jedec) {
> +				dev_err(&spi->dev, "fail to detect%s\n",
> +						id->name);
> +				return -ENODEV;
> +			} else
> +				dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> +						id->name);
>  		} else if (jid != id) {

-- 
Anton Vorontsov
email: cbouatmailru at gmail.com
irc://irc.freenode.net/bd2


From 21cnbao at gmail.com  Mon Jun 21 03:22:48 2010
From: 21cnbao at gmail.com (Barry Song)
Date: Mon, 21 Jun 2010 15:22:48 +0800
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: Reworkprobing/JEDEC
	code
In-Reply-To: <20100621071551.GA16109@oksana.dev.rtsoft.ru>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru> 
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com> 
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com> 
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
Message-ID: <AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com>

On Mon, Jun 21, 2010 at 3:15 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
> On Mon, Jun 21, 2010 at 11:27:31AM +0800, Barry Song wrote:
> [...]
>> > How about we add a non_jedec flag in platform_data, if the flag is 1, we
>> > let the detection pass even though the ID is 0? Otherwise, we need a
>> > valid ID?
>> Here i mean:
>
> This will break at least OF-enabled platforms (e.g. PowerPC),
> they assume that the driver will success for non-JEDEC flashes.
> OF platforms don't pass platform data, and even if they did,
> device tree doesn't specify if the flash is JEDEC or non-JEDEC.
>
> Which is why I think that, by default, the driver should
> successfully register the flash even if JEDEC probe fails. So,
> instead of checking for "!non_jedec", I would recommend
> "force_jedec" check.

Mike Frysinger suggested to use non_jedec since most devices are
standard jedec devices. Only if non_jedec=1, we let the detection pass
if ID is 0.

>
>> Index: drivers/mtd/devices/m25p80.c
>> ===================================================================
>> --- drivers/mtd/devices/m25p80.c ? ? ?(revision 8927)
>> +++ drivers/mtd/devices/m25p80.c ? ? ?(revision 8929)
>> @@ -795,8 +795,13 @@
>>
>> ? ? ? ? ? ? ? jid = jedec_probe(spi);
>> ? ? ? ? ? ? ? if (!jid) {
>> - ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?id->name);
>> + ? ? ? ? ? ? ? ? ? ? if (!data->non_jedec) {
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_err(&spi->dev, "fail to detect%s\n",
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id->name);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? return -ENODEV;
>> + ? ? ? ? ? ? ? ? ? ? } else
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id->name);
>> ? ? ? ? ? ? ? } else if (jid != id) {
>
> --
> Anton Vorontsov
> email: cbouatmailru at gmail.com
> irc://irc.freenode.net/bd2
>

From cbouatmailru at gmail.com  Mon Jun 21 03:39:09 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Mon, 21 Jun 2010 11:39:09 +0400
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80:
	Reworkprobing/JEDEC code
In-Reply-To: <AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru>
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com>
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com>
Message-ID: <20100621073909.GA20674@oksana.dev.rtsoft.ru>

On Mon, Jun 21, 2010 at 03:22:48PM +0800, Barry Song wrote:
> On Mon, Jun 21, 2010 at 3:15 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
> > On Mon, Jun 21, 2010 at 11:27:31AM +0800, Barry Song wrote:
> > [...]
> >> > How about we add a non_jedec flag in platform_data, if the flag is 1, we
> >> > let the detection pass even though the ID is 0? Otherwise, we need a
> >> > valid ID?
> >> Here i mean:
> >
> > This will break at least OF-enabled platforms (e.g. PowerPC),
> > they assume that the driver will success for non-JEDEC flashes.
> > OF platforms don't pass platform data, and even if they did,
> > device tree doesn't specify if the flash is JEDEC or non-JEDEC.
> >
> > Which is why I think that, by default, the driver should
> > successfully register the flash even if JEDEC probe fails. So,
> > instead of checking for "!non_jedec", I would recommend
> > "force_jedec" check.
> 
> Mike Frysinger suggested to use non_jedec since most devices are
> standard jedec devices.

Well, on OF platforms most devices that I'm aware of are non-JEDEC.

> Only if non_jedec=1, we let the detection pass
> if ID is 0.

Then please #ifdef it with CONFIG_OF.

Thanks,

> >> Index: drivers/mtd/devices/m25p80.c
> >> ===================================================================
> >> --- drivers/mtd/devices/m25p80.c ? ? ?(revision 8927)
> >> +++ drivers/mtd/devices/m25p80.c ? ? ?(revision 8929)
> >> @@ -795,8 +795,13 @@
> >>
> >> ? ? ? ? ? ? ? jid = jedec_probe(spi);
> >> ? ? ? ? ? ? ? if (!jid) {
> >> - ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?id->name);
> >> + ? ? ? ? ? ? ? ? ? ? if (!data->non_jedec) {
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_err(&spi->dev, "fail to detect%s\n",
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id->name);
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? return -ENODEV;
> >> + ? ? ? ? ? ? ? ? ? ? } else
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id->name);
> >> ? ? ? ? ? ? ? } else if (jid != id) {
> >
> > --
> > Anton Vorontsov
> > email: cbouatmailru at gmail.com
> > irc://irc.freenode.net/bd2
> >

-- 
Anton Vorontsov
email: cbouatmailru at gmail.com
irc://irc.freenode.net/bd2


From 21cnbao at gmail.com  Mon Jun 21 06:31:44 2010
From: 21cnbao at gmail.com (Barry Song)
Date: Mon, 21 Jun 2010 18:31:44 +0800
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: Reworkprobing/JEDEC
	code
In-Reply-To: <20100621073909.GA20674@oksana.dev.rtsoft.ru>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru> 
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com> 
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com> 
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com> 
	<20100621073909.GA20674@oksana.dev.rtsoft.ru>
Message-ID: <AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com>

On Mon, Jun 21, 2010 at 3:39 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
> On Mon, Jun 21, 2010 at 03:22:48PM +0800, Barry Song wrote:
>> On Mon, Jun 21, 2010 at 3:15 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
>> > On Mon, Jun 21, 2010 at 11:27:31AM +0800, Barry Song wrote:
>> > [...]
>> >> > How about we add a non_jedec flag in platform_data, if the flag is 1, we
>> >> > let the detection pass even though the ID is 0? Otherwise, we need a
>> >> > valid ID?
>> >> Here i mean:
>> >
>> > This will break at least OF-enabled platforms (e.g. PowerPC),
>> > they assume that the driver will success for non-JEDEC flashes.
>> > OF platforms don't pass platform data, and even if they did,
>> > device tree doesn't specify if the flash is JEDEC or non-JEDEC.
>> >
>> > Which is why I think that, by default, the driver should
>> > successfully register the flash even if JEDEC probe fails. So,
>> > instead of checking for "!non_jedec", I would recommend
>> > "force_jedec" check.
>>
>> Mike Frysinger suggested to use non_jedec since most devices are
>> standard jedec devices.
>
> Well, on OF platforms most devices that I'm aware of are non-JEDEC.
>
>> Only if non_jedec=1, we let the detection pass
>> if ID is 0.
>
> Then please #ifdef it with CONFIG_OF.
I think the patch has nothing to do with platform. Here SPI Flash is a
peripherals, doesn't depend on any platform. Adding a CONFIG_OF
doesn't make sense very much.
If you think most devices are non-JEDEC, we can change non_JEDEC to
force_JEDEC as you said. But anyway, is that real that most devices
are non_JEDEC?  If not, I think we should change OF platform codes to
fit with this patch.

>
> Thanks,
>
>> >> Index: drivers/mtd/devices/m25p80.c
>> >> ===================================================================
>> >> --- drivers/mtd/devices/m25p80.c ? ? ?(revision 8927)
>> >> +++ drivers/mtd/devices/m25p80.c ? ? ?(revision 8929)
>> >> @@ -795,8 +795,13 @@
>> >>
>> >> ? ? ? ? ? ? ? jid = jedec_probe(spi);
>> >> ? ? ? ? ? ? ? if (!jid) {
>> >> - ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
>> >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?id->name);
>> >> + ? ? ? ? ? ? ? ? ? ? if (!data->non_jedec) {
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_err(&spi->dev, "fail to detect%s\n",
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id->name);
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? return -ENODEV;
>> >> + ? ? ? ? ? ? ? ? ? ? } else
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id->name);
>> >> ? ? ? ? ? ? ? } else if (jid != id) {
>> >
>> > --
>> > Anton Vorontsov
>> > email: cbouatmailru at gmail.com
>> > irc://irc.freenode.net/bd2
>> >
>
> --
> Anton Vorontsov
> email: cbouatmailru at gmail.com
> irc://irc.freenode.net/bd2
>


From cbouatmailru at gmail.com  Mon Jun 21 07:20:49 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Mon, 21 Jun 2010 15:20:49 +0400
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80:
	Reworkprobing/JEDEC code
In-Reply-To: <AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru>
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com>
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com>
	<20100621073909.GA20674@oksana.dev.rtsoft.ru>
	<AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com>
Message-ID: <20100621112049.GA9273@oksana.dev.rtsoft.ru>

On Mon, Jun 21, 2010 at 06:31:44PM +0800, Barry Song wrote:
> On Mon, Jun 21, 2010 at 3:39 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
> > On Mon, Jun 21, 2010 at 03:22:48PM +0800, Barry Song wrote:
> >> On Mon, Jun 21, 2010 at 3:15 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
> >> > On Mon, Jun 21, 2010 at 11:27:31AM +0800, Barry Song wrote:
> >> > [...]
> >> >> > How about we add a non_jedec flag in platform_data, if the flag is 1, we
> >> >> > let the detection pass even though the ID is 0? Otherwise, we need a
> >> >> > valid ID?
> >> >> Here i mean:
> >> >
> >> > This will break at least OF-enabled platforms (e.g. PowerPC),
> >> > they assume that the driver will success for non-JEDEC flashes.
> >> > OF platforms don't pass platform data, and even if they did,
> >> > device tree doesn't specify if the flash is JEDEC or non-JEDEC.
> >> >
> >> > Which is why I think that, by default, the driver should
> >> > successfully register the flash even if JEDEC probe fails. So,
> >> > instead of checking for "!non_jedec", I would recommend
> >> > "force_jedec" check.
> >>
> >> Mike Frysinger suggested to use non_jedec since most devices are
> >> standard jedec devices.
> >
> > Well, on OF platforms most devices that I'm aware of are non-JEDEC.
> >
> >> Only if non_jedec=1, we let the detection pass
> >> if ID is 0.
> >
> > Then please #ifdef it with CONFIG_OF.
> I think the patch has nothing to do with platform. Here SPI Flash is a
> peripherals, doesn't depend on any platform. Adding a CONFIG_OF
> doesn't make sense very much.

With OF we don't place non-existent devices into the device
tree (or we mark them with status = "not-ok/disabled/absent"
property).

> If you think most devices are non-JEDEC, we can change non_JEDEC to
> force_JEDEC as you said.
> But anyway, is that real that most devices are non_JEDEC?

Why would this matter? We have to support both.

> If not, I think we should change OF platform codes to
> fit with this patch.

You can't easily change OF. It's like "let's change ACPI tables
or BIOS in these PCs". Doable, but involves things like reflashing.
And we usually have to support old BIOSes as well.

OTOH, I see (git grep m25p arch/powerpc/boot/dts/) that in
mainline kernel only MPC8569 board has a correct m25p
node, and it is STMicro variant (it is JEDEC capable).

As we don't really have to support out of tree code, I'd
just go with this patch, assuming that we have to change
device tree for boards with non-JEDEC flashes. It's
effectively the same thing as platform data flag, except
that it works automatically for OF platforms.

Signed-off-by: Anton Vorontsov <avorontsov at mvista.com>
---

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 81e49a9..a610ca9 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -680,6 +680,16 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
 	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
 
+	{ "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2, 0) },
+	{ "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4, 0) },
+	{ "m25p20-nonjedec",  INFO(0, 0,  64 * 1024,   4, 0) },
+	{ "m25p40-nonjedec",  INFO(0, 0,  64 * 1024,   8, 0) },
+	{ "m25p80-nonjedec",  INFO(0, 0,  64 * 1024,  16, 0) },
+	{ "m25p16-nonjedec",  INFO(0, 0,  64 * 1024,  32, 0) },
+	{ "m25p32-nonjedec",  INFO(0, 0,  64 * 1024,  64, 0) },
+	{ "m25p64-nonjedec",  INFO(0, 0,  64 * 1024, 128, 0) },
+	{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024,  64, 0) },
+
 	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, 0) },
 	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
 	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
@@ -795,8 +805,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 
 		jid = jedec_probe(spi);
 		if (!jid) {
-			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
-				 id->name);
+			return -ENODEV;
 		} else if (jid != id) {
 			/*
 			 * JEDEC knows better, so overwrite platform ID. We


From tglx at linutronix.de  Mon Jun 21 11:04:34 2010
From: tglx at linutronix.de (Thomas Gleixner)
Date: Mon, 21 Jun 2010 17:04:34 +0200 (CEST)
Subject: Reed Solomon FAQ
Message-ID: <alpine.LFD.2.00.1006211604160.4290@localhost.localdomain>

I got repeatedly questions like the following about Reed Solomon
codes:

> Say we have allocated 8bytes in spare area to store the ECC for 512
> bytes data. And we have to correct upto 4-bit in 512-byte data. And
> would you please let me know how to configure the rs-lib for the
> same? Say we are using the 8-bit data(symbol).

It's impossible to use 8bit symbol width for 512 byte data.

      m = number of bits per symbol
      n = code length in symbols up to 2^(m-1)
      k = original data length in symbols
      r = n - k = number of redundant symbols
      t = 1/2 (n-k) = error correction capability (number of symbols)

So for this use case we get for the kernel rs lib:

   k = 512

So for 512 byte data we need a symbol width of 10. The rs lib in the
kernel handles this in the encode/decode_rs8 functions by expanding
the 8 bit FLASH data to 10 bits internally.

   m = 10

If we can store 8 byte == 64bit of redundant symbols in the spare
area, so the number of redundant symbols is:

   r = 64/10 = 6

And the resulting code lenght is:

   n = k + r = 518

So the max. number of correctable symbols is:

   t = 1/2 * 6 = 3

That might be up to 24 bit of corrected data, when the errors are not
scattered over more than 3 bytes on FLASH.

If errors happen on 4 or more different FLASH bytes, they are
uncorrectable.

The 518/512 (10 bit symbol width) code is the optimum which can be
achieved for 512 byte FLASH read/write chunks with 8 byte of spare
area usage.

To correct 4 symbols in a 512 byte data chunk we need at least 8
redundant symbols, which means 80 bit == 10 bytes storage size in the
spare area.

> Is it possible to correct 4-symbols, by max 9-byte parity?

Yes, but that requires that the 512 byte data is converted into a
serialized bitstream w/o symbol width expansion so 9 bit symbol width
can be used.

    m = 9
    k = 456 [ 512 * 8 / 9 rounded up ]
    r = 8 [ 72 / 9 ]
    t = 4

Such modes are only useful when both the encoding and the decoding are
done in hardware, as serializing / deserializing for the software
en/decoder is making the already slow software RS even more horribly
slow.

As a side note: software RS encoding/decoding is performancewise a bad
idea in general.

Thanks,

	tglx


From vapier.adi at gmail.com  Mon Jun 21 12:34:05 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 21 Jun 2010 12:34:05 -0400
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: Reworkprobing/JEDEC
	code
In-Reply-To: <20100621112049.GA9273@oksana.dev.rtsoft.ru>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru> 
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com> 
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com> 
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com> 
	<20100621073909.GA20674@oksana.dev.rtsoft.ru>
	<AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com> 
	<20100621112049.GA9273@oksana.dev.rtsoft.ru>
Message-ID: <AANLkTinvHrjD-gwCMQIgaC4WqAbdXNstdNff2_C28byx@mail.gmail.com>

On Mon, Jun 21, 2010 at 07:20, Anton Vorontsov wrote:
> You can't easily change OF. It's like "let's change ACPI tables
> or BIOS in these PCs". Doable, but involves things like reflashing.
> And we usually have to support old BIOSes as well.
>
> OTOH, I see (git grep m25p arch/powerpc/boot/dts/) that in
> mainline kernel only MPC8569 board has a correct m25p
> node, and it is STMicro variant (it is JEDEC capable).
>
> As we don't really have to support out of tree code, I'd
> just go with this patch, assuming that we have to change
> device tree for boards with non-JEDEC flashes. It's
> effectively the same thing as platform data flag, except
> that it works automatically for OF platforms.
>
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index 81e49a9..a610ca9 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -680,6 +680,16 @@ static const struct spi_device_id m25p_ids[] = {
> ? ? ? ?{ "m25p64", ?INFO(0x202017, ?0, ?64 * 1024, 128, 0) },
> ? ? ? ?{ "m25p128", INFO(0x202018, ?0, 256 * 1024, ?64, 0) },
>
> + ? ? ? { "m25p05-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 2, 0) },
> + ? ? ? { "m25p10-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 4, 0) },
> + ? ? ? { "m25p20-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 4, 0) },
> + ? ? ? { "m25p40-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 8, 0) },
> + ? ? ? { "m25p80-nonjedec", ?INFO(0, 0, ?64 * 1024, ?16, 0) },
> + ? ? ? { "m25p16-nonjedec", ?INFO(0, 0, ?64 * 1024, ?32, 0) },
> + ? ? ? { "m25p32-nonjedec", ?INFO(0, 0, ?64 * 1024, ?64, 0) },
> + ? ? ? { "m25p64-nonjedec", ?INFO(0, 0, ?64 * 1024, 128, 0) },
> + ? ? ? { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, ?64, 0) },
> +

are you picking the m25p because its flash geometry matches whatever
you're using, or because you have some weird variant of the m25p that
has JEDEC commands removed ?
-mike


From cbouatmailru at gmail.com  Mon Jun 21 12:47:32 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Mon, 21 Jun 2010 20:47:32 +0400
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80:
	Reworkprobing/JEDEC code
In-Reply-To: <AANLkTinvHrjD-gwCMQIgaC4WqAbdXNstdNff2_C28byx@mail.gmail.com>
References: <AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com>
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com>
	<20100621073909.GA20674@oksana.dev.rtsoft.ru>
	<AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com>
	<20100621112049.GA9273@oksana.dev.rtsoft.ru>
	<AANLkTinvHrjD-gwCMQIgaC4WqAbdXNstdNff2_C28byx@mail.gmail.com>
Message-ID: <20100621164732.GA2725@oksana.dev.rtsoft.ru>

On Mon, Jun 21, 2010 at 12:34:05PM -0400, Mike Frysinger wrote:
> On Mon, Jun 21, 2010 at 07:20, Anton Vorontsov wrote:
> > You can't easily change OF. It's like "let's change ACPI tables
> > or BIOS in these PCs". Doable, but involves things like reflashing.
> > And we usually have to support old BIOSes as well.
> >
> > OTOH, I see (git grep m25p arch/powerpc/boot/dts/) that in
> > mainline kernel only MPC8569 board has a correct m25p
> > node, and it is STMicro variant (it is JEDEC capable).
> >
> > As we don't really have to support out of tree code, I'd
> > just go with this patch, assuming that we have to change
> > device tree for boards with non-JEDEC flashes. It's
> > effectively the same thing as platform data flag, except
> > that it works automatically for OF platforms.
> >
> > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> > index 81e49a9..a610ca9 100644
> > --- a/drivers/mtd/devices/m25p80.c
> > +++ b/drivers/mtd/devices/m25p80.c
> > @@ -680,6 +680,16 @@ static const struct spi_device_id m25p_ids[] = {
> > ? ? ? ?{ "m25p64", ?INFO(0x202017, ?0, ?64 * 1024, 128, 0) },
> > ? ? ? ?{ "m25p128", INFO(0x202018, ?0, 256 * 1024, ?64, 0) },
> >
> > + ? ? ? { "m25p05-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 2, 0) },
> > + ? ? ? { "m25p10-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 4, 0) },
> > + ? ? ? { "m25p20-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 4, 0) },
> > + ? ? ? { "m25p40-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 8, 0) },
> > + ? ? ? { "m25p80-nonjedec", ?INFO(0, 0, ?64 * 1024, ?16, 0) },
> > + ? ? ? { "m25p16-nonjedec", ?INFO(0, 0, ?64 * 1024, ?32, 0) },
> > + ? ? ? { "m25p32-nonjedec", ?INFO(0, 0, ?64 * 1024, ?64, 0) },
> > + ? ? ? { "m25p64-nonjedec", ?INFO(0, 0, ?64 * 1024, 128, 0) },
> > + ? ? ? { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, ?64, 0) },
> > +
> 
> are you picking the m25p because its flash geometry matches whatever
> you're using, or because you have some weird variant of the m25p that
> has JEDEC commands removed ?

The latter. It's Numonyx M25Pxx flashes, see
http://www.numonyx.com/Documents/Datasheets/M25P80.pdf

   The RDID instruction is available only for parts made with 110
   nm Technology identified with Process letter '4'.

-- 
Anton Vorontsov
email: cbouatmailru at gmail.com
irc://irc.freenode.net/bd2


From vapier.adi at gmail.com  Mon Jun 21 12:54:29 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 21 Jun 2010 12:54:29 -0400
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: Reworkprobing/JEDEC
	code
In-Reply-To: <20100621164732.GA2725@oksana.dev.rtsoft.ru>
References: <AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com> 
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com> 
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com> 
	<20100621073909.GA20674@oksana.dev.rtsoft.ru>
	<AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com> 
	<20100621112049.GA9273@oksana.dev.rtsoft.ru>
	<AANLkTinvHrjD-gwCMQIgaC4WqAbdXNstdNff2_C28byx@mail.gmail.com> 
	<20100621164732.GA2725@oksana.dev.rtsoft.ru>
Message-ID: <AANLkTimWHFak52cs7nv2DcRnaJkgi6xSXJKCJ-N5jAwD@mail.gmail.com>

On Mon, Jun 21, 2010 at 12:47, Anton Vorontsov wrote:
> On Mon, Jun 21, 2010 at 12:34:05PM -0400, Mike Frysinger wrote:
>> On Mon, Jun 21, 2010 at 07:20, Anton Vorontsov wrote:
>> > You can't easily change OF. It's like "let's change ACPI tables
>> > or BIOS in these PCs". Doable, but involves things like reflashing.
>> > And we usually have to support old BIOSes as well.
>> >
>> > OTOH, I see (git grep m25p arch/powerpc/boot/dts/) that in
>> > mainline kernel only MPC8569 board has a correct m25p
>> > node, and it is STMicro variant (it is JEDEC capable).
>> >
>> > As we don't really have to support out of tree code, I'd
>> > just go with this patch, assuming that we have to change
>> > device tree for boards with non-JEDEC flashes. It's
>> > effectively the same thing as platform data flag, except
>> > that it works automatically for OF platforms.
>> >
>> > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
>> > index 81e49a9..a610ca9 100644
>> > --- a/drivers/mtd/devices/m25p80.c
>> > +++ b/drivers/mtd/devices/m25p80.c
>> > @@ -680,6 +680,16 @@ static const struct spi_device_id m25p_ids[] = {
>> > ? ? ? ?{ "m25p64", ?INFO(0x202017, ?0, ?64 * 1024, 128, 0) },
>> > ? ? ? ?{ "m25p128", INFO(0x202018, ?0, 256 * 1024, ?64, 0) },
>> >
>> > + ? ? ? { "m25p05-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 2, 0) },
>> > + ? ? ? { "m25p10-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 4, 0) },
>> > + ? ? ? { "m25p20-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 4, 0) },
>> > + ? ? ? { "m25p40-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 8, 0) },
>> > + ? ? ? { "m25p80-nonjedec", ?INFO(0, 0, ?64 * 1024, ?16, 0) },
>> > + ? ? ? { "m25p16-nonjedec", ?INFO(0, 0, ?64 * 1024, ?32, 0) },
>> > + ? ? ? { "m25p32-nonjedec", ?INFO(0, 0, ?64 * 1024, ?64, 0) },
>> > + ? ? ? { "m25p64-nonjedec", ?INFO(0, 0, ?64 * 1024, 128, 0) },
>> > + ? ? ? { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, ?64, 0) },
>> > +
>>
>> are you picking the m25p because its flash geometry matches whatever
>> you're using, or because you have some weird variant of the m25p that
>> has JEDEC commands removed ?
>
> The latter. It's Numonyx M25Pxx flashes, see
> http://www.numonyx.com/Documents/Datasheets/M25P80.pdf
>
> ? The RDID instruction is available only for parts made with 110
> ? nm Technology identified with Process letter '4'.

lovely.  i guess this patch is the way to go to satisfy everyone's
requirements.  i'm also of the mindset that a mtd should not be
created if the SPI flash isnt there simply because the resources say
it might be.
-mike


From 21cnbao at gmail.com  Tue Jun 22 02:37:52 2010
From: 21cnbao at gmail.com (Barry Song)
Date: Tue, 22 Jun 2010 14:37:52 +0800
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80: Reworkprobing/JEDEC
	code
In-Reply-To: <20100621112049.GA9273@oksana.dev.rtsoft.ru>
References: <20090818214449.GA12848@oksana.dev.rtsoft.ru>
	<20090818214622.GA22651@oksana.dev.rtsoft.ru> 
	<AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com> 
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com> 
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com> 
	<20100621073909.GA20674@oksana.dev.rtsoft.ru>
	<AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com> 
	<20100621112049.GA9273@oksana.dev.rtsoft.ru>
Message-ID: <AANLkTikY9pfHsQ6xeVkixKF5kqL2nLyV2kgcR2iJKhG-@mail.gmail.com>

On Mon, Jun 21, 2010 at 7:20 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
> On Mon, Jun 21, 2010 at 06:31:44PM +0800, Barry Song wrote:
>> On Mon, Jun 21, 2010 at 3:39 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
>> > On Mon, Jun 21, 2010 at 03:22:48PM +0800, Barry Song wrote:
>> >> On Mon, Jun 21, 2010 at 3:15 PM, Anton Vorontsov <cbouatmailru at gmail.com> wrote:
>> >> > On Mon, Jun 21, 2010 at 11:27:31AM +0800, Barry Song wrote:
>> >> > [...]
>> >> >> > How about we add a non_jedec flag in platform_data, if the flag is 1, we
>> >> >> > let the detection pass even though the ID is 0? Otherwise, we need a
>> >> >> > valid ID?
>> >> >> Here i mean:
>> >> >
>> >> > This will break at least OF-enabled platforms (e.g. PowerPC),
>> >> > they assume that the driver will success for non-JEDEC flashes.
>> >> > OF platforms don't pass platform data, and even if they did,
>> >> > device tree doesn't specify if the flash is JEDEC or non-JEDEC.
>> >> >
>> >> > Which is why I think that, by default, the driver should
>> >> > successfully register the flash even if JEDEC probe fails. So,
>> >> > instead of checking for "!non_jedec", I would recommend
>> >> > "force_jedec" check.
>> >>
>> >> Mike Frysinger suggested to use non_jedec since most devices are
>> >> standard jedec devices.
>> >
>> > Well, on OF platforms most devices that I'm aware of are non-JEDEC.
>> >
>> >> Only if non_jedec=1, we let the detection pass
>> >> if ID is 0.
>> >
>> > Then please #ifdef it with CONFIG_OF.
>> I think the patch has nothing to do with platform. Here SPI Flash is a
>> peripherals, doesn't depend on any platform. Adding a CONFIG_OF
>> doesn't make sense very much.
>
> With OF we don't place non-existent devices into the device
> tree (or we mark them with status = "not-ok/disabled/absent"
> property).
>
>> If you think most devices are non-JEDEC, we can change non_JEDEC to
>> force_JEDEC as you said.
>> But anyway, is that real that most devices are non_JEDEC?
>
> Why would this matter? We have to support both.
>
>> If not, I think we should change OF platform codes to
>> fit with this patch.
>
> You can't easily change OF. It's like "let's change ACPI tables
> or BIOS in these PCs". Doable, but involves things like reflashing.
> And we usually have to support old BIOSes as well.
>
> OTOH, I see (git grep m25p arch/powerpc/boot/dts/) that in
> mainline kernel only MPC8569 board has a correct m25p
> node, and it is STMicro variant (it is JEDEC capable).
>
> As we don't really have to support out of tree code, I'd
> just go with this patch, assuming that we have to change
> device tree for boards with non-JEDEC flashes. It's
> effectively the same thing as platform data flag, except
> that it works automatically for OF platforms.
>
> Signed-off-by: Anton Vorontsov <avorontsov at mvista.com>
> ---
>
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index 81e49a9..a610ca9 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -680,6 +680,16 @@ static const struct spi_device_id m25p_ids[] = {
> ? ? ? ?{ "m25p64", ?INFO(0x202017, ?0, ?64 * 1024, 128, 0) },
> ? ? ? ?{ "m25p128", INFO(0x202018, ?0, 256 * 1024, ?64, 0) },
>
> + ? ? ? { "m25p05-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 2, 0) },
> + ? ? ? { "m25p10-nonjedec", ?INFO(0, 0, ?32 * 1024, ? 4, 0) },
> + ? ? ? { "m25p20-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 4, 0) },
> + ? ? ? { "m25p40-nonjedec", ?INFO(0, 0, ?64 * 1024, ? 8, 0) },
> + ? ? ? { "m25p80-nonjedec", ?INFO(0, 0, ?64 * 1024, ?16, 0) },
> + ? ? ? { "m25p16-nonjedec", ?INFO(0, 0, ?64 * 1024, ?32, 0) },
> + ? ? ? { "m25p32-nonjedec", ?INFO(0, 0, ?64 * 1024, ?64, 0) },
> + ? ? ? { "m25p64-nonjedec", ?INFO(0, 0, ?64 * 1024, 128, 0) },
> + ? ? ? { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, ?64, 0) },
> +
> ? ? ? ?{ "m45pe10", INFO(0x204011, ?0, 64 * 1024, ? ?2, 0) },
> ? ? ? ?{ "m45pe80", INFO(0x204014, ?0, 64 * 1024, ? 16, 0) },
> ? ? ? ?{ "m45pe16", INFO(0x204015, ?0, 64 * 1024, ? 32, 0) },
> @@ -795,8 +805,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
>
> ? ? ? ? ? ? ? ?jid = jedec_probe(spi);
> ? ? ? ? ? ? ? ?if (!jid) {
> - ? ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?id->name);
> + ? ? ? ? ? ? ? ? ? ? ? return -ENODEV;
The patch looks good to me. Only problem is NULL is also returned by
spi_write_then_read() fail:
static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
{
        int                     tmp;
        u8                      code = OPCODE_RDID;
        u8                      id[5];
        u32                     jedec;
        u16                     ext_jedec;
        struct flash_info       *info;

        /* JEDEC also defines an optional "extended device information"
         * string for after vendor-specific data, after the three bytes
         * we use here.  Supporting some chips might require using it.
         */
        tmp = spi_write_then_read(spi, &code, 1, id, 5);
        if (tmp < 0) {
                DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
                        dev_name(&spi->dev), tmp);
                return NULL;
        }
...
}

Here much better for -EIO (return tmp)?

> ? ? ? ? ? ? ? ?} else if (jid != id) {
> ? ? ? ? ? ? ? ? ? ? ? ?/*
> ? ? ? ? ? ? ? ? ? ? ? ? * JEDEC knows better, so overwrite platform ID. We
>


From ext-andriy.shevchenko at nokia.com  Thu Jun 17 04:42:37 2010
From: ext-andriy.shevchenko at nokia.com (Shevchenko Andriy (EXT-Teleca/Helsinki))
Date: Thu, 17 Jun 2010 10:42:37 +0200
Subject: [PATCH 1/3] mkfs.ubifs: check output first
Message-ID: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko at nokia.com>
---
 mkfs.ubifs/mkfs.ubifs.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index e4b4e3c..9061453 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -647,8 +647,11 @@ static int get_options(int argc, char**argv)
 
 	if (optind != argc && !output)
 		output = strdup(argv[optind]);
-	if (output)
-		out_ubi = !open_ubi(output);
+
+	if (!output)
+		return err_msg("not output device or file specified");
+
+	out_ubi = !open_ubi(output);
 
 	if (out_ubi) {
 		c->min_io_size = c->di.min_io_size;
@@ -656,9 +659,6 @@ static int get_options(int argc, char**argv)
 		c->max_leb_cnt = c->vi.rsvd_lebs;
 	}
 
-	if (!output)
-		return err_msg("not output device or file specified");
-
 	if (c->min_io_size == -1)
 		return err_msg("min. I/O unit was not specified "
 			       "(use -h for help)");
-- 
1.6.3.3



From ext-andriy.shevchenko at nokia.com  Thu Jun 17 04:42:38 2010
From: ext-andriy.shevchenko at nokia.com (Shevchenko Andriy (EXT-Teleca/Helsinki))
Date: Thu, 17 Jun 2010 10:42:38 +0200
Subject: [PATCH 2/3] flash_eraseall: move constants out of for loop
In-Reply-To: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
References: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
Message-ID: <1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com>

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko at nokia.com>
---
 flash_eraseall.c |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index a22fc49..f6319d1 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -194,21 +194,21 @@ void process_options (int argc, char *argv[])
 {
 	int error = 0;
 
+	static const char *short_options = "jq";
+	static const struct option long_options[] = {
+		{"help", no_argument, 0, 0},
+		{"version", no_argument, 0, 0},
+		{"jffs2", no_argument, 0, 'j'},
+		{"quiet", no_argument, 0, 'q'},
+		{"silent", no_argument, 0, 'q'},
+
+		{0, 0, 0, 0},
+	};
+
 	exe_name = argv[0];
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "jq";
-		static const struct option long_options[] = {
-			{"help", no_argument, 0, 0},
-			{"version", no_argument, 0, 0},
-			{"jffs2", no_argument, 0, 'j'},
-			{"quiet", no_argument, 0, 'q'},
-			{"silent", no_argument, 0, 'q'},
-
-			{0, 0, 0, 0},
-		};
-
 		int c = getopt_long(argc, argv, short_options,
 				long_options, &option_index);
 		if (c == EOF) {
-- 
1.6.3.3



From ext-andriy.shevchenko at nokia.com  Thu Jun 17 04:42:39 2010
From: ext-andriy.shevchenko at nokia.com (Shevchenko Andriy (EXT-Teleca/Helsinki))
Date: Thu, 17 Jun 2010 10:42:39 +0200
Subject: [PATCH 3/3] flash_eraseall: make -? option the same as --help
In-Reply-To: <1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com>
References: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
	<1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com>
Message-ID: <1276764159-28726-3-git-send-email-ext-andriy.shevchenko@nokia.com>

Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko at nokia.com>
---
 flash_eraseall.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index f6319d1..ebd329b 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -192,8 +192,6 @@ int main (int argc, char *argv[])
 
 void process_options (int argc, char *argv[])
 {
-	int error = 0;
-
 	static const char *short_options = "jq";
 	static const struct option long_options[] = {
 		{"help", no_argument, 0, 0},
@@ -233,15 +231,13 @@ void process_options (int argc, char *argv[])
 				jffs2 = 1;
 				break;
 			case '?':
-				error = 1;
+				display_help();
 				break;
 		}
 	}
+
 	if (optind == argc) {
 		fprintf(stderr, "%s: no MTD device specified\n", exe_name);
-		error = 1;
-	}
-	if (error) {
 		fprintf(stderr, "Try `%s --help' for more information.\n",
 				exe_name);
 		exit(1);
-- 
1.6.3.3



From adrian.wenl at gmail.com  Tue Jun 22 04:20:29 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Tue, 22 Jun 2010 16:20:29 +0800
Subject: [PATCH 07/25] pxa3xx_nand: mtd scan id process could be defined 
	by driver itself
In-Reply-To: <AANLkTimnaBO_Zb0UvPZYzmQNmqJafTv1gWV8KQm_LwC3@mail.gmail.com>
References: <AANLkTilY1gnS_jwZ_xPKhchTLR5cWj7FEla1V76OuMVK@mail.gmail.com>
	<AANLkTimnaBO_Zb0UvPZYzmQNmqJafTv1gWV8KQm_LwC3@mail.gmail.com>
Message-ID: <AANLkTimPAVPFX3vhYhkCBUCXk6-EEirsNBtD5R3xW8Yt@mail.gmail.com>

On Fri, Jun 18, 2010 at 2:58 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
> <haojian.zhuang at gmail.com> wrote:
>> From d2958ecbec5d0b7f7aee311fd3e87ed1a858864d Mon Sep 17 00:00:00 2001
>> From: Lei Wen <leiwen at marvell.com>
>> Date: Wed, 2 Jun 2010 21:55:51 +0800
>> Subject: [PATCH 07/25] pxa3xx_nand: mtd scan id process could be
>> defined by driver itself
>>
>> Different NAND driver may require its unique detection. For pxa3xx_nand,
>> it use its self id database to get the necessary info.
>
> I believe I get the central point of this patch: to have a specific
> pxa3xx_nand_scan()
> instead of using the generic nand_scan(). This point is good, yet I
> found it extremely
> difficult to read the patch. Like those chip->xxxx assignment, is that
> also part of this
> patch, I strongly recommend to remove irrelevant changes into separate patches.
>

That is also the part of this patch...
-       this->read_word         = pxa3xx_nand_read_word;
+       chip->read_word         = pxa3xx_nand_read_word;
Just use "chip" to take place of "this"...

Best regards,
Lei


From stanley.miao at windriver.com  Tue Jun 22 04:35:10 2010
From: stanley.miao at windriver.com (stanley.miao)
Date: Tue, 22 Jun 2010 16:35:10 +0800
Subject: [PATCH v3] Fix mtd-utils bugs
In-Reply-To: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
References: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
Message-ID: <4C2075BE.3000000@windriver.com>

Any other comments ?

Stanley.

Stanley.Miao wrote:
> Changes from V2:
> 1, Get the linux version via uname() according to Joakim Tjernlund.
> 2, Set the default version the latest version according to Joakim Tjernlund.
>
> The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
> is not enough for many big NAND chips. Therefore, this structure is replaced
> by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
> Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
>
> Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
> keep compatible with the old linux kernel, a linux version detection function
> is added.
>
> YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
> "forcejffs2", "forceyaffs" anymore. Now clean them up. 
>
>
> Stanley.
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
>   



From adrian.wenl at gmail.com  Tue Jun 22 05:34:07 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Tue, 22 Jun 2010 17:34:07 +0800
Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
In-Reply-To: <AANLkTikTzNY2hI0JDTOOZpGeOPc_MU79jVJ_1L9XxA_e@mail.gmail.com>
References: <AANLkTimvhEWIDupsj3Ty8vB9ualwU9RsaIxa0CDgWgYQ@mail.gmail.com>
	<AANLkTikTzNY2hI0JDTOOZpGeOPc_MU79jVJ_1L9XxA_e@mail.gmail.com>
Message-ID: <AANLkTikmuCHqJQY2g8G3FsrufO5dKGt9WNZFnmvoSGl2@mail.gmail.com>

On Fri, Jun 18, 2010 at 2:50 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
> <haojian.zhuang at gmail.com> wrote:
>> From 18d589a078871a09dec0862241fedd2d1d07be85 Mon Sep 17 00:00:00 2001
>> From: Lei Wen <leiwen at marvell.com>
>> Date: Mon, 31 May 2010 14:05:46 +0800
>> Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
>>
>> Enable all irq when we start the nand controller, and
>> put all the transaction logic in the pxa3xx_nand_irq.
>>
>
> Didn't look into the change too much, but the idea sounds to me like
> chaining all the logic with different IRQ events, which was my original
> reason of having different states. And considering the page read/write
> is actually to an internal SRAM within the controller, I guess it's quick
> enough. (though I'd suggest to do some experiments of time profiling
> to see if it's going to increase the interrupt latency)
>
>> By doing this way, we could dramatically increase the
>> performance by avoid unnecessary delay.
>>
>
> The removal of __read_id() doesn't look to be part of this patch, no?
>
For write_cmd function has been discard and __read_id function would
not be used, if
continue to keep the __read_id() definition would lead to make failure...

Best regards,
Lei


From eric.y.miao at gmail.com  Tue Jun 22 06:02:25 2010
From: eric.y.miao at gmail.com (Eric Miao)
Date: Tue, 22 Jun 2010 18:02:25 +0800
Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
In-Reply-To: <AANLkTikmuCHqJQY2g8G3FsrufO5dKGt9WNZFnmvoSGl2@mail.gmail.com>
References: <AANLkTimvhEWIDupsj3Ty8vB9ualwU9RsaIxa0CDgWgYQ@mail.gmail.com> 
	<AANLkTikTzNY2hI0JDTOOZpGeOPc_MU79jVJ_1L9XxA_e@mail.gmail.com> 
	<AANLkTikmuCHqJQY2g8G3FsrufO5dKGt9WNZFnmvoSGl2@mail.gmail.com>
Message-ID: <AANLkTinzmIud44FuZhZSs94yo16F0ipP-uPdX9gAhdPf@mail.gmail.com>

On Tue, Jun 22, 2010 at 5:34 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
> On Fri, Jun 18, 2010 at 2:50 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>> On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
>> <haojian.zhuang at gmail.com> wrote:
>>> From 18d589a078871a09dec0862241fedd2d1d07be85 Mon Sep 17 00:00:00 2001
>>> From: Lei Wen <leiwen at marvell.com>
>>> Date: Mon, 31 May 2010 14:05:46 +0800
>>> Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
>>>
>>> Enable all irq when we start the nand controller, and
>>> put all the transaction logic in the pxa3xx_nand_irq.
>>>
>>
>> Didn't look into the change too much, but the idea sounds to me like
>> chaining all the logic with different IRQ events, which was my original
>> reason of having different states. And considering the page read/write
>> is actually to an internal SRAM within the controller, I guess it's quick
>> enough. (though I'd suggest to do some experiments of time profiling
>> to see if it's going to increase the interrupt latency)
>>
>>> By doing this way, we could dramatically increase the
>>> performance by avoid unnecessary delay.
>>>
>>
>> The removal of __read_id() doesn't look to be part of this patch, no?
>>
> For write_cmd function has been discard and __read_id function would
> not be used, if
> continue to keep the __read_id() definition would lead to make failure...
>

Well, the logic is: this change doesn't belong to this patch, so is it possible
to separate the change apart and still keep it compiling?


From adrian.wenl at gmail.com  Tue Jun 22 07:24:20 2010
From: adrian.wenl at gmail.com (Lei Wen)
Date: Tue, 22 Jun 2010 19:24:20 +0800
Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
In-Reply-To: <AANLkTinzmIud44FuZhZSs94yo16F0ipP-uPdX9gAhdPf@mail.gmail.com>
References: <AANLkTimvhEWIDupsj3Ty8vB9ualwU9RsaIxa0CDgWgYQ@mail.gmail.com>
	<AANLkTikTzNY2hI0JDTOOZpGeOPc_MU79jVJ_1L9XxA_e@mail.gmail.com>
	<AANLkTikmuCHqJQY2g8G3FsrufO5dKGt9WNZFnmvoSGl2@mail.gmail.com>
	<AANLkTinzmIud44FuZhZSs94yo16F0ipP-uPdX9gAhdPf@mail.gmail.com>
Message-ID: <AANLkTinEOvQX0f6jKsGEALSLBMPmeSgx9n6QIsCcHVKG@mail.gmail.com>

On Tue, Jun 22, 2010 at 6:02 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
> On Tue, Jun 22, 2010 at 5:34 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
>> On Fri, Jun 18, 2010 at 2:50 PM, Eric Miao <eric.y.miao at gmail.com> wrote:
>>> On Fri, Jun 18, 2010 at 1:34 PM, Haojian Zhuang
>>> <haojian.zhuang at gmail.com> wrote:
>>>> From 18d589a078871a09dec0862241fedd2d1d07be85 Mon Sep 17 00:00:00 2001
>>>> From: Lei Wen <leiwen at marvell.com>
>>>> Date: Mon, 31 May 2010 14:05:46 +0800
>>>> Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic
>>>>
>>>> Enable all irq when we start the nand controller, and
>>>> put all the transaction logic in the pxa3xx_nand_irq.
>>>>
>>>
>>> Didn't look into the change too much, but the idea sounds to me like
>>> chaining all the logic with different IRQ events, which was my original
>>> reason of having different states. And considering the page read/write
>>> is actually to an internal SRAM within the controller, I guess it's quick
>>> enough. (though I'd suggest to do some experiments of time profiling
>>> to see if it's going to increase the interrupt latency)
>>>
>>>> By doing this way, we could dramatically increase the
>>>> performance by avoid unnecessary delay.
>>>>
>>>
>>> The removal of __read_id() doesn't look to be part of this patch, no?
>>>
>> For write_cmd function has been discard and __read_id function would
>> not be used, if
>> continue to keep the __read_id() definition would lead to make failure...
>>
>
> Well, the logic is: this change doesn't belong to this patch, so is it possible
> to separate the change apart and still keep it compiling?
>

Em... Seems reasonable, I'll try to do that. :-)

Best regards,
Lei


From Martin.Krause at tqs.de  Tue Jun 22 09:00:19 2010
From: Martin.Krause at tqs.de (Martin Krause)
Date: Tue, 22 Jun 2010 15:00:19 +0200
Subject: [PATCH]] mtdconcat: fix bug with uninitialized lock and unlock
	functions
Message-ID: <47F3F98010FF784EBEE6526EAAB078D10635E728@tq-mailsrv.tq-net.de>

Test if a lock or unlock function is present (pointer not NULL) before
calling it, to prevent a kernel dump.

Signed-off-by: Martin Krause <martin.krause at tqs.de>
---
 drivers/mtd/mtdconcat.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index db6de74..0a7ee03 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -541,10 +541,13 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		else
 			size = len;
 
-		err = subdev->lock(subdev, ofs, size);
+		if (subdev->lock) {
+			err = subdev->lock(subdev, ofs, size);
 
-		if (err)
-			break;
+			if (err)
+				break;
+		} else
+			err = -EOPNOTSUPP;
 
 		len -= size;
 		if (len == 0)
@@ -579,10 +582,13 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		else
 			size = len;
 
-		err = subdev->unlock(subdev, ofs, size);
+		if (subdev->unlock) {
+			err = subdev->unlock(subdev, ofs, size);
 
-		if (err)
-			break;
+			if (err)
+				break;
+		} else
+			err = -EOPNOTSUPP;
 
 		len -= size;
 		if (len == 0)
-- 
1.6.6.1


From cbouatmailru at gmail.com  Tue Jun 22 12:55:45 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Tue, 22 Jun 2010 20:55:45 +0400
Subject: [Uclinux-dist-devel] [PATCH 1/2] mtd: m25p80:
	Reworkprobing/JEDEC code
In-Reply-To: <AANLkTikY9pfHsQ6xeVkixKF5kqL2nLyV2kgcR2iJKhG-@mail.gmail.com>
References: <AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
	<20100618133212.GA5276@oksana.dev.rtsoft.ru>
	<0F1B54C89D5F954D8535DB252AF412FA065551D8@chinexm1.ad.analog.com>
	<AANLkTiksYofs6hhWta6uFX2cla_g8pBu0Mtbtcbv-2tl@mail.gmail.com>
	<20100621071551.GA16109@oksana.dev.rtsoft.ru>
	<AANLkTiknH95loHJsQNxvCCyQbriCFWqM5LHl3wKzmdWX@mail.gmail.com>
	<20100621073909.GA20674@oksana.dev.rtsoft.ru>
	<AANLkTinjhmkQafVlrtQC5yDnqIZz859_wrZqo45QOEJ2@mail.gmail.com>
	<20100621112049.GA9273@oksana.dev.rtsoft.ru>
	<AANLkTikY9pfHsQ6xeVkixKF5kqL2nLyV2kgcR2iJKhG-@mail.gmail.com>
Message-ID: <20100622165545.GA10255@oksana.dev.rtsoft.ru>

On Tue, Jun 22, 2010 at 02:37:52PM +0800, Barry Song wrote:
[...]
> > ? ? ? ? ? ? ? ?jid = jedec_probe(spi);
> > ? ? ? ? ? ? ? ?if (!jid) {
> > - ? ? ? ? ? ? ? ? ? ? ? dev_info(&spi->dev, "non-JEDEC variant of %s\n",
> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?id->name);
> > + ? ? ? ? ? ? ? ? ? ? ? return -ENODEV;
> The patch looks good to me. Only problem is NULL is also returned by
> spi_write_then_read() fail:
[...]
> Here much better for -EIO (return tmp)?

Agreed. Though, this is not a regression, and I guess desires
its own patch. 

Here are two patches, one for 2.6.35 (minimal changes to fix
the JEDEC problem), another for 2.6.36.


From avorontsov at mvista.com  Tue Jun 22 12:57:34 2010
From: avorontsov at mvista.com (Anton Vorontsov)
Date: Tue, 22 Jun 2010 20:57:34 +0400
Subject: [PATCH 1/2] mtd: m25p80: Fix false-positive probing
In-Reply-To: <20100622165545.GA10255@oksana.dev.rtsoft.ru>
References: <20100622165545.GA10255@oksana.dev.rtsoft.ru>
Message-ID: <20100622165734.GA20699@oksana.dev.rtsoft.ru>

Since commit 18c6182bae0acca220ed6611f741034d563cd19f ("Rework
probing/JEDEC code"), m25p80 driver successfully registers chips
even if JEDEC probing fails.

This was needed to support non-JEDEC flashes. Though, it appears
that some platforms (e.g. blackfin bf533 stamp[1]) used the old
behavior to detect if there's any flash connected, so the driver
have to fail on JEDEC probing errors.

This patch restores the old behavior for JEDEC flashes, and adds
"-nonjedec" SPI device IDs for M25Pxx flashes, so that the kernel
still supports non-JEDEC flashes.

[1] http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=5975

Reported-by: Mingquan Pan
Reported-by: Barry Song <21cnbao at gmail.com>
Signed-off-by: Anton Vorontsov <avorontsov at mvista.com>
---

This is for 2.6.35.

 drivers/mtd/devices/m25p80.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 81e49a9..a610ca9 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -680,6 +680,16 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
 	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
 
+	{ "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2, 0) },
+	{ "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4, 0) },
+	{ "m25p20-nonjedec",  INFO(0, 0,  64 * 1024,   4, 0) },
+	{ "m25p40-nonjedec",  INFO(0, 0,  64 * 1024,   8, 0) },
+	{ "m25p80-nonjedec",  INFO(0, 0,  64 * 1024,  16, 0) },
+	{ "m25p16-nonjedec",  INFO(0, 0,  64 * 1024,  32, 0) },
+	{ "m25p32-nonjedec",  INFO(0, 0,  64 * 1024,  64, 0) },
+	{ "m25p64-nonjedec",  INFO(0, 0,  64 * 1024, 128, 0) },
+	{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024,  64, 0) },
+
 	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, 0) },
 	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
 	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
@@ -795,8 +805,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 
 		jid = jedec_probe(spi);
 		if (!jid) {
-			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
-				 id->name);
+			return -ENODEV;
 		} else if (jid != id) {
 			/*
 			 * JEDEC knows better, so overwrite platform ID. We
-- 
1.7.0.5



From avorontsov at mvista.com  Tue Jun 22 12:57:42 2010
From: avorontsov at mvista.com (Anton Vorontsov)
Date: Tue, 22 Jun 2010 20:57:42 +0400
Subject: [PATCH 2/2] mtd: m25p80: Make jedec_probe() return proper errno values
In-Reply-To: <20100622165545.GA10255@oksana.dev.rtsoft.ru>
References: <20100622165545.GA10255@oksana.dev.rtsoft.ru>
Message-ID: <20100622165742.GB20699@oksana.dev.rtsoft.ru>

spi_write_then_read() may return its own return codes (e.g. -EIO),
so let's propagate the value down to the probe().

Also, remove jedec == 0 check, it isn't needed as nowadays we use
dedicated SPI device IDs for non-JEDEC flashes.

Suggested-by: Barry Song <21cnbao at gmail.com>
Signed-off-by: Anton Vorontsov <avorontsov at mvista.com>
---

This is for 2.6.36.

 drivers/mtd/devices/m25p80.c |   18 ++++++------------
 1 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index a610ca9..7bf5c45 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -16,6 +16,8 @@
  */
 
 #include <linux/init.h>
+#include <linux/err.h>
+#include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
@@ -733,7 +735,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 	if (tmp < 0) {
 		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
 			dev_name(&spi->dev), tmp);
-		return NULL;
+		return ERR_PTR(tmp);
 	}
 	jedec = id[0];
 	jedec = jedec << 8;
@@ -741,14 +743,6 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 	jedec = jedec << 8;
 	jedec |= id[2];
 
-	/*
-	 * Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants,
-	 * which depend on technology process. Officially RDID command doesn't
-	 * exist for non-JEDEC chips, but for compatibility they return ID 0.
-	 */
-	if (jedec == 0)
-		return NULL;
-
 	ext_jedec = id[3] << 8 | id[4];
 
 	for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
@@ -759,7 +753,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 			return &m25p_ids[tmp];
 		}
 	}
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 
 
@@ -804,8 +798,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
 		const struct spi_device_id *jid;
 
 		jid = jedec_probe(spi);
-		if (!jid) {
-			return -ENODEV;
+		if (IS_ERR(jid)) {
+			return PTR_ERR(jid);
 		} else if (jid != id) {
 			/*
 			 * JEDEC knows better, so overwrite platform ID. We
-- 
1.7.0.5


From vapier.adi at gmail.com  Tue Jun 22 13:31:57 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 22 Jun 2010 13:31:57 -0400
Subject: [PATCH 3/3] flash_eraseall: make -? option the same as --help
In-Reply-To: <1276764159-28726-3-git-send-email-ext-andriy.shevchenko@nokia.com>
References: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
	<1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com> 
	<1276764159-28726-3-git-send-email-ext-andriy.shevchenko@nokia.com>
Message-ID: <AANLkTilpJ9bGjcdxwfsrq7x7FQKC-vZDy6PyjpDSd4Ad@mail.gmail.com>

On Thu, Jun 17, 2010 at 04:42, Shevchenko Andriy wrote:
> --- a/flash_eraseall.c
> +++ b/flash_eraseall.c
> @@ -192,8 +192,6 @@ int main (int argc, char *argv[])
>
> ?void process_options (int argc, char *argv[])
> ?{
> - ? ? ? int error = 0;
> -
> ? ? ? ?static const char *short_options = "jq";
> ? ? ? ?static const struct option long_options[] = {
> ? ? ? ? ? ? ? ?{"help", no_argument, 0, 0},
> @@ -233,15 +231,13 @@ void process_options (int argc, char *argv[])
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jffs2 = 1;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ? ? ? ? ?case '?':
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? error = 1;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? display_help();
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?}
> ? ? ? ?}

NAK.  this isnt "-?", that's the error case of getopt.  look at the
invocation of getopt here ... ? is not a valid char.

also, your patch bombing seems screwed up as linux-mtd was bcc-ed.
-mike

From vapier.adi at gmail.com  Tue Jun 22 13:33:20 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 22 Jun 2010 13:33:20 -0400
Subject: [PATCH 2/3] flash_eraseall: move constants out of for loop
In-Reply-To: <1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com>
References: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
	<1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com>
Message-ID: <AANLkTilBFi58-kjjxM2Q5p0I1l9R5WQpiozBiV5udQYW@mail.gmail.com>

On Thu, Jun 17, 2010 at 04:42, Shevchenko Andriy wrote:
> --- a/flash_eraseall.c
> +++ b/flash_eraseall.c
> @@ -194,21 +194,21 @@ void process_options (int argc, char *argv[])
> ?{
> ? ? ? ?int error = 0;
>
> + ? ? ? static const char *short_options = "jq";
> + ? ? ? static const struct option long_options[] = {
> + ? ? ? ? ? ? ? {"help", no_argument, 0, 0},
> + ? ? ? ? ? ? ? {"version", no_argument, 0, 0},
> + ? ? ? ? ? ? ? {"jffs2", no_argument, 0, 'j'},
> + ? ? ? ? ? ? ? {"quiet", no_argument, 0, 'q'},
> + ? ? ? ? ? ? ? {"silent", no_argument, 0, 'q'},
> +
> + ? ? ? ? ? ? ? {0, 0, 0, 0},
> + ? ? ? };
> +
> ? ? ? ?exe_name = argv[0];
>
> ? ? ? ?for (;;) {
> ? ? ? ? ? ? ? ?int option_index = 0;
> - ? ? ? ? ? ? ? static const char *short_options = "jq";
> - ? ? ? ? ? ? ? static const struct option long_options[] = {
> - ? ? ? ? ? ? ? ? ? ? ? {"help", no_argument, 0, 0},
> - ? ? ? ? ? ? ? ? ? ? ? {"version", no_argument, 0, 0},
> - ? ? ? ? ? ? ? ? ? ? ? {"jffs2", no_argument, 0, 'j'},
> - ? ? ? ? ? ? ? ? ? ? ? {"quiet", no_argument, 0, 'q'},
> - ? ? ? ? ? ? ? ? ? ? ? {"silent", no_argument, 0, 'q'},
> -
> - ? ? ? ? ? ? ? ? ? ? ? {0, 0, 0, 0},
> - ? ? ? ? ? ? ? };
> -
> ? ? ? ? ? ? ? ?int c = getopt_long(argc, argv, short_options,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?long_options, &option_index);
> ? ? ? ? ? ? ? ?if (c == EOF) {

NAK: no explanation why you're doing this, and current code has the
variables scoped to where they actually get used.

i wonder though why this code even bothers with "static".
-mike

From vapier.adi at gmail.com  Tue Jun 22 13:56:00 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 22 Jun 2010 13:56:00 -0400
Subject: [PATCH 1/2] mtd: m25p80: Fix false-positive probing
In-Reply-To: <20100622165734.GA20699@oksana.dev.rtsoft.ru>
References: <20100622165545.GA10255@oksana.dev.rtsoft.ru>
	<20100622165734.GA20699@oksana.dev.rtsoft.ru>
Message-ID: <AANLkTinP63VyX2LjY-zIbnluasCiT3tOv6tlfZ6k1WqM@mail.gmail.com>

On Tue, Jun 22, 2010 at 12:57, Anton Vorontsov wrote:
> Since commit 18c6182bae0acca220ed6611f741034d563cd19f ("Rework
> probing/JEDEC code"), m25p80 driver successfully registers chips
> even if JEDEC probing fails.
>
> This was needed to support non-JEDEC flashes. Though, it appears
> that some platforms (e.g. blackfin bf533 stamp[1]) used the old
> behavior to detect if there's any flash connected, so the driver
> have to fail on JEDEC probing errors.
>
> This patch restores the old behavior for JEDEC flashes, and adds
> "-nonjedec" SPI device IDs for M25Pxx flashes, so that the kernel
> still supports non-JEDEC flashes.

Acked-by: Mike Frysinger <vapier at gentoo.org>

> [1] http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=5975

http://blackfin.uclinux.org/gf/tracker/5975

> Reported-by: Mingquan Pan

<Grace.Pan at analog.com>
-mike


From robin.gilks at taitradio.com  Tue Jun 22 19:51:15 2010
From: robin.gilks at taitradio.com (Robin Gilks)
Date: Wed, 23 Jun 2010 11:51:15 +1200
Subject: Updating kernel after 5 year gap!!
Message-ID: <4C214C73.7000709@taitradio.com>

Oh dear - I'm going to get some stick from the list for this one...

I've just come back to a project after a gap of 5 years and wish to 
update it from 2.4.22 to 2.4.37.9 (latest 2.4) but the functionality 
contained in maps/physmap seems to have moved on somewhat. How do I 
invoke the cmdlineparts parser these days - there used to be a 
part_probes array that defined what probes to do but I can't work out 
where that functionality has gone.

Also, the chips/cfi_cmdset_0001 used to have a fixup list for those 
chips that didn't quite comply with the CFI spec - eg. the ST chip I'm 
using doesn't support block write correctly. Has this gone entirely or 
has it moved to the platform stuff like a lot of other things did in 2.6

Some pointers to sample code would be the best pointer by far (being a 
master of the cut-n-paste) but just telling me would work as well :-)

Cheers

-- 
Robin Gilks
Senior Design Engineer
Tait Radio Communications
DDI: 64 3 3571569
www.taitradio.com
robin.gilks at tait.co.nz
TAIT: THE RIGHT FIT



From jamie at shareable.org  Tue Jun 22 20:23:35 2010
From: jamie at shareable.org (Jamie Lokier)
Date: Wed, 23 Jun 2010 01:23:35 +0100
Subject: [PATCH 2/3] flash_eraseall: move constants out of for loop
In-Reply-To: <AANLkTilBFi58-kjjxM2Q5p0I1l9R5WQpiozBiV5udQYW@mail.gmail.com>
References: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
	<1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com>
	<AANLkTilBFi58-kjjxM2Q5p0I1l9R5WQpiozBiV5udQYW@mail.gmail.com>
Message-ID: <20100623002334.GA22367@shareable.org>

Mike Frysinger wrote:
> NAK: no explanation why you're doing this, and current code has the
> variables scoped to where they actually get used.
> 
> i wonder though why this code even bothers with "static".

The array is static to avoid compiling to code which fills in the
array at runtime.  I.e. it makes the code smaller, to the same size as
if they were globals.  And then, only because its static, the const
can put them in the .rodata section, reducing unshared data size.

Because they're static there's no benefit to moving them to another
scope.

-- Jamie


From robin.gilks at taitradio.com  Tue Jun 22 21:07:01 2010
From: robin.gilks at taitradio.com (Robin Gilks)
Date: Wed, 23 Jun 2010 13:07:01 +1200
Subject: Progress but stuck on write_buffers/write_words without fixup
Message-ID: <4C215E35.7050503@taitradio.com>

OK - I've found a lot of the issues with updating 5 years in one hop - 
mtdblocks start from 1 because 0 is the whole phys mapped device, name 
of the partition list is hardcoded to 'phys' but I've still got a 
problem with the ST Micro M28W640ECB not supporting write_buffers in a 
CFI compliant fashion - I can get round it by setting the 
FORCE_WORD_WRITE in cfi_cmdset_0001.c but I'm hoping someone can tell me 
there is a better way

Cheers

-- 
Robin Gilks
Senior Design Engineer
Tait Radio Communications
DDI: 64 3 3571569
www.taitradio.com
robin.gilks at tait.co.nz
TAIT: THE RIGHT FIT



From vapier.adi at gmail.com  Tue Jun 22 22:05:32 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 22 Jun 2010 22:05:32 -0400
Subject: Updating kernel after 5 year gap!!
In-Reply-To: <4C214C73.7000709@taitradio.com>
References: <4C214C73.7000709@taitradio.com>
Message-ID: <AANLkTinJbP83XGao2an1wBzCiiXGQzUxIy4Zl24Dz1I2@mail.gmail.com>

On Tue, Jun 22, 2010 at 19:51, Robin Gilks wrote:
> I've just come back to a project after a gap of 5 years and wish to update
> it from 2.4.22 to 2.4.37.9 (latest 2.4)

no one really tracks 2.4 at all, so you're most likely going to be on
your own wrt "how does 2.4.xx behave ?".  maybe you'll get lucky and
someone knows, but i'm doubtful :p.
-mike


From vapier.adi at gmail.com  Tue Jun 22 22:11:01 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 22 Jun 2010 22:11:01 -0400
Subject: [PATCH 2/3] flash_eraseall: move constants out of for loop
In-Reply-To: <20100623002334.GA22367@shareable.org>
References: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
	<1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com> 
	<AANLkTilBFi58-kjjxM2Q5p0I1l9R5WQpiozBiV5udQYW@mail.gmail.com> 
	<20100623002334.GA22367@shareable.org>
Message-ID: <AANLkTimllsVj3nGC7vWP9oKPJXwIyjd71y0KbA7rFhPH@mail.gmail.com>

On Tue, Jun 22, 2010 at 20:23, Jamie Lokier wrote:
> Mike Frysinger wrote:
>> i wonder though why this code even bothers with "static".
>
> The array is static to avoid compiling to code which fills in the
> array at runtime. ?I.e. it makes the code smaller, to the same size as
> if they were globals. ?And then, only because its static, the const
> can put them in the .rodata section, reducing unshared data size.

if it were generated on the stack at runtime, the .text is shared too

> Because they're static there's no benefit to moving them to another
> scope.

that's sort of what i expected, but i found it odd that it isnt:
    static const char * const short_options = "jq";
-mike


From Ladislav.Michl at seznam.cz  Wed Jun 23 06:48:58 2010
From: Ladislav.Michl at seznam.cz (Ladislav Michl)
Date: Wed, 23 Jun 2010 12:48:58 +0200
Subject: [PATCH] flash_eraseall: do not use exit()
Message-ID: <20100623104858.GA2442@localhost.localdomain>

From: Ladislav Michl <ladis at linux-mips.org>

Returning from main() instead of using exit() makes code more readable
and smaller.

   text    data     bss     dec     hex filename
   6440     324      68    6832    1ab0 flash_eraseall
   6405     320      68    6793    1a89 flash_eraseall.noexit

Signed-off-by: Ladislav Michl <ladis at linux-mips.org>
---
 flash_eraseall.c |   42 ++++++++++++++++--------------------------
 1 file changed, 16 insertions(+), 26 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index 531bbe6..db65553 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -51,14 +51,6 @@ static int jffs2;		/* format for jffs2 usage */
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
 
-static void show_progress(mtd_info_t *meminfo, erase_info_t *erase)
-{
-	printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.",
-		meminfo->erasesize / 1024, erase->start,
-		(unsigned long long) erase->start * 100 / meminfo->size);
-	fflush(stdout);
-}
-
 static void display_help(void)
 {
 	printf("Usage: %s [OPTION] MTD_DEVICE\n"
@@ -70,10 +62,8 @@ static void display_help(void)
 			"      --help     display this help and exit\n"
 			"      --version  output version information and exit\n",
 			exe_name);
-	exit(0);
 }
 
-
 static void display_version(void)
 {
 	printf(PROGRAM " " VERSION "\n"
@@ -86,12 +76,22 @@ static void display_version(void)
 			"You may redistribute copies of " PROGRAM "\n"
 			"under the terms of the GNU General Public Licence.\n"
 			"See the file `COPYING' for more information.\n");
-	exit(0);
 }
 
-static void process_options(int argc, char *argv[])
+static void show_progress(mtd_info_t *meminfo, erase_info_t *erase)
+{
+	printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.",
+		meminfo->erasesize / 1024, erase->start,
+		(unsigned long long) erase->start * 100 / meminfo->size);
+	fflush(stdout);
+}
+
+int main(int argc, char *argv[])
 {
-	int error = 0;
+	mtd_info_t meminfo;
+	int fd, error = 0, clmpos = 0, clmlen = 8;
+	erase_info_t erase;
+	int isNAND, bbtest = 1;
 
 	exe_name = argv[0];
 
@@ -119,10 +119,10 @@ static void process_options(int argc, char *argv[])
 				switch (option_index) {
 					case 0:
 						display_help();
-						break;
+						return 0;
 					case 1:
 						display_version();
-						break;
+						return 0;
 				}
 				break;
 			case 'q':
@@ -143,20 +143,10 @@ static void process_options(int argc, char *argv[])
 	if (error) {
 		fprintf(stderr, "Try `%s --help' for more information.\n",
 				exe_name);
-		exit(1);
+		return 1;
 	}
 
 	mtd_device = argv[optind];
-}
-
-int main(int argc, char *argv[])
-{
-	mtd_info_t meminfo;
-	int fd, clmpos = 0, clmlen = 8;
-	erase_info_t erase;
-	int isNAND, bbtest = 1;
-
-	process_options(argc, argv);
 
 	if ((fd = open(mtd_device, O_RDWR)) < 0) {
 		fprintf(stderr, "%s: %s: %s\n", exe_name, mtd_device, strerror(errno));


From Ladislav.Michl at seznam.cz  Wed Jun 23 07:13:28 2010
From: Ladislav.Michl at seznam.cz (Ladislav Michl)
Date: Wed, 23 Jun 2010 13:13:28 +0200
Subject: [PATCH] flash_eraseall: do not use exit()
In-Reply-To: <20100623104858.GA2442@localhost.localdomain>
References: <20100623104858.GA2442@localhost.localdomain>
Message-ID: <20100623111328.GA3059@localhost.localdomain>

On Wed, Jun 23, 2010 at 12:48:58PM +0200, Ladislav Michl wrote:
> Returning from main() instead of using exit() makes code more readable
> and smaller.

Please disregard, I'll send update based on Stanley's patches, which looks
really good and I'm just testing them...

	ladis


From Ladislav.Michl at seznam.cz  Wed Jun 23 11:16:22 2010
From: Ladislav.Michl at seznam.cz (Ladislav Michl)
Date: Wed, 23 Jun 2010 17:16:22 +0200
Subject: [PATCH v3] Fix mtd-utils bugs
In-Reply-To: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
References: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
Message-ID: <20100623151622.GA2771@localhost.localdomain>

On Sun, Jun 20, 2010 at 08:22:57PM +0800, Stanley.Miao wrote:
> Changes from V2:
> 1, Get the linux version via uname() according to Joakim Tjernlund.
> 2, Set the default version the latest version according to Joakim Tjernlund.
> 
> The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
> is not enough for many big NAND chips. Therefore, this structure is replaced
> by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
> Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.
> 
> Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
> keep compatible with the old linux kernel, a linux version detection function
> is added.
> 
> YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
> "forcejffs2", "forceyaffs" anymore. Now clean them up. 

Tested with linux-2.6.32 (flash_eraseall -j finaly works now)

Tested-by: Ladislav Michl <ladis at linux-mips.org>

As a special bonus, here is simple patch on top of your patchset making
flash_eraseall smaller:

From: Ladislav Michl <ladis at linux-mips.org>

Returning from main() instead of using exit() makes code more readable
and smaller (ARM EABI binary sizes)

   text    data     bss     dec     hex filename
  10345     372      44   10761    2a09 flash_eraseall
  10286     368      44   10698    29ca flash_eraseall.noexit

Signed-off-by: Ladislav Michl <ladis at linux-mips.org>
---
 flash_eraseall.c |  197 ++++++++++++++++++++++++-------------------------------
 1 file changed, 89 insertions(+), 108 deletions(-)

--- a/flash_eraseall.c	2010-06-23 13:10:00.000000000 +0200
+++ b/flash_eraseall.c	2010-06-23 13:30:31.000000000 +0200
@@ -49,15 +49,45 @@
 static const char *exe_name;
 static const char *mtd_device;
 static int quiet;		/* true -- don't output progress */
-static int jffs2;		// format for jffs2 usage
-
-static void process_options (int argc, char *argv[]);
-void show_progress (mtd_info_t *meminfo, erase_info_t *erase);
-static void display_help (void);
-static void display_version (void);
+static int jffs2;		/* format for jffs2 usage */
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
 
+static void show_progress(mtd_info_t *meminfo, erase_info_t *erase)
+{
+	printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.",
+		meminfo->erasesize / 1024, erase->start,
+		(unsigned long long) erase->start * 100 / meminfo->size);
+	fflush(stdout);
+}
+
+static void display_help(void)
+{
+	printf("Usage: %s [OPTION] MTD_DEVICE\n"
+			"Erases all of the specified MTD device.\n"
+			"\n"
+			"  -j, --jffs2    format the device for jffs2\n"
+			"  -q, --quiet    don't display progress messages\n"
+			"      --silent   same as --quiet\n"
+			"      --help     display this help and exit\n"
+			"      --version  output version information and exit\n",
+			exe_name);
+}
+
+static void display_version(void)
+{
+	printf(PROGRAM " " VERSION "\n"
+			"\n"
+			"Copyright (C) 2000 Arcom Control Systems Ltd\n"
+			"\n"
+			PROGRAM " comes with NO WARRANTY\n"
+			"to the extent permitted by law.\n"
+			"\n"
+			"You may redistribute copies of " PROGRAM "\n"
+			"under the terms of the GNU General Public Licence.\n"
+			"See the file `COPYING' for more information.\n");
+}
+
 static int get_linux_version(void)
 {
 	int a, b, c, ret, err = 0;
@@ -80,23 +110,73 @@
 	return LINUX_VERSION(a, b, c);
 }
 
-int main (int argc, char *argv[])
+int main(int argc, char *argv[])
 {
 	mtd_info_t meminfo;
 	int fd;
 	erase_info_t erase;
 	int isNAND, bbtest = 1;
+	int error = 0;
 	unsigned char oobbuf[128];
 	memset(oobbuf, 0xFF, 128);
 
-	process_options(argc, argv);
+	exe_name = argv[0];
+	for (;;) {
+		int option_index = 0;
+		static const char *short_options = "jq";
+		static const struct option long_options[] = {
+			{"help", no_argument, 0, 0},
+			{"version", no_argument, 0, 0},
+			{"jffs2", no_argument, 0, 'j'},
+			{"quiet", no_argument, 0, 'q'},
+			{"silent", no_argument, 0, 'q'},
+
+			{0, 0, 0, 0},
+		};
+
+		int c = getopt_long(argc, argv, short_options,
+				long_options, &option_index);
+		if (c == EOF)
+			break;
+
+		switch (c) {
+		case 0:
+			switch (option_index) {
+			case 0:
+				display_help();
+				return 0;
+			case 1:
+				display_version();
+				return 0;
+			}
+			break;
+		case 'q':
+			quiet = 1;
+			break;
+		case 'j':
+			jffs2 = 1;
+			break;
+		case '?':
+			error = 1;
+			break;
+		}
+	}
+	if (optind == argc) {
+		fprintf(stderr, "%s: no MTD device specified\n", exe_name);
+		error = 1;
+	}
+	if (error) {
+		fprintf(stderr, "Try `%s --help' for more information.\n",
+				exe_name);
+		return 1;
+	}
+	mtd_device = argv[optind];
 
 	if ((fd = open(mtd_device, O_RDWR)) < 0) {
 		fprintf(stderr, "%s: %s: %s\n", exe_name, mtd_device, strerror(errno));
 		return 1;
 	}
 
-
 	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
 		fprintf(stderr, "%s: %s: unable to get MTD device info\n", exe_name, mtd_device);
 		return 1;
@@ -213,102 +293,3 @@
 
 	return 0;
 }
-
-
-void process_options (int argc, char *argv[])
-{
-	int error = 0;
-
-	exe_name = argv[0];
-
-	for (;;) {
-		int option_index = 0;
-		static const char *short_options = "jq";
-		static const struct option long_options[] = {
-			{"help", no_argument, 0, 0},
-			{"version", no_argument, 0, 0},
-			{"jffs2", no_argument, 0, 'j'},
-			{"quiet", no_argument, 0, 'q'},
-			{"silent", no_argument, 0, 'q'},
-
-			{0, 0, 0, 0},
-		};
-
-		int c = getopt_long(argc, argv, short_options,
-				long_options, &option_index);
-		if (c == EOF) {
-			break;
-		}
-
-		switch (c) {
-			case 0:
-				switch (option_index) {
-					case 0:
-						display_help();
-						break;
-					case 1:
-						display_version();
-						break;
-				}
-				break;
-			case 'q':
-				quiet = 1;
-				break;
-			case 'j':
-				jffs2 = 1;
-				break;
-			case '?':
-				error = 1;
-				break;
-		}
-	}
-	if (optind == argc) {
-		fprintf(stderr, "%s: no MTD device specified\n", exe_name);
-		error = 1;
-	}
-	if (error) {
-		fprintf(stderr, "Try `%s --help' for more information.\n",
-				exe_name);
-		exit(1);
-	}
-
-	mtd_device = argv[optind];
-}
-
-void show_progress (mtd_info_t *meminfo, erase_info_t *erase)
-{
-	printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.",
-		meminfo->erasesize / 1024, erase->start,
-		(unsigned long long) erase->start * 100 / meminfo->size);
-	fflush(stdout);
-}
-
-void display_help (void)
-{
-	printf("Usage: %s [OPTION] MTD_DEVICE\n"
-			"Erases all of the specified MTD device.\n"
-			"\n"
-			"  -j, --jffs2    format the device for jffs2\n"
-			"  -q, --quiet    don't display progress messages\n"
-			"      --silent   same as --quiet\n"
-			"      --help     display this help and exit\n"
-			"      --version  output version information and exit\n",
-			exe_name);
-	exit(0);
-}
-
-
-void display_version (void)
-{
-	printf(PROGRAM " " VERSION "\n"
-			"\n"
-			"Copyright (C) 2000 Arcom Control Systems Ltd\n"
-			"\n"
-			PROGRAM " comes with NO WARRANTY\n"
-			"to the extent permitted by law.\n"
-			"\n"
-			"You may redistribute copies of " PROGRAM "\n"
-			"under the terms of the GNU General Public Licence.\n"
-			"See the file `COPYING' for more information.\n");
-	exit(0);
-}


From Artem.Bityutskiy at nokia.com  Wed Jun 23 09:18:54 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Wed, 23 Jun 2010 16:18:54 +0300
Subject: [PATCH v3] Fix mtd-utils bugs
In-Reply-To: <4C2075BE.3000000@windriver.com>
References: <1277036580-3501-1-git-send-email-stanley.miao@windriver.com>
	<4C2075BE.3000000@windriver.com>
Message-ID: <1277299134.18458.0.camel@localhost>

On Tue, 2010-06-22 at 16:35 +0800, stanley.miao wrote:
> Any other comments ?

I'll pick this as when I find few hours to go through the MTD ML.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From taliaferro62 at gmail.com  Wed Jun 23 13:04:23 2010
From: taliaferro62 at gmail.com (twebb)
Date: Wed, 23 Jun 2010 13:04:23 -0400
Subject: ubifs_scan() error handling
Message-ID: <AANLkTilwqK96Btosh4kzW0kMDjRWzWskrG_ymekpV9Uz@mail.gmail.com>

Without having a complete understanding of how the UBI and UBIFS
internals work, I have a question regarding error handling in
ubifs_scan().

When ubifs_scan() encounters SCANNED_EMPTY_SPACE during execution, it
checks whether the LEB is all 0xFFs and if not - returns -EUCLEAN.  In
some cases (for example, in orphan.c/kill_orphans()), any error
returned by ubifs_scan() results in a call to ubifs_recover_leb().
Would it make sense and be acceptable to make this call any time
ubifs_scan() returns an error?  And if so, would it make more sense to
include the ubifs_recover_leb() call in ubifs_scan() at goto
corruption?

Thanks,
twebb


From dave+gmane at wuertele.com  Wed Jun 23 15:26:33 2010
From: dave+gmane at wuertele.com (David Wuertele)
Date: Wed, 23 Jun 2010 19:26:33 +0000 (UTC)
Subject: Performance effect of mounting jffs2 via mtdblock
Message-ID: <loom.20100623T212106-800@post.gmane.org>

Reading http://www.linux-mtd.infradead.org/faq/jffs2.html, it says that jffs2
can be mounted with or without the mtdblock driver.  Eg:

  mount -t jffs2 mtd2 /foo 
vs
  mount -t jffs2 /dev/mtdblock2 /foo

I'm wondering what is the difference between these two methods with respect to
performance?

Thanks,
Dave




From norris at broadcom.com  Wed Jun 23 16:36:02 2010
From: norris at broadcom.com (Brian Norris)
Date: Wed, 23 Jun 2010 13:36:02 -0700
Subject: [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block
Message-ID: <1277325362-13326-1-git-send-email-norris@broadcom.com>

NAND_BB_LAST_PAGE used to be in nand.h, but it pertained to bad block
management and so belongs next to NAND_BBT_SCAN2NDPAGE in bbm.h. Also,
its previous flag value (0x00000400) conflicted with NAND_BBT_SCANALLPAGES
so I changed its value to 0x00008000. All uses of the name were modified to
provide consistency with other "NAND_BBT_*" flags.

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 drivers/mtd/nand/nand_base.c |    6 +++---
 drivers/mtd/nand/nand_bbt.c  |    2 +-
 include/linux/mtd/bbm.h      |    2 ++
 include/linux/mtd/nand.h     |    2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 4a7b864..e6cf9ae 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -347,7 +347,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 
-	if (chip->options & NAND_BB_LAST_PAGE)
+	if (chip->options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
@@ -399,7 +399,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	uint8_t buf[2] = { 0, 0 };
 	int block, ret;
 
-	if (chip->options & NAND_BB_LAST_PAGE)
+	if (chip->options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	/* Get block number */
@@ -2946,7 +2946,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			 *maf_id == NAND_MFR_HYNIX))
-		chip->options |= NAND_BB_LAST_PAGE;
+		chip->options |= NAND_BBT_SCANLASTPAGE;
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ad97c0c..71d83be 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -432,7 +432,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		from = (loff_t)startblock << (this->bbt_erase_shift - 1);
 	}
 
-	if (this->options & NAND_BB_LAST_PAGE)
+	if (this->options & NAND_BBT_SCANLASTPAGE)
 		from += mtd->erasesize - (mtd->writesize * len);
 
 	for (i = startblock; i < numblocks;) {
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 9c3757c..8ad0b86 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -82,6 +82,8 @@ struct nand_bbt_descr {
 #define NAND_BBT_SAVECONTENT	0x00002000
 /* Search good / bad pattern on the first and the second page */
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
+/* Search good / bad pattern on the last page of the eraseblock */
+#define NAND_BBT_SCANLASTPAGE	0x00008000
 
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index a81b185..50f3aa0 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -181,8 +181,6 @@ typedef enum {
 #define NAND_NO_READRDY		0x00000100
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE	0x00000200
-/* Chip stores bad block marker on the last page of the eraseblock */
-#define NAND_BB_LAST_PAGE	0x00000400
 
 /* Device is one of 'new' xD cards that expose fake nand command set */
 #define NAND_BROKEN_XD		0x00000400
-- 
1.7.1




From SteveDeiters at BASLER.com  Wed Jun 23 18:20:48 2010
From: SteveDeiters at BASLER.com (Steve Deiters)
Date: Wed, 23 Jun 2010 17:20:48 -0500
Subject: JFFS2 corruption when mounting filesystem with filenames of length > 7
Message-ID: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com>

I found an archived post which seems to be identical to my issue.
However, this is quite old and there never seemed to be any resolution.

http://www.infradead.org/pipermail/linux-mtd/2006-September/016491.html

If I mount a filesystem that has filenames greater than 7 characters in
length, the files are corrupted when I mount.  In my case, I am making a
JFFS2 image with mkfs.jffs2 and flashing it in with u-boot.  However, I
have attached a workflow where I erase the Flash and create a new
filesystem completely within Linux and it gives the same behavior.  I
can list the files with the 'ls' command from within u-boot.  If I mount
from within Linux, and then reboot into u-boot, it will not display any
files that had a filename greater than 7 characters.

I enabled the MTD debug verbosity at level 2 for the attached example
session.

I am running on a custom board with a MPC5121 and Linux 2.6.33.4.

Thanks in advance for any help.


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

[root at freescale /]# cat /proc/version 
Linux version 2.6.33.4 (steved at teutatis) (gcc version 4.1.2) #1 PREEMPT
Wed Jun 23 21:29:57 UTC 2010
[root at freescale /]# uname -r
2.6.33.4
[root at freescale /]# flash_eraseall /dev/mtd0
[  476.694877] MTD_open
[  476.697768] MTD_ioctl
[  476.700995] MTD_ioctl
Erasing 128 Kiby[  476.705074] MTD_ioctl
te @ 0 --  0 % complete.Erasing 128 Kiby[  477.311449] MTD_ioctl
te @ 20000 --  0 % complete.Erasing 128 Kiby[  477.937350] MTD_ioctl
te @ 40000 --  1 % complete.Erasing 128 Kiby[  478.543415] MTD_ioctl
te @ 60000 --  2 % complete.Erasing 128 Kiby[  479.169413] MTD_ioctl
te @ 80000 --  3 % complete.Erasing 128 Kiby[  479.797409] MTD_ioctl
te @ a0000 --  4 % complete.Erasing 128 Kiby[  480.385415] MTD_ioctl
te @ c0000 --  5 % complete.Erasing 128 Kiby[  481.005417] MTD_ioctl
te @ e0000 --  5 % complete.Erasing 128 Kiby[  481.613412] MTD_ioctl
te @ 100000 --  6 % complete.Erasing 128 Kiby[  482.207417] MTD_ioctl
te @ 120000 --  7 % complete.Erasing 128 Kiby[  482.777411] MTD_ioctl
te @ 140000 --  8 % complete.Erasing 128 Kiby[  483.341414] MTD_ioctl
te @ 160000 --  9 % complete.Erasing 128 Kiby[  483.937408] MTD_ioctl
te @ 180000 -- 10 % complete.Erasing 128 Kiby[  484.539407] MTD_ioctl
te @ 1a0000 -- 10 % complete.Erasing 128 Kiby[  485.129387] MTD_ioctl
te @ 1c0000 -- 11 % complete.Erasing 128 Kiby[  485.711408] MTD_ioctl
te @ 1e0000 -- 12 % complete.Erasing 128 Kiby[  486.307414] MTD_ioctl
te @ 200000 -- 13 % complete.Erasing 128 Kiby[  486.859403] MTD_ioctl
te @ 220000 -- 14 % complete.Erasing 128 Kiby[  487.405413] MTD_ioctl
te @ 240000 -- 15 % complete.Erasing 128 Kiby[  487.949406] MTD_ioctl
te @ 260000 -- 15 % complete.Erasing 128 Kiby[  488.501398] MTD_ioctl
te @ 280000 -- 16 % complete.Erasing 128 Kiby[  489.039463] MTD_ioctl
te @ 2a0000 -- 17 % complete.Erasing 128 Kiby[  489.597407] MTD_ioctl
te @ 2c0000 -- 18 % complete.Erasing 128 Kiby[  490.135431] MTD_ioctl
te @ 2e0000 -- 19 % complete.Erasing 128 Kiby[  490.667421] MTD_ioctl
te @ 300000 -- 20 % complete.Erasing 128 Kiby[  491.225421] MTD_ioctl
te @ 320000 -- 20 % complete.Erasing 128 Kiby[  491.801422] MTD_ioctl
te @ 340000 -- 21 % complete.Erasing 128 Kiby[  492.359406] MTD_ioctl
te @ 360000 -- 22 % complete.Erasing 128 Kiby[  492.929373] MTD_ioctl
te @ 380000 -- 23 % complete.Erasing 128 Kiby[  493.517406] MTD_ioctl
te @ 3a0000 -- 24 % complete.Erasing 128 Kiby[  494.081421] MTD_ioctl
te @ 3c0000 -- 25 % complete.Erasing 128 Kiby[  494.657392] MTD_ioctl
te @ 3e0000 -- 25 % complete.Erasing 128 Kiby[  495.239480] MTD_ioctl
te @ 400000 -- 26 % complete.Erasing 128 Kiby[  495.785315] MTD_ioctl
te @ 420000 -- 27 % complete.Erasing 128 Kiby[  496.337561] MTD_ioctl
te @ 440000 -- 28 % complete.Erasing 128 Kiby[  496.890433] MTD_ioctl
te @ 460000 -- 29 % complete.Erasing 128 Kiby[  497.448404] MTD_ioctl
te @ 480000 -- 30 % complete.Erasing 128 Kiby[  498.006428] MTD_ioctl
te @ 4a0000 -- 30 % complete.Erasing 128 Kiby[  498.558430] MTD_ioctl
te @ 4c0000 -- 31 % complete.Erasing 128 Kiby[  499.104345] MTD_ioctl
te @ 4e0000 -- 32 % complete.Erasing 128 Kiby[  499.656398] MTD_ioctl
te @ 500000 -- 33 % complete.Erasing 128 Kiby[  500.188449] MTD_ioctl
te @ 520000 -- 34 % complete.Erasing 128 Kiby[  500.752413] MTD_ioctl
te @ 540000 -- 35 % complete.Erasing 128 Kiby[  501.310413] MTD_ioctl
te @ 560000 -- 35 % complete.Erasing 128 Kiby[  501.886407] MTD_ioctl
te @ 580000 -- 36 % complete.Erasing 128 Kiby[  502.438414] MTD_ioctl
te @ 5a0000 -- 37 % complete.Erasing 128 Kiby[  502.970403] MTD_ioctl
te @ 5c0000 -- 38 % complete.Erasing 128 Kiby[  503.534406] MTD_ioctl
te @ 5e0000 -- 39 % complete.Erasing 128 Kiby[  504.078407] MTD_ioctl
te @ 600000 -- 40 % complete.Erasing 128 Kiby[  504.642422] MTD_ioctl
te @ 620000 -- 40 % complete.Erasing 128 Kiby[  505.168390] MTD_ioctl
te @ 640000 -- 41 % complete.Erasing 128 Kiby[  505.720386] MTD_ioctl
te @ 660000 -- 42 % complete.Erasing 128 Kiby[  506.260435] MTD_ioctl
te @ 680000 -- 43 % complete.Erasing 128 Kiby[  506.794364] MTD_ioctl
te @ 6a0000 -- 44 % complete.Erasing 128 Kiby[  507.334434] MTD_ioctl
te @ 6c0000 -- 45 % complete.Erasing 128 Kiby[  507.860302] MTD_ioctl
te @ 6e0000 -- 45 % complete.Erasing 128 Kiby[  508.406415] MTD_ioctl
te @ 700000 -- 46 % complete.Erasing 128 Kiby[  508.964411] MTD_ioctl
te @ 720000 -- 47 % complete.Erasing 128 Kiby[  509.516411] MTD_ioctl
te @ 740000 -- 48 % complete.Erasing 128 Kiby[  510.048430] MTD_ioctl
te @ 760000 -- 49 % complete.Erasing 128 Kiby[  510.580409] MTD_ioctl
te @ 780000 -- 50 % complete.Erasing 128 Kiby[  511.120408] MTD_ioctl
te @ 7a0000 -- 50 % complete.Erasing 128 Kiby[  511.658412] MTD_ioctl
te @ 7c0000 -- 51 % complete.Erasing 128 Kiby[  512.190418] MTD_ioctl
te @ 7e0000 -- 52 % complete.Erasing 128 Kiby[  512.736399] MTD_ioctl
te @ 800000 -- 53 % complete.Erasing 128 Kiby[  513.262410] MTD_ioctl
te @ 820000 -- 54 % complete.Erasing 128 Kiby[  513.778481] MTD_ioctl
te @ 840000 -- 55 % complete.Erasing 128 Kiby[  514.298396] MTD_ioctl
te @ 860000 -- 55 % complete.Erasing 128 Kiby[  514.818489] MTD_ioctl
te @ 880000 -- 56 % complete.Erasing 128 Kiby[  515.358407] MTD_ioctl
te @ 8a0000 -- 57 % complete.Erasing 128 Kiby[  515.898442] MTD_ioctl
te @ 8c0000 -- 58 % complete.Erasing 128 Kiby[  516.492418] MTD_ioctl
te @ 8e0000 -- 59 % complete.Erasing 128 Kiby[  517.026409] MTD_ioctl
te @ 900000 -- 60 % complete.Erasing 128 Kiby[  517.560417] MTD_ioctl
te @ 920000 -- 60 % complete.Erasing 128 Kiby[  518.120397] MTD_ioctl
te @ 940000 -- 61 % complete.Erasing 128 Kiby[  518.654387] MTD_ioctl
te @ 960000 -- 62 % complete.Erasing 128 Kiby[  519.188439] MTD_ioctl
te @ 980000 -- 63 % complete.Erasing 128 Kiby[  519.722411] MTD_ioctl
te @ 9a0000 -- 64 % complete.Erasing 128 Kiby[  520.268410] MTD_ioctl
te @ 9c0000 -- 65 % complete.Erasing 128 Kiby[  520.808371] MTD_ioctl
te @ 9e0000 -- 65 % complete.Erasing 128 Kiby[  521.340426] MTD_ioctl
te @ a00000 -- 66 % complete.Erasing 128 Kiby[  521.886375] MTD_ioctl
te @ a20000 -- 67 % complete.Erasing 128 Kiby[  522.406406] MTD_ioctl
te @ a40000 -- 68 % complete.Erasing 128 Kiby[  522.932404] MTD_ioctl
te @ a60000 -- 69 % complete.Erasing 128 Kiby[  523.466408] MTD_ioctl
te @ a80000 -- 70 % complete.Erasing 128 Kiby[  523.986405] MTD_ioctl
te @ aa0000 -- 70 % complete.Erasing 128 Kiby[  524.520416] MTD_ioctl
te @ ac0000 -- 71 % complete.Erasing 128 Kiby[  525.060405] MTD_ioctl
te @ ae0000 -- 72 % complete.Erasing 128 Kiby[  525.588414] MTD_ioctl
te @ b00000 -- 73 % complete.Erasing 128 Kiby[  526.108414] MTD_ioctl
te @ b20000 -- 74 % complete.Erasing 128 Kiby[  526.624459] MTD_ioctl
te @ b40000 -- 75 % complete.Erasing 128 Kiby[  527.144416] MTD_ioctl
te @ b60000 -- 75 % complete.Erasing 128 Kiby[  527.664407] MTD_ioctl
te @ b80000 -- 76 % complete.Erasing 128 Kiby[  528.184584] MTD_ioctl
te @ ba0000 -- 77 % complete.Erasing 128 Kiby[  528.723423] MTD_ioctl
te @ bc0000 -- 78 % complete.Erasing 128 Kiby[  529.275406] MTD_ioctl
te @ be0000 -- 79 % complete.Erasing 128 Kiby[  529.815405] MTD_ioctl
te @ c00000 -- 80 % complete.Erasing 128 Kiby[  530.349408] MTD_ioctl
te @ c20000 -- 80 % complete.Erasing 128 Kiby[  530.869434] MTD_ioctl
te @ c40000 -- 81 % complete.Erasing 128 Kiby[  531.409400] MTD_ioctl
te @ c60000 -- 82 % complete.Erasing 128 Kiby[  531.937449] MTD_ioctl
te @ c80000 -- 83 % complete.Erasing 128 Kiby[  532.465425] MTD_ioctl
te @ ca0000 -- 84 % complete.Erasing 128 Kiby[  533.025384] MTD_ioctl
te @ cc0000 -- 85 % complete.Erasing 128 Kiby[  533.559411] MTD_ioctl
te @ ce0000 -- 85 % complete.Erasing 128 Kiby[  534.081395] MTD_ioctl
te @ d00000 -- 86 % complete.Erasing 128 Kiby[  534.597458] MTD_ioctl
te @ d20000 -- 87 % complete.Erasing 128 Kiby[  535.113484] MTD_ioctl
te @ d40000 -- 88 % complete.Erasing 128 Kiby[  535.641426] MTD_ioctl
te @ d60000 -- 89 % complete.Erasing 128 Kiby[  536.161425] MTD_ioctl
te @ d80000 -- 90 % complete.Erasing 128 Kiby[  536.677463] MTD_ioctl
te @ da0000 -- 90 % complete.Erasing 128 Kiby[  537.197360] MTD_ioctl
te @ dc0000 -- 91 % complete.Erasing 128 Kiby[  537.717470] MTD_ioctl
te @ de0000 -- 92 % complete.Erasing 128 Kiby[  538.251328] MTD_ioctl
te @ e00000 -- 93 % complete.Erasing 128 Kiby[  538.777539] MTD_ioctl
te @ e20000 -- 94 % complete.Erasing 128 Kiby[  539.337395] MTD_ioctl
te @ e40000 -- 95 % complete.Erasing 128 Kiby[  539.871411] MTD_ioctl
te @ e60000 -- 95 % complete.Erasing 128 Kiby[  540.393400] MTD_ioctl
te @ e80000 -- 96 % complete.Erasing 128 Kiby[  540.927416] MTD_ioctl
te @ ea0000 -- 97 % complete.Erasing 128 Kiby[  541.455414] MTD_ioctl
te @ ec0000 -- 98 % complete.Erasing 128 Kiby[  541.975420] MTD_ioctl
te @ ee0000 -- 99 % complete.Erasing 128 Kiby[  542.492047] MTD_close
te @ f00000 -- 100 % complete.
[root at freescale /]# mount -t jffs2 mtd0 /mnt/flash
[  636.371343] MTDSB: dev_name "mtd0"
[  636.374726] MTDSB: mtd%d, mtdnr 0
[  636.378013] MTDSB: New superblock for device 0 ("filesystem")
[root at freescale /]# cd /mnt/flash
[root at freescale flash]# touch 1
[root at freescale flash]# touch 12
[root at freescale flash]# touch 123
[root at freescale flash]# touch 1234
[root at freescale flash]# touch 12345
[root at freescale flash]# touch 123456
[root at freescale flash]# touch 1234567
[root at freescale flash]# touch 12345678
[root at freescale flash]# touch 123456789
[root at freescale flash]# touch 1234567890
[root at freescale flash]# ls -l
-rw-r--r--    1 root     root             0 Jan  1 00:10 1
-rw-r--r--    1 root     root             0 Jan  1 00:10 12
-rw-r--r--    1 root     root             0 Jan  1 00:10 123
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234
-rw-r--r--    1 root     root             0 Jan  1 00:10 12345
-rw-r--r--    1 root     root             0 Jan  1 00:10 123456
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234567
-rw-r--r--    1 root     root             0 Jan  1 00:10 12345678
-rw-r--r--    1 root     root             0 Jan  1 00:10 123456789
-rw-r--r--    1 root     root             0 Jan  1 00:11 1234567890
[root at freescale flash]# cd /
[root at freescale /]# umount /mnt/flash
[root at freescale /]# mount -t jffs2 mtd0 /mnt/flash
[  718.170535] MTDSB: dev_name "mtd0"
[  718.173934] MTDSB: mtd%d, mtdnr 0
[  718.177206] MTDSB: New superblock for device 0 ("filesystem")
[  718.189602] jffs2_scan_dirent_node(): Name CRC failed on node at
0x00e4036c: Read 0xffc205c6, calculated 0x88d63443
[  718.200658] jffs2_scan_dirent_node(): Name CRC failed on node at
0x00e403e0: Read 0x2dfd2d88, calculated 0xb0584e16
[  718.211700] jffs2_scan_dirent_node(): Name CRC failed on node at
0x00e40458: Read 0xc597c693, calculated 0xd2bdddb3
[root at freescale /]# ls -l /mnt/flash
-rw-r--r--    1 root     root             0 Jan  1 00:10 1
-rw-r--r--    1 root     root             0 Jan  1 00:10 12
-rw-r--r--    1 root     root             0 Jan  1 00:10 123
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234
-rw-r--r--    1 root     root             0 Jan  1 00:10 12345
-rw-r--r--    1 root     root             0 Jan  1 00:10 123456
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234567
[root at freescale /]# 


From norris at broadcom.com  Wed Jun 23 18:42:26 2010
From: norris at broadcom.com (Brian Norris)
Date: Wed, 23 Jun 2010 15:42:26 -0700
Subject: [PATCH] mtd-www doc, FAQ, general: spelling fixes
Message-ID: <1277332946-14580-1-git-send-email-norris@broadcom.com>

Several spelling, word choice, etc. edits throughout

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 doc/general.xml |    2 +-
 doc/nand.xml    |   60 +++++++++++++++++++++++++++---------------------------
 doc/onenand.xml |   18 ++++++++--------
 doc/ubi.xml     |   14 ++++++------
 doc/ubifs.xml   |   18 ++++++++--------
 faq/general.xml |    6 ++--
 faq/jffs2.xml   |   18 ++++++++--------
 faq/nand.xml    |   14 ++++++------
 faq/ubi.xml     |   48 ++++++++++++++++++++++----------------------
 faq/ubifs.xml   |   48 ++++++++++++++++++++++----------------------
 source.xml      |    2 +-
 11 files changed, 124 insertions(+), 124 deletions(-)

diff --git a/doc/general.xml b/doc/general.xml
index e170ace..4e1bfdd 100644
--- a/doc/general.xml
+++ b/doc/general.xml
@@ -122,7 +122,7 @@ git://git.infradead.org/users/ahunter/nand-tests.git
 	and nasty DMA issues on an OMAP2 board with OneNAND flash, just by
 	running this tests for few hours.</li>
 
-	<li><b>mtd_nandecctest</b>: a simple test that checks correctess of the
+	<li><b>mtd_nandecctest</b>: a simple test that checks correctness of the
 	built-in software ECC for 256 and 512-byte buffers; this test is not
 	driver-specific but tests general NAND support code.</li>
 </ul>
diff --git a/doc/nand.xml b/doc/nand.xml
index 549827b..776f891 100644
--- a/doc/nand.xml
+++ b/doc/nand.xml
@@ -16,8 +16,8 @@ NAND and NOR Flash is the bus interface. NOR Flash is connected to a address / d
  bus direct like other memory devices as SRAM etc. NAND Flash uses a multiplexed I/O 
  Interface with some additional control pins. NAND flash is a sequential access device 
  appropriate for mass storage applications, while NOR flash is a random access device 
- appropriate for code storage application.NOR Flash can be used for code storage and 
- code execution. Code stored on NAND Flash can't be executed frome there. It must be 
+ appropriate for code storage application. NOR Flash can be used for code storage and 
+ code execution. Code stored on NAND Flash can't be executed from there. It must be 
  loaded into RAM memory and executed from there.</p>
 		
 <table border="1" cellpadding="2" cellspacing="0">
@@ -72,13 +72,13 @@ smart by software.</p>
 <p>The memory is arranged as an array of pages. A page consists of 256 / 512 Byte data 
 and 8 / 16 Byte spare (out of band) area. Newer chips have 2048 Bytes data and and 64 
 Bytes spare area sizes. The spare area is used to store ECC (error correction code), 
-bad block information and filesystem dependend data.
+bad block information and filesystem-dependent data.
 n pages build one block. The read / write access to data is on a per page basis. 
 Erase is done on a per block basis. The commands to read / write / erase the chip 
 is given by writing to the chip with the Command Latch Enable pin high. Address is 
 given by writing with the Address Latch Enable pin high.</p>
 
-<p>There are only a few lines neccecary to access NAND Flashmemory.</p>
+<p>There are only a few lines necessary to access NAND Flashmemory.</p>
 <p>16 bit buswidth chips are supported.</p>
 <table border="1" cellpadding="2" cellspacing="0">
 <tr><td><b>Pin(s) </b></td><td><b>Function </b></td></tr>
@@ -92,7 +92,7 @@ given by writing with the Address Latch Enable pin high.</p>
 <tr><td>/SE </td><td>Spare area Enable </td></tr>
 <tr><td>R/B </td><td>Ready / Busy Output </td></tr>
 </table>
-<p>As it is neccecary to use the spare area, the /SE (Spare area Enable) pin should 
+<p>As it is necessary to use the spare area, the /SE (Spare area Enable) pin should 
 be tied to GND. /CE, CLE and ALE should be GPIO pins or latched signals. It's possible 
 to use address lines for ALE and CLE, but you have to take care about the timing 
 restrictions of the chip ! </p>
@@ -103,8 +103,8 @@ of your NAND chip. Data hold time after rising edge of /WE is different to data
 time after rising edge of chipselect lines!</p>
 <p>I/O 0-7(15) are connected to the databus D0-D7(D15). The /WP pin can be used for write 
 protection or connected to VCC to enable writes unconditionally. As NAND flash uses 
-a command driven programming and erasing, an  accidential write or erase is not 
-likely to happen. The Ready / Busy output is not neccecary for operation, 
+a command driven programming and erasing, an  accidental write or erase is not 
+likely to happen. The Ready / Busy output is not necessary for operation, 
  but it can be tied to a GPIO or an interrupt line. </p>
 </div>
 	
@@ -115,7 +115,7 @@ likely to happen. The Ready / Busy output is not neccecary for operation,
 <p>One major problem for using NAND Flash is, that you cannot write as often as you 
 want to a page. The consecutive writes to a page, before erasing it again, are 
 restricted to 1-3 writes, depending on the manufacturers specifications. This applies 
-similar to the spare area. This makes it neccecary for the filesystem to handle a writebuffer,
+similar to the spare area. This makes it necessary for the filesystem to handle a writebuffer,
 which contains data, that is less than a page</p>
 <p>At the moment there are only a few filesystems, which support NAND</p>
 <ul>
@@ -133,7 +133,7 @@ NAND code, is planned. There are some other Open Source projects for NAND filesy
 support, but there's no other working solution than JFFS2 and YAFFS at the moment of this writing. 
 YAFFS is available from <a href="http://www.aleph1.co.uk/armlinux/projects/yaffs">YAFFS-Homepage</a>.
 YAFFS is faster than JFFS2 and consumes less RAM, JFFS2 provides on the fly file compression and
-decompression, which is very helpfull for small FLASHs.</p>
+decompression, which is very helpful for small FLASHs.</p>
 <p> There is currently no support for the wide spread SmartMedia DOS-FAT filesystem, 
  mainly because it's not a reliable filesystem for industrial usage. It's ok for 
  multimedia applications. The hardware support layer is designed to support an 
@@ -156,11 +156,11 @@ area is the storage of the cleanmarker</p>
 <table border="1" cellpadding="2" cellspacing="0">
 <tr><td><b>Offset</b></td><td><b>Content</b></td><td><b>Comment</b></td></tr>
 <tr><td>0x06</td><td>Clean marker byte 0</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x85. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x07</td><td>Clean marker byte 1</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased this 
+block was erased under JFFS2 control. If the page was successfully erased this 
 byte in the first page of a block is programmed to 0x19. In the remaining 
 pages this byte is reserved</td></tr>
 </table>
@@ -170,35 +170,35 @@ pages this byte is reserved</td></tr>
 <table border="1" cellpadding="2" cellspacing="0">
 <tr><td><b>Offset</b></td><td><b>Content</b></td><td><b>Comment</b></td></tr>
 <tr><td>0x08</td><td>Clean marker byte 0</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x85. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x09</td><td>Clean marker byte 1</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x19. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0a</td><td>Clean marker byte 2</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x03. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0b</td><td>Clean marker byte 3</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x20. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0c</td><td>Clean marker byte 4</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x08. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0d</td><td>Clean marker byte 5</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0e</td><td>Clean marker byte 6</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0f</td><td>Clean marker byte 7</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 </table>
@@ -208,35 +208,35 @@ pages this byte is reserved</td></tr>
 <table border="1" cellpadding="2" cellspacing="0">
 <tr><td><b>Offset</b></td><td><b>Content</b></td><td><b>Comment</b></td></tr>
 <tr><td>0x10</td><td>Clean marker byte 0</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x85. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x11</td><td>Clean marker byte 1</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x19. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x12</td><td>Clean marker byte 2</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x03. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x13</td><td>Clean marker byte 3</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x20. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x14</td><td>Clean marker byte 4</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x08. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x15</td><td>Clean marker byte 5</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x16</td><td>Clean marker byte 6</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x17</td><td>Clean marker byte 7</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 </table>
@@ -260,9 +260,9 @@ kernel code at the moment. The latest code is available from
 <li>Hardware specific driver </li>
 </ol>
 <p>the MTD driver just provides a mount point for JFFS2. The generic NAND 
-driver provides all functions, which are neccecary to identify, read, write 
-and erase NAND Flash. The hardware dependend functions are provided by 
-the hardware driver. They provide mainly the hardware access informations and
+driver provides all functions, which are necessary to identify, read, write 
+and erase NAND Flash. The hardware dependent functions are provided by 
+the hardware driver. They provide mainly the hardware access information and
 functions for the generic NAND driver. For YAFFS applies the same.</p>
 </div>
 
diff --git a/doc/onenand.xml b/doc/onenand.xml
index c8fdd6e..e3bf69b 100644
--- a/doc/onenand.xml
+++ b/doc/onenand.xml
@@ -50,35 +50,35 @@ Nand chips with 2048 byte pagesize and 64 byte OOB size</h4>
 <table border="1" cellpadding="2" cellspacing="0">
 <tr><td><b>Offset</b></td><td><b>Content</b></td><td><b>Comment</b></td></tr>
 <tr><td>0x02</td><td>Clean marker byte 0</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x85. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x03</td><td>Clean marker byte 1</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x19. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x04</td><td>Clean marker byte 2</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x03. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0e</td><td>Clean marker byte 3</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x20. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x0f</td><td>Clean marker byte 4</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x08. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x12</td><td>Clean marker byte 5</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x13</td><td>Clean marker byte 6</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 <tr><td>0x14</td><td>Clean marker byte 7</td><td>This byte indicates that a 
-block was erased under JFFS2 control. If the page was succesfully erased 
+block was erased under JFFS2 control. If the page was successfully erased 
 this byte in the first page of a block is programmed to 0x00. In the remaining 
 pages this byte is reserved</td></tr>
 </table>
@@ -211,7 +211,7 @@ JFFS2 write-buffering enabled buffer (2048) erasesize (126976)<br />
 <h2>Yaffs2</h2>
 
 <p>The yaffs2 can run on OneNAND</p>
-<p>If your yaffs2 dosen't work, please check this <a href="http://git.infradead.org/?p=users/vwool/mtd-2.6.git;a=commitdiff;h=ee5b82bdacf2a69d247eca93271da2c72acdc950">patch</a></p>
+<p>If your yaffs2 doesn't work, please check this <a href="http://git.infradead.org/?p=users/vwool/mtd-2.6.git;a=commitdiff;h=ee5b82bdacf2a69d247eca93271da2c72acdc950">patch</a></p>
 
 <hr size="2" />
 		
diff --git a/doc/ubi.xml b/doc/ubi.xml
index 06d8cbd..9290f4a 100644
--- a/doc/ubi.xml
+++ b/doc/ubi.xml
@@ -46,7 +46,7 @@
 		</ol>
 	</li>
 	<li><a href="ubi.html#L_ubidoc">More documentation</a></li>
-	<li><a href="ubi.html#L_how_send_bugreport">How to send a bugreport?</a></li>
+	<li><a href="ubi.html#L_how_send_bugreport">How do I send a bug report?</a></li>
 </ol>
 
 
@@ -117,7 +117,7 @@ Bit-flips are corrected by ECC checksums, but they may accumulate over
 time and cause data loss. UBI handles this by moving data from physical
 eraseblocks which have bit-flips to other physical eraseblocks. This process is
 called <b>scrubbing</b>. Scrubbing is done transparently in background and is
-hidden from upper layes.</p>
+hidden from upper layers.</p>
 
 <p>Here is a short list of the main UBI features:</p>
 <ul>
@@ -343,7 +343,7 @@ table records</b>. Each record contains the following information:</p>
 	<li><code>CRC-32</code> checksum for this record.</li>
 </ul>
 
-<p>Each record descripes one UBI volume and record index in the volume table
+<p>Each record describes one UBI volume and record index in the volume table
 array corresponds to the volume ID. I.e, UBI volume 0 is described by record 0
 in the volume table, and so on. Count of records in the volume table is limited
 by the LEB size, but cannot be greater than 128. This means that UBI devices
@@ -377,7 +377,7 @@ volumes.</p>
 </ul>
 
 <p>When attaching the MTD device, UBI makes sure that the 2 volume table copies
-are equivalent. If they are not equevalent, which may be caused by an unclean
+are equivalent. If they are not equivalent, which may be caused by an unclean
 reboot, UBI picks the one from LEB0 and copies it to LEB1 of the layout volume
 (because it is newer). If one of the volume table copies is corrupted, UBI
 restores it from the other volume table copy.</p>
@@ -817,7 +817,7 @@ order to build in-RAM EC and EBA tables.</p>
 <p>The drawbacks of this design are poor scalability and relatively high
 overhead on NAND flashes (e.g., the overhead is 1.5%-3% of flash space in case
 of a NAND flash with 2KiB NAND page and 128KiB eraseblock). The advantages are
-simple binary format and robustness, as the result of symplicity.</p>
+simple binary format and robustness, as the result of simplicity.</p>
 
 <p>Nonetheless, it is always possible to create UBI2 which would maintain the
 tables in separate flash areas. UBI2 would not be compatible with UBI because
@@ -1182,7 +1182,7 @@ function (just above the body of the function).</p>
 
 
 
-<h2><a name="L_how_send_bugreport">How to send an UBI bugreport?</a></h2>
+<h2><a name="L_how_send_bugreport">How do I send an UBI bug report?</a></h2>
 
 <p>Before sending a bug report:</p>
 <ul>
@@ -1227,7 +1227,7 @@ function (just above the body of the function).</p>
 <p>Please, attach all the bug-related messages including the UBI messages from
 the kernel ring buffer, which may be collected using the <code>dmesg</code>
 utility or using <code>minicom</code> with serial console capturing. Please,
-describe how the problem can be reproduced (if it can be). The bugreport
+describe how the problem can be reproduced (if it can be). The bug report
 should be sent to the <a href="../mail.html">MTD mailing list</a>. Please,
 <b>do not</b> send private e-mails to UBI authors, always CC the mailing
 list!</p>
diff --git a/doc/ubifs.xml b/doc/ubifs.xml
index ed1a82d..afa5987 100644
--- a/doc/ubifs.xml
+++ b/doc/ubifs.xml
@@ -31,7 +31,7 @@
 	<li><a href="ubifs.html#L_mountopts">Mount options</a></li>
 	<li><a href="ubifs.html#L_spaceacc">Flash space accounting issues</a></li>
 	<li><a href="ubifs.html#L_documentation">Documentation</a></li>
-	<li><a href="ubifs.html#L_how_send_bugreport">How to send an UBIFS bugreport?</a></li>
+	<li><a href="ubifs.html#L_how_send_bugreport">How do I send an UBIFS bug report?</a></li>
 	<li><a href="ubifs.html#L_raw_vs_ftl">Raw flash vs. FTL devices</a></li>
 </ol>
 
@@ -328,7 +328,7 @@ describes the issues in more details.</p>
 	    bytes to the flash. If there are many random small writes all
 	    over the place, the file system becomes fragmented. JFFS2 merges
 	    small fragments to 4KiB chunks, which involves re-compression and
-	    re-writing the data. But this "de-fragmentation" is happening
+	    re-writing the data. But this "defragmentation" is happening
 	    during garbage collection and at random time, because JFFS2
 	    wear-leveling algorithm is based on random eraseblock selection. So
 	    if there were a lot of small writes, JFFS2 becomes slower some time
@@ -716,8 +716,8 @@ do this :-).</p>
 
 <h2><a name="L_compression">Compression</a></h2>
 
-<p>UBIFS supports on-the-flight compression, which means it compresses data
-before writing them to the flash media, and de-compresses before reading them,
+<p>UBIFS supports on-the-fly compression, which means it compresses data
+before writing them to the flash media, and decompresses before reading them,
 and this is absolutely transparent to the users. UBIFS compresses only regular
 files data. Directories, device nodes and so on are not compressed. Meta-data
 and the indexing information are not compressed as well.</p>
@@ -856,11 +856,11 @@ it will already be in the cache.</p>
 you should be careful. It is also worth noting that bulk-read feature cannot
 help on highly fragmented file-systems. Although UBIFS does not fragment
 file-systems (e.g., the Garbage-Collector does not re-order data nodes), but
-UBIFS does not try to de-fragment them. For example, if you write a file
+UBIFS does not try to defragment them. For example, if you write a file
 sequentially, it won't be fragmented. But if you write more than one file at
 a time, they may become fragmented (well, this also depends on how write-back
-flushes the changes), and UBIFS won't automatically de-fragment them. However,
-it is possible to implement a background de-fragmentator. It is also possible
+flushes the changes), and UBIFS won't automatically defragment them. However,
+it is possible to implement a background defragmenter. It is also possible
 to have per-inode journal head and avoid mixing data nodes belonging to
 different inodes in the same LEB. So there is room for improvements.</p>
 
@@ -1208,7 +1208,7 @@ at the <a href="ubifs.html#L_ml">UBIFS mailing list.</a></p>
 
 
 
-<h2><a name="L_how_send_bugreport">How to send an UBIFS bugreport?</a></h2>
+<h2><a name="L_how_send_bugreport">How do I send an UBIFS bug report?</a></h2>
 
 <p>Before sending a bug report, please, try to do the following:</p>
 <ol>
@@ -1446,7 +1446,7 @@ requirements.</p>
 	hints about unused sectors. Nevertheless, in general, UBIFS should do
 	better job on a bare NAND, than a traditional FS on an FTL device with
 	a similar NAND chip. On the other hand, FTL devices may	include
-	multiple NAND chips, highly parallelise things and provide fast I/O.
+	multiple NAND chips, highly parallelize things and provide fast I/O.
 	Probably SSD is a good example.</li>
 
 	<li>Obviously, the advantage of FTL devices is that you use old and
diff --git a/faq/general.xml b/faq/general.xml
index be1a0d4..9cd81ff 100644
--- a/faq/general.xml
+++ b/faq/general.xml
@@ -19,7 +19,7 @@
 	<LI><A HREF="general.html#L_ext2_mtd">Can I mount ext2 over an MTD device?</A></LI>
 	<LI><A HREF="general.html#L_point">What are the point() and unpoint() functions used for?</A></LI>
 	<LI><A HREF="general.html#L_unlock">I keep getting errors whenever I try to write or erase to my MTD device</A></LI>
-	<LI><A HREF="general.html#L_compile_mtd">How to compile the mtd-utils tree?</A></LI>
+	<LI><A HREF="general.html#L_compile_mtd">How do I compile the mtd-utils tree?</A></LI>
 </OL>
 
 
@@ -113,7 +113,7 @@ also block devices.</P>
 	</TR>
 	<TR>
 		<TD>Sectors are devoid of the wear-out property (in FTL devices
-			it is the resposibility of FTL to provide this) </TD>
+			it is the responsibility of FTL to provide this) </TD>
 		<TD>
 			Eraseblocks wear-out and become bad and unusable after
 			about 10<SUP>3</SUP> (for MLC NAND) - 10<SUP>5</SUP>
@@ -250,7 +250,7 @@ unlock them.
 
 
 <A NAME="L_compile_mtd">
-<H2>How to compile the mtd-utils tree?</H2>
+<H2>How do I compile the mtd-utils tree?</H2>
 </A>
 
 <p>You have to install libraries the tools depend on. Please, find
diff --git a/faq/jffs2.xml b/faq/jffs2.xml
index 50f525f..1bc8680 100644
--- a/faq/jffs2.xml
+++ b/faq/jffs2.xml
@@ -19,11 +19,11 @@
 	<LI><A HREF="jffs2.html#L_loopback">I cannot loop mount a JFFS2 image</A></LI>
 	<LI><A HREF="jffs2.html#L_mtdblock">Do I need to use mtdblock to mount my JFFS2 filesystem?</A></LI>
 	<LI><A HREF="jffs2.html#L_rootfs">How do I get the 2.6 kernel to recognize JFFS2 as my rootfs?</A></LI>
-	<LI><A HREF="jffs2.html#L_writewell">How is ensured, that data is written to flash?</A></LI>
-	<LI><A HREF="jffs2.html#L_putimage">How to program an image to FLASH?</A></LI>
+	<LI><A HREF="jffs2.html#L_writewell">How do I ensure that data is written to flash?</A></LI>
+	<LI><A HREF="jffs2.html#L_putimage">How do I program an image to flash?</A></LI>
 	<LI><A HREF="jffs2.html#L_bbhandle">How does JFFS2 handle a block going bad in NAND flash?</A></LI>
 	<LI><A HREF="jffs2.html#L_clmarker">What is cleanmarker and what it is used for?</A></LI>
-	<LI><A HREF="jffs2.html#L_mkfs_jffs2_comp">How to compile mkfs.jffs2?</A></LI>
+	<LI><A HREF="jffs2.html#L_mkfs_jffs2_comp">How do I compile mkfs.jffs2?</A></LI>
 </OL>
 
 
@@ -135,8 +135,8 @@ conventional HDD-oriented file system. And one of its drawbacks is that mount
 time as well as memory consumption grow linearly with growing flash size. So
 beware you may end up with tremendous amount memory eaten and huge mount time if
 your block device is very large. Also, JFFS2 implements only write-through
-caching (while convectional FS-es have write-back) and does many thing which are
-not really needed in case of hard drives.
+caching (while conventional filesystems have write-back) and does many things which are
+not really needed in the case of hard drives.
 </P>
 
 <P>
@@ -295,7 +295,7 @@ the kernel command line to use it as a root filesystem
 
 
 <A NAME="L_writewell">
-<H2>How is ensured, that data is written to flash?</H2>
+<H2>How do I ensure that data is written to flash?</H2>
 </A>
 
 <P>On <B>NOR FLASH</B> each write goes directly into the FLASH.</P>
@@ -321,14 +321,14 @@ dismounted, the filesystem should be remounted read only on shutdown. In the
 case of JFFS2 this will cause the garbage collector to flush its write buffers.
 Failure to do this may cause the filesystem to generate warnings regarding bad
 CRC. These are partially collected garbage blocks which will be rescheduled
-for garbage collection some time later. This kind of behaviour may also be
+for garbage collection some time later. This kind of behavior may also be
 observed after a system crash.
 </P>
 
 
 
 <A NAME="L_putimage">
-<H2>How to program an image to FLASH?</H2>
+<H2>How do I program an image to flash?</H2>
 </A>
 
 <P>There are several possibilities to do so:</P>
@@ -408,7 +408,7 @@ time.
 
 
 <A NAME="L_mkfs_jffs2_comp">
-<H2>How to compile mkfs.jffs2?</H2>
+<H2>How do I compile mkfs.jffs2?</H2>
 </A>
 
 <p>The <code>mkfs.jffs2</code> utility requires the <code>ACL</code> and
diff --git a/faq/nand.xml b/faq/nand.xml
index d105d63..a9188c5 100644
--- a/faq/nand.xml
+++ b/faq/nand.xml
@@ -13,12 +13,12 @@
 <OL>
 	<LI><A HREF="nand.html#L_nand_boot">Can I boot from NAND flash?</A></LI>
 	<LI><A HREF="nand.html#L_nand_32bit">Is there support for 32-bit wide NAND flash ?</A></LI>
-	<LI><A HREF="nand.html#L_nand_erase">How to erase my MTD partition on NAND flash?</A></LI>
+	<LI><A HREF="nand.html#L_nand_erase">How do I erase my MTD partition on NAND flash?</A></LI>
 	<LI><A HREF="nand.html#L_nand_copyimg">Can I copy a JFFS2 image to NAND via /dev/mtdX?</A></LI>
 	<LI><A HREF="nand.html#L_nand_srw">Can I use seek/read/write on /dev/mtdX?</A></LI>
 	<LI><A HREF="nand.html#L_nand_bootloader">Must my boot-loader be aware of NAND flash?</A></LI>
 	<LI><A HREF="nand.html#L_nand_jtag">Can I program NAND via JTAG?</A></LI>
-	<LI><A HREF="nand.html#L_nand_nandsim">How to use NAND simulator?</A></LI>
+	<LI><A HREF="nand.html#L_nand_nandsim">How do I use NAND simulator?</A></LI>
 </OL>
 
 
@@ -69,7 +69,7 @@ neither.
 
 
 <A NAME="L_nand_erase">
-<H2>How to erase my MTD partition on NAND flash?</H2>
+<H2>How do I erase my MTD partition on NAND flash?</H2>
 </A>
 
 <P>
@@ -78,7 +78,7 @@ utilities may be used. If you are going to use this partition with JFFS2, then
 it is recommended to use <CODE>-j</CODE> or <CODE>--jffs2</CODE> options. This
 will write the so called "clean-marker" to the out of band area, so you can
 mount the file-system and no further formatting is needed. This is also
-necessary before you copy a FS-image to the chip.
+necessary before you copy a filesystem image to the chip.
 </P>
 
 
@@ -177,7 +177,7 @@ Yes, you can. The requirements are the same as for boot-loaders
 
 
 <A NAME="L_nand_nandsim">
-<H2>How to use NAND simulator?</H2>
+<H2>How do I use NAND simulator?</H2>
 </A>
 
 <P>
@@ -236,10 +236,10 @@ flash on top of a file. Please, use the <CODE>cache_file</CODE> nandsim module
 parameter.</P>
 
 <P><CODE>nandsim</CODE> can emulate various errors and report wear statistics,
-which is extrimely useful when testing how flash software handles errors (e.g.,
+which is extremely useful when testing how flash software handles errors (e.g.,
 what does JFFS2 do in case of bit-flips or write errors).</P>
 
-<P>Note, theoretically <CODE>nandsim</CODE> can emulate 16-bit bus witdth
+<P>Note, theoretically <CODE>nandsim</CODE> can emulate 16-bit bus width
 devices, but it this may not work.</P>
 
 <INCLUDE file="../inc/footer.tmpl" />
diff --git a/faq/ubi.xml b/faq/ubi.xml
index 1b2f2f3..908b095 100644
--- a/faq/ubi.xml
+++ b/faq/ubi.xml
@@ -13,35 +13,35 @@
 
 <h2>Table of contents</h2>
 <ol>
-	<li><a href="ubi.html#L_enable_ubi">How to enable UBI?</a></li>
-	<li><a href="ubi.html#L_attachmtd">How to attach an MTD device?</a></li>
-	<li><a href="ubi.html#L_mkvol">How to create/delete UBI volumes?</a></li>
-	<li><a href="ubi.html#L_run_jffs2">How to run JFFS2 on top of an UBI volume?</a></li>
+	<li><a href="ubi.html#L_enable_ubi">How do I enable UBI?</a></li>
+	<li><a href="ubi.html#L_attachmtd">How do I attach an MTD device?</a></li>
+	<li><a href="ubi.html#L_mkvol">How do I create/delete UBI volumes?</a></li>
+	<li><a href="ubi.html#L_run_jffs2">How do I run JFFS2 on top of an UBI volume?</a></li>
 	<li><a href="ubi.html#L_ext2_over_ubi">Can I run ext2 on top of UBI?</a></li>
 	<li><a href="ubi.html#L_format_mtd">Do I have to format my empty flash before running UBI on top of it?</a></li>
-	<li><a href="ubi.html#L_ubierase">How to erase flash and preserve erase counters?</a></li>
-	<li><a href="ubi.html#L_ubi_mkimg">How to create UBI images?</a></li>
-	<li><a href="ubi.html#L_find_min_io_size">How to find out min. I/O unit size, sub-page size, and LEB size?</a></li>
-	<li><a href="ubi.html#L_flash_img">How to flash UBI images and preserve erase counters?</a></li>
+	<li><a href="ubi.html#L_ubierase">How do I erase flash and preserve erase counters?</a></li>
+	<li><a href="ubi.html#L_ubi_mkimg">How do I create UBI images?</a></li>
+	<li><a href="ubi.html#L_find_min_io_size">How do I find out min. I/O unit size, sub-page size, and LEB size?</a></li>
+	<li><a href="ubi.html#L_flash_img">How do I flash UBI images and preserve erase counters?</a></li>
 	<li><a href="ubi.html#L_restrict">Can UBI logical eraseblocks be written randomly?</a></li>
 	<li><a href="ubi.html#L_why_no_oob">Why UBI does not use OOB area of NAND flashes?</a></li>
 	<li><a href="ubi.html#L_crash_safe">Is UBI tolerant of power failures?</a></li>
 	<li><a href="ubi.html#L_mlc">May UBI be used on MLC flash?</a></li>
 	<li><a href="ubi.html#L_vid_offset_mismatch">Why does ubiattach on a freshly formatted device fail with "Invalid argument"?</a></li>
-	<li><a href="ubi.html#L_subpage">What is sub-page?</a></li>
+	<li><a href="ubi.html#L_subpage">What is a sub-page?</a></li>
 	<li><a href="ubi.html#L_subpage_verify_fail">I get "ubi_io_write: error -5 while writing 512 bytes to PEB 5:512"</a></li>
 	<li><a href="ubi.html#L_no_vid_header">I get "no VID header found at PEB 7923, only 0xFF bytes"</a></li>
 	<li><a href="ubi.html#L_ecc_error">I get: "ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 47:4096, read 126976 bytes"</a></li>
-	<li><a href="ubi.html#L_force_no_subpage">How to force UBI to ignore sub-pages?</a></li>
-	<li><a href="ubi.html#L_flasher">How to implement UBI flasher?</a></li>
+	<li><a href="ubi.html#L_force_no_subpage">How do I force UBI to ignore sub-pages?</a></li>
+	<li><a href="ubi.html#L_flasher">How do I implement UBI flasher?</a></li>
 	<li><a href="ubi.html#L_bgt_thread">What does the "ubi_bgt0d" thread do?</a></li>
 	<li><a href="ubi.html#L_attach_faster">How do I speed up UBI initialization</a></li>
-	<li><a href="ubi.html#L_how_debug">How to debug UBI?</a></li>
+	<li><a href="ubi.html#L_how_debug">How do I debug UBI?</a></li>
 </ol>
 
 
 
-<h2><a name="L_enable_ubi">How to enable UBI?</a></h2>
+<h2><a name="L_enable_ubi">How do I enable UBI?</a></h2>
 
 <p>In the Linux configuration menu, go to "<b>Device Drivers</b>" ->
 "<b>Memory Technology Devices (MTD)</b>" -> "<b>UBI - Unsorted block images</b>",
@@ -50,7 +50,7 @@ kernel or be built as a kernel module.</p>
 
 
 
-<h2><a name="L_attachmtd">How to attach an MTD device?</a></h2>
+<h2><a name="L_attachmtd">How do I attach an MTD device?</a></h2>
 
 <p>Each MTD device has a name and a number, which you may find out by
 examining the <code>/proc/mtd</code> file. The preferable way to attach
@@ -112,7 +112,7 @@ numbers.</p>
 
 
 
-<h2><a name="L_mkvol">How to create/delete UBI volumes?</a></h2>
+<h2><a name="L_mkvol">How do I create/delete UBI volumes?</a></h2>
 
 <p>Use the <code>ubimkvol</code> and <code>ubirmvol</code>
 <a href="../doc/ubi.html#L_usptools">utilities</a>. For example, the below command
@@ -133,7 +133,7 @@ $ ubirmvol /dev/ubi0 -n 0
 
 
 
-<h2><a name="L_run_jffs2">How to run JFFS2 on top of an UBI volume?</a></h2>
+<h2><a name="L_run_jffs2">How do I run JFFS2 on top of an UBI volume?</a></h2>
 
 <p>There is an additional driver called <code>gluebi</code> which can emulate
 fake MTD devices for each UBI volume and JFFS2 can be used with these emulated
@@ -192,7 +192,7 @@ flashing programs.</p>
 
 
 <h2><a name="L_ubierase">
-	How to erase flash and preserve erase counters?
+	How do I erase flash and preserve erase counters?
 </a></h2>
 
 <p>Use the <a href="../doc/ubi.html#L_usptools"><code>ubiformat</code></a>
@@ -217,7 +217,7 @@ for those who implement a custom UBI flasher.</p>
 
 
 
-<h2><a name="L_ubi_mkimg">How to create UBI images?</a></h2>
+<h2><a name="L_ubi_mkimg">How do I create UBI images?</a></h2>
 
 <p>UBI images may be created using the
 <a href="../doc/ubi.html#L_usptools"><code>ubinize</code></a> utility. This
@@ -317,7 +317,7 @@ UBI-aware flashing programs should work in
 
 
 <h2><a name="L_find_min_io_size">
-	How to find out min. I/O unit size, sub-page size, and LEB size?
+	How do I find out min. I/O unit size, sub-page size, and LEB size?
 </a></h2>
 
 <p>If you run kernel version <code>2.6.30</code> or later, the easiest
@@ -347,7 +347,7 @@ there).</p>
 
 
 <h2><a name="L_flash_img">
-	How to flash UBI images and preserve erase counters?
+	How do I flash UBI images and preserve erase counters?
 </a></h2>
 
 <p>Use the <a href="../doc/ubi.html#L_usptools"><code>ubiformat</code></a>
@@ -515,7 +515,7 @@ ubi.mtd=0,2048
 
 
 
-<h2><a name="L_subpage">What is sub-page?</a></h2>
+<h2><a name="L_subpage">What is a sub-page?</a></h2>
 
 <p>Please, refer <a href="../doc/ubi.html#L_subpage">this</a> section.</p>
 
@@ -575,7 +575,7 @@ them properly.</p>
 
 
 
-<h2><a name="L_force_no_subpage">How to force UBI to ignore sub-pages?"</a></h2>
+<h2><a name="L_force_no_subpage">How do I force UBI to ignore sub-pages?"</a></h2>
 
 <p>If your NAND flash supports
 <a href="../doc/ubi.html#L_subpage">sub-pages</a>, UBI will use them. But
@@ -625,7 +625,7 @@ avoid using the <code>-s</code> parameter.</p>
 
 
 
-<h2><a name="L_flasher">How to implement UBI flasher?</a></h2>
+<h2><a name="L_flasher">How do I implement UBI flasher?</a></h2>
 
 <p>Please, read <a href="../doc/ubi.html#L_flasher_algo">here</a></p>
 
@@ -706,7 +706,7 @@ can do about it but without re-designing. Here are some ideas</p>
 
 
 
-<h2><a name="L_how_debug">How to debug UBI?</a></h2>
+<h2><a name="L_how_debug">How do I debug UBI?</a></h2>
 
 <h3><a name="L_how_debug_fake_mtd">Use fake MTD device</a></h3>
 
diff --git a/faq/ubifs.xml b/faq/ubifs.xml
index d61a0c5..9dd5d3d 100644
--- a/faq/ubifs.xml
+++ b/faq/ubifs.xml
@@ -13,31 +13,31 @@
 
 <h2>Table of contents</h2>
 <ol>
-	<li><a href="ubifs.html#L_enable_ubifs">How to enable UBIFS?</a></li>
+	<li><a href="ubifs.html#L_enable_ubifs">How do I enable UBIFS?</a></li>
 	<li><a href="ubifs.html#L_ubifs_mlc">May UBIFS be used on MLC NAND flash?</a></li>
-	<li><a href="ubifs.html#L_mount_ubifs">How to mount UBIFS?</a></li>
-	<li><a href="ubifs.html#L_mkfubifs">How to create an UBIFS image?</a></li>
+	<li><a href="ubifs.html#L_mount_ubifs">How do I mount UBIFS?</a></li>
+	<li><a href="ubifs.html#L_mkfubifs">How do I create an UBIFS image?</a></li>
 	<li><a href="ubifs.html#L_emptyflash">May an empty UBI volume be mounted?</a></li>
 	<li><a href="ubifs.html#L_max_leb_cnt">What is the purpose of -c (--max-leb-cnt) mkfs.ubifs option?</a></li>
-	<li><a href="ubifs.html#L_why_ubiformat">Why I have to use ubiformat?</a></li>
-	<li><a href="ubifs.html#L_mkfs_ubifs_comp">How to compile mkfs.ubifs?</a></li>
+	<li><a href="ubifs.html#L_why_ubiformat">Why do I have to use ubiformat?</a></li>
+	<li><a href="ubifs.html#L_mkfs_ubifs_comp">How do I compile mkfs.ubifs?</a></li>
 	<li><a href="ubifs.html#L_favor_lzo">What is "favor LZO" compression?</a></li>
 	<li><a href="ubifs.html#L_loop_mount">Can UBIFS mount loop-back devices?</a></li>
-	<li><a href="ubifs.html#L_atomic_change">How to change a file atomically?</a></li>
+	<li><a href="ubifs.html#L_atomic_change">How do I change a file atomically?</a></li>
 	<li><a href="ubifs.html#L_atime">Does UBIFS support atime?</a></li>
 	<li><a href="ubifs.html#L_nfs">Does UBIFS support NFS?</a></li>
 	<li><a href="ubifs.html#L_slow_when_full">Does UBIFS become slower when it is full?</a></li>
 	<li><a href="ubifs.html#L_df_report">Why <code>df</code> reports too few free space?</a></li>
-	<li><a href="ubifs.html#L_comproff">How to disable compression?</a></li>
-	<li><a href="ubifs.html#L_ubifs_nandsim">How to use UBIFS with nandsim?</a></li>
-	<li><a href="ubifs.html#L_ubifs_extract">How to extract files from an UBI/UBIFS image?</a></li>
+	<li><a href="ubifs.html#L_comproff">How do I disable compression?</a></li>
+	<li><a href="ubifs.html#L_ubifs_nandsim">How do I use UBIFS with nandsim?</a></li>
+	<li><a href="ubifs.html#L_ubifs_extract">How do I extract files from an UBI/UBIFS image?</a></li>
 	<li><a href="ubifs.html#L_powercut">Is UBIFS tolerant to power-cuts?</a></li>
 	<li><a href="ubifs.html#L_smaller_jrn">I need more space - should I make UBIFS journal smaller?</a></li>
 	<li><a href="ubifs.html#L_empty_file">Why my file is empty after an unclean reboot?</a></li>
 	<li><a href="ubifs.html#L_end_hole">Why my file has zeroes at the end after an unclean reboot?</a></li>
 	<li><a href="ubifs.html#L_bgt_thread">What does the "ubifs_bgt0_0" thread do?</a></li>
 	<li><a href="ubifs.html#L_sudden_ro">UBIFS suddenly became read-only - what is this?</a></li>
-	<li><a href="ubifs.html#L_detect_ro">How to detect if UBIFS became read-only?</a></li>
+	<li><a href="ubifs.html#L_detect_ro">How do I detect if UBIFS became read-only?</a></li>
 	<li><a href="ubifs.html#L_lebsz_mismatch">I get: "validate_sb: LEB size mismatch: 129024 in superblock, 126976 real"</a></li>
 	<li><a href="ubifs.html#L_pdflush_blocked">I get: "INFO: task pdflush:110 blocked for more than 120 seconds"</a></li>
 	<li><a href="ubifs.html#L_few_lebs">I get: "init_constants_early: too few LEBs (12), min. is 17"</a></li>
@@ -46,7 +46,7 @@
 
 
 
-<h2><a name="L_enable_ubifs">How to enable UBIFS?</a></h2>
+<h2><a name="L_enable_ubifs">How do I enable UBIFS?</a></h2>
 
 <p>Since UBIFS works on top of UBI, you have to enable UBI first (see
 <a href="ubi.html#L_enable_ubi">here</a>).</p>
@@ -122,7 +122,7 @@ appreciated.</p>
 
 
 
-<h2><a name="L_mount_ubifs">How to mount UBIFS?</a></h2>
+<h2><a name="L_mount_ubifs">How do I mount UBIFS?</a></h2>
 
 <p>The modern way of mounting UBIFS is mounting UBI volume character device
 nodes, e.g.:</p>
@@ -196,7 +196,7 @@ UBI volumes.</p>
 
 
 
-<h2><a name="L_mkfubifs">How to create an UBIFS image?</a></h2>
+<h2><a name="L_mkfubifs">How do I create an UBIFS image?</a></h2>
 
 <p>Creating UBIFS images might be a little trickier than creating JFFS2 images.
 First of all, you have to understand that UBIFS works on top of UBI which works
@@ -549,7 +549,7 @@ in the kernel.</p>
 
 
 
-<h2><a name="L_why_ubiformat">Why I have to use ubiformat?</a></h2>
+<h2><a name="L_why_ubiformat">Why do I have to use ubiformat?</a></h2>
 
 <p>The first obvious reason is that <code>ubiformat</code> preserves erase
 counters, so you do not lose your wear-leveling information when flashing new
@@ -595,7 +595,7 @@ written once and only once after the erasure. If you use
 
 
 
-<h2><a name="L_mkfs_ubifs_comp">How to compile mkfs.ubifs?</a></h2>
+<h2><a name="L_mkfs_ubifs_comp">How do I compile mkfs.ubifs?</a></h2>
 
 <p>The <code>mkfs.ubifs</code> utility requires <i>zlib</i>, <i>lzo</i> and
 <i>uuid</i> libraries. The former two are used for compressing the data, and the
@@ -611,7 +611,7 @@ information about other dependencies in the  <code>mtd-utils</code> tree.</p>
 
 
 
-<h2><a name="L_atomic_change">How to change a file atomically?</a></h2>
+<h2><a name="L_atomic_change">How do I change a file atomically?</a></h2>
 
 <p>Changing a file atomically means changing its contents in a way that unclean
 reboots could not lead to any corruption or inconsistency in the file. The only
@@ -778,7 +778,7 @@ the <code>df</code> report is changing, you will notice that the amount of free
 space continuously grows until reaches its final value. This happens because the
 kernel starts writing the dirty data back by time-out (5 sec by default) and
 the amount of dirty data goes down, making the <code>df</code> report more
-precize.</p>
+precise.</p>
 
 <p>If you want to have as precise free space prediction as possible -
 synchronize the file-system. This not only flushes dirty data to the media,
@@ -806,7 +806,7 @@ accurate is free space reporting.</p>
 
 
 
-<h2><a name="L_comproff">How to disable compression?</a></h2>
+<h2><a name="L_comproff">How do I disable compression?</a></h2>
 
 <p>UBIFS compression may be disabled for whole file system during the image
 creation time using the "<code>-x none</code>" <a
@@ -845,7 +845,7 @@ embedded systems.</p>
 
 
 
-<h2><a name="L_ubifs_nandsim">How to use UBIFS with nandsim?</a></h2>
+<h2><a name="L_ubifs_nandsim">How do I use UBIFS with nandsim?</a></h2>
 
 <p>The same way as with any MTD device. Here is an example of how to load
 <code>nandsim</code>, create an UBI volume and mount it.</p>
@@ -876,13 +876,13 @@ mount -t ubifs /dev/ubi0_0 /mnt/ubifs
 
 
 
-<h2><a name="L_ubifs_extract">How to extract files from an UBI/UBIFS image?</a></h2>
+<h2><a name="L_ubifs_extract">How do I extract files from an UBI/UBIFS image?</a></h2>
 
 <p>Unfortunately, at the moment there are no user-space tools which can
-un-wrap UBI and UBIFS images. UBIFS cannot be loop-back mounted as well,
+unwrap UBI and UBIFS images. UBIFS cannot be loop-back mounted as well,
 because it does not work with block devices.</p>
 
-<p>However, there is a hacky way to un-wrap UBI/UBIFS images. But you have
+<p>However, there is a hacky way to unwrap UBI/UBIFS images. But you have
 to make sure you have UBIFS support in your host machine. UBIFS is a relatively
 new file system and is not supported by all Linux distributions. But at least
 Fedora 11 does include it.</p>
@@ -1105,7 +1105,7 @@ an UBIFS bug, please, send a
 
 
 
-<h2><a name="L_detect_ro">How to detect if UBIFS became read-only?</a></h2>
+<h2><a name="L_detect_ro">How do I detect if UBIFS became read-only?</a></h2>
 
 <p>If you use up-to-date UBIFS which includes commit
 <code>2fde99cb55fb9d9b88180512a5e8a5d939d27fec</code>
@@ -1178,7 +1178,7 @@ I get: "init_constants_early: too few LEBs (12), min. is 17"
 <p>This error means that you are trying to mount too small UBI volume.
 Probably because you flash is too small? Try to use JFFS2 then, becasue it
 suits small flashes better since it has much lower space overhead. Indeed,
-UBIFS sotores much more indexing information on the flash media than JFFS2, so
+UBIFS stores much more indexing information on the flash media than JFFS2, so
 it has much higher overhead. Also, UBI has some overhead (see
 <a href="../doc/ubi.html#L_overhead">here</a>). Thus, if you have a small flash
 device (e.g., about 64MiB), it makes sense to consider using JFFS2.</p>
diff --git a/source.xml b/source.xml
index c3c5e0e..3df28da 100644
--- a/source.xml
+++ b/source.xml
@@ -103,7 +103,7 @@ or not.</P>
   thing. Please don't ask us about it though.</P>
 
 <P>If you are using the ancient 2.4 kernel, that's probably
-because you're interested in stabliity -- it is old and long-tested
+because you're interested in stablity -- it is old and long-tested
 code. If that's what you want, then you should use the original JFFS2
 code which is part of the 2.4 kernel. It's old and slow and doesn't
 support NAND flash, but it <em>is</em> stable, and is maintained.</P>
-- 
1.7.1




From SteveDeiters at BASLER.com  Wed Jun 23 18:42:02 2010
From: SteveDeiters at BASLER.com (Steve Deiters)
Date: Wed, 23 Jun 2010 17:42:02 -0500
Subject: JFFS2 corruption when mounting filesystem with filenames of
	length > 7
In-Reply-To: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com>
References: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com>
Message-ID: <181804936ABC2349BE503168465576460F1AAEE1@exchserver.basler.com>

> -----Original Message-----
> From: linux-mtd-bounces at lists.infradead.org 
> [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of 
> Steve Deiters
> Sent: Wednesday, June 23, 2010 5:21 PM
> To: linux-mtd at lists.infradead.org
> Subject: JFFS2 corruption when mounting filesystem with 
> filenames of length > 7
> 
> I found an archived post which seems to be identical to my issue.
> However, this is quite old and there never seemed to be any 
> resolution.
> 
> http://www.infradead.org/pipermail/linux-mtd/2006-September/01
> 6491.html
> 
> If I mount a filesystem that has filenames greater than 7 
> characters in length, the files are corrupted when I mount.  
> In my case, I am making a
> JFFS2 image with mkfs.jffs2 and flashing it in with u-boot.  
> However, I have attached a workflow where I erase the Flash 
> and create a new filesystem completely within Linux and it 
> gives the same behavior.  I can list the files with the 'ls' 
> command from within u-boot.  If I mount from within Linux, 
> and then reboot into u-boot, it will not display any files 
> that had a filename greater than 7 characters.
> 
> I enabled the MTD debug verbosity at level 2 for the attached 
> example session.
> 
> I am running on a custom board with a MPC5121 and Linux 2.6.33.4.
> 
> Thanks in advance for any help.


Sorry for the jumbled mess.  Looks like the line endings are messed up.
Trying again.  I also provided this as an attachment in case it gets
messed up again.

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

[root at freescale /]# cat /proc/version 
Linux version 2.6.33.4 (steved at teutatis) (gcc version 4.1.2) #1 PREEMPT
Wed Jun 23 21:29:57 UTC 2010
[root at freescale /]# uname -r
2.6.33.4
[root at freescale /]# flash_eraseall /dev/mtd0
[  476.694877] MTD_open
[  476.697768] MTD_ioctl
[  476.700995] MTD_ioctl
Erasing 128 Kiby[  476.705074] MTD_ioctl
te @ 0 --  0 % complete.Erasing 128 Kiby[  477.311449] MTD_ioctl
te @ 20000 --  0 % complete.Erasing 128 Kiby[  477.937350] MTD_ioctl
te @ 40000 --  1 % complete.Erasing 128 Kiby[  478.543415] MTD_ioctl
te @ 60000 --  2 % complete.Erasing 128 Kiby[  479.169413] MTD_ioctl
te @ 80000 --  3 % complete.Erasing 128 Kiby[  479.797409] MTD_ioctl
te @ a0000 --  4 % complete.Erasing 128 Kiby[  480.385415] MTD_ioctl
te @ c0000 --  5 % complete.Erasing 128 Kiby[  481.005417] MTD_ioctl
te @ e0000 --  5 % complete.Erasing 128 Kiby[  481.613412] MTD_ioctl
te @ 100000 --  6 % complete.Erasing 128 Kiby[  482.207417] MTD_ioctl
te @ 120000 --  7 % complete.Erasing 128 Kiby[  482.777411] MTD_ioctl
te @ 140000 --  8 % complete.Erasing 128 Kiby[  483.341414] MTD_ioctl
te @ 160000 --  9 % complete.Erasing 128 Kiby[  483.937408] MTD_ioctl
te @ 180000 -- 10 % complete.Erasing 128 Kiby[  484.539407] MTD_ioctl
te @ 1a0000 -- 10 % complete.Erasing 128 Kiby[  485.129387] MTD_ioctl
te @ 1c0000 -- 11 % complete.Erasing 128 Kiby[  485.711408] MTD_ioctl
te @ 1e0000 -- 12 % complete.Erasing 128 Kiby[  486.307414] MTD_ioctl
te @ 200000 -- 13 % complete.Erasing 128 Kiby[  486.859403] MTD_ioctl
te @ 220000 -- 14 % complete.Erasing 128 Kiby[  487.405413] MTD_ioctl
te @ 240000 -- 15 % complete.Erasing 128 Kiby[  487.949406] MTD_ioctl
te @ 260000 -- 15 % complete.Erasing 128 Kiby[  488.501398] MTD_ioctl
te @ 280000 -- 16 % complete.Erasing 128 Kiby[  489.039463] MTD_ioctl
te @ 2a0000 -- 17 % complete.Erasing 128 Kiby[  489.597407] MTD_ioctl
te @ 2c0000 -- 18 % complete.Erasing 128 Kiby[  490.135431] MTD_ioctl
te @ 2e0000 -- 19 % complete.Erasing 128 Kiby[  490.667421] MTD_ioctl
te @ 300000 -- 20 % complete.Erasing 128 Kiby[  491.225421] MTD_ioctl
te @ 320000 -- 20 % complete.Erasing 128 Kiby[  491.801422] MTD_ioctl
te @ 340000 -- 21 % complete.Erasing 128 Kiby[  492.359406] MTD_ioctl
te @ 360000 -- 22 % complete.Erasing 128 Kiby[  492.929373] MTD_ioctl
te @ 380000 -- 23 % complete.Erasing 128 Kiby[  493.517406] MTD_ioctl
te @ 3a0000 -- 24 % complete.Erasing 128 Kiby[  494.081421] MTD_ioctl
te @ 3c0000 -- 25 % complete.Erasing 128 Kiby[  494.657392] MTD_ioctl
te @ 3e0000 -- 25 % complete.Erasing 128 Kiby[  495.239480] MTD_ioctl
te @ 400000 -- 26 % complete.Erasing 128 Kiby[  495.785315] MTD_ioctl
te @ 420000 -- 27 % complete.Erasing 128 Kiby[  496.337561] MTD_ioctl
te @ 440000 -- 28 % complete.Erasing 128 Kiby[  496.890433] MTD_ioctl
te @ 460000 -- 29 % complete.Erasing 128 Kiby[  497.448404] MTD_ioctl
te @ 480000 -- 30 % complete.Erasing 128 Kiby[  498.006428] MTD_ioctl
te @ 4a0000 -- 30 % complete.Erasing 128 Kiby[  498.558430] MTD_ioctl
te @ 4c0000 -- 31 % complete.Erasing 128 Kiby[  499.104345] MTD_ioctl
te @ 4e0000 -- 32 % complete.Erasing 128 Kiby[  499.656398] MTD_ioctl
te @ 500000 -- 33 % complete.Erasing 128 Kiby[  500.188449] MTD_ioctl
te @ 520000 -- 34 % complete.Erasing 128 Kiby[  500.752413] MTD_ioctl
te @ 540000 -- 35 % complete.Erasing 128 Kiby[  501.310413] MTD_ioctl
te @ 560000 -- 35 % complete.Erasing 128 Kiby[  501.886407] MTD_ioctl
te @ 580000 -- 36 % complete.Erasing 128 Kiby[  502.438414] MTD_ioctl
te @ 5a0000 -- 37 % complete.Erasing 128 Kiby[  502.970403] MTD_ioctl
te @ 5c0000 -- 38 % complete.Erasing 128 Kiby[  503.534406] MTD_ioctl
te @ 5e0000 -- 39 % complete.Erasing 128 Kiby[  504.078407] MTD_ioctl
te @ 600000 -- 40 % complete.Erasing 128 Kiby[  504.642422] MTD_ioctl
te @ 620000 -- 40 % complete.Erasing 128 Kiby[  505.168390] MTD_ioctl
te @ 640000 -- 41 % complete.Erasing 128 Kiby[  505.720386] MTD_ioctl
te @ 660000 -- 42 % complete.Erasing 128 Kiby[  506.260435] MTD_ioctl
te @ 680000 -- 43 % complete.Erasing 128 Kiby[  506.794364] MTD_ioctl
te @ 6a0000 -- 44 % complete.Erasing 128 Kiby[  507.334434] MTD_ioctl
te @ 6c0000 -- 45 % complete.Erasing 128 Kiby[  507.860302] MTD_ioctl
te @ 6e0000 -- 45 % complete.Erasing 128 Kiby[  508.406415] MTD_ioctl
te @ 700000 -- 46 % complete.Erasing 128 Kiby[  508.964411] MTD_ioctl
te @ 720000 -- 47 % complete.Erasing 128 Kiby[  509.516411] MTD_ioctl
te @ 740000 -- 48 % complete.Erasing 128 Kiby[  510.048430] MTD_ioctl
te @ 760000 -- 49 % complete.Erasing 128 Kiby[  510.580409] MTD_ioctl
te @ 780000 -- 50 % complete.Erasing 128 Kiby[  511.120408] MTD_ioctl
te @ 7a0000 -- 50 % complete.Erasing 128 Kiby[  511.658412] MTD_ioctl
te @ 7c0000 -- 51 % complete.Erasing 128 Kiby[  512.190418] MTD_ioctl
te @ 7e0000 -- 52 % complete.Erasing 128 Kiby[  512.736399] MTD_ioctl
te @ 800000 -- 53 % complete.Erasing 128 Kiby[  513.262410] MTD_ioctl
te @ 820000 -- 54 % complete.Erasing 128 Kiby[  513.778481] MTD_ioctl
te @ 840000 -- 55 % complete.Erasing 128 Kiby[  514.298396] MTD_ioctl
te @ 860000 -- 55 % complete.Erasing 128 Kiby[  514.818489] MTD_ioctl
te @ 880000 -- 56 % complete.Erasing 128 Kiby[  515.358407] MTD_ioctl
te @ 8a0000 -- 57 % complete.Erasing 128 Kiby[  515.898442] MTD_ioctl
te @ 8c0000 -- 58 % complete.Erasing 128 Kiby[  516.492418] MTD_ioctl
te @ 8e0000 -- 59 % complete.Erasing 128 Kiby[  517.026409] MTD_ioctl
te @ 900000 -- 60 % complete.Erasing 128 Kiby[  517.560417] MTD_ioctl
te @ 920000 -- 60 % complete.Erasing 128 Kiby[  518.120397] MTD_ioctl
te @ 940000 -- 61 % complete.Erasing 128 Kiby[  518.654387] MTD_ioctl
te @ 960000 -- 62 % complete.Erasing 128 Kiby[  519.188439] MTD_ioctl
te @ 980000 -- 63 % complete.Erasing 128 Kiby[  519.722411] MTD_ioctl
te @ 9a0000 -- 64 % complete.Erasing 128 Kiby[  520.268410] MTD_ioctl
te @ 9c0000 -- 65 % complete.Erasing 128 Kiby[  520.808371] MTD_ioctl
te @ 9e0000 -- 65 % complete.Erasing 128 Kiby[  521.340426] MTD_ioctl
te @ a00000 -- 66 % complete.Erasing 128 Kiby[  521.886375] MTD_ioctl
te @ a20000 -- 67 % complete.Erasing 128 Kiby[  522.406406] MTD_ioctl
te @ a40000 -- 68 % complete.Erasing 128 Kiby[  522.932404] MTD_ioctl
te @ a60000 -- 69 % complete.Erasing 128 Kiby[  523.466408] MTD_ioctl
te @ a80000 -- 70 % complete.Erasing 128 Kiby[  523.986405] MTD_ioctl
te @ aa0000 -- 70 % complete.Erasing 128 Kiby[  524.520416] MTD_ioctl
te @ ac0000 -- 71 % complete.Erasing 128 Kiby[  525.060405] MTD_ioctl
te @ ae0000 -- 72 % complete.Erasing 128 Kiby[  525.588414] MTD_ioctl
te @ b00000 -- 73 % complete.Erasing 128 Kiby[  526.108414] MTD_ioctl
te @ b20000 -- 74 % complete.Erasing 128 Kiby[  526.624459] MTD_ioctl
te @ b40000 -- 75 % complete.Erasing 128 Kiby[  527.144416] MTD_ioctl
te @ b60000 -- 75 % complete.Erasing 128 Kiby[  527.664407] MTD_ioctl
te @ b80000 -- 76 % complete.Erasing 128 Kiby[  528.184584] MTD_ioctl
te @ ba0000 -- 77 % complete.Erasing 128 Kiby[  528.723423] MTD_ioctl
te @ bc0000 -- 78 % complete.Erasing 128 Kiby[  529.275406] MTD_ioctl
te @ be0000 -- 79 % complete.Erasing 128 Kiby[  529.815405] MTD_ioctl
te @ c00000 -- 80 % complete.Erasing 128 Kiby[  530.349408] MTD_ioctl
te @ c20000 -- 80 % complete.Erasing 128 Kiby[  530.869434] MTD_ioctl
te @ c40000 -- 81 % complete.Erasing 128 Kiby[  531.409400] MTD_ioctl
te @ c60000 -- 82 % complete.Erasing 128 Kiby[  531.937449] MTD_ioctl
te @ c80000 -- 83 % complete.Erasing 128 Kiby[  532.465425] MTD_ioctl
te @ ca0000 -- 84 % complete.Erasing 128 Kiby[  533.025384] MTD_ioctl
te @ cc0000 -- 85 % complete.Erasing 128 Kiby[  533.559411] MTD_ioctl
te @ ce0000 -- 85 % complete.Erasing 128 Kiby[  534.081395] MTD_ioctl
te @ d00000 -- 86 % complete.Erasing 128 Kiby[  534.597458] MTD_ioctl
te @ d20000 -- 87 % complete.Erasing 128 Kiby[  535.113484] MTD_ioctl
te @ d40000 -- 88 % complete.Erasing 128 Kiby[  535.641426] MTD_ioctl
te @ d60000 -- 89 % complete.Erasing 128 Kiby[  536.161425] MTD_ioctl
te @ d80000 -- 90 % complete.Erasing 128 Kiby[  536.677463] MTD_ioctl
te @ da0000 -- 90 % complete.Erasing 128 Kiby[  537.197360] MTD_ioctl
te @ dc0000 -- 91 % complete.Erasing 128 Kiby[  537.717470] MTD_ioctl
te @ de0000 -- 92 % complete.Erasing 128 Kiby[  538.251328] MTD_ioctl
te @ e00000 -- 93 % complete.Erasing 128 Kiby[  538.777539] MTD_ioctl
te @ e20000 -- 94 % complete.Erasing 128 Kiby[  539.337395] MTD_ioctl
te @ e40000 -- 95 % complete.Erasing 128 Kiby[  539.871411] MTD_ioctl
te @ e60000 -- 95 % complete.Erasing 128 Kiby[  540.393400] MTD_ioctl
te @ e80000 -- 96 % complete.Erasing 128 Kiby[  540.927416] MTD_ioctl
te @ ea0000 -- 97 % complete.Erasing 128 Kiby[  541.455414] MTD_ioctl
te @ ec0000 -- 98 % complete.Erasing 128 Kiby[  541.975420] MTD_ioctl
te @ ee0000 -- 99 % complete.Erasing 128 Kiby[  542.492047] MTD_close
te @ f00000 -- 100 % complete.
[root at freescale /]# mount -t jffs2 mtd0 /mnt/flash
[  636.371343] MTDSB: dev_name "mtd0"
[  636.374726] MTDSB: mtd%d, mtdnr 0
[  636.378013] MTDSB: New superblock for device 0 ("filesystem")
[root at freescale /]# cd /mnt/flash
[root at freescale flash]# touch 1
[root at freescale flash]# touch 12
[root at freescale flash]# touch 123
[root at freescale flash]# touch 1234
[root at freescale flash]# touch 12345
[root at freescale flash]# touch 123456
[root at freescale flash]# touch 1234567
[root at freescale flash]# touch 12345678
[root at freescale flash]# touch 123456789
[root at freescale flash]# touch 1234567890
[root at freescale flash]# ls -l
-rw-r--r--    1 root     root             0 Jan  1 00:10 1
-rw-r--r--    1 root     root             0 Jan  1 00:10 12
-rw-r--r--    1 root     root             0 Jan  1 00:10 123
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234
-rw-r--r--    1 root     root             0 Jan  1 00:10 12345
-rw-r--r--    1 root     root             0 Jan  1 00:10 123456
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234567
-rw-r--r--    1 root     root             0 Jan  1 00:10 12345678
-rw-r--r--    1 root     root             0 Jan  1 00:10 123456789
-rw-r--r--    1 root     root             0 Jan  1 00:11 1234567890
[root at freescale flash]# cd /
[root at freescale /]# umount /mnt/flash
[root at freescale /]# mount -t jffs2 mtd0 /mnt/flash
[  718.170535] MTDSB: dev_name "mtd0"
[  718.173934] MTDSB: mtd%d, mtdnr 0
[  718.177206] MTDSB: New superblock for device 0 ("filesystem")
[  718.189602] jffs2_scan_dirent_node(): Name CRC failed on node at
0x00e4036c: Read 0xffc205c6, calculated 0x88d63443
[  718.200658] jffs2_scan_dirent_node(): Name CRC failed on node at
0x00e403e0: Read 0x2dfd2d88, calculated 0xb0584e16
[  718.211700] jffs2_scan_dirent_node(): Name CRC failed on node at
0x00e40458: Read 0xc597c693, calculated 0xd2bdddb3
[root at freescale /]# ls -l /mnt/flash
-rw-r--r--    1 root     root             0 Jan  1 00:10 1
-rw-r--r--    1 root     root             0 Jan  1 00:10 12
-rw-r--r--    1 root     root             0 Jan  1 00:10 123
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234
-rw-r--r--    1 root     root             0 Jan  1 00:10 12345
-rw-r--r--    1 root     root             0 Jan  1 00:10 123456
-rw-r--r--    1 root     root             0 Jan  1 00:10 1234567
[root at freescale /]# 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jffs2.log
Type: application/octet-stream
Size: 11333 bytes
Desc: jffs2.log
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20100623/519b8973/attachment-0001.obj>

From jamie at shareable.org  Wed Jun 23 20:39:54 2010
From: jamie at shareable.org (Jamie Lokier)
Date: Thu, 24 Jun 2010 01:39:54 +0100
Subject: [PATCH 2/3] flash_eraseall: move constants out of for loop
In-Reply-To: <AANLkTimllsVj3nGC7vWP9oKPJXwIyjd71y0KbA7rFhPH@mail.gmail.com>
References: <1276764159-28726-1-git-send-email-ext-andriy.shevchenko@nokia.com>
	<1276764159-28726-2-git-send-email-ext-andriy.shevchenko@nokia.com>
	<AANLkTilBFi58-kjjxM2Q5p0I1l9R5WQpiozBiV5udQYW@mail.gmail.com>
	<20100623002334.GA22367@shareable.org>
	<AANLkTimllsVj3nGC7vWP9oKPJXwIyjd71y0KbA7rFhPH@mail.gmail.com>
Message-ID: <20100624003954.GK7058@shareable.org>

Mike Frysinger wrote:
> On Tue, Jun 22, 2010 at 20:23, Jamie Lokier wrote:
> > Mike Frysinger wrote:
> >> i wonder though why this code even bothers with "static".
> >
> > The array is static to avoid compiling to code which fills in the
> > array at runtime. ?I.e. it makes the code smaller, to the same size as
> > if they were globals. ?And then, only because its static, the const
> > can put them in the .rodata section, reducing unshared data size.
> 
> if it were generated on the stack at runtime, the .text is shared too

Shared, but larger than the static-const data it replaces.

> > Because they're static there's no benefit to moving them to another
> > scope.
> 
> that's sort of what i expected, but i found it odd that it isnt:
>     static const char * const short_options = "jq";

You're right, I missed that.
I'd have used this myself:

static const char short_options[] = "jq";

-- Jamie



From enrico.scholz at sigma-chemnitz.de  Thu Jun 24 09:02:40 2010
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Thu, 24 Jun 2010 15:02:40 +0200
Subject: [PATCH/mtd-utils] fix integer underflow in jffs2_rtime_compress()
Message-ID: <1277384560-15329-1-git-send-email-enrico.scholz@sigma-chemnitz.de>

When '*dstlen' is 0 or 1, comparison will return wrong result.  Reported
by valgrind as

==5919== Invalid write of size 1
==5919==    at 0x40564E: jffs2_rtime_compress (compr_rtime.c:51)
==5919==    by 0x40676B: jffs2_compress (compr.c:246)
==5919==    by 0x403EE4: recursive_populate_directory (mkfs.jffs2.c:884)
==5919==  Address 0x4e1bdb1 is 0 bytes after a block of size 1 alloc'd
==5919==    at 0x4A0515D: malloc (vg_replace_malloc.c:195)
==5919==    by 0x40671C: jffs2_compress (compr.c:229)
==5919==    by 0x403EE4: recursive_populate_directory (mkfs.jffs2.c:884)

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
---
 compr_rtime.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/compr_rtime.c b/compr_rtime.c
index 131536c..5613963 100644
--- a/compr_rtime.c
+++ b/compr_rtime.c
@@ -32,7 +32,7 @@ static int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out
 
 	memset(positions,0,sizeof(positions));
 
-	while (pos < (*sourcelen) && outpos <= (*dstlen)-2) {
+	while (pos < (*sourcelen) && outpos+2 <= (*dstlen)) {
 		int backpos, runlen=0;
 		unsigned char value;
 
-- 
1.7.0.1



From pjohn at mvista.com  Thu Jun 24 09:52:02 2010
From: pjohn at mvista.com (Philby John)
Date: Thu, 24 Jun 2010 19:22:02 +0530
Subject: [PATCH] mtd-www doc, FAQ, general: spelling fixes
In-Reply-To: <1277332946-14580-1-git-send-email-norris@broadcom.com>
References: <1277332946-14580-1-git-send-email-norris@broadcom.com>
Message-ID: <1277387522.24980.6.camel@localhost.localdomain>

On Wed, 2010-06-23 at 15:42 -0700, Brian Norris wrote:
> Several spelling, word choice, etc. edits throughout
> 
> Signed-off-by: Brian Norris <norris at broadcom.com>
> ---
>  doc/general.xml |    2 +-
>  doc/nand.xml    |   60 +++++++++++++++++++++++++++---------------------------
>  doc/onenand.xml |   18 ++++++++--------
>  doc/ubi.xml     |   14 ++++++------
>  doc/ubifs.xml   |   18 ++++++++--------
>  faq/general.xml |    6 ++--
>  faq/jffs2.xml   |   18 ++++++++--------
>  faq/nand.xml    |   14 ++++++------
>  faq/ubi.xml     |   48 ++++++++++++++++++++++----------------------
>  faq/ubifs.xml   |   48 ++++++++++++++++++++++----------------------
>  source.xml      |    2 +-
>  11 files changed, 124 insertions(+), 124 deletions(-)
> 
> diff --git a/doc/general.xml b/doc/general.xml
> index e170ace..4e1bfdd 100644
> --- a/doc/general.xml
> +++ b/doc/general.xml
> @@ -122,7 +122,7 @@ git://git.infradead.org/users/ahunter/nand-tests.git
>  	and nasty DMA issues on an OMAP2 board with OneNAND flash, just by
>  	running this tests for few hours.</li>
>  
> -	<li><b>mtd_nandecctest</b>: a simple test that checks correctess of the
> +	<li><b>mtd_nandecctest</b>: a simple test that checks correctness of the
>  	built-in software ECC for 256 and 512-byte buffers; this test is not
>  	driver-specific but tests general NAND support code.</li>
>  </ul>
> diff --git a/doc/nand.xml b/doc/nand.xml
> index 549827b..776f891 100644
> --- a/doc/nand.xml
> +++ b/doc/nand.xml
> @@ -16,8 +16,8 @@ NAND and NOR Flash is the bus interface. NOR Flash is connected to a address / d
>   bus direct like other memory devices as SRAM etc. NAND Flash uses a multiplexed I/O 
>   Interface with some additional control pins. NAND flash is a sequential access device 
>   appropriate for mass storage applications, while NOR flash is a random access device 
> - appropriate for code storage application.NOR Flash can be used for code storage and 
> - code execution. Code stored on NAND Flash can't be executed frome there. It must be 
> + appropriate for code storage application. NOR Flash can be used for code storage and 
> + code execution. Code stored on NAND Flash can't be executed from there. It must be 
>   loaded into RAM memory and executed from there.</p>

<-snip->

>  Probably because you flash is too small? Try to use JFFS2 then, becasue it
                    ^^^                                            ^^^^^
You missed "you", should be "your", and "becasue".

Regards,
Philby



From norris at broadcom.com  Thu Jun 24 12:41:48 2010
From: norris at broadcom.com (Brian Norris)
Date: Thu, 24 Jun 2010 09:41:48 -0700
Subject: [PATCH] mtd-www doc, FAQ, general: spelling fixes
In-Reply-To: <1277387522.24980.6.camel@localhost.localdomain>
References: <1277332946-14580-1-git-send-email-norris@broadcom.com>
	<1277387522.24980.6.camel@localhost.localdomain>
Message-ID: <4C238ACC.8050004@broadcom.com>

On 06/24/2010 06:52 AM, Philby John wrote:

> 
>>   Probably because you flash is too small? Try to use JFFS2 then, becasue it
>                      ^^^                                            ^^^^^
> You missed "you", should be "your", and "becasue".
> 
> Regards,
> Philby
> 
> 

Thanks. Here's just a couple more missed edits.

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 faq/jffs2.xml |    4 ++--
 faq/ubifs.xml |   14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/faq/jffs2.xml b/faq/jffs2.xml
index 1bc8680..a08af7a 100644
--- a/faq/jffs2.xml
+++ b/faq/jffs2.xml
@@ -277,8 +277,8 @@ There are two cases where this does not work. The first is when JFFS2 is used
 as a root filesystem. For now, this requires the mtdblock device to be
 specified for <CODE>root=</CODE> on the kernel command line. The second case is
 when the mount binary that is being used does not play nicely with the above
-format. The busybox version of mount is known to not work without the mtdblock
-device.
+format. The BusyBox version of <CODE>mount</CODE> is known to not work without
+the mtdblock device.
 </P>
 
 
diff --git a/faq/ubifs.xml b/faq/ubifs.xml
index 9dd5d3d..ea371f6 100644
--- a/faq/ubifs.xml
+++ b/faq/ubifs.xml
@@ -33,8 +33,8 @@
 	<li><a href="ubifs.html#L_ubifs_extract">How do I extract files from an UBI/UBIFS image?</a></li>
 	<li><a href="ubifs.html#L_powercut">Is UBIFS tolerant to power-cuts?</a></li>
 	<li><a href="ubifs.html#L_smaller_jrn">I need more space - should I make UBIFS journal smaller?</a></li>
-	<li><a href="ubifs.html#L_empty_file">Why my file is empty after an unclean reboot?</a></li>
-	<li><a href="ubifs.html#L_end_hole">Why my file has zeroes at the end after an unclean reboot?</a></li>
+	<li><a href="ubifs.html#L_empty_file">Why is my file empty after an unclean reboot?</a></li>
+	<li><a href="ubifs.html#L_end_hole">Why does my file have zeroes at the end after an unclean reboot?</a></li>
 	<li><a href="ubifs.html#L_bgt_thread">What does the "ubifs_bgt0_0" thread do?</a></li>
 	<li><a href="ubifs.html#L_sudden_ro">UBIFS suddenly became read-only - what is this?</a></li>
 	<li><a href="ubifs.html#L_detect_ro">How do I detect if UBIFS became read-only?</a></li>
@@ -986,12 +986,12 @@ size.</p>
 
 <p>To put it simple, the amount of available space on UBIFS does not really
 depend on the journal size. There is very weak dependency, though, because for
-bigger journal we need bigger log, but it is really something which does not
-make any noticeable difference.</p>
+a bigger journal we need a bigger log, but it really does not make a
+noticeable difference.</p>
 
 
 
-<h2><a name="L_empty_file">Why my file is empty after an unclean reboot?</a></h2>
+<h2><a name="L_empty_file">Why is my file empty after an unclean reboot?</a></h2>
 
 <p>Zero-length files are a special case of corruption which happens when
 an application first truncates a file, then updates it. The truncation is
@@ -1048,7 +1048,7 @@ to implement it.</p>
 
 
 
-<h2><a name="L_end_hole">Why my file has zeroes at the end after an unclean reboot?</a></h2>
+<h2><a name="L_end_hole">Why does my file have zeroes at the end after an unclean reboot?</a></h2>
 
 <p>Power cuts often lead to holes at the end of files. Holes are areas of
 the file which contain no data. For example, if you truncate a file to a larger
@@ -1176,7 +1176,7 @@ I get: "init_constants_early: too few LEBs (12), min. is 17"
 </a></h2>
 
 <p>This error means that you are trying to mount too small UBI volume.
-Probably because you flash is too small? Try to use JFFS2 then, becasue it
+Probably because your flash is too small? Try to use JFFS2, then, because it
 suits small flashes better since it has much lower space overhead. Indeed,
 UBIFS stores much more indexing information on the flash media than JFFS2, so
 it has much higher overhead. Also, UBI has some overhead (see
-- 
1.7.1




From taliaferro62 at gmail.com  Thu Jun 24 16:00:15 2010
From: taliaferro62 at gmail.com (twebb)
Date: Thu, 24 Jun 2010 16:00:15 -0400
Subject: error handling in replay_log_leb()
Message-ID: <AANLkTik882oGTwZZZ31T7YjfyvCmETlZgisjS6teDCB1@mail.gmail.com>

In the replay.c/replay_log_leb(), is there any disadvantage to calling
ubifs_recover_log_leb() regardless of whether need_recovery is true or
not?  I'm having an issue with ubifs dealing with a PEB with corrupt
empty space and this condition is handled fine during a mount when
need_recovery is true, but is not handled the same otherwise and
results in a failed mount.  A patch with the proposed change is below.

This question is along the same lines as one I asked yesterday about
ubifs_scan() error handling.

Thanks,
twebb


Index: replay.c
================================================
--- replay.c    (revision 2438)
+++ replay.c    (working copy)
@@ -838,7 +838,7 @@
        dbg_mnt("replay log LEB %d:%d", lnum, offs);
        sleb = ubifs_scan(c, lnum, offs, sbuf);
        if (IS_ERR(sleb) ) {
-               if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
+               if (PTR_ERR(sleb) != -EUCLEAN)
                        return PTR_ERR(sleb);
                sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
                if (IS_ERR(sleb))


From SteveDeiters at BASLER.com  Thu Jun 24 16:01:36 2010
From: SteveDeiters at BASLER.com (Steve Deiters)
Date: Thu, 24 Jun 2010 15:01:36 -0500
Subject: JFFS2 corruption when mounting filesystem with filenames oflength
	> 7
In-Reply-To: <181804936ABC2349BE503168465576460F1AAEE1@exchserver.basler.com>
References: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com> 
	<181804936ABC2349BE503168465576460F1AAEE1@exchserver.basler.com>
Message-ID: <181804936ABC2349BE503168465576460F1AB73E@exchserver.basler.com>

> -----Original Message-----
> From: linux-mtd-bounces at lists.infradead.org 
> [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of 
> Steve Deiters
> Sent: Wednesday, June 23, 2010 5:42 PM
> To: linux-mtd at lists.infradead.org
> Subject: RE: JFFS2 corruption when mounting filesystem with 
> filenames oflength > 7
> 
> > -----Original Message-----
> > From: linux-mtd-bounces at lists.infradead.org
> > [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of Steve 
> > Deiters
> > Sent: Wednesday, June 23, 2010 5:21 PM
> > To: linux-mtd at lists.infradead.org
> > Subject: JFFS2 corruption when mounting filesystem with 
> filenames of 
> > length > 7
> > 
> > I found an archived post which seems to be identical to my issue.
> > However, this is quite old and there never seemed to be any 
> > resolution.
> > 
> > http://www.infradead.org/pipermail/linux-mtd/2006-September/01
> > 6491.html
> > 
> > If I mount a filesystem that has filenames greater than 7 
> characters 
> > in length, the files are corrupted when I mount.
> > In my case, I am making a
> > JFFS2 image with mkfs.jffs2 and flashing it in with u-boot.  
> > However, I have attached a workflow where I erase the Flash 
> and create 
> > a new filesystem completely within Linux and it gives the same 
> > behavior.  I can list the files with the 'ls'
> > command from within u-boot.  If I mount from within Linux, and then 
> > reboot into u-boot, it will not display any files that had 
> a filename 
> > greater than 7 characters.
> > 
> > I enabled the MTD debug verbosity at level 2 for the 
> attached example 
> > session.
> > 
> > I am running on a custom board with a MPC5121 and Linux 2.6.33.4.
> > 
> > Thanks in advance for any help.
> 
> 
> Sorry for the jumbled mess.  Looks like the line endings are 
> messed up.
> Trying again.  I also provided this as an attachment in case 
> it gets messed up again.

Once again sorry for the mess.

I tried this again with the DENX-v2.6.34 tag in the DENX git repository
(git://git.denx.de/linux-2.6-denx.git).  The only modification I made
was to add my dts file.  I still get the same issue I had before.

I've attached my kernel config if that gives any clues.

Are there any thoughts on what may be causing this?

Thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: kernel.config
Type: application/octet-stream
Size: 25320 bytes
Desc: kernel.config
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20100624/81c2e4a3/attachment-0001.obj>

From s-ghorai at ti.com  Fri Jun 25 02:35:38 2010
From: s-ghorai at ti.com (Ghorai, Sukumar)
Date: Fri, 25 Jun 2010 12:05:38 +0530
Subject: Reed Solomon FAQ
In-Reply-To: <alpine.LFD.2.00.1006211604160.4290@localhost.localdomain>
References: <alpine.LFD.2.00.1006211604160.4290@localhost.localdomain>
Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030DF4EC92@dbde02.ent.ti.com>

> -----Original Message-----
> From: Thomas Gleixner [mailto:tglx at linutronix.de]
> Sent: Monday, June 21, 2010 8:35 PM
> To: linux-mtd at lists.infradead.org
> Cc: Ghorai, Sukumar
> Subject: Reed Solomon FAQ
> 
> I got repeatedly questions like the following about Reed Solomon
> codes:
> 
> > Say we have allocated 8bytes in spare area to store the ECC for 512
> > bytes data. And we have to correct upto 4-bit in 512-byte data. And
> > would you please let me know how to configure the rs-lib for the
> > same? Say we are using the 8-bit data(symbol).
> 
> It's impossible to use 8bit symbol width for 512 byte data.
> 
>       m = number of bits per symbol
>       n = code length in symbols up to 2^(m-1)
>       k = original data length in symbols
>       r = n - k = number of redundant symbols
>       t = 1/2 (n-k) = error correction capability (number of symbols)
> 
> So for this use case we get for the kernel rs lib:
> 
>    k = 512
> 
> So for 512 byte data we need a symbol width of 10. The rs lib in the
> kernel handles this in the encode/decode_rs8 functions by expanding
> the 8 bit FLASH data to 10 bits internally.
> 
>    m = 10
> 
> If we can store 8 byte == 64bit of redundant symbols in the spare
> area, so the number of redundant symbols is:
> 
>    r = 64/10 = 6
> 
> And the resulting code lenght is:
> 
>    n = k + r = 518
> 
> So the max. number of correctable symbols is:
> 
>    t = 1/2 * 6 = 3
> 
> That might be up to 24 bit of corrected data, when the errors are not
> scattered over more than 3 bytes on FLASH.
> 
> If errors happen on 4 or more different FLASH bytes, they are
> uncorrectable.
> 
> The 518/512 (10 bit symbol width) code is the optimum which can be
> achieved for 512 byte FLASH read/write chunks with 8 byte of spare
> area usage.
> 
> To correct 4 symbols in a 512 byte data chunk we need at least 8
> redundant symbols, which means 80 bit == 10 bytes storage size in the
> spare area.
> 
> > Is it possible to correct 4-symbols, by max 9-byte parity?
> 
> Yes, but that requires that the 512 byte data is converted into a
> serialized bitstream w/o symbol width expansion so 9 bit symbol width
> can be used.
> 
>     m = 9
>     k = 456 [ 512 * 8 / 9 rounded up ]
>     r = 8 [ 72 / 9 ]
>     t = 4
> 
> Such modes are only useful when both the encoding and the decoding are
> done in hardware, as serializing / deserializing for the software
> en/decoder is making the already slow software RS even more horribly
> slow.
> 
> As a side note: software RS encoding/decoding is performancewise a bad
> idea in general.
> 
> Thanks,
> 
> 	tglx
[Ghorai] Thanks Gleixner,
It's a very informative email for me.


From vaurora at redhat.com  Fri Jun 25 15:05:02 2010
From: vaurora at redhat.com (Valerie Aurora)
Date: Fri, 25 Jun 2010 12:05:02 -0700
Subject: [PATCH 12/38] whiteout: jffs2 whiteout support
In-Reply-To: <1277492728-11446-1-git-send-email-vaurora@redhat.com>
References: <1277492728-11446-1-git-send-email-vaurora@redhat.com>
Message-ID: <1277492728-11446-13-git-send-email-vaurora@redhat.com>

From: Felix Fietkau <nbd at openwrt.org>

Add support for whiteout dentries to jffs2.

XXX - David Woodhouse suggests several changes and provides an
untested patch.  See:

http://patchwork.ozlabs.org/patch/50466/

Signed-off-by: Felix Fietkau <nbd at openwrt.org>
Signed-off-by: Valerie Aurora <vaurora at redhat.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: linux-mtd at lists.infradead.org
---
 fs/jffs2/dir.c        |   72 +++++++++++++++++++++++++++++++++++++++++++++++-
 fs/jffs2/fs.c         |    4 +++
 fs/jffs2/super.c      |    2 +-
 include/linux/jffs2.h |    2 +
 4 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 7aa4417..c259193 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -34,6 +34,8 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
 static int jffs2_rename (struct inode *, struct dentry *,
 			 struct inode *, struct dentry *);
 
+static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *);
+
 const struct file_operations jffs2_dir_operations =
 {
 	.read =		generic_read_dir,
@@ -56,6 +58,7 @@ const struct inode_operations jffs2_dir_inode_operations =
 	.mknod =	jffs2_mknod,
 	.rename =	jffs2_rename,
 	.check_acl =	jffs2_check_acl,
+	.whiteout =     jffs2_whiteout,
 	.setattr =	jffs2_setattr,
 	.setxattr =	jffs2_setxattr,
 	.getxattr =	jffs2_getxattr,
@@ -98,8 +101,14 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
 			fd = fd_list;
 		}
 	}
-	if (fd)
-		ino = fd->ino;
+	if (fd) {
+		spin_lock(&target->d_lock);
+		if (fd->type == DT_WHT)
+			target->d_flags |= DCACHE_WHITEOUT;
+		else
+			ino = fd->ino;
+		spin_unlock(&target->d_lock);
+	}
 	mutex_unlock(&dir_f->sem);
 	if (ino) {
 		inode = jffs2_iget(dir_i->i_sb, ino);
@@ -498,6 +507,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
 		return PTR_ERR(inode);
 	}
 
+	if (dentry->d_flags & DCACHE_WHITEOUT) {
+		inode->i_flags |= S_OPAQUE;
+		ri->flags = cpu_to_je16(JFFS2_INO_FLAG_OPAQUE);
+	}
+
 	inode->i_op = &jffs2_dir_inode_operations;
 	inode->i_fop = &jffs2_dir_operations;
 
@@ -779,6 +793,60 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
 	return 0;
 }
 
+static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry,
+			   struct dentry *new_dentry)
+{
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb);
+	struct jffs2_inode_info *victim_f = NULL;
+	uint32_t now;
+	int ret;
+
+	/* If it's a directory, then check whether it is really empty */
+	if (new_dentry->d_inode) {
+		victim_f = JFFS2_INODE_INFO(old_dentry->d_inode);
+		if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+			struct jffs2_full_dirent *fd;
+
+			mutex_lock(&victim_f->sem);
+			for (fd = victim_f->dents; fd; fd = fd->next) {
+				if (fd->ino) {
+					mutex_unlock(&victim_f->sem);
+					return -ENOTEMPTY;
+				}
+			}
+			mutex_unlock(&victim_f->sem);
+		}
+	}
+
+	now = get_seconds();
+	ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_WHT,
+			    new_dentry->d_name.name, new_dentry->d_name.len, now);
+	if (ret)
+		return ret;
+
+	spin_lock(&new_dentry->d_lock);
+	new_dentry->d_flags |= DCACHE_WHITEOUT;
+	spin_unlock(&new_dentry->d_lock);
+	d_add(new_dentry, NULL);
+
+	if (victim_f) {
+		/* There was a victim. Kill it off nicely */
+		drop_nlink(old_dentry->d_inode);
+		/* Don't oops if the victim was a dirent pointing to an
+		   inode which didn't exist. */
+		if (victim_f->inocache) {
+			mutex_lock(&victim_f->sem);
+			if (S_ISDIR(old_dentry->d_inode->i_mode))
+				victim_f->inocache->pino_nlink = 0;
+			else
+				victim_f->inocache->pino_nlink--;
+			mutex_unlock(&victim_f->sem);
+		}
+	}
+
+	return 0;
+}
+
 static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 			 struct inode *new_dir_i, struct dentry *new_dentry)
 {
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 3451a81..c1e333c 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -301,6 +301,10 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
 
 		inode->i_op = &jffs2_dir_inode_operations;
 		inode->i_fop = &jffs2_dir_operations;
+
+		if (je16_to_cpu(latest_node.flags) & JFFS2_INO_FLAG_OPAQUE)
+			inode->i_flags |= S_OPAQUE;
+
 		break;
 	}
 	case S_IFREG:
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 9a80e8e..c12cd1c 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -172,7 +172,7 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 
 	sb->s_op = &jffs2_super_operations;
 	sb->s_export_op = &jffs2_export_ops;
-	sb->s_flags = sb->s_flags | MS_NOATIME;
+	sb->s_flags = sb->s_flags | MS_NOATIME | MS_WHITEOUT;
 	sb->s_xattr = jffs2_xattr_handlers;
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 	sb->s_flags |= MS_POSIXACL;
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index 2b32d63..65533bb 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -87,6 +87,8 @@
 #define JFFS2_INO_FLAG_USERCOMPR  2	/* User has requested a specific
 					   compression type */
 
+#define JFFS2_INO_FLAG_OPAQUE     4	/* Directory is opaque (for union mounts) */
+
 
 /* These can go once we've made sure we've caught all uses without
    byteswapping */
-- 
1.6.3.3



From vaurora at redhat.com  Fri Jun 25 15:05:05 2010
From: vaurora at redhat.com (Valerie Aurora)
Date: Fri, 25 Jun 2010 12:05:05 -0700
Subject: [PATCH 15/38] fallthru: jffs2 fallthru support
In-Reply-To: <1277492728-11446-1-git-send-email-vaurora@redhat.com>
References: <1277492728-11446-1-git-send-email-vaurora@redhat.com>
Message-ID: <1277492728-11446-16-git-send-email-vaurora@redhat.com>

From: Felix Fietkau <nbd at openwrt.org>

Add support for fallthru dentries to jffs2.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: linux-mtd at lists.infradead.org
Signed-off-by: Felix Fietkau <nbd at openwrt.org>
Signed-off-by: Valerie Aurora <vaurora at redhat.com>
---
 fs/jffs2/dir.c        |   36 +++++++++++++++++++++++++++++++++---
 include/linux/jffs2.h |    6 ++++++
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index c259193..98397b3 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -35,6 +35,7 @@ static int jffs2_rename (struct inode *, struct dentry *,
 			 struct inode *, struct dentry *);
 
 static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *);
+static int jffs2_fallthru (struct inode *, struct dentry *);
 
 const struct file_operations jffs2_dir_operations =
 {
@@ -59,6 +60,7 @@ const struct inode_operations jffs2_dir_inode_operations =
 	.rename =	jffs2_rename,
 	.check_acl =	jffs2_check_acl,
 	.whiteout =     jffs2_whiteout,
+	.fallthru =     jffs2_fallthru,
 	.setattr =	jffs2_setattr,
 	.setxattr =	jffs2_setxattr,
 	.getxattr =	jffs2_getxattr,
@@ -103,10 +105,14 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
 	}
 	if (fd) {
 		spin_lock(&target->d_lock);
-		if (fd->type == DT_WHT)
+		switch (fd->type) {
+		case DT_WHT:
 			target->d_flags |= DCACHE_WHITEOUT;
-		else
+		case JFFS2_DT_FALLTHRU:
+			target->d_flags |= DCACHE_FALLTHRU;
+		default:
 			ino = fd->ino;
+		}
 		spin_unlock(&target->d_lock);
 	}
 	mutex_unlock(&dir_f->sem);
@@ -164,7 +170,10 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
 				  fd->name, fd->ino, fd->type, curofs, offset));
 			continue;
 		}
-		if (!fd->ino) {
+		if (fd->type == JFFS2_DT_FALLTHRU)
+			/* XXX Should really do a lookup for the real inode number here */
+			fd->ino = 100;
+		else if (!fd->ino && (fd->type != DT_WHT)) {
 			D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name));
 			offset++;
 			continue;
@@ -793,6 +802,26 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
 	return 0;
 }
 
+static int jffs2_fallthru (struct inode *dir, struct dentry *dentry)
+{
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb);
+	uint32_t now;
+	int ret;
+
+	now = get_seconds();
+	ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_UNKNOWN,
+			    dentry->d_name.name, dentry->d_name.len, now);
+	if (ret)
+		return ret;
+
+	d_instantiate(dentry, NULL);
+	spin_lock(&dentry->d_lock);
+	dentry->d_flags |= DCACHE_FALLTHRU;
+	spin_unlock(&dentry->d_lock);
+
+	return 0;
+}
+
 static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry,
 			   struct dentry *new_dentry)
 {
@@ -825,6 +854,7 @@ static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry,
 		return ret;
 
 	spin_lock(&new_dentry->d_lock);
+	new_dentry->d_flags &= ~DCACHE_FALLTHRU;
 	new_dentry->d_flags |= DCACHE_WHITEOUT;
 	spin_unlock(&new_dentry->d_lock);
 	d_add(new_dentry, NULL);
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index 65533bb..dbe8c93 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -114,6 +114,12 @@ struct jffs2_unknown_node
 	jint32_t hdr_crc;
 };
 
+/*
+ * Non-standard directory entry type(s), for on-disk use
+ */
+
+#define                JFFS2_DT_FALLTHRU       (DT_WHT + 1)
+
 struct jffs2_raw_dirent
 {
 	jint16_t magic;
-- 
1.6.3.3



From norris at broadcom.com  Fri Jun 25 17:36:31 2010
From: norris at broadcom.com (Brian Norris)
Date: Fri, 25 Jun 2010 14:36:31 -0700
Subject: [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2,
	last and byte 1 or 6
In-Reply-To: <1277325362-13326-1-git-send-email-norris@broadcom.com>
References: <1277325362-13326-1-git-send-email-norris@broadcom.com>
Message-ID: <1277501791-3146-1-git-send-email-norris@broadcom.com>

Some level of support for various scanning locations was already built in,
but this required clean-up. First, BB marker location cannot be determined
_only_ by the page size. Instead, I implemented some heuristic detection
based on data sheets from various manufacturers (all found in
nand_base.c:nand_get_flash_type()).

Second, once these options were identified, they were not handled properly
by nand_bbt.c:nand_default_bbt(). I believe there are only 5 combinations
of page location/byte offset, so I updated the nand_bbt_desc structs
accordingly.

I have tested these changes with several chips, but particularly a Micron
29F8G08MAA chip. We use a memory-based, not flash-based, BBT; hence the
edits only to the "memory_based" side of things. Most edits could be
applicable to both, but I can't verify that. For instance, I do not
understand why the small discrepancies between the "memory_based" and
"flash_based" nand_bbt_descr structs.

Finally, please provide any feedback you can. I'm sure there's something
I have overlooked, but I feel this is a step in the right direction.

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 drivers/mtd/nand/nand_base.c |   23 +++++++++++++++++++----
 drivers/mtd/nand/nand_bbt.c  |   41 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e6cf9ae..2d1ee3c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2920,9 +2920,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
 
 	/* Set the bad block position */
-	chip->badblockpos = mtd->writesize > 512 ?
-		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-	chip->badblockbits = 8;
+	chip->badblockpos = (!(busw & NAND_BUSWIDTH_16) &&
+			(*maf_id == NAND_MFR_STMICRO ||
+			 (*maf_id == NAND_MFR_SAMSUNG &&
+			  mtd->writesize == 512) ||
+			 *maf_id == NAND_MFR_AMD))
+		? NAND_SMALL_BADBLOCK_POS : NAND_LARGE_BADBLOCK_POS;
+
 
 	/* Get chip options, preserve non chip based options */
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
@@ -2941,12 +2945,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 	/*
 	 * Bad block marker is stored in the last page of each block
-	 * on Samsung and Hynix MLC devices
+	 * on Samsung and Hynix MLC devices; stored in first two pages 
+	 * of each block on Micron devices with 2KiB pages and on 
+	 * SLC Samsung, Hynix, and AMD/Spansion. All others scan only 
+	 * the first page.
 	 */
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			 *maf_id == NAND_MFR_HYNIX))
 		chip->options |= NAND_BBT_SCANLASTPAGE;
+	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+				(*maf_id == NAND_MFR_SAMSUNG ||
+				 *maf_id == NAND_MFR_HYNIX ||
+				 *maf_id == NAND_MFR_AMD)) ||
+			(mtd->writesize == 2048 &&
+			 *maf_id == NAND_MFR_MICRON))
+		chip->options |= NAND_BBT_SCAN2NDPAGE;
+
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 71d83be..1719c56 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1093,29 +1093,50 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 static struct nand_bbt_descr smallpage_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
+	.options = 0,
+	.offs = NAND_SMALL_BADBLOCK_POS,
 	.len = 1,
 	.pattern = scan_ff_pattern
 };
 
+static struct nand_bbt_descr smallpage_scan2nd_memorybased = {
+	.options = NAND_BBT_SCAN2NDPAGE,
+	.offs = NAND_SMALL_BADBLOCK_POS,
+	.len = 2,
+	.pattern = scan_ff_pattern
+};
+
 static struct nand_bbt_descr largepage_memorybased = {
 	.options = 0,
-	.offs = 0,
+	.offs = NAND_LARGE_BADBLOCK_POS,
+	.len = 1,
+	.pattern = scan_ff_pattern
+};
+
+static struct nand_bbt_descr largepage_scan2nd_memorybased = {
+	.options = NAND_BBT_SCAN2NDPAGE,
+	.offs = NAND_LARGE_BADBLOCK_POS,
 	.len = 2,
 	.pattern = scan_ff_pattern
 };
 
+static struct nand_bbt_descr lastpage_memorybased = {
+	.options = NAND_BBT_SCANLASTPAGE,
+	.offs = 0,
+	.len = 1,
+	.pattern = scan_ff_pattern
+};
+
 static struct nand_bbt_descr smallpage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
+	.offs = NAND_SMALL_BADBLOCK_POS,
 	.len = 1,
 	.pattern = scan_ff_pattern
 };
 
 static struct nand_bbt_descr largepage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 0,
+	.offs = NAND_LARGE_BADBLOCK_POS,
 	.len = 2,
 	.pattern = scan_ff_pattern
 };
@@ -1197,8 +1218,14 @@ int nand_default_bbt(struct mtd_info *mtd)
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
 		if (!this->badblock_pattern) {
-			this->badblock_pattern = (mtd->writesize > 512) ?
-			    &largepage_memorybased : &smallpage_memorybased;
+			if (this->options & NAND_BBT_SCANLASTPAGE)
+				this->badblock_pattern = &lastpage_memorybased;
+			else if (this->options & NAND_BBT_SCAN2NDPAGE)
+				this->badblock_pattern = this->badblockpos == NAND_SMALL_BADBLOCK_POS ? 
+					&smallpage_scan2nd_memorybased : &largepage_scan2nd_memorybased;
+			else
+				this->badblock_pattern = this->badblockpos == NAND_SMALL_BADBLOCK_POS ? 
+					&smallpage_memorybased : &largepage_memorybased;
 		}
 	}
 	return nand_scan_bbt(mtd, this->badblock_pattern);
-- 
1.7.1




From SteveDeiters at BASLER.com  Fri Jun 25 19:48:23 2010
From: SteveDeiters at BASLER.com (Steve Deiters)
Date: Fri, 25 Jun 2010 18:48:23 -0500
Subject: JFFS2 corruption when mounting filesystem with filenames
	oflength> 7
In-Reply-To: <181804936ABC2349BE503168465576460F1AB73E@exchserver.basler.com>
References: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com> 
	<181804936ABC2349BE503168465576460F1AAEE1@exchserver.basler.com> 
	<181804936ABC2349BE503168465576460F1AB73E@exchserver.basler.com>
Message-ID: <181804936ABC2349BE503168465576460F20CB90@exchserver.basler.com>

> -----Original Message-----
> From: linux-mtd-bounces at lists.infradead.org 
> [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of 
> Steve Deiters
> Sent: Thursday, June 24, 2010 3:02 PM
> To: linux-mtd at lists.infradead.org
> Subject: RE: JFFS2 corruption when mounting filesystem with 
> filenames oflength> 7
> 
> > -----Original Message-----
> > From: linux-mtd-bounces at lists.infradead.org
> > [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of Steve 
> > Deiters
> > Sent: Wednesday, June 23, 2010 5:42 PM
> > To: linux-mtd at lists.infradead.org
> > Subject: RE: JFFS2 corruption when mounting filesystem with 
> filenames 
> > oflength > 7
> > 
> > > -----Original Message-----
> > > From: linux-mtd-bounces at lists.infradead.org
> > > [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of Steve 
> > > Deiters
> > > Sent: Wednesday, June 23, 2010 5:21 PM
> > > To: linux-mtd at lists.infradead.org
> > > Subject: JFFS2 corruption when mounting filesystem with
> > filenames of
> > > length > 7
> > > 
> > > I found an archived post which seems to be identical to my issue.
> > > However, this is quite old and there never seemed to be any 
> > > resolution.
> > > 
> > > http://www.infradead.org/pipermail/linux-mtd/2006-September/01
> > > 6491.html
> > > 
> > > If I mount a filesystem that has filenames greater than 7
> > characters
> > > in length, the files are corrupted when I mount.
> > > In my case, I am making a
> > > JFFS2 image with mkfs.jffs2 and flashing it in with u-boot.  
> > > However, I have attached a workflow where I erase the Flash
> > and create
> > > a new filesystem completely within Linux and it gives the same 
> > > behavior.  I can list the files with the 'ls'
> > > command from within u-boot.  If I mount from within 
> Linux, and then 
> > > reboot into u-boot, it will not display any files that had
> > a filename
> > > greater than 7 characters.
> > > 
> > > I enabled the MTD debug verbosity at level 2 for the
> > attached example
> > > session.
> > > 
> > > I am running on a custom board with a MPC5121 and Linux 2.6.33.4.
> > > 
> > > Thanks in advance for any help.
> > 
> > 
> > Sorry for the jumbled mess.  Looks like the line endings are messed 
> > up.
> > Trying again.  I also provided this as an attachment in 
> case it gets 
> > messed up again.
> 
> Once again sorry for the mess.
> 
> I tried this again with the DENX-v2.6.34 tag in the DENX git 
> repository (git://git.denx.de/linux-2.6-denx.git).  The only 
> modification I made was to add my dts file.  I still get the 
> same issue I had before.
> 
> I've attached my kernel config if that gives any clues.
> 
> Are there any thoughts on what may be causing this?
> 
> Thanks.


I think there may be something weird going on with the memcpy in my
build.  If I use the following patch I no longer get errors when I mount
the filesystem.  All I did was replace the memcpy with a loop.

I'm not sure what's special about this particular use of memcpy.  I
can't believe that things would be working as well as they do if memcpy
was broken in general.

This is on a PowerPC 32 bit build for a MPC5121.  I am using a GCC 4.1.2
to compile.  Is anyone aware of any issues with memcpy in this
configuration?

Thanks.

-------

diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 46f870d..673caa2 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -1038,7 +1038,10 @@ static int jffs2_scan_dirent_node(struct
jffs2_sb_info *c, struct jffs2_eraseblo
 	if (!fd) {
 		return -ENOMEM;
 	}
-	memcpy(&fd->name, rd->name, checkedlen);
+	int i;
+	for(i = 0; i < checkedlen; i++)
+		((unsigned char*)fd->name)[i] = ((const unsigned
char*)rd->name)[i];
+
 	fd->name[checkedlen] = 0;
 
 	crc = crc32(0, fd->name, rd->nsize);


From norris at broadcom.com  Fri Jun 25 20:58:03 2010
From: norris at broadcom.com (Brian Norris)
Date: Fri, 25 Jun 2010 17:58:03 -0700
Subject: [PATCH 1/2] mtd-utils: formatting of odd-sized OOB in nanddump
Message-ID: <1277513884-14715-1-git-send-email-norris@broadcom.com>

Changed OOB output formatting in nanddump.
Most NAND devices have OOB regions with multiples of 16 bytes.
With newer devices, a 218-byte OOB does not split nicely into
lines of 16 bytes. This patch fixes the formatting, allowing a
last line of 10 bytes instead of 16.

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 nanddump.c |   31 ++++++++++++++++++++++---------
 1 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index e44ab36..190a653 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -381,15 +381,28 @@ int main(int argc, char * const argv[])
 			}
 
 			for (i = 0; i < meminfo.oobsize; i += 16) {
-				sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
-						"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-						oobbuf[i], oobbuf[i+1], oobbuf[i+2],
-						oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
-						oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
-						oobbuf[i+9], oobbuf[i+10], oobbuf[i+11],
-						oobbuf[i+12], oobbuf[i+13], oobbuf[i+14],
-						oobbuf[i+15]);
-				write(ofd, pretty_buf, 60);
+				/* Check if we have a full 16 bytes left in the OOB */
+				if (i+15 < meminfo.oobsize) {
+					/* Print 16 bytes */
+					sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
+							"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+							oobbuf[i], oobbuf[i+1], oobbuf[i+2],
+							oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
+							oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
+							oobbuf[i+9], oobbuf[i+10], oobbuf[i+11],
+							oobbuf[i+12], oobbuf[i+13], oobbuf[i+14],
+							oobbuf[i+15]);
+					write(ofd, pretty_buf, 60);
+				} else {
+					/* Print 10 bytes */
+					sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
+							"%02x %02x %02x %02x\n",
+							oobbuf[i], oobbuf[i+1], oobbuf[i+2],
+							oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
+							oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
+							oobbuf[i+9]);
+					write(ofd, pretty_buf, 42);
+				}
 			}
 		} else
 			write(ofd, oobbuf, meminfo.oobsize);
-- 
1.7.1




From norris at broadcom.com  Fri Jun 25 20:58:04 2010
From: norris at broadcom.com (Brian Norris)
Date: Fri, 25 Jun 2010 17:58:04 -0700
Subject: [PATCH 2/2] mtd-utils (nandwrite + nanddump): Support 4096+218,
	4096+224 OOB
In-Reply-To: <1277513884-14715-1-git-send-email-norris@broadcom.com>
References: <1277513884-14715-1-git-send-email-norris@broadcom.com>
Message-ID: <1277513884-14715-2-git-send-email-norris@broadcom.com>

Parts of this are a resubmission of this patch:
http://lists.infradead.org/pipermail/linux-mtd/2010-May/029885.html

This was tested with Samsung K9GAG08U0D.

Signed-off-by: Brian Norris <norris at broadcom.com>
---
 nanddump.c  |    8 ++++++--
 nandwrite.c |    6 ++++--
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 190a653..b0dd227 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -174,8 +174,12 @@ static void process_options (int argc, char * const argv[])
 /*
  * Buffers for reading data from flash
  */
-static unsigned char readbuf[4096];
-static unsigned char oobbuf[128];
+
+#define NAND_MAX_PAGESIZE 4096
+#define NAND_MAX_OOBSIZE 256
+
+static unsigned char readbuf[NAND_MAX_PAGESIZE];
+static unsigned char oobbuf[NAND_MAX_OOBSIZE];
 
 /*
  * Main program
diff --git a/nandwrite.c b/nandwrite.c
index 1b4ca3d..0d59171 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -43,7 +43,7 @@
 #define VERSION "$Revision: 1.32 $"
 
 #define MAX_PAGE_SIZE	4096
-#define MAX_OOB_SIZE	128
+#define MAX_OOB_SIZE	256
 
 // oob layouts to pass into the kernel as default
 static struct nand_oobinfo none_oobinfo = {
@@ -302,7 +302,9 @@ int main(int argc, char * const argv[])
 			!(meminfo.oobsize == 8 && meminfo.writesize == 256) &&
 			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
 			!(meminfo.oobsize == 64 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 128 && meminfo.writesize == 4096)) {
+			!(meminfo.oobsize == 128 && meminfo.writesize == 4096) &&
+			!(meminfo.oobsize == 218 && meminfo.writesize == 4096) &&
+			!(meminfo.oobsize == 224 && meminfo.writesize == 4096)) {
 		fprintf(stderr, "Unknown flash (not normal NAND)\n");
 		close(fd);
 		exit (EXIT_FAILURE);
-- 
1.7.1




From joakim.tjernlund at transmode.se  Sat Jun 26 09:27:05 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Sat, 26 Jun 2010 15:27:05 +0200
Subject: JFFS2 corruption when mounting filesystem with
	filenames	oflength> 7
In-Reply-To: <181804936ABC2349BE503168465576460F20CB90@exchserver.basler.com>
References: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com>
	<181804936ABC2349BE503168465576460F1AAEE1@exchserver.basler.com>
	<181804936ABC2349BE503168465576460F1AB73E@exchserver.basler.com>
	<181804936ABC2349BE503168465576460F20CB90@exchserver.basler.com>
Message-ID: <OFFDC634FC.2BD6844E-ONC125774E.0049ADAC-C125774E.0049E418@transmode.se>

>
> > -----Original Message-----
> > From: linux-mtd-bounces at lists.infradead.org
> > [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of
> > Steve Deiters
> > Sent: Thursday, June 24, 2010 3:02 PM
> > To: linux-mtd at lists.infradead.org
> > Subject: RE: JFFS2 corruption when mounting filesystem with
> > filenames oflength> 7
> >
> > > -----Original Message-----
> > > From: linux-mtd-bounces at lists.infradead.org
> > > [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of Steve
> > > Deiters
> > > Sent: Wednesday, June 23, 2010 5:42 PM
> > > To: linux-mtd at lists.infradead.org
> > > Subject: RE: JFFS2 corruption when mounting filesystem with
> > filenames
> > > oflength > 7
> > >
> > > > -----Original Message-----
> > > > From: linux-mtd-bounces at lists.infradead.org
> > > > [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of Steve
> > > > Deiters
> > > > Sent: Wednesday, June 23, 2010 5:21 PM
> > > > To: linux-mtd at lists.infradead.org
> > > > Subject: JFFS2 corruption when mounting filesystem with
> > > filenames of
> > > > length > 7
> > > >
> > > > I found an archived post which seems to be identical to my issue.
> > > > However, this is quite old and there never seemed to be any
> > > > resolution.
> > > >
> > > > http://www.infradead.org/pipermail/linux-mtd/2006-September/01
> > > > 6491.html
> > > >
> > > > If I mount a filesystem that has filenames greater than 7
> > > characters
> > > > in length, the files are corrupted when I mount.
> > > > In my case, I am making a
> > > > JFFS2 image with mkfs.jffs2 and flashing it in with u-boot.
> > > > However, I have attached a workflow where I erase the Flash
> > > and create
> > > > a new filesystem completely within Linux and it gives the same
> > > > behavior.  I can list the files with the 'ls'
> > > > command from within u-boot.  If I mount from within
> > Linux, and then
> > > > reboot into u-boot, it will not display any files that had
> > > a filename
> > > > greater than 7 characters.
> > > >
> > > > I enabled the MTD debug verbosity at level 2 for the
> > > attached example
> > > > session.
> > > >
> > > > I am running on a custom board with a MPC5121 and Linux 2.6.33.4.
> > > >
> > > > Thanks in advance for any help.
> > >
> > >
> > > Sorry for the jumbled mess.  Looks like the line endings are messed
> > > up.
> > > Trying again.  I also provided this as an attachment in
> > case it gets
> > > messed up again.
> >
> > Once again sorry for the mess.
> >
> > I tried this again with the DENX-v2.6.34 tag in the DENX git
> > repository (git://git.denx.de/linux-2.6-denx.git).  The only
> > modification I made was to add my dts file.  I still get the
> > same issue I had before.
> >
> > I've attached my kernel config if that gives any clues.
> >
> > Are there any thoughts on what may be causing this?
> >
> > Thanks.
>
>
> I think there may be something weird going on with the memcpy in my
> build.  If I use the following patch I no longer get errors when I mount
> the filesystem.  All I did was replace the memcpy with a loop.
>
> I'm not sure what's special about this particular use of memcpy.  I
> can't believe that things would be working as well as they do if memcpy
> was broken in general.
>
> This is on a PowerPC 32 bit build for a MPC5121.  I am using a GCC 4.1.2
> to compile.  Is anyone aware of any issues with memcpy in this
> configuration?
>
> Thanks.
>
> -------
>
> diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
> index 46f870d..673caa2 100644
> --- a/fs/jffs2/scan.c
> +++ b/fs/jffs2/scan.c
> @@ -1038,7 +1038,10 @@ static int jffs2_scan_dirent_node(struct
> jffs2_sb_info *c, struct jffs2_eraseblo
>     if (!fd) {
>        return -ENOMEM;
>     }
> -   memcpy(&fd->name, rd->name, checkedlen);

Are the pointers to memcpy overlapping? If so memcpy is undefined
and you have to use memmove().

> +   int i;
> +   for(i = 0; i < checkedlen; i++)
> +      ((unsigned char*)fd->name)[i] = ((const unsigned
> char*)rd->name)[i];
> +
>     fd->name[checkedlen] = 0;
>
>     crc = crc32(0, fd->name, rd->nsize);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
>



From miltonm at bga.com  Mon Jun 28 03:18:59 2010
From: miltonm at bga.com (Milton Miller)
Date: Mon, 28 Jun 2010 02:18:59 -0500
Subject: of-flash: Unable to ioremap() both 128MB NOR flashes on 32-bit
	system with 2GB+ RAM
In-Reply-To: <AANLkTikMtZsg5ameUY9dnZoEqV-hfa7tkfGIO1hBtDq1@mail.gmail.com>
References: <AANLkTikMtZsg5ameUY9dnZoEqV-hfa7tkfGIO1hBtDq1@mail.gmail.com>
Message-ID: <1277709539_13309@mail4.comsite.net>

On Fri Jun 25 around 14:01:51 EST 2010 Kyle Moffett wrote:
> Oops... put the old linuxppc list on the CC, sorry!
> 
> On Thu, Jun 24, 2010 at 23:45, Kyle Moffett <kyle at moffetthome.net> wrote:
> > Hello,
> >
> > I've got a new P2020 (32bit mpc85xx family) board I'm working on a
> > port for that includes 2 NOR flashes (128MB each) and a removable
> > SO-RDIMM of 2GB or 4GB.  Unfortunately when I configure both flashes
> > in the device-tree off my elbc, Linux is completely unable to access
> > the second one because it attempts to ioremap() the entire virtual
> > address space of both FLASH chips.
> >
> > Even with only one flash chip enabled, there's a bit of a noticeable
> > performance degradation because the mapping consumes almost all of my
> > available vmalloc space and forces bounce-buffering for all my
> > HIGHMEM.
> >
> > It looks like the "of-flash" driver currently requires that the whole
> > chip be mapped in the kernel at once.  I would much rather have a 50%
> > performance penalty on flash accesses (which are already very slow)
> > and regain most of the vmap space.
> >
> > So the question is, is there a way to convince the MTD layer to
> > iomap() only what it needs to access to do reads and writes?  If not,
> > what changes would need to be made to MTD and/or "of-flash" to create
> > such functionality?
> >
> > Cheers,
> > Kyle Moffett
> >

I believe the MTD layer would be happy, but it is beyond the scope of
the physmap_of driver.  A look at drivers/mtd/maps/pcmciamtd.c shows
the concept of paging in a section of flash, although it has the advantage
of hardware to move the window instead of calling ioremap or swapping
translations.  Another example is drivers/mtd/maps/pci.c, also with
hardware assist.

milton


From re.wirth at web.de  Mon Jun 28 04:21:10 2010
From: re.wirth at web.de (re)
Date: Mon, 28 Jun 2010 10:21:10 +0200
Subject: UBIFS failed to recover master node
In-Reply-To: <1274763982.2106.2.camel@localhost>
References: <AANLkTimPxrQzSS_n6CofW8ePwCKuE7sbENJZXUl1Yszl@mail.gmail.com>
	<1274763982.2106.2.camel@localhost>
Message-ID: <4C285B76.5010108@web.de>

 Am 25.05.2010 07:06, schrieb Artem Bityutskiy:
> On Mon, 2010-05-24 at 11:22 -0400, twebb wrote:
>> I've had several cases where our MLC NAND flash appears corrupted in
>> such a way that one of three UBIFS volumes can not be mounted due to
>> "failed to recover master node".  I haven't been able to reproduce the
>> problem, but we've had at least 5 incidents where this has occurred.
>> (A partial capture from one of the failures is below.)
>>
>> I'm starting to investigate this problem and don't know if this is a
>> UBIFS/UBI problem or a NAND driver problem.  I'm starting the process
>> of back-porting the latest UBIFS code to our 2.6.29 kernel - hoping
>> that new UBIFS code will solve the problem.  However, this may also be
>> a driver problem and I wonder if I also need to update that driver
>> (pxa3xx_nand).  Any suggestions for debugging this problem?
>>
>> Thanks,
>> twebb
>>
>>
>> capture:
>> [root at ESIedge mtd-utils]# mount -t ubifs ubi0_0 /mnt/
>> [  239.605869] UBI error: ubi_io_read: error -74 while reading 516096
>> bytes from PEB 4:8192, read 516096 bytes
>> [  239.616317] UBIFS error (pid 676): ubifs_scan: corrupt empty space
>> at LEB 2:268135
>> [  239.623996] UBIFS error (pid 676): ubifs_scanned_corruption:
>> corruption at LEB 2:268135
>> [  239.642101] UBIFS error (pid 676): ubifs_scan: LEB 2 scanning failed
>> [  239.976396] UBI error: ubi_io_read: error -74 while reading 516096
>> bytes from PEB 4:8192, read 516096 bytes
>> [  239.986742] UBIFS error (pid 676): ubifs_recover_master_node:
>> failed to recover master node
>> mount: mounting ubi0_0 on /mnt/ failed: Invalid argument
> And BTW, it is a good idea not to erase/re-flash this device if you want
> to fix this problem.
>
Our power off tests causes this sporadic error too  (ubifs_recover_master_node: failed
to recover master node).
We use kernel 2.6.29 with the git-patch (from 3/2010) for 47MB NOR flash partition.

I tried to find with debugging  the error reason.
The recover of the master_node reads the master_node1 and master_node2.
The master_node1 was emty.
The error was detected in:
int ubifs_recover_master_node(struct ubifs_info *c)
    ....
    if (mst1) {
       ......
    } else {
        if (!mst2)
            goto out_err;          
        /* 1st LEB was unmapped and about to be written, so there must
         * be no room left in 2nd LEB.         */
        offs2 = (void *)mst2 - buf2;
        if (offs2 + sz + sz <= c->leb_size)
            goto out_err;                               !!!!!!!!!!!!!!!!!!!
        mst = mst2;
    }
I checked the values of the compare "if (115712 + 512 +512  (=116736) <= 130944)".
I skipped this error for test purpose. The master_node was recovered. I saw no problems
with the FS. I was not able to follow this check.

I was able to provoke this error manual.
My UBIFS use LEB:1 for the first master_node and LEB:2 for the second.
I searched the LEB:1 and deleted this sector.
The following loading and mounting causes the error.
A ignoring of the error causes a successful recovery.
I used 15 MB and 47 MB NOR flash partitions for this tries.
The 15MB partition flash checks the error in the compare "if (9216 + 512 +512  (=10240)
<= 130944)",
These values are independent to the PEB of LEB:1 and LEB:2 and independent to the free
space of the FS.

Regards
Reinhold






From kyle at moffetthome.net  Mon Jun 28 13:05:56 2010
From: kyle at moffetthome.net (Kyle Moffett)
Date: Mon, 28 Jun 2010 13:05:56 -0400
Subject: of-flash: Unable to ioremap() both 128MB NOR flashes on 32-bit 
	system with 2GB+ RAM
In-Reply-To: <1277709539_13309@mail4.comsite.net>
References: <AANLkTikMtZsg5ameUY9dnZoEqV-hfa7tkfGIO1hBtDq1@mail.gmail.com> 
	<1277709539_13309@mail4.comsite.net>
Message-ID: <AANLkTiliAex8bgu5UPrEwpVjgfwZHUuFbE2R199wow-H@mail.gmail.com>

On Mon, Jun 28, 2010 at 03:18, Milton Miller <miltonm at bga.com> wrote:
> On Fri Jun 25 around 14:01:51 EST 2010 Kyle Moffett wrote:
>> I've got a new P2020 (32bit mpc85xx family) board I'm working on a
>> port for that includes 2 NOR flashes (128MB each) and a removable
>> SO-RDIMM of 2GB or 4GB. ?Unfortunately when I configure both flashes
>> in the device-tree off my elbc, Linux is completely unable to access
>> the second one because it attempts to ioremap() the entire virtual
>> address space of both FLASH chips.
>>
>> Even with only one flash chip enabled, there's a bit of a noticeable
>> performance degradation because the mapping consumes almost all of my
>> available vmalloc space and forces bounce-buffering for all my
>> HIGHMEM.
>>
>> It looks like the "of-flash" driver currently requires that the whole
>> chip be mapped in the kernel at once. ?I would much rather have a 50%
>> performance penalty on flash accesses (which are already very slow)
>> and regain most of the vmap space.
>>
>> So the question is, is there a way to convince the MTD layer to
>> iomap() only what it needs to access to do reads and writes? ?If not,
>> what changes would need to be made to MTD and/or "of-flash" to create
>> such functionality?
>
> I believe the MTD layer would be happy, but it is beyond the scope of
> the physmap_of driver.

Well, I believe that the physmap_of driver is the correct place for
it; that driver is used by a large number of embedded PPC systems and
at present it is completely unable to handle some of the larger flash
memories currently being produced (256MByte+), and there's a decent
system-wide performance penalty (due to lack of ioremap space) even
for the larger flash memories which do function.

Cheers,
Kyle Moffett


From SteveDeiters at BASLER.com  Mon Jun 28 17:25:02 2010
From: SteveDeiters at BASLER.com (Steve Deiters)
Date: Mon, 28 Jun 2010 16:25:02 -0500
Subject: JFFS2 corruption when mounting filesystem with filenamesoflength>
	7
In-Reply-To: <181804936ABC2349BE503168465576460F20CB90@exchserver.basler.com>
References: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com> 
	<181804936ABC2349BE503168465576460F1AAEE1@exchserver.basler.com> 
	<181804936ABC2349BE503168465576460F1AB73E@exchserver.basler.com> 
	<181804936ABC2349BE503168465576460F20CB90@exchserver.basler.com>
Message-ID: <181804936ABC2349BE503168465576460F20D651@exchserver.basler.com>

> I think there may be something weird going on with the memcpy 
> in my build.  If I use the following patch I no longer get 
> errors when I mount the filesystem.  All I did was replace 
> the memcpy with a loop.
> 
> I'm not sure what's special about this particular use of 
> memcpy.  I can't believe that things would be working as well 
> as they do if memcpy was broken in general.
> 
> This is on a PowerPC 32 bit build for a MPC5121.  I am using 
> a GCC 4.1.2 to compile.  Is anyone aware of any issues with 
> memcpy in this configuration?
> 
> Thanks.

It seems this processor is mangling the data when it access unaligned
addresses into Flash with a lwz instruction.  The memcpy implementation
in copy_32.S aligns the destination, leaving the source possibly
unaligned.  In this particular instance the source is an address into my
Flash address space which is causing the problem.  When the filenames
were < 8 it always does a bytewise copy which is why I wasn't having
problems with those.

It seems this only occurs when I have the translation enabled.  If I
clear the DR bit in the MSR and then repeat the instruction with the
corresponding physical address it will read correctly.

I'm not sure if this is expected behavior with this core.  I can fix at
least this one problem by using memcpy_fromio since it does alignment
checks for the source and destination.

I'm not sure what the proper fix is for this.  If I use memcpy_fromio I
think I'll just run into problems somewhere else.  Any other
suggestions?

Thanks.


From wd at denx.de  Mon Jun 28 18:30:47 2010
From: wd at denx.de (Wolfgang Denk)
Date: Tue, 29 Jun 2010 00:30:47 +0200
Subject: JFFS2 corruption when mounting filesystem with filenamesoflength>
	7
In-Reply-To: <181804936ABC2349BE503168465576460F20D651@exchserver.basler.com>
References: <181804936ABC2349BE503168465576460F1AAEC6@exchserver.basler.com>
	<181804936ABC2349BE503168465576460F1AAEE1@exchserver.basler.com>
	<181804936ABC2349BE503168465576460F1AB73E@exchserver.basler.com>
	<181804936ABC2349BE503168465576460F20CB90@exchserver.basler.com>
	<181804936ABC2349BE503168465576460F20D651@exchserver.basler.com>
Message-ID: <20100628223047.6F7F514EBF7@gemini.denx.de>

Dear "Steve Deiters",

In message <181804936ABC2349BE503168465576460F20D651 at exchserver.basler.com> you wrote:
> > I think there may be something weird going on with the memcpy 
> > in my build.  If I use the following patch I no longer get 
> > errors when I mount the filesystem.  All I did was replace 
> > the memcpy with a loop.
> > 
> > I'm not sure what's special about this particular use of 
> > memcpy.  I can't believe that things would be working as well 
> > as they do if memcpy was broken in general.
> > 
> > This is on a PowerPC 32 bit build for a MPC5121.  I am using 
> > a GCC 4.1.2 to compile.  Is anyone aware of any issues with 
> > memcpy in this configuration?
> > 
> > Thanks.
> 
> It seems this processor is mangling the data when it access unaligned
> addresses into Flash with a lwz instruction.  The memcpy implementation
> in copy_32.S aligns the destination, leaving the source possibly
> unaligned.  In this particular instance the source is an address into my
> Flash address space which is causing the problem.  When the filenames
> were < 8 it always does a bytewise copy which is why I wasn't having
> problems with those.
> 
> It seems this only occurs when I have the translation enabled.  If I
> clear the DR bit in the MSR and then repeat the instruction with the
> corresponding physical address it will read correctly.
> 
> I'm not sure if this is expected behavior with this core.  I can fix at
> least this one problem by using memcpy_fromio since it does alignment
> checks for the source and destination.

Both the MPC52xx and MPC512x have know problems (silent data
corruption) with unaligned accesses on the local bus.

This can be trivially demonstrated in U-Boot by reading the flash
memory with 32 bit accesses; for example like this:

=> md FC0C0000 20
fc0c0000: 7012ab65 01616464 636f6e73 3d736574    p..e.addcons=set
fc0c0010: 656e7620 626f6f74 61726773 20247b62    env bootargs ${b
fc0c0020: 6f6f7461 7267737d 20636f6e 736f6c65    ootargs} console
fc0c0030: 3d247b63 6f6e736f 6c657d2c 247b6261    =${console},${ba
fc0c0040: 75647261 74657d00 61646469 703d7365    udrate}.addip=se
fc0c0050: 74656e76 20626f6f 74617267 7320247b    tenv bootargs ${
fc0c0060: 626f6f74 61726773 7d206970 3d247b69    bootargs} ip=${i
fc0c0070: 70616464 727d3a24 7b736572 76657269    paddr}:${serveri
=> md FC0C0001 20
fc0c0001: 65726901 00000063 0000003d 00000065    eri....c...=...e
fc0c0011: 00000062 00000061 00000020 0000006f    ...b...a... ...o
fc0c0021: 00000072 00000020 00000073 0000003d    ...r... ...s...=
fc0c0031: 0000006f 0000006c 00000024 00000075    ...o...l...$...u
fc0c0041: 00000074 00000061 00000070 00000074    ...t...a...p...t
fc0c0051: 00000020 00000074 00000073 00000062    ... ...t...s...b
fc0c0061: 00000061 0000007d 0000003d 00000070    ...a...}...=...p
fc0c0071: 00000072 0000007b 00000076 00000070    ...r...{...v...p

> I'm not sure what the proper fix is for this.  If I use memcpy_fromio I
> think I'll just run into problems somewhere else.  Any other
> suggestions?

See http://article.gmane.org/gmane.comp.boot-loaders.u-boot/80278 for
how we fix this in U-Boot.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"On two occasions I have been  asked  [by  members  of  Parliament!],
'Pray,  Mr.  Babbage, if you put into the machine wrong figures, will
the right answers come out?' I am not able rightly to  apprehend  the
kind of confusion of ideas that could provoke such a question."
- Charles Babbage


From dedekind1 at gmail.com  Mon Jun 28 23:46:37 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 06:46:37 +0300
Subject: [RFC/PATCH] doc2000: Fix uninitialized variable in
	doc_ecc_decode()
In-Reply-To: <4BFDCEC3.7070601@elphinstone.net>
References: <4BFDCEC3.7070601@elphinstone.net>
Message-ID: <1277783197.3599.3.camel@localhost.localdomain>

On Thu, 2010-05-27 at 11:45 +1000, Mark Ware wrote:
> The variable 'syn' was being used uninitialized.  Also
> fixed incorrect use of syn[] vs s[].
> 
> Tested on powerpc board with 64MB DOC2000.
> ---
> 
> I am porting from a 2.4.18 kernel to 2.6.32, and I saw random media header
> mismatches causing a failure to detect the DOC device partitions.  Tracing
> through, I saw this variable being used uninitialized and I suspect
> incorrectly also.
> 
> I do not really understand how the ecc/syndrome code works, so I do not
> know if this patch is the correct solution, but it did make my problem
> go away...
> 
> CC: Thomas Gleixner as I believe he may have written this function initially.
> 
>  drivers/mtd/nand/diskonchip.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
> index a5bf9ff..7da2321 100644
> --- a/drivers/mtd/nand/diskonchip.c
> +++ b/drivers/mtd/nand/diskonchip.c
> @@ -145,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
>  	uint8_t parity;
>  	uint16_t ds[4], s[5], tmp, errval[8], syn[4];
>  
> +	memset(syn, 0, sizeof(syn));

I also do not know the math of this stuff, but this change is not
needed ...

>  	/* Convert the ecc bytes into words */
>  	ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8);
>  	ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6);
> @@ -168,9 +169,9 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
>  			s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
>  	}
>  
> -	/* Calc s[i] = s[i] / alpha^(v + i) */
> +	/* Calc syn[i] = s[i] / alpha^(v + i) */
>  	for (i = 0; i < NROOTS; i++) {
> -		if (syn[i])
> +		if (s[i])
>  			syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
>  	}

... after this change, right?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun 28 23:58:33 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 06:58:33 +0300
Subject: [RFC/PATCH] doc2000: Fix uninitialized variable in
	doc_ecc_decode()
In-Reply-To: <1277783197.3599.3.camel@localhost.localdomain>
References: <4BFDCEC3.7070601@elphinstone.net>
	<1277783197.3599.3.camel@localhost.localdomain>
Message-ID: <1277783913.3599.4.camel@localhost.localdomain>

On Tue, 2010-06-29 at 06:46 +0300, Artem Bityutskiy wrote:
> On Thu, 2010-05-27 at 11:45 +1000, Mark Ware wrote:
> > The variable 'syn' was being used uninitialized.  Also
> > fixed incorrect use of syn[] vs s[].
> > 
> > Tested on powerpc board with 64MB DOC2000.
> > ---
> > 
> > I am porting from a 2.4.18 kernel to 2.6.32, and I saw random media header
> > mismatches causing a failure to detect the DOC device partitions.  Tracing
> > through, I saw this variable being used uninitialized and I suspect
> > incorrectly also.
> > 
> > I do not really understand how the ecc/syndrome code works, so I do not
> > know if this patch is the correct solution, but it did make my problem
> > go away...
> > 
> > CC: Thomas Gleixner as I believe he may have written this function initially.
> > 
> >  drivers/mtd/nand/diskonchip.c |    5 +++--
> >  1 files changed, 3 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
> > index a5bf9ff..7da2321 100644
> > --- a/drivers/mtd/nand/diskonchip.c
> > +++ b/drivers/mtd/nand/diskonchip.c
> > @@ -145,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
> >  	uint8_t parity;
> >  	uint16_t ds[4], s[5], tmp, errval[8], syn[4];
> >  
> > +	memset(syn, 0, sizeof(syn));
> 
> I also do not know the math of this stuff, but this change is not
> needed ...

Sorry, ignore this, I'll put this patch to my l2-mtd-2.6 tree and let
dwmw2 decide whether it is good or not :-)
-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:29:46 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:29:46 +0300
Subject: [RFC/PATCH] doc2000: Fix uninitialized variable in
	doc_ecc_decode()
In-Reply-To: <4BFDCEC3.7070601@elphinstone.net>
References: <4BFDCEC3.7070601@elphinstone.net>
Message-ID: <1277792986.1041.959.camel@localhost>

On Thu, 2010-05-27 at 11:45 +1000, Mark Ware wrote:
> The variable 'syn' was being used uninitialized.  Also
> fixed incorrect use of syn[] vs s[].
> 
> Tested on powerpc board with 64MB DOC2000.
> ---
> 
> I am porting from a 2.4.18 kernel to 2.6.32, and I saw random media header
> mismatches causing a failure to detect the DOC device partitions.  Tracing
> through, I saw this variable being used uninitialized and I suspect
> incorrectly also.
> 
> I do not really understand how the ecc/syndrome code works, so I do not
> know if this patch is the correct solution, but it did make my problem
> go away...
> 
> CC: Thomas Gleixner as I believe he may have written this function initially.

Please, always add Signed-off-by for kernel patches. I added it for you.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:35:12 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:35:12 +0300
Subject: [PATCH v5 2/3] mtd-utils: support >4GiB devices
In-Reply-To: <1276342579.19028.116.camel@localhost>
References: <cd4bcbb843643dc463d2a2853766bcf57c23f546@localhost.localdomain>
	<5e05b5a05a30b2dc2035b87a60bb82f3137174cb@localhost.localdomain>
	<1273745471.22706.163.camel@localhost>
	<1276342579.19028.116.camel@localhost>
Message-ID: <1277793312.1041.963.camel@localhost>

On Sat, 2010-06-12 at 14:36 +0300, Artem Bityutskiy wrote:
> On Thu, 2010-05-13 at 13:11 +0300, Artem Bityutskiy wrote:
> > >  nandwrite.c           |   60 +++++-----
> > >  13 files changed, 570 insertions(+), 171 deletions(-)
> > >  create mode 100644 mtd_ioctl.c
> > >  create mode 100644 mtd_ioctl.h
> > 
> > Any chance to extend and use mtd-utils/ubi-utils/src/libmtd.c instead of
> > mtd_ioctl.c?
> 
> Does silence mean that that answer is "no"? :-)

I have a dilemma whether to take your patches as they are or not :-) On
the one hand, they are needed, on the other hand, if we re-use libmtd.c,
we do not have duplicated code. libmtd.c is tested and it distinguish
beween old kernels (no sysfs support in mtd) and new kernels (expose
stuff via sysfs). It would be nice to share more code...

I guess I do not take your patches so far.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:38:30 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:38:30 +0300
Subject: [PATCH 1/2] mtd: OneNAND: Add runtime badblock check feature
In-Reply-To: <012f01cb0b4e$db1a7550$914f5ff0$%park@samsung.com>
References: <1275380256-15315-1-git-send-email-jy0922.shim@samsung.com>
	<1276421200.19028.192.camel@localhost>
	<012f01cb0b4e$db1a7550$914f5ff0$%park@samsung.com>
Message-ID: <1277793510.1041.966.camel@localhost>

On Mon, 2010-06-14 at 08:19 +0900, Kyungmin Park wrote:
> Hi,
> 
> > -----Original Message-----
> > From: Artem Bityutskiy [mailto:dedekind1 at gmail.com]
> > Sent: Sunday, June 13, 2010 6:27 PM
> > To: Joonyoung Shim
> > Cc: linux-mtd at lists.infradead.org; Kyungmin Park; Thomas Gleixner
> > Subject: Re: [PATCH 1/2] mtd: OneNAND: Add runtime badblock check feature
> > 
> > On Tue, 2010-06-01 at 17:17 +0900, Joonyoung Shim wrote:
> > > From: Kyungmin Park <kyungmin.park at samsung.com>
> > >
> > > This patch is to support runtime badblock checking. This supports only
> > > OneNAND currently. The OneNAND badblock checking when boots occurs boot
> > > time delay. We can reduce boot time because can detect badblock at
> > > runtime.
> > >
> > > Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> > 
> > Hi, this feature is interesting. But why not to use bad block table
> > instead of adding more complexity to the already very complex and
> > difficult to follow code?
> 
> > 
> > Also, if you really want this, it should be rather lazy checking, where
> > you read OOB on demand, and then save this information to the in-ram
> > BBT, and when you get another ->block_isbad() for a block which was
> > previously checked, you do not read OOB for the second time.
> 
> It's based on BBT already. Now I set the BBT values as 0x2 and then check it at runtime and then mark it 0 for good, 3 for bad block.
> 
> Right, it's same word lazy checking and runtime check.
> 
> The original ideas are from UBI scan it read all blocks again at probe.
> I just scan almost block read once at ubi scan.

I think this this stuff should:

1. refrain from adding any new config option
2. be the default method and fully replace the old method

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:41:36 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:41:36 +0300
Subject: [PATCH] mxc_nand: fix PM
In-Reply-To: <4C15D542.2060102@eukrea.com>
References: <1274942000-3580-2-git-send-email-eric@eukrea.com>
	<1274982919-13251-1-git-send-email-eric@eukrea.com>
	<4C15D542.2060102@eukrea.com>
Message-ID: <1277793696.1041.967.camel@localhost>

On Mon, 2010-06-14 at 09:07 +0200, Eric B?nard wrote:
> Hi Sascha,
> 
> Le 27/05/2010 19:55, Eric B?nard a ?crit :
> > * when resuming, we get the following log :
> > nand_resume called for a chip which is not in suspended state
> > * this happens because mtd->suspend and mtd->resume are already
> > called from the mtd layer, thus they were called a second time
> > in mxc_nand so mtd complains when trying to resume for the
> > second time
> > * the fix is to remove these call and thus remove the supend and
> > resume functions of mxc_nand
> >
> any news concerning this patch ?
> 

Pushed to l2-mtd-2.6.git / dunno

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:42:16 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:42:16 +0300
Subject: [PATCH] mtd: Added an ioctl to query the lock status of a
	flash sector.
In-Reply-To: <20100614161033.GA24877@riccoc20.at.omicron.at>
References: <20100531131214.GA15887@riccoc20.at.omicron.at>
	<1276419903.19028.180.camel@localhost>
	<20100614161033.GA24877@riccoc20.at.omicron.at>
Message-ID: <1277793736.1041.968.camel@localhost>

On Mon, 2010-06-14 at 18:10 +0200, Richard Cochran wrote:
> On Sun, Jun 13, 2010 at 12:05:03PM +0300, Artem Bityutskiy wrote:
> > I think it is tiny bit nicer to name 'is_locked', which is a bit more
> > consistent with the already existing 'block_isbad'?
> 
> Okay, here it is again.

Pushed to l2-mtd-2.6.git / master

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From mware at elphinstone.net  Tue Jun 29 02:47:03 2010
From: mware at elphinstone.net (Mark Ware)
Date: Tue, 29 Jun 2010 16:47:03 +1000
Subject: [RFC/PATCH] doc2000: Fix uninitialized variable
	in	doc_ecc_decode()
In-Reply-To: <1277792986.1041.959.camel@localhost>
References: <4BFDCEC3.7070601@elphinstone.net>
	<1277792986.1041.959.camel@localhost>
Message-ID: <4C2996E7.9040209@elphinstone.net>

On 29/06/10 16:29, Artem Bityutskiy wrote:
> On Thu, 2010-05-27 at 11:45 +1000, Mark Ware wrote:
>> The variable 'syn' was being used uninitialized.  Also
>> fixed incorrect use of syn[] vs s[].
>>
>> Tested on powerpc board with 64MB DOC2000.
>> ---
>>
>> I am porting from a 2.4.18 kernel to 2.6.32, and I saw random media header
>> mismatches causing a failure to detect the DOC device partitions.  Tracing
>> through, I saw this variable being used uninitialized and I suspect
>> incorrectly also.
>>
>> I do not really understand how the ecc/syndrome code works, so I do not
>> know if this patch is the correct solution, but it did make my problem
>> go away...
>>
>> CC: Thomas Gleixner as I believe he may have written this function initially.
> 
> Please, always add Signed-off-by for kernel patches. I added it for you.
> 

Thanks.  I guess I expected to be told that I was smoking something and that
my DOC error disappearing was unrelated...

Mark


From dedekind1 at gmail.com  Tue Jun 29 02:45:18 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:45:18 +0300
Subject: [PATCH] mtd: cfi_probe: print manufacturer and id of probed chip
In-Reply-To: <20100614103345.26103.40429.stgit@dev.siriade.com>
References: <20100614103345.26103.40429.stgit@dev.siriade.com>
Message-ID: <1277793918.1041.970.camel@localhost>

On Mon, 2010-06-14 at 12:33 +0200, Guillaume LECERF wrote:
> Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
> ---
>  drivers/mtd/chips/cfi_probe.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
> index b2acd32..5f5ba3e 100644
> --- a/drivers/mtd/chips/cfi_probe.c
> +++ b/drivers/mtd/chips/cfi_probe.c
> @@ -235,9 +235,9 @@ static int __xipram cfi_chip_setup(struct map_info *map,
>  	cfi_qry_mode_off(base, map, cfi);
>  	xip_allowed(base, map);
>  
> -	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
> +	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. mfr=0x%08x id=0x%08x\n",
>  	       map->name, cfi->interleave, cfi->device_type*8, base,
> -	       map->bankwidth*8);
> +	       map->bankwidth*8, cfi->mfr, cfi->id);

This is not a debugging print, so I think you should do it in a more
user-friendly way. E.g., "manufect. ID %#08x, chip id %#08x".

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:47:48 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:47:48 +0300
Subject: [PATCH] ixp4xx: add support for static flash partitions
In-Reply-To: <20100614161519.GB24877@riccoc20.at.omicron.at>
References: <20100531162434.GA4599@riccoc20.at.omicron.at>
	<1276420566.19028.184.camel@localhost>
	<20100614161519.GB24877@riccoc20.at.omicron.at>
Message-ID: <1277794068.1041.971.camel@localhost>

On Mon, 2010-06-14 at 18:15 +0200, Richard Cochran wrote:
> On Sun, Jun 13, 2010 at 12:16:06PM +0300, Artem Bityutskiy wrote:
> > I could fix your patch up myself, but I do not know the code, so please,
> > re-send a patch against the latest mtd-2.6 tree.
> 
> Okay, here it is again, this time against today's master branch of 
> git://git.infradead.org/mtd-2.6.git
> 
> Thanks,
> Richard
> 
> 
> This patch adds support for static flash partitioning from a platform
> device. Also, we clean up some weirdness where statements were separated
> by commas instead of semicolons. While we are at it, fix some minor bad
> white space, too.
> 
> Signed-off-by: Richard Cochran <richard.cochran at omicron.at>

Pushed to l2-mtd-2.6.git / dunno.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:49:28 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:49:28 +0300
Subject: [PATCH] mtd: physmap.c: use resource_size()
In-Reply-To: <0D753D10438DA54287A00B02708426976371223143@AUSP01VMBX24.collaborationhost.net>
References: <0D753D10438DA54287A00B02708426976371223143@AUSP01VMBX24.collaborationhost.net>
Message-ID: <1277794168.1041.972.camel@localhost>

On Mon, 2010-06-14 at 11:57 -0500, H Hartley Sweeten wrote:
> Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
> Cc: David Woodhouse <David.Woodhouse at intel.com>

Pushed to l2-mtd-2.6.git / master

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun 29 02:50:40 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 29 Jun 2010 09:50:40 +0300
Subject: [RFC/PATCH] doc2000: Fix uninitialized variable in
	doc_ecc_decode()
In-Reply-To: <4C2996E7.9040209@elphinstone.net>
References: <4BFDCEC3.7070601@elphinstone.net>
	<1277792986.1041.959.camel@localhost>
	<4C2996E7.9040209@elphinstone.net>
Message-ID: <1277794240.1041.973.camel@localhost>

On Tue, 2010-06-29 at 16:47 +1000, Mark Ware wrote:
> On 29/06/10 16:29, Artem Bityutskiy wrote:
> > On Thu, 2010-05-27 at 11:45 +1000, Mark Ware wrote:
> >> The variable 'syn' was being used uninitialized.  Also
> >> fixed incorrect use of syn[] vs s[].
> >>
> >> Tested on powerpc board with 64MB DOC2000.
> >> ---
> >>
> >> I am porting from a 2.4.18 kernel to 2.6.32, and I saw random media header
> >> mismatches causing a failure to detect the DOC device partitions.  Tracing
> >> through, I saw this variable being used uninitialized and I suspect
> >> incorrectly also.
> >>
> >> I do not really understand how the ecc/syndrome code works, so I do not
> >> know if this patch is the correct solution, but it did make my problem
> >> go away...
> >>
> >> CC: Thomas Gleixner as I believe he may have written this function initially.
> > 
> > Please, always add Signed-off-by for kernel patches. I added it for you.
> > 
> 
> Thanks.  I guess I expected to be told that I was smoking something and that
> my DOC error disappearing was unrelated...

Note, I did not really review your patch - the MTD maintainer will take
a look at it later, probably.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From glecerf at gmail.com  Tue Jun 29 04:32:37 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 29 Jun 2010 10:32:37 +0200
Subject: [PATCH] mtd: cfi_probe: print manufacturer and id of probed chip
Message-ID: <20100629083204.11146.37097.stgit@dev.siriade.com>

2010/6/29 Artem Bityutskiy <dedekind1 at gmail.com>:
> This is not a debugging print, so I think you should do it in a more
> user-friendly way. E.g., "manufect. ID %#08x, chip id %#08x".

OK, here it is again.

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_probe.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index b2acd32..8f5b96a 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -235,9 +235,9 @@ static int __xipram cfi_chip_setup(struct map_info *map,
 	cfi_qry_mode_off(base, map, cfi);
 	xip_allowed(base, map);
 
-	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
+	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n",
 	       map->name, cfi->interleave, cfi->device_type*8, base,
-	       map->bankwidth*8);
+	       map->bankwidth*8, cfi->mfr, cfi->id);
 
 	return 1;
 }




From segooon at gmail.com  Tue Jun 29 06:14:57 2010
From: segooon at gmail.com (Kulikov Vasiliy)
Date: Tue, 29 Jun 2010 14:14:57 +0400
Subject: [PATCH 01/25] r852: remove casts from void*
Message-ID: <1277806498-30738-1-git-send-email-segooon@gmail.com>

Remove unnesessary casts from void*.

Signed-off-by: Kulikov Vasiliy <segooon at gmail.com>
---
 drivers/mtd/nand/r852.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 78a4232..c0a9835 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -64,8 +64,8 @@ static inline void r852_write_reg_dword(struct r852_device *dev,
 /* returns pointer to our private structure */
 static inline struct r852_device *r852_get_dev(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
-	return (struct r852_device *)chip->priv;
+	struct nand_chip *chip = mtd->priv;
+	return chip->priv;
 }
 
 
-- 
1.7.0.4



From segooon at gmail.com  Tue Jun 29 06:15:13 2010
From: segooon at gmail.com (Kulikov Vasiliy)
Date: Tue, 29 Jun 2010 14:15:13 +0400
Subject: [PATCH 05/25] mtd_dataflash: remove casts from void*
Message-ID: <1277806514-30874-1-git-send-email-segooon@gmail.com>

Remove unnesessary casts from void*.

Signed-off-by: Kulikov Vasiliy <segooon at gmail.com>
---
 drivers/mtd/devices/mtd_dataflash.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 1981740..c5015cc 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -141,7 +141,7 @@ static int dataflash_waitready(struct spi_device *spi)
  */
 static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	struct spi_device	*spi = priv->spi;
 	struct spi_transfer	x = { .tx_dma = 0, };
 	struct spi_message	msg;
@@ -231,7 +231,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
 static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 			       size_t *retlen, u_char *buf)
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	struct spi_transfer	x[2] = { { .tx_dma = 0, }, };
 	struct spi_message	msg;
 	unsigned int		addr;
@@ -304,7 +304,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
 				size_t * retlen, const u_char * buf)
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	struct spi_device	*spi = priv->spi;
 	struct spi_transfer	x[2] = { { .tx_dma = 0, }, };
 	struct spi_message	msg;
@@ -515,7 +515,7 @@ static ssize_t otp_read(struct spi_device *spi, unsigned base,
 static int dataflash_read_fact_otp(struct mtd_info *mtd,
 		loff_t from, size_t len, size_t *retlen, u_char *buf)
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	int			status;
 
 	/* 64 bytes, from 0..63 ... start at 64 on-chip */
@@ -532,7 +532,7 @@ static int dataflash_read_fact_otp(struct mtd_info *mtd,
 static int dataflash_read_user_otp(struct mtd_info *mtd,
 		loff_t from, size_t len, size_t *retlen, u_char *buf)
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	int			status;
 
 	/* 64 bytes, from 0..63 ... start at 0 on-chip */
@@ -553,7 +553,7 @@ static int dataflash_write_user_otp(struct mtd_info *mtd,
 	const size_t		l = 4 + 64;
 	uint8_t			*scratch;
 	struct spi_transfer	t;
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	int			status;
 
 	if (len > 64)
-- 
1.7.0.4



From segooon at gmail.com  Tue Jun 29 06:15:17 2010
From: segooon at gmail.com (Kulikov Vasiliy)
Date: Tue, 29 Jun 2010 14:15:17 +0400
Subject: [PATCH 06/25] nandsim: remove casts from void*
Message-ID: <1277806517-30908-1-git-send-email-segooon@gmail.com>

Remove unnesessary casts from void*.

Signed-off-by: Kulikov Vasiliy <segooon at gmail.com>
---
 drivers/mtd/nand/nandsim.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 261337e..c25648b 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -553,8 +553,8 @@ static uint64_t divide(uint64_t n, uint32_t d)
  */
 static int init_nandsim(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
-	struct nandsim   *ns   = (struct nandsim *)(chip->priv);
+	struct nand_chip *chip = mtd->priv;
+	struct nandsim   *ns   = chip->priv;
 	int i, ret = 0;
 	uint64_t remains;
 	uint64_t next_offset;
@@ -1877,7 +1877,7 @@ static void switch_state(struct nandsim *ns)
 
 static u_char ns_nand_read_byte(struct mtd_info *mtd)
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 	u_char outb = 0x00;
 
 	/* Sanity and correctness checks */
@@ -1950,7 +1950,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
 
 static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 
 	/* Sanity and correctness checks */
 	if (!ns->lines.ce) {
@@ -2132,7 +2132,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd)
 
 static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 
 	/* Check that chip is expecting data input */
 	if (!(ns->state & STATE_DATAIN_MASK)) {
@@ -2159,7 +2159,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 
 static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 
 	/* Sanity and correctness checks */
 	if (!ns->lines.ce) {
@@ -2352,7 +2352,7 @@ module_init(ns_init_module);
  */
 static void __exit ns_cleanup_module(void)
 {
-	struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
+	struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv;
 	int i;
 
 	free_nandsim(ns);    /* Free nandsim private resources */
-- 
1.7.0.4



From segooon at gmail.com  Tue Jun 29 06:15:20 2010
From: segooon at gmail.com (Kulikov Vasiliy)
Date: Tue, 29 Jun 2010 14:15:20 +0400
Subject: [PATCH 07/25] r852: remove casts from void*
Message-ID: <1277806521-30942-1-git-send-email-segooon@gmail.com>

Remove unnesessary casts from void*.

Signed-off-by: Kulikov Vasiliy <segooon at gmail.com>
---
 drivers/mtd/nand/r852.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index c0a9835..43f0366 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -380,7 +380,7 @@ void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl)
  */
 int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
-	struct r852_device *dev = (struct r852_device *)chip->priv;
+	struct r852_device *dev = chip->priv;
 
 	unsigned long timeout;
 	int status;
-- 
1.7.0.4



From segooon at gmail.com  Tue Jun 29 06:15:24 2010
From: segooon at gmail.com (Kulikov Vasiliy)
Date: Tue, 29 Jun 2010 14:15:24 +0400
Subject: [PATCH 08/25] sm_common: remove casts from void*
Message-ID: <1277806525-30976-1-git-send-email-segooon@gmail.com>

Remove unnesessary casts from void*.

Signed-off-by: Kulikov Vasiliy <segooon at gmail.com>
---
 drivers/mtd/nand/sm_common.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c
index ac80fb3..4a8f367 100644
--- a/drivers/mtd/nand/sm_common.c
+++ b/drivers/mtd/nand/sm_common.c
@@ -109,7 +109,7 @@ static struct nand_flash_dev nand_xd_flash_ids[] = {
 
 int sm_register_device(struct mtd_info *mtd, int smartmedia)
 {
-	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	int ret;
 
 	chip->options |= NAND_SKIP_BBTSCAN;
-- 
1.7.0.4



From teemu.peltola at nextfour.com  Tue Jun 29 07:29:00 2010
From: teemu.peltola at nextfour.com (Teemu Peltola)
Date: Tue, 29 Jun 2010 14:29:00 +0300 (EEST)
Subject: mxc_nand: write problem with i.MX-27L + ST NAND512R3A2DZA6E flash
In-Reply-To: <30032862.4841277810798847.JavaMail.root@hermes>
Message-ID: <482801.4861277810940495.JavaMail.root@hermes>

Hi,

I have a device based on i.MX-27L and I am updating kernel from 2.6.24 with a custom set of patches to vanilla 2.6.34. I am having problems using mxc_nand driver with ST NAND512R3A2DZA6E flash chip (64MB, 8-bit, 512 byte page size). I am using arch/arm/mach-mx2/mach-mx27ads.c based board file.

I am using physmap to create three partitions (mxc_nand:1M(factset),2M(opt),-(root)) on NAND and they are created successfully with correct sizes. In my mxc_nand_platform_data I have the following values: .width=1, .hw_ecc=1, .flash_bbt=0. The chip is probed successfully at device startup: NAND device: Manufacturer ID: 0x20, Chip ID: 0x36 (ST Micro NAND 64MiB 1,8V 8-bit).

I added some debug outputs to mxcnd_probe (mxc_nand.c):
mxcnd_probe: pdata->width: 1, mtd->writesize: 512, mtd->size: 67108864, mtd->erasesize: 16384, mtd->oobsize: 16, mtd->oobavail: 9, mtd->numeraseregions: 0, mtd->usecount: 0

The problem is that write operations fail. If I have CONFIG_MTD_NAND_VERIFY_WRITE=y, CONFIG_MTD_DEBUG=y, CONFIG_MTD_DEBUG_VERBOSE=0 enabled in my kernel config and use mtd_pagetest module I see the following output:

$> modprobe mtd_pagetest dev=4
=================================================
mtd_pagetest: MTD device: 4
mtd_pagetest: MTD device size 1048576, eraseblock size 16384, page size 512, count of eraseblocks 64, pages per eraseblock 32, OOB size 16
mtd_pagetest: scanning for bad eraseblocks
mtd_pagetest: scanned 64 eraseblocks, 0 are bad
mtd_pagetest: erasing whole device
mtd_pagetest: erased 64 eraseblocks
mtd_pagetest: writing whole device
mtd_pagetest: error: write failed at 0x0
mtd_pagetest: error -5 occurred
=================================================
$> cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00040000 00010000 "uboot"
mtd1: 00010000 00010000 "ubootenv"
mtd2: 001b0000 00010000 "kernel"
mtd3: 00200000 00010000 "norroot"
mtd4: 00100000 00004000 "factset"
mtd5: 00200000 00004000 "opt"
mtd6: 03d00000 00004000 "root"

I tried to apply this patch: http://patchwork.ozlabs.org/patch/53870/ but it did not help.

Any ideas what could be wrong?

--
Teemu


From s-ghorai at ti.com  Tue Jun 29 09:22:34 2010
From: s-ghorai at ti.com (Ghorai, Sukumar)
Date: Tue, 29 Jun 2010 18:52:34 +0530
Subject: Info: BCH correction and GPL 
Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030DFE919D@dbde02.ent.ti.com>

Hi,

Is there any GPL license code of BCH error correction that could be used for NAND ECC?

We have h/w module for error detection. And we need s/w algorithm/code for error correction for our platform. And we are looking t=4 and t=8 error correction using degree-13 dimension of Galois field (m=13).

Please let me know. 

Thanks & regards,
Ghorai




From s-ghorai at ti.com  Wed Jun 30 10:42:13 2010
From: s-ghorai at ti.com (Ghorai, Sukumar)
Date: Wed, 30 Jun 2010 20:12:13 +0530
Subject: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
References: <s-ghorai@ti.com> <1275637205-489-1-git-send-email-s-ghorai@ti.com>
	<AANLkTinf8OcvHbLggdEJNGLvlAtSeExKri-IqNlwLpYD@mail.gmail.com> 
Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030DFE9927@dbde02.ent.ti.com>

Tony,
Please let me know if any have input on following two series. 

http://www.mail-archive.com/linux-omap at vger.kernel.org/msg30305.html
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg30735.html

Regards,
Ghorai

> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: Tuesday, June 15, 2010 6:57 PM
> To: 'Tony Lindgren'
> Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org;
> tony at atomide.com; mike at compulab.co.il; 'Vimal Singh'
> Subject: RE: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related
> code
> 
> Tony,
> 
> > -----Original Message-----
> > From: Vimal Singh [mailto:vimal.newwork at gmail.com]
> > Sent: Tuesday, June 08, 2010 10:43 PM
> > To: Ghorai, Sukumar
> > Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org;
> > tony at atomide.com; mike at compulab.co.il
> > Subject: Re: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related
> > code
> >
> > Reviewed-by: Vimal Singh <vimal.newwork at gmail.com>
> >
> > On Fri, Jun 4, 2010 at 1:10 PM, Sukumar Ghorai <s-ghorai at ti.com> wrote:
> > > ? The following set of patches applies on top of for-next branch.
> > > ? ? ? ?http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-
> > 2.6.git
> > > ? Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle
> > board
> > >
> > > ? And these are the patches required to address the following input -
> > > ? ? 1. The NAND driver needs to stop tinkering with the GPMC registers
> > > ? ? ? ?The omap General Purpose Memory Controller (GPMC) registers are
> > omap
> > > ? ? ? ?specific, and not driver specific. Tinkering with these
> registers
> > can
> > > ? ? ? ?cause issues with the other devices on the GPMC.
> > >
> > > ? ? 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board
> files
> > > ? ? ? ?Passing hardcoded GPMC virtual addressess is sure way to mess
> up
> > things.
> > > ? ? ? ?This should all become unnecessary once the NAND drivers stops
> > messing
> > > ? ? ? ?with the GPMC registers directly.
> > > ? ? Discussion: http://www.mail-archive.com/linux-
> > omap at vger.kernel.org/msg27630.html
> > >
> > > ? Changes in this series -
> > > ? ? ? ? ? ? ? ?Unused function removed.
> > >
> > > ?Functions related to ecc and prefetch engine are optimized.
> > > ?v4: http://www.mail-archive.com/linux-
> > omap at vger.kernel.org/msg29458.html
> > >
> > > ?Few functionality was missing ?like - There should be some locking as
> > only
> > > ? one chipselect can use the ECC or prefetch engine at a time. If you
> > have
> > > ? NAND in two chipselects, bad things would happen.
> > > ?v3: http://www.mail-archive.com/linux-
> > omap at vger.kernel.org/msg28715.html
> > >
> > > ?Additionally, it was needed to implement more functions for the
> > platform
> > > ?init code to use.
> > > ?v2: http://www.mail-archive.com/linux-
> > omap at vger.kernel.org/msg28467.html
> > >
> > > ?v1: http://www.mail-archive.com/linux-
> > omap at vger.kernel.org/msg28164.html
> > >
> > >
> > > Sukumar Ghorai (3):
> > > ? ? ? ?omap3 gpmc: functionality enhancement
> > > ? ? ? ?omap3 nand: cleanup virtual address usages
> > > ? ? ? ?omap3 nand: fix issue in board file to detect nand
> > > ?arch/arm/mach-omap2/board-cm-t35.c ? ? ? ? | ? 20 +---
> > > ?arch/arm/mach-omap2/board-devkit8000.c ? ? | ? 25 +---
> > > ?arch/arm/mach-omap2/board-omap3beagle.c ? ?| ? 24 +---
> > > ?arch/arm/mach-omap2/board-omap3touchbook.c | ? 25 +---
> > > ?arch/arm/mach-omap2/board-overo.c ? ? ? ? ?| ? 24 +---
> > > ?arch/arm/mach-omap2/board-sdp-flash.c ? ? ?| ? ?5 -
> > > ?arch/arm/mach-omap2/gpmc-nand.c ? ? ? ? ? ?| ? 39 ++----
> > > ?arch/arm/mach-omap2/gpmc.c ? ? ? ? ? ? ? ? | ?228
> > +++++++++++++++++++++++++---
> > > ?arch/arm/plat-omap/include/plat/gpmc.h ? ? | ? 36 ++++-
> > > ?arch/arm/plat-omap/include/plat/nand.h ? ? | ? ?6 +-
> > > ?drivers/mtd/nand/omap2.c ? ? ? ? ? ? ? ? ? | ?229 ++++++++-----------
> --
> > -------
> > > ?11 files changed, 320 insertions(+), 341 deletions(-)
> 
> [Ghorai] Any comments or input on these patch?
> 
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-omap"
> in
> > > the body of a message to majordomo at vger.kernel.org
> > > More majordomo info at ?http://vger.kernel.org/majordomo-info.html
> > >
> >
> >
> >
> > --
> > Regards,
> > Vimal Singh


From dedekind1 at gmail.com  Wed Jun 30 23:44:45 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 01 Jul 2010 06:44:45 +0300
Subject: [PATCH] mtd: Added an ioctl to query the lock status of a
	flash sector.
In-Reply-To: <20100614161033.GA24877@riccoc20.at.omicron.at>
References: <20100531131214.GA15887@riccoc20.at.omicron.at>
	<1276419903.19028.180.camel@localhost>
	<20100614161033.GA24877@riccoc20.at.omicron.at>
Message-ID: <1277955885.3599.27.camel@localhost.localdomain>

On Mon, 2010-06-14 at 18:10 +0200, Richard Cochran wrote:
> On Sun, Jun 13, 2010 at 12:05:03PM +0300, Artem Bityutskiy wrote:
> > I think it is tiny bit nicer to name 'is_locked', which is a bit more
> > consistent with the already existing 'block_isbad'?
> 
> Okay, here it is again.
> 
> Thanks,
> Richard
> 
> 
> This patchs adds a way for user space programs to find out whether a
> flash sector is locked. An optional driver method in the mtd_info struct
> provides the information.
> 
> Signed-off-by: Richard Cochran <richard.cochran at omicron.at>

Pushed to l2-mtd-2.6.git / master.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun 30 23:47:01 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 01 Jul 2010 06:47:01 +0300
Subject: [PATCH] mtd/mxc_nand: remove unused variable
In-Reply-To: <1276498911-28115-1-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1276498911-28115-1-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <1277956021.3599.28.camel@localhost.localdomain>

On Mon, 2010-06-14 at 09:01 +0200, Uwe Kleine-K?nig wrote:
> This fixes:
> 
> 	drivers/mtd/nand/mxc_nand.c: In function 'mxcnd_resume':
> 	drivers/mtd/nand/mxc_nand.c:901: warning: unused variable 'host'
> 
> Removing this variable was missed in 9c14b153e6af.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>

Pushed to l2-mtd-2.6.git / master

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun 30 23:47:52 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 01 Jul 2010 06:47:52 +0300
Subject: [PATCH] mxc_nand: fix PM
In-Reply-To: <4C15D542.2060102@eukrea.com>
References: <1274942000-3580-2-git-send-email-eric@eukrea.com>
	<1274982919-13251-1-git-send-email-eric@eukrea.com>
	<4C15D542.2060102@eukrea.com>
Message-ID: <1277956072.3599.29.camel@localhost.localdomain>

On Mon, 2010-06-14 at 09:07 +0200, Eric B?nard wrote:
> Hi Sascha,
> 
> Le 27/05/2010 19:55, Eric B?nard a ?crit :
> > * when resuming, we get the following log :
> > nand_resume called for a chip which is not in suspended state
> > * this happens because mtd->suspend and mtd->resume are already
> > called from the mtd layer, thus they were called a second time
> > in mxc_nand so mtd complains when trying to resume for the
> > second time
> > * the fix is to remove these call and thus remove the supend and
> > resume functions of mxc_nand
> >
> any news concerning this patch ?

Pushed to l2-mtd-2.6.git / dunno

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From chuanxiao.dong at intel.com  Mon Jun 21 06:30:43 2010
From: chuanxiao.dong at intel.com (Chuanxiao Dong)
Date: Mon, 21 Jun 2010 18:30:43 +0800
Subject: [PATCH 1/5] [MTD/denali] fixed all checkpatch errors
Message-ID: <mailman.65.1278925440.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Chuanxiao Dong <chuanxiao.dong at intel.com>
---
 drivers/mtd/nand/denali.c |  806 +++++++++++++++++++++++------------------=
----
 drivers/mtd/nand/denali.h |   88 +++---
 2 files changed, 451 insertions(+), 443 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index ca03428..4e255ff 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -29,15 +29,15 @@

 MODULE_LICENSE("GPL");

-/* We define a module parameter that allows the user to override
+/* We define a module parameter that allows the user to override
  * the hardware and decide what timing mode should be used.
  */
 #define NAND_DEFAULT_TIMINGS   -1

 static int onfi_timing_mode =3D NAND_DEFAULT_TIMINGS;
 module_param(onfi_timing_mode, int, S_IRUGO);
-MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 ind=
icates"
-                                       " use default timings");
+MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
+                                       "-1 indicates use default timings")=
;

 #define DENALI_NAND_NAME    "denali-nand"

@@ -54,13 +54,13 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default O=
NFI setting. -1 indicates
                        INTR_STATUS0__RST_COMP | \
                        INTR_STATUS0__ERASE_COMP)

-/* indicates whether or not the internal value for the flash bank is
+/* indicates whether or not the internal value for the flash bank is
    valid or not */
-#define CHIP_SELECT_INVALID    -1
+#define CHIP_SELECT_INVALID    -1

 #define SUPPORT_8BITECC                1

-/* This macro divides two integers and rounds fractional values up
+/* This macro divides two integers and rounds fractional values up
  * to the nearest integer value. */
 #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))

@@ -83,7 +83,7 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONF=
I setting. -1 indicates
 #define ADDR_CYCLE     1
 #define STATUS_CYCLE   2

-/* this is a helper macro that allows us to
+/* this is a helper macro that allows us to
  * format the bank into the proper bits for the controller */
 #define BANK(x) ((x) << 24)

@@ -95,59 +95,63 @@ static const struct pci_device_id denali_pci_ids[] =3D =
{
 };


-/* these are static lookup tables that give us easy access to
-   registers in the NAND controller.
+/* these are static lookup tables that give us easy access to
+   registers in the NAND controller.
  */
-static const uint32_t intr_status_addresses[4] =3D {INTR_STATUS0,
-                                                 INTR_STATUS1,
-                                                 INTR_STATUS2,
+static const uint32_t intr_status_addresses[4] =3D {INTR_STATUS0,
+                                                 INTR_STATUS1,
+                                               INTR_STATUS2,
                                                  INTR_STATUS3};

 static const uint32_t device_reset_banks[4] =3D {DEVICE_RESET__BANK0,
-                                               DEVICE_RESET__BANK1,
-                                               DEVICE_RESET__BANK2,
-                                               DEVICE_RESET__BANK3};
+                                                       DEVICE_RESET__BANK1=
,
+                                                       DEVICE_RESET__BANK2=
,
+                                                       DEVICE_RESET__BANK3=
};

 static const uint32_t operation_timeout[4] =3D {INTR_STATUS0__TIME_OUT,
-                                             INTR_STATUS1__TIME_OUT,
-                                             INTR_STATUS2__TIME_OUT,
-                                             INTR_STATUS3__TIME_OUT};
+                                                       INTR_STATUS1__TIME_=
OUT,
+                                                       INTR_STATUS2__TIME_=
OUT,
+                                                       INTR_STATUS3__TIME_=
OUT};

 static const uint32_t reset_complete[4] =3D {INTR_STATUS0__RST_COMP,
-                                          INTR_STATUS1__RST_COMP,
-                                          INTR_STATUS2__RST_COMP,
-                                          INTR_STATUS3__RST_COMP};
+                                                       INTR_STATUS1__RST_C=
OMP,
+                                                       INTR_STATUS2__RST_C=
OMP,
+                                                       INTR_STATUS3__RST_C=
OMP};

 /* specifies the debug level of the driver */
-static int nand_debug_level =3D 0;
+static int nand_debug_level;

 /* forward declarations */
 static void clear_interrupts(struct denali_nand_info *denali);
-static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq=
_mask);
-static void denali_irq_enable(struct denali_nand_info *denali, uint32_t in=
t_mask);
+static uint32_t wait_for_irq(struct denali_nand_info *denali,
+                                                       uint32_t irq_mask);
+static void denali_irq_enable(struct denali_nand_info *denali,
+                                                       uint32_t int_mask);
 static uint32_t read_interrupt_status(struct denali_nand_info *denali);

 #define DEBUG_DENALI 0

 /* This is a wrapper for writing to the denali registers.
  * this allows us to create debug information so we can
- * observe how the driver is programming the device.
+ * observe how the driver is programming the device.
  * it uses standard linux convention for (val, addr) */
 static void denali_write32(uint32_t value, void *addr)
 {
-       iowrite32(value, addr);
+       iowrite32(value, addr);

 #if DEBUG_DENALI
-       printk(KERN_ERR "wrote: 0x%x -> 0x%x\n", value, (uint32_t)((uint32_=
t)addr & 0x1fff));
+       printk(KERN_ERR "wrote: 0x%x -> 0x%x\n", value,
+                       (uint32_t)((uint32_t)addr & 0x1fff));
 #endif
-}
+}

-/* Certain operations for the denali NAND controller use an indexed mode t=
o read/write
-   data. The operation is performed by writing the address value of the co=
mmand to
-   the device memory followed by the data. This function abstracts this co=
mmon
-   operation.
+/* Certain operations for the denali NAND controller use an indexed mode
+ * to read/write data. The operation is performed by writing the address
+ * value of the command to the device memory followed by the data. This
+ * function abstracts this common operation.
 */
-static void index_addr(struct denali_nand_info *denali, uint32_t address, =
uint32_t data)
+static void index_addr(struct denali_nand_info *denali,
+                                       uint32_t address, uint32_t data)
 {
        denali_write32(address, denali->flash_mem);
        denali_write32(data, denali->flash_mem + 0x10);
@@ -161,7 +165,7 @@ static void index_addr_read_data(struct denali_nand_inf=
o *denali,
        *pdata =3D ioread32(denali->flash_mem + 0x10);
 }

-/* We need to buffer some data for some of the NAND core routines.
+/* We need to buffer some data for some of the NAND core routines.
  * The operations manage buffering that data. */
 static void reset_buf(struct denali_nand_info *denali)
 {
@@ -183,7 +187,7 @@ static void read_status(struct denali_nand_info *denali=
)
        reset_buf(denali);

        /* initiate a device status read */
-       cmd =3D MODE_11 | BANK(denali->flash_bank);
+       cmd =3D MODE_11 | BANK(denali->flash_bank);
        index_addr(denali, cmd | COMMAND_CYCLE, 0x70);
        denali_write32(cmd | STATUS_CYCLE, denali->flash_mem);

@@ -191,7 +195,8 @@ static void read_status(struct denali_nand_info *denali=
)
        write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10));

 #if DEBUG_DENALI
-       printk("device reporting status value of 0x%2x\n", denali->buf.buf[=
0]);
+       printk(KERN_INFO "device reporting status value of 0x%2x\n",
+                       denali->buf.buf[0]);
 #endif
 }

@@ -199,7 +204,7 @@ static void read_status(struct denali_nand_info *denali=
)
 static void reset_bank(struct denali_nand_info *denali)
 {
        uint32_t irq_status =3D 0;
-       uint32_t irq_mask =3D reset_complete[denali->flash_bank] |
+       uint32_t irq_mask =3D reset_complete[denali->flash_bank] |
                            operation_timeout[denali->flash_bank];
        int bank =3D 0;

@@ -209,11 +214,9 @@ static void reset_bank(struct denali_nand_info *denali=
)
        denali_write32(bank, denali->flash_reg + DEVICE_RESET);

        irq_status =3D wait_for_irq(denali, irq_mask);
-
+
        if (irq_status & operation_timeout[denali->flash_bank])
-       {
                printk(KERN_ERR "reset bank failed.\n");
-       }
 }

 /* Reset the flash controller */
@@ -229,9 +232,12 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_in=
fo *denali)
                denali->flash_reg + intr_status_addresses[i]);

        for (i =3D 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
-               denali_write32(device_reset_banks[i], denali->flash_reg + D=
EVICE_RESET);
-               while (!(ioread32(denali->flash_reg + intr_status_addresses=
[i]) &
-                       (reset_complete[i] | operation_timeout[i])))
+               denali_write32(device_reset_banks[i],
+                               denali->flash_reg + DEVICE_RESET);
+               while (!(ioread32(denali->flash_reg +
+                                       intr_status_addresses[i]) &
+                                       (reset_complete[i] |
+                                        operation_timeout[i])))
                        ;
                if (ioread32(denali->flash_reg + intr_status_addresses[i]) =
&
                        operation_timeout[i])
@@ -247,10 +253,11 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_i=
nfo *denali)
 }

 /* this routine calculates the ONFI timing values for a given mode and pro=
grams
- * the clocking register accordingly. The mode is determined by the get_on=
fi_nand_para
-   routine.
+ * the clocking register accordingly. The mode is determined by the
+ * get_onfi_nand_para routine.
  */
-static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali, uint16_=
t mode)
+static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali,
+                                                               uint16_t mo=
de)
 {
        uint16_t Trea[6] =3D {40, 30, 25, 20, 20, 16};
        uint16_t Trp[6] =3D {50, 25, 17, 15, 12, 10};
@@ -356,10 +363,11 @@ static void set_ecc_config(struct denali_nand_info *d=
enali)
                denali_write32(8, denali->flash_reg + ECC_CORRECTION);
 #endif

-       if ((ioread32(denali->flash_reg + ECC_CORRECTION) & ECC_CORRECTION_=
_VALUE)
-               =3D=3D 1) {
+       if ((ioread32(denali->flash_reg + ECC_CORRECTION) &
+                               ECC_CORRECTION__VALUE) =3D=3D 1) {
                denali->dev_info.wECCBytesPerSector =3D 4;
-               denali->dev_info.wECCBytesPerSector *=3D denali->dev_info.w=
DevicesConnected;
+               denali->dev_info.wECCBytesPerSector *=3D
+                       denali->dev_info.wDevicesConnected;
                denali->dev_info.wNumPageSpareFlag =3D
                        denali->dev_info.wPageSpareSize -
                        denali->dev_info.wPageDataSize /
@@ -375,8 +383,10 @@ static void set_ecc_config(struct denali_nand_info *de=
nali)
                else
                        denali->dev_info.wECCBytesPerSector +=3D 1;

-               denali->dev_info.wECCBytesPerSector *=3D denali->dev_info.w=
DevicesConnected;
-               denali->dev_info.wNumPageSpareFlag =3D denali->dev_info.wPa=
geSpareSize -
+               denali->dev_info.wECCBytesPerSector *=3D
+                       denali->dev_info.wDevicesConnected;
+               denali->dev_info.wNumPageSpareFlag =3D
+                       denali->dev_info.wPageSpareSize -
                        denali->dev_info.wPageDataSize /
                        (ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnect=
ed) *
                        denali->dev_info.wECCBytesPerSector
@@ -399,8 +409,10 @@ static uint16_t get_onfi_nand_para(struct denali_nand_=
info *denali)
                INTR_STATUS0__TIME_OUT)))
                ;

-       if (ioread32(denali->flash_reg + INTR_STATUS0) & INTR_STATUS0__RST_=
COMP) {
-               denali_write32(DEVICE_RESET__BANK1, denali->flash_reg + DEV=
ICE_RESET);
+       if (ioread32(denali->flash_reg + INTR_STATUS0) &
+                       INTR_STATUS0__RST_COMP) {
+               denali_write32(DEVICE_RESET__BANK1,
+                               denali->flash_reg + DEVICE_RESET);
                while (!((ioread32(denali->flash_reg + INTR_STATUS1) &
                        INTR_STATUS1__RST_COMP) |
                        (ioread32(denali->flash_reg + INTR_STATUS1) &
@@ -421,9 +433,11 @@ static uint16_t get_onfi_nand_para(struct denali_nand_=
info *denali)
                                INTR_STATUS2__RST_COMP) {
                                denali_write32(DEVICE_RESET__BANK3,
                                        denali->flash_reg + DEVICE_RESET);
-                               while (!((ioread32(denali->flash_reg + INTR=
_STATUS3) &
+                               while (!((ioread32(denali->flash_reg +
+                                                               INTR_STATUS=
3) &
                                        INTR_STATUS3__RST_COMP) |
-                                       (ioread32(denali->flash_reg + INTR_=
STATUS3) &
+                                       (ioread32(denali->flash_reg +
+                                                         INTR_STATUS3) &
                                        INTR_STATUS3__TIME_OUT)))
                                        ;
                        } else {
@@ -434,10 +448,14 @@ static uint16_t get_onfi_nand_para(struct denali_nand=
_info *denali)
                }
        }

-       denali_write32(INTR_STATUS0__TIME_OUT, denali->flash_reg + INTR_STA=
TUS0);
-       denali_write32(INTR_STATUS1__TIME_OUT, denali->flash_reg + INTR_STA=
TUS1);
-       denali_write32(INTR_STATUS2__TIME_OUT, denali->flash_reg + INTR_STA=
TUS2);
-       denali_write32(INTR_STATUS3__TIME_OUT, denali->flash_reg + INTR_STA=
TUS3);
+       denali_write32(INTR_STATUS0__TIME_OUT,
+                       denali->flash_reg + INTR_STATUS0);
+       denali_write32(INTR_STATUS1__TIME_OUT,
+                       denali->flash_reg + INTR_STATUS1);
+       denali_write32(INTR_STATUS2__TIME_OUT,
+                       denali->flash_reg + INTR_STATUS2);
+       denali_write32(INTR_STATUS3__TIME_OUT,
+                       denali->flash_reg + INTR_STATUS3);

        denali->dev_info.wONFIDevFeatures =3D
                ioread32(denali->flash_reg + ONFI_DEVICE_FEATURES);
@@ -450,8 +468,10 @@ static uint16_t get_onfi_nand_para(struct denali_nand_=
info *denali)

        n_of_luns =3D ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) =
&
                ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS;
-       blks_lun_l =3D ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCK=
S_PER_LUN_L);
-       blks_lun_h =3D ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCK=
S_PER_LUN_U);
+       blks_lun_l =3D ioread32(denali->flash_reg +
+                       ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L);
+       blks_lun_h =3D ioread32(denali->flash_reg +
+                       ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U);

        blockperlun =3D (blks_lun_h << 16) | blks_lun_l;

@@ -462,7 +482,8 @@ static uint16_t get_onfi_nand_para(struct denali_nand_i=
nfo *denali)
                return FAIL;

        for (i =3D 5; i > 0; i--) {
-               if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) & (0x01 =
<< i))
+               if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) &
+                               (0x01 << i))
                        break;
        }

@@ -497,7 +518,8 @@ static void get_samsung_nand_para(struct denali_nand_in=
fo *denali)
        index_addr(denali, (uint32_t)(MODE_11 | 0), 0x90);
        index_addr(denali, (uint32_t)(MODE_11 | 1), 0);
        for (i =3D 0; i < 5; i++)
-               index_addr_read_data(denali, (uint32_t)(MODE_11 | 2), &id_b=
ytes[i]);
+               index_addr_read_data(denali, (uint32_t)(MODE_11 | 2),
+                                                       &id_bytes[i]);

        nand_dbg_print(NAND_DBG_DEBUG,
                "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
@@ -517,7 +539,8 @@ static void get_samsung_nand_para(struct denali_nand_in=
fo *denali)

        no_of_planes =3D 1 << ((id_bytes[4] & 0x0c) >> 2);
        plane_size  =3D (uint64_t)64 << ((id_bytes[4] & 0x70) >> 4);
-       blk_size =3D 64 << ((ioread32(denali->flash_reg + DEVICE_PARAM_1) &=
 0x30) >> 4);
+       blk_size =3D 64 << ((ioread32(denali->flash_reg + DEVICE_PARAM_1) &
+                               0x30) >> 4);
        capacity =3D (uint64_t)128 * plane_size * no_of_planes;

        do_div(capacity, blk_size);
@@ -536,7 +559,8 @@ static void get_toshiba_nand_para(struct denali_nand_in=
fo *denali)
                denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_S=
IZE);
                tmp =3D ioread32(denali->flash_reg + DEVICES_CONNECTED) *
                        ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE=
);
-               denali_write32(tmp, denali->flash_reg + LOGICAL_PAGE_SPARE_=
SIZE);
+               denali_write32(tmp, denali->flash_reg +
+                               LOGICAL_PAGE_SPARE_SIZE);
 #if SUPPORT_15BITECC
                denali_write32(15, denali->flash_reg + ECC_CORRECTION);
 #elif SUPPORT_8BITECC
@@ -575,10 +599,14 @@ static void get_hynix_nand_para(struct denali_nand_in=
fo *denali)
                denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK);
                denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_S=
IZE);
                denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_S=
IZE);
-               main_size =3D 4096 * ioread32(denali->flash_reg + DEVICES_C=
ONNECTED);
-               spare_size =3D 224 * ioread32(denali->flash_reg + DEVICES_C=
ONNECTED);
-               denali_write32(main_size, denali->flash_reg + LOGICAL_PAGE_=
DATA_SIZE);
-               denali_write32(spare_size, denali->flash_reg + LOGICAL_PAGE=
_SPARE_SIZE);
+               main_size =3D 4096 * ioread32(denali->flash_reg +
+                                                       DEVICES_CONNECTED);
+               spare_size =3D 224 * ioread32(denali->flash_reg +
+                                                       DEVICES_CONNECTED);
+               denali_write32(main_size, denali->flash_reg +
+                                                       LOGICAL_PAGE_DATA_S=
IZE);
+               denali_write32(spare_size, denali->flash_reg +
+                                               LOGICAL_PAGE_SPARE_SIZE);
                denali_write32(0, denali->flash_reg + DEVICE_WIDTH);
 #if SUPPORT_15BITECC
                denali_write32(15, denali->flash_reg + ECC_CORRECTION);
@@ -610,7 +638,7 @@ static void get_hynix_nand_para(struct denali_nand_info=
 *denali)
 }

 /* determines how many NAND chips are connected to the controller. Note fo=
r
-   Intel CE4100 devices we don't support more than one device.
+   Intel CE4100 devices we don't support more than one device.
  */
 static void find_valid_banks(struct denali_nand_info *denali)
 {
@@ -621,7 +649,8 @@ static void find_valid_banks(struct denali_nand_info *d=
enali)
        for (i =3D 0; i < LLD_MAX_FLASH_BANKS; i++) {
                index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x9=
0);
                index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0);
-               index_addr_read_data(denali, (uint32_t)(MODE_11 | (i << 24)=
 | 2), &id[i]);
+               index_addr_read_data(denali,
+                               (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]=
);

                nand_dbg_print(NAND_DBG_DEBUG,
                        "Return 1st ID for bank[%d]: %x\n", i, id[i]);
@@ -638,18 +667,15 @@ static void find_valid_banks(struct denali_nand_info =
*denali)
        }

        if (denali->platform =3D=3D INTEL_CE4100)
-       {
                /* Platform limitations of the CE4100 device limit
                 * users to a single chip solution for NAND.
-                 * Multichip support is not enabled.
-                */
-               if (denali->total_used_banks !=3D 1)
-               {
+                * Multichip support is not enabled.
+                */
+               if (denali->total_used_banks !=3D 1) {
                        printk(KERN_ERR "Sorry, Intel CE4100 only supports =
"
                                        "a single NAND device.\n");
                        BUG();
                }
-       }
        nand_dbg_print(NAND_DBG_DEBUG,
                "denali->total_used_banks: %d\n", denali->total_used_banks)=
;
 }
@@ -675,7 +701,8 @@ static void detect_partition_feature(struct denali_nand=
_info *denali)
                            (ioread32(denali->flash_reg + MAX_BLK_ADDR_1) &
                            MAX_BLK_ADDR_1__VALUE);

-                       denali->dev_info.wTotalBlocks *=3D denali->total_us=
ed_banks;
+                       denali->dev_info.wTotalBlocks *=3D
+                               denali->total_used_banks;

                        if (denali->dev_info.wSpectraEndBlock >=3D
                            denali->dev_info.wTotalBlocks) {
@@ -687,8 +714,10 @@ static void detect_partition_feature(struct denali_nan=
d_info *denali)
                                denali->dev_info.wSpectraEndBlock -
                                denali->dev_info.wSpectraStartBlock + 1;
                } else {
-                       denali->dev_info.wTotalBlocks *=3D denali->total_us=
ed_banks;
-                       denali->dev_info.wSpectraStartBlock =3D SPECTRA_STA=
RT_BLOCK;
+                       denali->dev_info.wTotalBlocks *=3D
+                               denali->total_used_banks;
+                       denali->dev_info.wSpectraStartBlock =3D
+                               SPECTRA_START_BLOCK;
                        denali->dev_info.wSpectraEndBlock =3D
                                denali->dev_info.wTotalBlocks - 1;
                        denali->dev_info.wDataBlockNum =3D
@@ -698,7 +727,8 @@ static void detect_partition_feature(struct denali_nand=
_info *denali)
        } else {
                denali->dev_info.wTotalBlocks *=3D denali->total_used_banks=
;
                denali->dev_info.wSpectraStartBlock =3D SPECTRA_START_BLOCK=
;
-               denali->dev_info.wSpectraEndBlock =3D denali->dev_info.wTot=
alBlocks - 1;
+               denali->dev_info.wSpectraEndBlock =3D
+                       denali->dev_info.wTotalBlocks - 1;
                denali->dev_info.wDataBlockNum =3D
                        denali->dev_info.wSpectraEndBlock -
                        denali->dev_info.wSpectraStartBlock + 1;
@@ -780,13 +810,19 @@ static uint16_t NAND_Read_Device_ID(struct denali_nan=
d_info *denali)
        nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
                       __FILE__, __LINE__, __func__);

-       denali->dev_info.wDeviceMaker =3D ioread32(denali->flash_reg + MANU=
FACTURER_ID);
-       denali->dev_info.wDeviceID =3D ioread32(denali->flash_reg + DEVICE_=
ID);
-       denali->dev_info.bDeviceParam0 =3D ioread32(denali->flash_reg + DEV=
ICE_PARAM_0);
-       denali->dev_info.bDeviceParam1 =3D ioread32(denali->flash_reg + DEV=
ICE_PARAM_1);
-       denali->dev_info.bDeviceParam2 =3D ioread32(denali->flash_reg + DEV=
ICE_PARAM_2);
+       denali->dev_info.wDeviceMaker =3D
+               ioread32(denali->flash_reg + MANUFACTURER_ID);
+       denali->dev_info.wDeviceID =3D
+               ioread32(denali->flash_reg + DEVICE_ID);
+       denali->dev_info.bDeviceParam0 =3D
+               ioread32(denali->flash_reg + DEVICE_PARAM_0);
+       denali->dev_info.bDeviceParam1 =3D
+               ioread32(denali->flash_reg + DEVICE_PARAM_1);
+       denali->dev_info.bDeviceParam2 =3D
+               ioread32(denali->flash_reg + DEVICE_PARAM_2);

-       denali->dev_info.MLCDevice =3D ioread32(denali->flash_reg + DEVICE_=
PARAM_0) & 0x0c;
+       denali->dev_info.MLCDevice =3D
+               ioread32(denali->flash_reg + DEVICE_PARAM_0) & 0x0c;

        if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) &
                ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */
@@ -835,7 +871,8 @@ static uint16_t NAND_Read_Device_ID(struct denali_nand_=
info *denali)
        denali->dev_info.wPageSpareSize =3D
                ioread32(denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);

-       denali->dev_info.wPagesPerBlock =3D ioread32(denali->flash_reg + PA=
GES_PER_BLOCK);
+       denali->dev_info.wPagesPerBlock =3D
+               ioread32(denali->flash_reg + PAGES_PER_BLOCK);

        denali->dev_info.wPageSize =3D
            denali->dev_info.wPageDataSize + denali->dev_info.wPageSpareSiz=
e;
@@ -844,11 +881,13 @@ static uint16_t NAND_Read_Device_ID(struct denali_nan=
d_info *denali)
        denali->dev_info.wBlockDataSize =3D
            denali->dev_info.wPagesPerBlock * denali->dev_info.wPageDataSiz=
e;

-       denali->dev_info.wDeviceWidth =3D ioread32(denali->flash_reg + DEVI=
CE_WIDTH);
+       denali->dev_info.wDeviceWidth =3D
+               ioread32(denali->flash_reg + DEVICE_WIDTH);
        denali->dev_info.wDeviceType =3D
                ((ioread32(denali->flash_reg + DEVICE_WIDTH) > 0) ? 16 : 8)=
;

-       denali->dev_info.wDevicesConnected =3D ioread32(denali->flash_reg +=
 DEVICES_CONNECTED);
+       denali->dev_info.wDevicesConnected =3D
+               ioread32(denali->flash_reg + DEVICES_CONNECTED);

        denali->dev_info.wSpareSkipBytes =3D
                ioread32(denali->flash_reg + SPARE_AREA_SKIP_BYTES) *
@@ -885,12 +924,10 @@ static uint16_t NAND_Read_Device_ID(struct denali_nan=
d_info *denali)
        dump_device_info(denali);

        /* If the user specified to override the default timings
-        * with a specific ONFI mode, we apply those changes here.
+        * with a specific ONFI mode, we apply those changes here.
         */
        if (onfi_timing_mode !=3D NAND_DEFAULT_TIMINGS)
-       {
                NAND_ONFi_Timing_Mode(denali, onfi_timing_mode);
-       }

        return status;
 }
@@ -912,7 +949,7 @@ static void NAND_LLD_Enable_Disable_Interrupts(struct d=
enali_nand_info *denali,
  */
 static inline bool is_flash_bank_valid(int flash_bank)
 {
-       return (flash_bank >=3D 0 && flash_bank < 4);
+       return (flash_bank >=3D 0 && flash_bank < 4);
 }

 static void denali_irq_init(struct denali_nand_info *denali)
@@ -939,7 +976,8 @@ static void denali_irq_cleanup(int irqnum, struct denal=
i_nand_info *denali)
        free_irq(irqnum, denali);
 }

-static void denali_irq_enable(struct denali_nand_info *denali, uint32_t in=
t_mask)
+static void denali_irq_enable(struct denali_nand_info *denali,
+                                                       uint32_t int_mask)
 {
        denali_write32(int_mask, denali->flash_reg + INTR_EN0);
        denali_write32(int_mask, denali->flash_reg + INTR_EN1);
@@ -948,15 +986,16 @@ static void denali_irq_enable(struct denali_nand_info=
 *denali, uint32_t int_mask
 }

 /* This function only returns when an interrupt that this driver cares abo=
ut
- * occurs. This is to reduce the overhead of servicing interrupts
+ * occurs. This is to reduce the overhead of servicing interrupts
  */
 static inline uint32_t denali_irq_detected(struct denali_nand_info *denali=
)
 {
-       return (read_interrupt_status(denali) & DENALI_IRQ_ALL);
+       return read_interrupt_status(denali) & DENALI_IRQ_ALL;
 }

 /* Interrupts are cleared by writing a 1 to the appropriate status bit */
-static inline void clear_interrupt(struct denali_nand_info *denali, uint32=
_t irq_mask)
+static inline void clear_interrupt(struct denali_nand_info *denali,
+                                                       uint32_t irq_mask)
 {
        uint32_t intr_status_reg =3D 0;

@@ -995,17 +1034,15 @@ static void print_irq_log(struct denali_nand_info *d=
enali)
 {
        int i =3D 0;

-       printk("ISR debug log index =3D %X\n", denali->idx);
+       printk(KERN_INFO "ISR debug log index =3D %X\n", denali->idx);
        for (i =3D 0; i < 32; i++)
-       {
-               printk("%08X: %08X\n", i, denali->irq_debug_array[i]);
-       }
+               printk(KERN_INFO "%08X: %08X\n", i, denali->irq_debug_array=
[i]);
 }
 #endif

-/* This is the interrupt service routine. It handles all interrupts
- * sent to this device. Note that on CE4100, this is a shared
- * interrupt.
+/* This is the interrupt service routine. It handles all interrupts
+ * sent to this device. Note that on CE4100, this is a shared
+ * interrupt.
  */
 static irqreturn_t denali_isr(int irq, void *dev_id)
 {
@@ -1015,20 +1052,20 @@ static irqreturn_t denali_isr(int irq, void *dev_id=
)

        spin_lock(&denali->irq_lock);

-       /* check to see if a valid NAND chip has
-         * been selected.
+       /* check to see if a valid NAND chip has
+        * been selected.
         */
-       if (is_flash_bank_valid(denali->flash_bank))
-       {
-               /* check to see if controller generated
+       if (is_flash_bank_valid(denali->flash_bank)) {
+               /* check to see if controller generated
                 * the interrupt, since this is a shared interrupt */
-               if ((irq_status =3D denali_irq_detected(denali)) !=3D 0)
-               {
+               irq_status =3D denali_irq_detected(denali);
+               if (irq_status !=3D 0) {
 #if DEBUG_DENALI
-                       denali->irq_debug_array[denali->idx++] =3D 0x100000=
00 | irq_status;
+                       denali->irq_debug_array[denali->idx++] =3D
+                               0x10000000 | irq_status;
                        denali->idx %=3D 32;

-                       printk("IRQ status =3D 0x%04x\n", irq_status);
+                       printk(KERN_INFO "IRQ status =3D 0x%04x\n", irq_sta=
tus);
 #endif
                        /* handle interrupt */
                        /* first acknowledge it */
@@ -1054,61 +1091,62 @@ static uint32_t wait_for_irq(struct denali_nand_inf=
o *denali, uint32_t irq_mask)
        bool retry =3D false;
        unsigned long timeout =3D msecs_to_jiffies(1000);

-       do
-       {
+       do {
 #if DEBUG_DENALI
-               printk("waiting for 0x%x\n", irq_mask);
+               printk(KERN_INFO "waiting for 0x%x\n", irq_mask);
 #endif
-               comp_res =3D wait_for_completion_timeout(&denali->complete,=
 timeout);
+               comp_res =3D
+                       wait_for_completion_timeout(&denali->complete, time=
out);
                spin_lock_irq(&denali->irq_lock);
                intr_status =3D denali->irq_status;

 #if DEBUG_DENALI
-               denali->irq_debug_array[denali->idx++] =3D 0x20000000 | (ir=
q_mask << 16) | intr_status;
+               denali->irq_debug_array[denali->idx++] =3D
+                       0x20000000 | (irq_mask << 16) | intr_status;
                denali->idx %=3D 32;
 #endif

-               if (intr_status & irq_mask)
-               {
+               if (intr_status & irq_mask) {
                        denali->irq_status &=3D ~irq_mask;
                        spin_unlock_irq(&denali->irq_lock);
 #if DEBUG_DENALI
-                       if (retry) printk("status on retry =3D 0x%x\n", int=
r_status);
+                       if (retry)
+                               printk(KERN_INFO "status on retry =3D 0x%x\=
n",
+                                               intr_status);
 #endif
                        /* our interrupt was detected */
                        break;
-               }
-               else
-               {
-                       /* these are not the interrupts you are looking for=
 -
-                          need to wait again */
+               } else {
+                       /* these are not the interrupts you are looking for
+                        * need to wait again */
                        spin_unlock_irq(&denali->irq_lock);
 #if DEBUG_DENALI
                        print_irq_log(denali);
-                       printk("received irq nobody cared: irq_status =3D 0=
x%x,"
-                               " irq_mask =3D 0x%x, timeout =3D %ld\n", in=
tr_status, irq_mask, comp_res);
+                       printk(KERN_INFO "received irq nobody cared: "
+                                       "irq_status =3D 0x%x, irq_mask =3D =
0x%x, "
+                                       "timeout =3D %ld\n", intr_status,
+                                       irq_mask, comp_res);
 #endif
                        retry =3D true;
                }
        } while (comp_res !=3D 0);

-       if (comp_res =3D=3D 0)
-       {
+       if (comp_res =3D=3D 0) {
                /* timeout */
-               printk(KERN_ERR "timeout occurred, status =3D 0x%x, mask =
=3D 0x%x\n",
-                               intr_status, irq_mask);
+               printk(KERN_ERR "timeout occurred, status =3D 0x%x, mask =
=3D 0x%x\n",
+                               intr_status, irq_mask);

                intr_status =3D 0;
        }
        return intr_status;
 }

-/* This helper function setups the registers for ECC and whether or not
+/* This helper function setups the registers for ECC and whether or not
    the spare area will be transfered. */
-static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_e=
n,
+static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_e=
n,
                                bool transfer_spare)
 {
-       int ecc_en_flag =3D 0, transfer_spare_flag =3D 0;
+       int ecc_en_flag =3D 0, transfer_spare_flag =3D 0;

        /* set ECC, transfer spare bits if needed */
        ecc_en_flag =3D ecc_en ? ECC_ENABLE__FLAG : 0;
@@ -1116,85 +1154,85 @@ static void setup_ecc_for_xfer(struct denali_nand_i=
nfo *denali, bool ecc_en,

        /* Enable spare area/ECC per user's request. */
        denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE);
-       denali_write32(transfer_spare_flag, denali->flash_reg + TRANSFER_SP=
ARE_REG);
+       denali_write32(transfer_spare_flag,
+                       denali->flash_reg + TRANSFER_SPARE_REG);
 }

-/* sends a pipeline command operation to the controller. See the Denali NA=
ND
-   controller's user guide for more information (section 4.2.3.6).
+/* sends a pipeline command operation to the controller. See the Denali NA=
ND
+   controller's user guide for more information (section 4.2.3.6).
  */
-static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool =
ecc_en,
-                                       bool transfer_spare, int access_typ=
e,
-                                       int op)
+static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
+                                                       bool ecc_en,
+                                                       bool transfer_spare=
,
+                                                       int access_type,
+                                                       int op)
 {
        int status =3D PASS;
-       uint32_t addr =3D 0x0, cmd =3D 0x0, page_count =3D 1, irq_status =
=3D 0,
+       uint32_t addr =3D 0x0, cmd =3D 0x0, page_count =3D 1, irq_status =
=3D 0,
                 irq_mask =3D 0;

-       if (op =3D=3D DENALI_READ) irq_mask =3D INTR_STATUS0__LOAD_COMP;
-       else if (op =3D=3D DENALI_WRITE) irq_mask =3D 0;
-       else BUG();
+       if (op =3D=3D DENALI_READ)
+               irq_mask =3D INTR_STATUS0__LOAD_COMP;
+       else if (op =3D=3D DENALI_WRITE)
+               irq_mask =3D 0;
+       else
+               BUG();

        setup_ecc_for_xfer(denali, ecc_en, transfer_spare);

 #if DEBUG_DENALI
        spin_lock_irq(&denali->irq_lock);
-       denali->irq_debug_array[denali->idx++] =3D 0x40000000 | ioread32(de=
nali->flash_reg + ECC_ENABLE) | (access_type << 4);
+       denali->irq_debug_array[denali->idx++] =3D
+               0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) |
+               (access_type << 4);
        denali->idx %=3D 32;
        spin_unlock_irq(&denali->irq_lock);
 #endif


        /* clear interrupts */
-       clear_interrupts(denali);
+       clear_interrupts(denali);

        addr =3D BANK(denali->flash_bank) | denali->page;

-       if (op =3D=3D DENALI_WRITE && access_type !=3D SPARE_ACCESS)
-       {
-               cmd =3D MODE_01 | addr;
+       if (op =3D=3D DENALI_WRITE && access_type !=3D SPARE_ACCESS) {
+               cmd =3D MODE_01 | addr;
                denali_write32(cmd, denali->flash_mem);
-       }
-       else if (op =3D=3D DENALI_WRITE && access_type =3D=3D SPARE_ACCESS)
-       {
+       } else if (op =3D=3D DENALI_WRITE && access_type =3D=3D SPARE_ACCES=
S) {
                /* read spare area */
-               cmd =3D MODE_10 | addr;
+               cmd =3D MODE_10 | addr;
                index_addr(denali, (uint32_t)cmd, access_type);

-               cmd =3D MODE_01 | addr;
+               cmd =3D MODE_01 | addr;
                denali_write32(cmd, denali->flash_mem);
-       }
-       else if (op =3D=3D DENALI_READ)
-       {
+       } else if (op =3D=3D DENALI_READ) {
                /* setup page read request for access type */
-               cmd =3D MODE_10 | addr;
+               cmd =3D MODE_10 | addr;
                index_addr(denali, (uint32_t)cmd, access_type);

                /* page 33 of the NAND controller spec indicates we should =
not
-                  use the pipeline commands in Spare area only mode. So we
+                  use the pipeline commands in Spare area only mode. So we
                   don't.
                 */
-               if (access_type =3D=3D SPARE_ACCESS)
-               {
+               if (access_type =3D=3D SPARE_ACCESS) {
                        cmd =3D MODE_01 | addr;
                        denali_write32(cmd, denali->flash_mem);
-               }
-               else
-               {
-                       index_addr(denali, (uint32_t)cmd, 0x2000 | op | pag=
e_count);
-
-                       /* wait for command to be accepted
-                        * can always use status0 bit as the mask is identi=
cal for each
+               } else {
+                       index_addr(denali, (uint32_t)cmd,
+                                       0x2000 | op | page_count);
+
+                       /* wait for command to be accepted
+                        * can always use status0 bit as the mask is
+                        * identical for each
                         * bank. */
                        irq_status =3D wait_for_irq(denali, irq_mask);

-                       if (irq_status =3D=3D 0)
-                       {
+                       if (irq_status =3D=3D 0) {
                                printk(KERN_ERR "cmd, page, addr on timeout=
 "
-                                       "(0x%x, 0x%x, 0x%x)\n", cmd, denali=
->page, addr);
+                                       "(0x%x, 0x%x, 0x%x)\n", cmd,
+                                       denali->page, addr);
                                status =3D FAIL;
-                       }
-                       else
-                       {
+                       } else {
                                cmd =3D MODE_01 | addr;
                                denali_write32(cmd, denali->flash_mem);
                        }
@@ -1204,36 +1242,35 @@ static int denali_send_pipeline_cmd(struct denali_n=
and_info *denali, bool ecc_en
 }

 /* helper function that simply writes a buffer to the flash */
-static int write_data_to_flash_mem(struct denali_nand_info *denali, const =
uint8_t *buf,
-                                       int len)
+static int write_data_to_flash_mem(struct denali_nand_info *denali,
+                                                       const uint8_t *buf,
+                                                       int len)
 {
        uint32_t i =3D 0, *buf32;

-       /* verify that the len is a multiple of 4. see comment in
-        * read_data_from_flash_mem() */
+       /* verify that the len is a multiple of 4. see comment in
+        * read_data_from_flash_mem() */
        BUG_ON((len % 4) !=3D 0);

        /* write the data to the flash memory */
        buf32 =3D (uint32_t *)buf;
        for (i =3D 0; i < len / 4; i++)
-       {
                denali_write32(*buf32++, denali->flash_mem + 0x10);
-       }
-       return i*4; /* intent is to return the number of bytes read */
+       return i*4; /* intent is to return the number of bytes read */
 }

 /* helper function that simply reads a buffer from the flash */
-static int read_data_from_flash_mem(struct denali_nand_info *denali, uint8=
_t *buf,
-                                       int len)
+static int read_data_from_flash_mem(struct denali_nand_info *denali,
+                                                       uint8_t *buf,
+                                                       int len)
 {
        uint32_t i =3D 0, *buf32;

        /* we assume that len will be a multiple of 4, if not
         * it would be nice to know about it ASAP rather than
-        * have random failures...
-         *
-        * This assumption is based on the fact that this
-        * function is designed to be used to read flash pages,
+        * have random failures...
+        * This assumption is based on the fact that this
+        * function is designed to be used to read flash pages,
         * which are typically multiples of 4...
         */

@@ -1242,10 +1279,8 @@ static int read_data_from_flash_mem(struct denali_na=
nd_info *denali, uint8_t *bu
        /* transfer the data from the flash */
        buf32 =3D (uint32_t *)buf;
        for (i =3D 0; i < len / 4; i++)
-       {
                *buf32++ =3D ioread32(denali->flash_mem + 0x10);
-       }
-       return i*4; /* intent is to return the number of bytes read */
+       return i*4; /* intent is to return the number of bytes read */
 }

 /* writes OOB data to the device */
@@ -1253,38 +1288,35 @@ static int write_oob_data(struct mtd_info *mtd, uin=
t8_t *buf, int page)
 {
        struct denali_nand_info *denali =3D mtd_to_denali(mtd);
        uint32_t irq_status =3D 0;
-       uint32_t irq_mask =3D INTR_STATUS0__PROGRAM_COMP |
+       uint32_t irq_mask =3D INTR_STATUS0__PROGRAM_COMP |
                                                INTR_STATUS0__PROGRAM_FAIL;
        int status =3D 0;

        denali->page =3D page;

-       if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS,
-                                                       DENALI_WRITE) =3D=
=3D PASS)
-       {
+       if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS,
+                                                       DENALI_WRITE) =3D=
=3D PASS) {
                write_data_to_flash_mem(denali, buf, mtd->oobsize);

 #if DEBUG_DENALI
                spin_lock_irq(&denali->irq_lock);
-               denali->irq_debug_array[denali->idx++] =3D 0x80000000 | mtd=
->oobsize;
+               denali->irq_debug_array[denali->idx++] =3D
+                       0x80000000 | mtd->oobsize;
                denali->idx %=3D 32;
                spin_unlock_irq(&denali->irq_lock);
 #endif

-
+
                /* wait for operation to complete */
                irq_status =3D wait_for_irq(denali, irq_mask);

-               if (irq_status =3D=3D 0)
-               {
+               if (irq_status =3D=3D 0) {
                        printk(KERN_ERR "OOB write failed\n");
                        status =3D -EIO;
                }
-       }
-       else
-       {
+       } else {
                printk(KERN_ERR "unable to send pipeline command\n");
-               status =3D -EIO;
+               status =3D -EIO;
        }
        return status;
 }
@@ -1293,60 +1325,56 @@ static int write_oob_data(struct mtd_info *mtd, uin=
t8_t *buf, int page)
 static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
        struct denali_nand_info *denali =3D mtd_to_denali(mtd);
-       uint32_t irq_mask =3D INTR_STATUS0__LOAD_COMP, irq_status =3D 0, ad=
dr =3D 0x0, cmd =3D 0x0;
+       uint32_t irq_mask =3D INTR_STATUS0__LOAD_COMP,
+                        irq_status =3D 0, addr =3D 0x0, cmd =3D 0x0;

        denali->page =3D page;

 #if DEBUG_DENALI
-       printk("read_oob %d\n", page);
+       printk(KERN_INFO "read_oob %d\n", page);
 #endif
-       if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS,
-                                                       DENALI_READ) =3D=3D=
 PASS)
-       {
-               read_data_from_flash_mem(denali, buf, mtd->oobsize);
+       if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS,
+                                                       DENALI_READ) =3D=3D=
 PASS) {
+               read_data_from_flash_mem(denali, buf, mtd->oobsize);

-               /* wait for command to be accepted
+               /* wait for command to be accepted
                 * can always use status0 bit as the mask is identical for =
each
                 * bank. */
                irq_status =3D wait_for_irq(denali, irq_mask);

                if (irq_status =3D=3D 0)
-               {
-                       printk(KERN_ERR "page on OOB timeout %d\n", denali-=
>page);
-               }
+                       printk(KERN_ERR "page on OOB timeout %d\n",
+                                       denali->page);

                /* We set the device back to MAIN_ACCESS here as I observed
                 * instability with the controller if you do a block erase
                 * and the last transaction was a SPARE_ACCESS. Block erase
                 * is reliable (according to the MTD test infrastructure)
-                * if you are in MAIN_ACCESS.
+                * if you are in MAIN_ACCESS.
                 */
                addr =3D BANK(denali->flash_bank) | denali->page;
-               cmd =3D MODE_10 | addr;
+               cmd =3D MODE_10 | addr;
                index_addr(denali, (uint32_t)cmd, MAIN_ACCESS);

 #if DEBUG_DENALI
                spin_lock_irq(&denali->irq_lock);
-               denali->irq_debug_array[denali->idx++] =3D 0x60000000 | mtd=
->oobsize;
+               denali->irq_debug_array[denali->idx++] =3D
+                       0x60000000 | mtd->oobsize;
                denali->idx %=3D 32;
                spin_unlock_irq(&denali->irq_lock);
 #endif
        }
 }

-/* this function examines buffers to see if they contain data that
+/* this function examines buffers to see if they contain data that
  * indicate that the buffer is part of an erased region of flash.
  */
 bool is_erased(uint8_t *buf, int len)
 {
        int i =3D 0;
        for (i =3D 0; i < len; i++)
-       {
                if (buf[i] !=3D 0xFF)
-               {
                        return false;
-               }
-       }
        return true;
 }
 #define ECC_SECTOR_SIZE 512
@@ -1358,64 +1386,58 @@ bool is_erased(uint8_t *buf, int len)
 #define ECC_ERR_DEVICE(x)      ((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8)
 #define ECC_LAST_ERR(x)                ((x) & ERR_CORRECTION_INFO__LAST_ER=
R_INFO)

-static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
+static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
                        uint8_t *oobbuf, uint32_t irq_status)
 {
        bool check_erased_page =3D false;

-       if (irq_status & INTR_STATUS0__ECC_ERR)
-       {
+       if (irq_status & INTR_STATUS0__ECC_ERR) {
                /* read the ECC errors. we'll ignore them for now */
                uint32_t err_address =3D 0, err_correction_info =3D 0;
                uint32_t err_byte =3D 0, err_sector =3D 0, err_device =3D 0=
;
                uint32_t err_correction_value =3D 0;

-               do
-               {
-                       err_address =3D ioread32(denali->flash_reg +
+               do {
+                       err_address =3D ioread32(denali->flash_reg +
                                                ECC_ERROR_ADDRESS);
                        err_sector =3D ECC_SECTOR(err_address);
                        err_byte =3D ECC_BYTE(err_address);


-                       err_correction_info =3D ioread32(denali->flash_reg =
+
+                       err_correction_info =3D ioread32(denali->flash_reg =
+
                                                ERR_CORRECTION_INFO);
-                       err_correction_value =3D
+                       err_correction_value =3D
                                ECC_CORRECTION_VALUE(err_correction_info);
                        err_device =3D ECC_ERR_DEVICE(err_correction_info);

-                       if (ECC_ERROR_CORRECTABLE(err_correction_info))
-                       {
+                       if (ECC_ERROR_CORRECTABLE(err_correction_info)) {
                                /* offset in our buffer is computed as:
-                                  sector number * sector size + offset in
+                                  sector number * sector size + offset in
                                   sector
                                 */
-                               int offset =3D err_sector * ECC_SECTOR_SIZE=
 +
+                               int offset =3D err_sector * ECC_SECTOR_SIZE=
 +
                                                                err_byte;
-                               if (offset < denali->mtd.writesize)
-                               {
+                               if (offset < denali->mtd.writesize) {
                                        /* correct the ECC error */
                                        buf[offset] ^=3D err_correction_val=
ue;
                                        denali->mtd.ecc_stats.corrected++;
-                               }
-                               else
-                               {
+                               } else {
                                        /* bummer, couldn't correct the err=
or */
                                        printk(KERN_ERR "ECC offset invalid=
\n");
                                        denali->mtd.ecc_stats.failed++;
                                }
-                       }
-                       else
-                       {
-                               /* if the error is not correctable, need to
-                                * look at the page to see if it is an eras=
ed page.
-                                * if so, then it's not a real ECC error */
+                       } else {
+                               /* if the error is not correctable, need to
+                                * look at the page to see if it is an
+                                * erased page.
+                                * if so, then it's not a real ECC error */
                                check_erased_page =3D true;
                        }

-#if DEBUG_DENALI
-                       printk("Detected ECC error in page %d: err_addr =3D=
 0x%08x,"
-                               " info to fix is 0x%08x\n", denali->page, e=
rr_address,
+#if DEBUG_DENALI
+                       printk(KERN_INFO "Detected ECC error in page %d: "
+                               "err_addr =3D 0x%08x, info to fix is 0x%08x=
\n",
+                               denali->page, err_address,
                                err_correction_info);
 #endif
                } while (!ECC_LAST_ERR(err_correction_info));
@@ -1428,7 +1450,8 @@ static void denali_enable_dma(struct denali_nand_info=
 *denali, bool en)
 {
        uint32_t reg_val =3D 0x0;

-       if (en) reg_val =3D DMA_ENABLE__FLAG;
+       if (en)
+               reg_val =3D DMA_ENABLE__FLAG;

        denali_write32(reg_val, denali->flash_reg + DMA_ENABLE);
        ioread32(denali->flash_reg + DMA_ENABLE);
@@ -1458,9 +1481,9 @@ static void denali_setup_dma(struct denali_nand_info =
*denali, int op)
        index_addr(denali, mode | 0x14000, 0x2400);
 }

-/* writes a page. user specifies type, and this function handles the
+/* writes a page. user specifies type, and this function handles the
    configuration details. */
-static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
+static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
                        const uint8_t *buf, bool raw_xfer)
 {
        struct denali_nand_info *denali =3D mtd_to_denali(mtd);
@@ -1470,7 +1493,7 @@ static void write_page(struct mtd_info *mtd, struct n=
and_chip *chip,
        size_t size =3D denali->mtd.writesize + denali->mtd.oobsize;

        uint32_t irq_status =3D 0;
-       uint32_t irq_mask =3D INTR_STATUS0__DMA_CMD_COMP |
+       uint32_t irq_mask =3D INTR_STATUS0__DMA_CMD_COMP |
                                                INTR_STATUS0__PROGRAM_FAIL;

        /* if it is a raw xfer, we want to disable ecc, and send
@@ -1484,73 +1507,71 @@ static void write_page(struct mtd_info *mtd, struct=
 nand_chip *chip,
        memcpy(denali->buf.buf, buf, mtd->writesize);

        if (raw_xfer)
-       {
                /* transfer the data to the spare area */
-               memcpy(denali->buf.buf + mtd->writesize,
-                       chip->oob_poi,
-                       mtd->oobsize);
-       }
+               memcpy(denali->buf.buf + mtd->writesize,
+                       chip->oob_poi,
+                       mtd->oobsize);

        pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVIC=
E);

        clear_interrupts(denali);
-       denali_enable_dma(denali, true);
+       denali_enable_dma(denali, true);

        denali_setup_dma(denali, DENALI_WRITE);

        /* wait for operation to complete */
        irq_status =3D wait_for_irq(denali, irq_mask);

-       if (irq_status =3D=3D 0)
-       {
-               printk(KERN_ERR "timeout on write_page (type =3D %d)\n", ra=
w_xfer);
-               denali->status =3D
-                  (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? NAND_STATUS_=
FAIL :
-                                                            PASS;
+       if (irq_status =3D=3D 0) {
+               printk(KERN_ERR "timeout on write_page (type =3D %d)\n",
+                               raw_xfer);
+               denali->status =3D
+                       (irq_status & INTR_STATUS0__PROGRAM_FAIL) ?
+                       NAND_STATUS_FAIL : PASS;
        }

-       denali_enable_dma(denali, false);
+       denali_enable_dma(denali, false);
        pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE);
 }

 /* NAND core entry points */

-/* this is the callback that the NAND core calls to write a page. Since
-   writing a page with ECC or without is similar, all the work is done
+/* this is the callback that the NAND core calls to write a page. Since
+   writing a page with ECC or without is similar, all the work is done
    by write_page above.   */
-static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip=
,
+static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip=
,
                                const uint8_t *buf)
 {
        /* for regular page writes, we let HW handle all the ECC
-         * data written to the device. */
+        * data written to the device. */
        write_page(mtd, chip, buf, false);
 }

-/* This is the callback that the NAND core calls to write a page without E=
CC.
+/* This is the callback that the NAND core calls to write a page without E=
CC.
    raw access is similiar to ECC page writes, so all the work is done in t=
he
-   write_page() function above.
+   write_page() function above.
  */
-static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *=
chip,
+static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *=
chip,
                                        const uint8_t *buf)
 {
-       /* for raw page writes, we want to disable ECC and simply write
+       /* for raw page writes, we want to disable ECC and simply write
           whatever data is in the buffer. */
        write_page(mtd, chip, buf, true);
 }

-static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
                            int page)
 {
-       return write_oob_data(mtd, chip->oob_poi, page);
+       return write_oob_data(mtd, chip->oob_poi, page);
 }

-static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
                           int page, int sndcmd)
 {
        read_oob_data(mtd, chip->oob_poi, page);

-       return 0; /* notify NAND core to send command to
-                   * NAND device. */
+       return 0; /* notify NAND core to send command to
+                                NAND device. */
 }

 static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
@@ -1563,7 +1584,7 @@ static int denali_read_page(struct mtd_info *mtd, str=
uct nand_chip *chip,
        size_t size =3D denali->mtd.writesize + denali->mtd.oobsize;

        uint32_t irq_status =3D 0;
-       uint32_t irq_mask =3D INTR_STATUS0__ECC_TRANSACTION_DONE |
+       uint32_t irq_mask =3D INTR_STATUS0__ECC_TRANSACTION_DONE |
                            INTR_STATUS0__ECC_ERR;
        bool check_erased_page =3D false;

@@ -1581,26 +1602,20 @@ static int denali_read_page(struct mtd_info *mtd, s=
truct nand_chip *chip,
        pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE=
);

        memcpy(buf, denali->buf.buf, mtd->writesize);
-
+
        check_erased_page =3D handle_ecc(denali, buf, chip->oob_poi, irq_st=
atus);
        denali_enable_dma(denali, false);

-       if (check_erased_page)
-       {
+       if (check_erased_page) {
                read_oob_data(&denali->mtd, chip->oob_poi, denali->page);

                /* check ECC failures that may have occurred on erased page=
s */
-               if (check_erased_page)
-               {
+               if (check_erased_page) {
                        if (!is_erased(buf, denali->mtd.writesize))
-                       {
                                denali->mtd.ecc_stats.failed++;
-                       }
                        if (!is_erased(buf, denali->mtd.oobsize))
-                       {
                                denali->mtd.ecc_stats.failed++;
-                       }
-               }
+               }
        }
        return 0;
 }
@@ -1616,7 +1631,7 @@ static int denali_read_page_raw(struct mtd_info *mtd,=
 struct nand_chip *chip,

        uint32_t irq_status =3D 0;
        uint32_t irq_mask =3D INTR_STATUS0__DMA_CMD_COMP;
-
+
        setup_ecc_for_xfer(denali, false, true);
        denali_enable_dma(denali, true);

@@ -1644,12 +1659,10 @@ static uint8_t denali_read_byte(struct mtd_info *mt=
d)
        uint8_t result =3D 0xff;

        if (denali->buf.head < denali->buf.tail)
-       {
                result =3D denali->buf.buf[denali->buf.head++];
-       }

 #if DEBUG_DENALI
-       printk("read byte -> 0x%02x\n", result);
+       printk(KERN_INFO "read byte -> 0x%02x\n", result);
 #endif
        return result;
 }
@@ -1658,7 +1671,7 @@ static void denali_select_chip(struct mtd_info *mtd, =
int chip)
 {
        struct denali_nand_info *denali =3D mtd_to_denali(mtd);
 #if DEBUG_DENALI
-       printk("denali select chip %d\n", chip);
+       printk(KERN_INFO "denali select chip %d\n", chip);
 #endif
        spin_lock_irq(&denali->irq_lock);
        denali->flash_bank =3D chip;
@@ -1672,7 +1685,7 @@ static int denali_waitfunc(struct mtd_info *mtd, stru=
ct nand_chip *chip)
        denali->status =3D 0;

 #if DEBUG_DENALI
-       printk("waitfunc %d\n", status);
+       printk(KERN_INFO "waitfunc %d\n", status);
 #endif
        return status;
 }
@@ -1684,76 +1697,77 @@ static void denali_erase(struct mtd_info *mtd, int =
page)
        uint32_t cmd =3D 0x0, irq_status =3D 0;

 #if DEBUG_DENALI
-       printk("erase page: %d\n", page);
+       printk(KERN_INFO "erase page: %d\n", page);
 #endif
        /* clear interrupts */
-       clear_interrupts(denali);
+       clear_interrupts(denali);

        /* setup page read request for access type */
        cmd =3D MODE_10 | BANK(denali->flash_bank) | page;
        index_addr(denali, (uint32_t)cmd, 0x1);

        /* wait for erase to complete or failure to occur */
-       irq_status =3D wait_for_irq(denali, INTR_STATUS0__ERASE_COMP |
+       irq_status =3D wait_for_irq(denali, INTR_STATUS0__ERASE_COMP |
                                        INTR_STATUS0__ERASE_FAIL);

-       denali->status =3D (irq_status & INTR_STATUS0__ERASE_FAIL) ? NAND_S=
TATUS_FAIL :
-                                                                PASS;
+       denali->status =3D (irq_status & INTR_STATUS0__ERASE_FAIL) ?
+                                       NAND_STATUS_FAIL : PASS;
 }

-static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col=
,
+static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col=
,
                           int page)
 {
        struct denali_nand_info *denali =3D mtd_to_denali(mtd);

 #if DEBUG_DENALI
-       printk("cmdfunc: 0x%x %d %d\n", cmd, col, page);
+       printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page);
 #endif
-       switch (cmd)
-       {
-               case NAND_CMD_PAGEPROG:
-                       break;
-               case NAND_CMD_STATUS:
-                       read_status(denali);
-                       break;
-               case NAND_CMD_READID:
-                       reset_buf(denali);
-                       if (denali->flash_bank < denali->total_used_banks)
-                       {
-                               /* write manufacturer information into nand
-                                  buffer for NAND subsystem to fetch.
-                                */
-                               write_byte_to_buf(denali, denali->dev_info.=
wDeviceMaker);
-                               write_byte_to_buf(denali, denali->dev_info.=
wDeviceID);
-                               write_byte_to_buf(denali, denali->dev_info.=
bDeviceParam0);
-                               write_byte_to_buf(denali, denali->dev_info.=
bDeviceParam1);
-                               write_byte_to_buf(denali, denali->dev_info.=
bDeviceParam2);
-                       }
-                       else
-                       {
-                               int i;
-                               for (i =3D 0; i < 5; i++)
-                                       write_byte_to_buf(denali, 0xff);
-                       }
-                       break;
-               case NAND_CMD_READ0:
-               case NAND_CMD_SEQIN:
-                       denali->page =3D page;
-                       break;
-               case NAND_CMD_RESET:
-                       reset_bank(denali);
-                       break;
-               case NAND_CMD_READOOB:
-                       /* TODO: Read OOB data */
-                       break;
-               default:
-                       printk(KERN_ERR ": unsupported command received 0x%=
x\n", cmd);
-                       break;
+       switch (cmd) {
+       case NAND_CMD_PAGEPROG:
+               break;
+       case NAND_CMD_STATUS:
+               read_status(denali);
+               break;
+       case NAND_CMD_READID:
+               reset_buf(denali);
+               if (denali->flash_bank < denali->total_used_banks) {
+                       /* write manufacturer information into nand
+                          buffer for NAND subsystem to fetch.
+                                */
+                       write_byte_to_buf(denali,
+                                       denali->dev_info.wDeviceMaker);
+                       write_byte_to_buf(denali,
+                                       denali->dev_info.wDeviceID);
+                       write_byte_to_buf(denali,
+                                       denali->dev_info.bDeviceParam0);
+                       write_byte_to_buf(denali,
+                                       denali->dev_info.bDeviceParam1);
+                       write_byte_to_buf(denali,
+                                       denali->dev_info.bDeviceParam2);
+               } else {
+                       int i;
+                       for (i =3D 0; i < 5; i++)
+                               write_byte_to_buf(denali, 0xff);
+               }
+               break;
+       case NAND_CMD_READ0:
+       case NAND_CMD_SEQIN:
+               denali->page =3D page;
+               break;
+       case NAND_CMD_RESET:
+               reset_bank(denali);
+               break;
+       case NAND_CMD_READOOB:
+               /* TODO: Read OOB data */
+               break;
+       default:
+               printk(KERN_ERR ": unsupported command received 0x%x\n", cm=
d);
+               break;
        }
 }

 /* stubs for ECC functions not used by the NAND core */
-static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
+static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
                                uint8_t *ecc_code)
 {
        printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n");
@@ -1761,7 +1775,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd,=
 const uint8_t *data,
        return -EIO;
 }

-static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
+static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
                                uint8_t *read_ecc, uint8_t *calc_ecc)
 {
        printk(KERN_ERR "denali_ecc_correct called unexpectedly\n");
@@ -1782,7 +1796,8 @@ static void denali_hw_init(struct denali_nand_info *d=
enali)
        denali_irq_init(denali);
        NAND_Flash_Reset(denali);
        denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
-       denali_write32(CHIP_EN_DONT_CARE__FLAG, denali->flash_reg + CHIP_EN=
ABLE_DONT_CARE);
+       denali_write32(CHIP_EN_DONT_CARE__FLAG,
+                       denali->flash_reg + CHIP_ENABLE_DONT_CARE);

        denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES);
        denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER);
@@ -1793,24 +1808,26 @@ static void denali_hw_init(struct denali_nand_info =
*denali)
 }

 /* ECC layout for SLC devices. Denali spec indicates SLC fixed at 4 bytes =
*/
-#define ECC_BYTES_SLC   4 * (2048 / ECC_SECTOR_SIZE)
+#define ECC_BYTES_SLC   (4 * (2048 / ECC_SECTOR_SIZE))
 static struct nand_ecclayout nand_oob_slc =3D {
        .eccbytes =3D 4,
        .eccpos =3D { 0, 1, 2, 3 }, /* not used */
-       .oobfree =3D {{
-                       .offset =3D ECC_BYTES_SLC,
-                       .length =3D 64 - ECC_BYTES_SLC
-                  }}
+       .oobfree =3D {{
+                       .offset =3D ECC_BYTES_SLC,
+                       .length =3D 64 - ECC_BYTES_SLC
+                  }
+       }
 };

-#define ECC_BYTES_MLC   14 * (2048 / ECC_SECTOR_SIZE)
+#define ECC_BYTES_MLC   (14 * (2048 / ECC_SECTOR_SIZE))
 static struct nand_ecclayout nand_oob_mlc_14bit =3D {
        .eccbytes =3D 14,
        .eccpos =3D { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, /* not u=
sed */
-       .oobfree =3D {{
-                       .offset =3D ECC_BYTES_MLC,
-                       .length =3D 64 - ECC_BYTES_MLC
-                  }}
+       .oobfree =3D {{
+                       .offset =3D ECC_BYTES_MLC,
+                       .length =3D 64 - ECC_BYTES_MLC
+                  }
+       }
 };

 static uint8_t bbt_pattern[] =3D {'B', 'b', 't', '0' };
@@ -1842,12 +1859,12 @@ void denali_drv_init(struct denali_nand_info *denal=
i)
        denali->idx =3D 0;

        /* setup interrupt handler */
-       /* the completion object will be used to notify
+       /* the completion object will be used to notify
         * the callee that the interrupt is done */
        init_completion(&denali->complete);

        /* the spinlock will be used to synchronize the ISR
-        * with any element that might be access shared
+        * with any element that might be access shared
         * data (interrupt status) */
        spin_lock_init(&denali->irq_lock);

@@ -1880,13 +1897,12 @@ static int denali_pci_probe(struct pci_dev *dev, co=
nst struct pci_device_id *id)
        }

        if (id->driver_data =3D=3D INTEL_CE4100) {
-               /* Due to a silicon limitation, we can only support
-                * ONFI timing mode 1 and below.
-                */
-               if (onfi_timing_mode < -1 || onfi_timing_mode > 1)
-               {
-                       printk("Intel CE4100 only supports ONFI timing mode=
 1 "
-                               "or below\n");
+               /* Due to a silicon limitation, we can only support
+                * ONFI timing mode 1 and below.
+                */
+               if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
+                       printk(KERN_ERR "Intel CE4100 only supports ONFI"
+                                       " timing mode 1 or below\n");
                        ret =3D -EINVAL;
                        goto failed_enable;
                }
@@ -1905,7 +1921,8 @@ static int denali_pci_probe(struct pci_dev *dev, cons=
t struct pci_device_id *id)
                        mem_base =3D csr_base + csr_len;
                        mem_len =3D csr_len;
                        nand_dbg_print(NAND_DBG_WARN,
-                                      "Spectra: No second BAR for PCI devi=
ce; assuming %08Lx\n",
+                                      "Spectra: No second BAR for PCI devi=
ce;"
+                                          " assuming %08Lx\n",
                                       (uint64_t)csr_base);
                }
        }
@@ -1913,16 +1930,15 @@ static int denali_pci_probe(struct pci_dev *dev, co=
nst struct pci_device_id *id)
        /* Is 32-bit DMA supported? */
        ret =3D pci_set_dma_mask(dev, DMA_BIT_MASK(32));

-       if (ret)
-       {
+       if (ret) {
                printk(KERN_ERR "Spectra: no usable DMA configuration\n");
                goto failed_enable;
        }
-       denali->buf.dma_buf =3D pci_map_single(dev, denali->buf.buf, DENALI=
_BUF_SIZE,
-                                        PCI_DMA_BIDIRECTIONAL);
+       denali->buf.dma_buf =3D pci_map_single(dev, denali->buf.buf,
+                                                       DENALI_BUF_SIZE,
+                                                       PCI_DMA_BIDIRECTION=
AL);

-       if (pci_dma_mapping_error(dev, denali->buf.dma_buf))
-       {
+       if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) {
                printk(KERN_ERR "Spectra: failed to map DMA buffer\n");
                goto failed_enable;
        }
@@ -1976,11 +1992,10 @@ static int denali_pci_probe(struct pci_dev *dev, co=
nst struct pci_device_id *id)

        NAND_Read_Device_ID(denali);

-       /* MTD supported page sizes vary by kernel. We validate our
-           kernel supports the device here.
+       /* MTD supported page sizes vary by kernel. We validate our
+        * kernel supports the device here.
         */
-       if (denali->dev_info.wPageSize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSI=
ZE)
-       {
+       if (denali->dev_info.wPageSize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSI=
ZE) {
                ret =3D -ENODEV;
                printk(KERN_ERR "Spectra: device size not supported by this=
 "
                        "version of MTD.");
@@ -2009,18 +2024,17 @@ static int denali_pci_probe(struct pci_dev *dev, co=
nst struct pci_device_id *id)
        denali->nand.read_byte =3D denali_read_byte;
        denali->nand.waitfunc =3D denali_waitfunc;

-       /* scan for NAND devices attached to the controller
+       /* scan for NAND devices attached to the controller
         * this is the first stage in a two step process to register
-        * with the nand subsystem */
-       if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL))
-       {
+        * with the nand subsystem */
+       if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) {
                ret =3D -ENXIO;
                goto failed_nand;
        }
-
-       /* second stage of the NAND scan
-        * this stage requires information regarding ECC and
-         * bad block management. */
+
+       /* second stage of the NAND scan
+        * this stage requires information regarding ECC and
+        * bad block management. */

        /* Bad block management */
        denali->nand.bbt_td =3D &bbt_main_descr;
@@ -2030,20 +2044,17 @@ static int denali_pci_probe(struct pci_dev *dev, co=
nst struct pci_device_id *id)
        denali->nand.options |=3D NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
        denali->nand.ecc.mode =3D NAND_ECC_HW_SYNDROME;

-       if (denali->dev_info.MLCDevice)
-       {
+       if (denali->dev_info.MLCDevice) {
                denali->nand.ecc.layout =3D &nand_oob_mlc_14bit;
                denali->nand.ecc.bytes =3D ECC_BYTES_MLC;
-       }
-       else /* SLC */
-       {
+       } else { /* SLC */
                denali->nand.ecc.layout =3D &nand_oob_slc;
                denali->nand.ecc.bytes =3D ECC_BYTES_SLC;
        }

-       /* These functions are required by the NAND core framework, otherwi=
se,
-           the NAND core will assert. However, we don't need them, so we'l=
l stub
-           them out. */
+       /* These functions are required by the NAND core framework, otherwi=
se,
+        * the NAND core will assert. However, we don't need them, so we'll=
 stub
+        * them out. */
        denali->nand.ecc.calculate =3D denali_ecc_calculate;
        denali->nand.ecc.correct =3D denali_ecc_correct;
        denali->nand.ecc.hwctl =3D denali_ecc_hwctl;
@@ -2058,15 +2069,15 @@ static int denali_pci_probe(struct pci_dev *dev, co=
nst struct pci_device_id *id)
        denali->nand.ecc.write_oob =3D denali_write_oob;
        denali->nand.erase_cmd =3D denali_erase;

-       if (nand_scan_tail(&denali->mtd))
-       {
+       if (nand_scan_tail(&denali->mtd)) {
                ret =3D -ENXIO;
                goto failed_nand;
        }

        ret =3D add_mtd_device(&denali->mtd);
        if (ret) {
-               printk(KERN_ERR "Spectra: Failed to register MTD device: %d=
\n", ret);
+               printk(KERN_ERR "Spectra: Failed to register"
+                               " MTD device: %d\n", ret);
                goto failed_nand;
        }
        return 0;
@@ -2079,7 +2090,7 @@ static int denali_pci_probe(struct pci_dev *dev, cons=
t struct pci_device_id *id)
  failed_remap_csr:
        pci_release_regions(dev);
  failed_req_csr:
-       pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+       pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
                                                        PCI_DMA_BIDIRECTION=
AL);
  failed_enable:
        kfree(denali);
@@ -2103,7 +2114,7 @@ static void denali_pci_remove(struct pci_dev *dev)
        iounmap(denali->flash_mem);
        pci_release_regions(dev);
        pci_disable_device(dev);
-       pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+       pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
                                                        PCI_DMA_BIDIRECTION=
AL);
        pci_set_drvdata(dev, NULL);
        kfree(denali);
@@ -2120,7 +2131,8 @@ static struct pci_driver denali_pci_driver =3D {

 static int __devinit denali_init(void)
 {
-       printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n", __DATE__,=
 __TIME__);
+       printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n",
+                       __DATE__, __TIME__);
        return pci_register_driver(&denali_pci_driver);
 }

diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 422a29a..a38c8ae 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -17,7 +17,7 @@
  *
  */

-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand.h>

 #define DEVICE_RESET                           0x0
 #define     DEVICE_RESET__BANK0                                0x0001
@@ -83,7 +83,7 @@
 #define RE_2_WE                                        0x120
 #define     RE_2_WE__VALUE                             0x003f

-#define ACC_CLKS                               0x130
+#define ACC_CLKS                               0x130
 #define     ACC_CLKS__VALUE                            0x000f

 #define NUMBER_OF_PLANES                       0x140
@@ -622,43 +622,40 @@

 /* flash.h */
 struct device_info_tag {
-        uint16_t wDeviceMaker;
-        uint16_t wDeviceID;
+       uint16_t wDeviceMaker;
+       uint16_t wDeviceID;
        uint8_t  bDeviceParam0;
        uint8_t  bDeviceParam1;
        uint8_t  bDeviceParam2;
-        uint32_t wDeviceType;
-        uint32_t wSpectraStartBlock;
-        uint32_t wSpectraEndBlock;
-        uint32_t wTotalBlocks;
-        uint16_t wPagesPerBlock;
-        uint16_t wPageSize;
-        uint16_t wPageDataSize;
-        uint16_t wPageSpareSize;
-        uint16_t wNumPageSpareFlag;
-        uint16_t wECCBytesPerSector;
-        uint32_t wBlockSize;
-        uint32_t wBlockDataSize;
-        uint32_t wDataBlockNum;
-        uint8_t bPlaneNum;
-        uint16_t wDeviceMainAreaSize;
-        uint16_t wDeviceSpareAreaSize;
-        uint16_t wDevicesConnected;
-        uint16_t wDeviceWidth;
-        uint16_t wHWRevision;
-        uint16_t wHWFeatures;
-
-        uint16_t wONFIDevFeatures;
-        uint16_t wONFIOptCommands;
-        uint16_t wONFITimingMode;
-        uint16_t wONFIPgmCacheTimingMode;
-
-        uint16_t MLCDevice;
-        uint16_t wSpareSkipBytes;
-
-        uint8_t nBitsInPageNumber;
-        uint8_t nBitsInPageDataSize;
-        uint8_t nBitsInBlockDataSize;
+       uint32_t wDeviceType;
+       uint32_t wSpectraStartBlock;
+       uint32_t wSpectraEndBlock;
+       uint32_t wTotalBlocks;
+       uint16_t wPagesPerBlock;
+       uint16_t wPageSize;
+       uint16_t wPageDataSize;
+       uint16_t wPageSpareSize;
+       uint16_t wNumPageSpareFlag;
+       uint16_t wECCBytesPerSector;
+       uint32_t wBlockSize;
+       uint32_t wBlockDataSize;
+       uint32_t wDataBlockNum;
+       uint8_t bPlaneNum;
+       uint16_t wDeviceMainAreaSize;
+       uint16_t wDeviceSpareAreaSize;
+       uint16_t wDevicesConnected;
+       uint16_t wDeviceWidth;
+       uint16_t wHWRevision;
+       uint16_t wHWFeatures;
+       uint16_t wONFIDevFeatures;
+       uint16_t wONFIOptCommands;
+       uint16_t wONFITimingMode;
+       uint16_t wONFIPgmCacheTimingMode;
+       uint16_t MLCDevice;
+       uint16_t wSpareSkipBytes;
+       uint8_t nBitsInPageNumber;
+       uint8_t nBitsInPageDataSize;
+       uint8_t nBitsInBlockDataSize;
 };

 /* ffsdefs.h */
@@ -684,11 +681,11 @@ struct device_info_tag {
 #define NAND_DBG_TRACE 3

 #ifdef VERBOSE
-#define nand_dbg_print(level, args...)                  \
-        do {                                            \
-                if (level <=3D nand_debug_level)          \
-                        printk(KERN_ALERT args);        \
-        } while (0)
+#define nand_dbg_print(level, args...)         \
+       do {            \
+                       if (level <=3D nand_debug_level)  \
+                               printk(KERN_ALERT args);        \
+       } while (0)
 #else
 #define nand_dbg_print(level, args...)
 #endif
@@ -772,10 +769,9 @@ struct device_info_tag {
 #define ECC_SECTOR_SIZE     512
 #define LLD_MAX_FLASH_BANKS     4

-#define DENALI_BUF_SIZE                NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZ=
E
+#define DENALI_BUF_SIZE                (NAND_MAX_PAGESIZE + NAND_MAX_OOBSI=
ZE)

-struct nand_buf
-{
+struct nand_buf {
        int head;
        int tail;
        uint8_t buf[DENALI_BUF_SIZE];
@@ -810,7 +806,7 @@ struct denali_nand_info {

 static uint16_t  NAND_Flash_Reset(struct denali_nand_info *denali);
 static uint16_t  NAND_Read_Device_ID(struct denali_nand_info *denali);
-static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *de=
nali, uint16_t INT_ENABLE);
+static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *de=
nali,
+                                                       uint16_t INT_ENABLE=
);

 #endif /*_LLD_NAND_*/
-
--
1.6.6.1


--_002_5D8008F58939784290FAB48F549751981D09B718B2shsmsx502ccrc_
Content-Type: application/octet-stream;
	name="0001-MTD-denali-fixed-all-checkpatch-errors.patch"
Content-Description: 0001-MTD-denali-fixed-all-checkpatch-errors.patch
Content-Disposition: attachment;
	filename="0001-MTD-denali-fixed-all-checkpatch-errors.patch"; size=63235;
	creation-date="Mon, 21 Jun 2010 18:56:23 GMT";
	modification-date="Mon, 21 Jun 2010 18:56:23 GMT"
Content-Transfer-Encoding: base64

[encoded data, 85393 characters]
QU5EXyovCi0KLS0gCjEuNi42LjEKCg==

--_002_5D8008F58939784290FAB48F549751981D09B718B2shsmsx502ccrc_--


From chuanxiao.dong at intel.com  Mon Jun 21 06:31:32 2010
From: chuanxiao.dong at intel.com (Chuanxiao Dong)
Date: Mon, 21 Jun 2010 18:31:32 +0800
Subject: [PATCH 2/5] [MTD/denali] renamed functions which is named by using=
 capitals
Message-ID: <mailman.66.1278925445.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Chuanxiao Dong <chuanxiao.dong at intel.com>
---
 drivers/mtd/nand/denali.c |   22 +++++++++++-----------
 drivers/mtd/nand/denali.h |    5 -----
 2 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 4e255ff..fbdd9f0 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -220,7 +220,7 @@ static void reset_bank(struct denali_nand_info *denali)
 }
=20
 /* Reset the flash controller */
-static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali)
+static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 {
 	uint32_t i;
=20
@@ -256,7 +256,7 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_inf=
o *denali)
  * the clocking register accordingly. The mode is determined by the
  * get_onfi_nand_para routine.
  */
-static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali,
+static void nand_onfi_timing_set(struct denali_nand_info *denali,
 								uint16_t mode)
 {
 	uint16_t Trea[6] =3D {40, 30, 25, 20, 20, 16};
@@ -487,7 +487,7 @@ static uint16_t get_onfi_nand_para(struct denali_nand_i=
nfo *denali)
 			break;
 	}
=20
-	NAND_ONFi_Timing_Mode(denali, i);
+	nand_onfi_timing_set(denali, i);
=20
 	index_addr(denali, MODE_11 | 0, 0x90);
 	index_addr(denali, MODE_11 | 1, 0);
@@ -802,7 +802,7 @@ static void dump_device_info(struct denali_nand_info *d=
enali)
 		denali->dev_info.nBitsInBlockDataSize);
 }
=20
-static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali)
+static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 {
 	uint16_t status =3D PASS;
 	uint8_t no_of_planes;
@@ -927,12 +927,12 @@ static uint16_t NAND_Read_Device_ID(struct denali_nan=
d_info *denali)
 	 * with a specific ONFI mode, we apply those changes here.
 	 */
 	if (onfi_timing_mode !=3D NAND_DEFAULT_TIMINGS)
-		NAND_ONFi_Timing_Mode(denali, onfi_timing_mode);
+		nand_onfi_timing_set(denali, onfi_timing_mode);
=20
 	return status;
 }
=20
-static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *de=
nali,
+static void denali_set_intr_mode(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 {
 	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
@@ -957,7 +957,7 @@ static void denali_irq_init(struct denali_nand_info *de=
nali)
 	uint32_t int_mask =3D 0;
=20
 	/* Disable global interrupts */
-	NAND_LLD_Enable_Disable_Interrupts(denali, false);
+	denali_set_intr_mode(denali, false);
=20
 	int_mask =3D DENALI_IRQ_ALL;
=20
@@ -972,7 +972,7 @@ static void denali_irq_init(struct denali_nand_info *de=
nali)
=20
 static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali=
)
 {
-	NAND_LLD_Enable_Disable_Interrupts(denali, false);
+	denali_set_intr_mode(denali, false);
 	free_irq(irqnum, denali);
 }
=20
@@ -1794,7 +1794,7 @@ static void denali_ecc_hwctl(struct mtd_info *mtd, in=
t mode)
 static void denali_hw_init(struct denali_nand_info *denali)
 {
 	denali_irq_init(denali);
-	NAND_Flash_Reset(denali);
+	denali_nand_reset(denali);
 	denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
 	denali_write32(CHIP_EN_DONT_CARE__FLAG,
 			denali->flash_reg + CHIP_ENABLE_DONT_CARE);
@@ -1986,11 +1986,11 @@ static int denali_pci_probe(struct pci_dev *dev, co=
nst struct pci_device_id *id)
 	}
=20
 	/* now that our ISR is registered, we can enable interrupts */
-	NAND_LLD_Enable_Disable_Interrupts(denali, true);
+	denali_set_intr_mode(denali, true);
=20
 	pci_set_drvdata(dev, denali);
=20
-	NAND_Read_Device_ID(denali);
+	denali_nand_timing_set(denali);
=20
 	/* MTD supported page sizes vary by kernel. We validate our
 	 * kernel supports the device here.
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index a38c8ae..fc6be39 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -804,9 +804,4 @@ struct denali_nand_info {
 	int idx;
 };
=20
-static uint16_t  NAND_Flash_Reset(struct denali_nand_info *denali);
-static uint16_t  NAND_Read_Device_ID(struct denali_nand_info *denali);
-static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *de=
nali,
-							uint16_t INT_ENABLE);
-
 #endif /*_LLD_NAND_*/
--=20
1.6.6.1


--_002_5D8008F58939784290FAB48F549751981D09B718B3shsmsx502ccrc_
Content-Type: application/octet-stream;
	name="0002-MTD-denali-renamed-functions-which-is-named-by-using.patch"
Content-Description: 0002-MTD-denali-renamed-functions-which-is-named-by-using.patch
Content-Disposition: attachment;
	filename="0002-MTD-denali-renamed-functions-which-is-named-by-using.patch";
	size=4362; creation-date="Mon, 21 Jun 2010 18:56:23 GMT";
	modification-date="Mon, 21 Jun 2010 18:56:23 GMT"
Content-Transfer-Encoding: base64

[encoded data, 5852 characters]
ZiAvKl9MTERfTkFORF8qLwotLSAKMS42LjYuMQoK

--_002_5D8008F58939784290FAB48F549751981D09B718B3shsmsx502ccrc_--


From chuanxiao.dong at intel.com  Mon Jun 21 06:46:10 2010
From: chuanxiao.dong at intel.com (Chuanxiao Dong)
Date: Mon, 21 Jun 2010 18:46:10 +0800
Subject: [PATCH 4/5] [MTD/denali] Fixed ECC handler bug
 1. when found ecc errors while reading, handler only process these errors =
Message-ID: <mailman.69.1278936648.27306.linux-mtd@lists.infradead.org>

in MAIN area,
    just ignore these ecc errors in spare area
 2. corrected some wrong defines

Signed-off-by: Chuanxiao Dong <chuanxiao.dong at intel.com>
---
 drivers/mtd/nand/denali.c |   28 +++++++++++++++++-----------
 1 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 57818eb..1555921 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1382,12 +1382,12 @@ bool is_erased(uint8_t *buf, int len)
 #define ECC_SECTOR(x)	(((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12)
 #define ECC_BYTE(x)	(((x) & ECC_ERROR_ADDRESS__OFFSET))
 #define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK)
-#define ECC_ERROR_CORRECTABLE(x) (!((x) & ERR_CORRECTION_INFO))
-#define ECC_ERR_DEVICE(x)	((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8)
+#define ECC_ERROR_CORRECTABLE(x) (!((x) & ERR_CORRECTION_INFO__ERROR_TYPE)=
)
+#define ECC_ERR_DEVICE(x)	(((x) & ERR_CORRECTION_INFO__DEVICE_NR) >> 8)
 #define ECC_LAST_ERR(x)		((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO)
=20
 static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
-			uint8_t *oobbuf, uint32_t irq_status)
+			uint32_t irq_status)
 {
 	bool check_erased_page =3D false;
=20
@@ -1412,13 +1412,19 @@ static bool handle_ecc(struct denali_nand_info *den=
ali, uint8_t *buf,
=20
 			if (ECC_ERROR_CORRECTABLE(err_correction_info)) {
 				/* offset in our buffer is computed as:
-				   sector number * sector size + offset in
-				   sector
-				 */
-				int offset =3D (err_sector * ECC_SECTOR_SIZE +
-						err_byte) * denali->devnum +
-						err_device;
-				if (offset < denali->mtd.writesize) {
+				 * sector number * sector size + offset in
+				 * sector + err_device
+				 * If err_byte is larger than ECC_SECTOR_SIZE,
+				 * means error happend in OOB, so we ignore
+				 * it. It's no need for us to correct it
+				 * */
+				if (err_byte < ECC_SECTOR_SIZE) {
+					int offset;
+					offset =3D (err_sector *
+							ECC_SECTOR_SIZE +
+							err_byte) *
+							denali->devnum +
+							err_device;
 					/* correct the ECC error */
 					buf[offset] ^=3D err_correction_value;
 					denali->mtd.ecc_stats.corrected++;
@@ -1604,7 +1610,7 @@ static int denali_read_page(struct mtd_info *mtd, str=
uct nand_chip *chip,
=20
 	memcpy(buf, denali->buf.buf, mtd->writesize);
=20
-	check_erased_page =3D handle_ecc(denali, buf, chip->oob_poi, irq_status);
+	check_erased_page =3D handle_ecc(denali, buf, irq_status);
 	denali_enable_dma(denali, false);
=20
 	if (check_erased_page) {
--=20
1.6.6.1


--_002_5D8008F58939784290FAB48F549751981D09B718B6shsmsx502ccrc_
Content-Type: application/octet-stream;
	name="0004-MTD-denali-Fixed-ECC-handler-bug.patch"
Content-Description: 0004-MTD-denali-Fixed-ECC-handler-bug.patch
Content-Disposition: attachment;
	filename="0004-MTD-denali-Fixed-ECC-handler-bug.patch"; size=2816;
	creation-date="Mon, 21 Jun 2010 18:56:23 GMT";
	modification-date="Mon, 21 Jun 2010 18:56:23 GMT"
Content-Transfer-Encoding: base64

RnJvbSBiNzAyMTNmYWE0NWZmZDQzMmQxN2IyZjNjNDVjNjg2MjFmMTUyODFiIE1vbiBTZXAgMTcg
MDA6MDA6MDAgMjAwMQpGcm9tOiBDaHVhbnhpYW8gRG9uZyA8Y2h1YW54aWFvLmRvbmdAaW50ZWwu
Y29tPgpEYXRlOiBNb24sIDIxIEp1biAyMDEwIDE4OjQ2OjEwICswODAwClN1YmplY3Q6IFtQQVRD
SCA0LzVdIFtNVEQvZGVuYWxpXSBGaXhlZCBFQ0MgaGFuZGxlciBidWcKIDEuIHdoZW4gZm91bmQg
ZWNjIGVycm9ycyB3aGlsZSByZWFkaW5nLCBoYW5kbGVyIG9ubHkgcHJvY2VzcyB0aGVzZSBlcnJv
cnMgaW4gTUFJTiBhcmVhLAogICAganVzdCBpZ25vcmUgdGhlc2UgZWNjIGVycm9ycyBpbiBzcGFy
ZSBhcmVhCiAyLiBjb3JyZWN0ZWQgc29tZSB3cm9uZyBkZWZpbmVzCgpTaWduZWQtb2ZmLWJ5OiBD
aHVhbnhpYW8gRG9uZyA8Y2h1YW54aWFvLmRvbmdAaW50ZWwuY29tPgotLS0KIGRyaXZlcnMvbXRk
L25hbmQvZGVuYWxpLmMgfCAgIDI4ICsrKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0KIDEgZmls
ZXMgY2hhbmdlZCwgMTcgaW5zZXJ0aW9ucygrKSwgMTEgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0
IGEvZHJpdmVycy9tdGQvbmFuZC9kZW5hbGkuYyBiL2RyaXZlcnMvbXRkL25hbmQvZGVuYWxpLmMK
aW5kZXggNTc4MThlYi4uMTU1NTkyMSAxMDA2NDQKLS0tIGEvZHJpdmVycy9tdGQvbmFuZC9kZW5h
bGkuYworKysgYi9kcml2ZXJzL210ZC9uYW5kL2RlbmFsaS5jCkBAIC0xMzgyLDEyICsxMzgyLDEy
IEBAIGJvb2wgaXNfZXJhc2VkKHVpbnQ4X3QgKmJ1ZiwgaW50IGxlbikKICNkZWZpbmUgRUNDX1NF
Q1RPUih4KQkoKCh4KSAmIEVDQ19FUlJPUl9BRERSRVNTX19TRUNUT1JfTlIpID4+IDEyKQogI2Rl
ZmluZSBFQ0NfQllURSh4KQkoKCh4KSAmIEVDQ19FUlJPUl9BRERSRVNTX19PRkZTRVQpKQogI2Rl
ZmluZSBFQ0NfQ09SUkVDVElPTl9WQUxVRSh4KSAoKHgpICYgRVJSX0NPUlJFQ1RJT05fSU5GT19f
QllURU1BU0spCi0jZGVmaW5lIEVDQ19FUlJPUl9DT1JSRUNUQUJMRSh4KSAoISgoeCkgJiBFUlJf
Q09SUkVDVElPTl9JTkZPKSkKLSNkZWZpbmUgRUNDX0VSUl9ERVZJQ0UoeCkJKCh4KSAmIEVSUl9D
T1JSRUNUSU9OX0lORk9fX0RFVklDRV9OUiA+PiA4KQorI2RlZmluZSBFQ0NfRVJST1JfQ09SUkVD
VEFCTEUoeCkgKCEoKHgpICYgRVJSX0NPUlJFQ1RJT05fSU5GT19fRVJST1JfVFlQRSkpCisjZGVm
aW5lIEVDQ19FUlJfREVWSUNFKHgpCSgoKHgpICYgRVJSX0NPUlJFQ1RJT05fSU5GT19fREVWSUNF
X05SKSA+PiA4KQogI2RlZmluZSBFQ0NfTEFTVF9FUlIoeCkJCSgoeCkgJiBFUlJfQ09SUkVDVElP
Tl9JTkZPX19MQVNUX0VSUl9JTkZPKQogCiBzdGF0aWMgYm9vbCBoYW5kbGVfZWNjKHN0cnVjdCBk
ZW5hbGlfbmFuZF9pbmZvICpkZW5hbGksIHVpbnQ4X3QgKmJ1ZiwKLQkJCXVpbnQ4X3QgKm9vYmJ1
ZiwgdWludDMyX3QgaXJxX3N0YXR1cykKKwkJCXVpbnQzMl90IGlycV9zdGF0dXMpCiB7CiAJYm9v
bCBjaGVja19lcmFzZWRfcGFnZSA9IGZhbHNlOwogCkBAIC0xNDEyLDEzICsxNDEyLDE5IEBAIHN0
YXRpYyBib29sIGhhbmRsZV9lY2Moc3RydWN0IGRlbmFsaV9uYW5kX2luZm8gKmRlbmFsaSwgdWlu
dDhfdCAqYnVmLAogCiAJCQlpZiAoRUNDX0VSUk9SX0NPUlJFQ1RBQkxFKGVycl9jb3JyZWN0aW9u
X2luZm8pKSB7CiAJCQkJLyogb2Zmc2V0IGluIG91ciBidWZmZXIgaXMgY29tcHV0ZWQgYXM6Ci0J
CQkJICAgc2VjdG9yIG51bWJlciAqIHNlY3RvciBzaXplICsgb2Zmc2V0IGluCi0JCQkJICAgc2Vj
dG9yCi0JCQkJICovCi0JCQkJaW50IG9mZnNldCA9IChlcnJfc2VjdG9yICogRUNDX1NFQ1RPUl9T
SVpFICsKLQkJCQkJCWVycl9ieXRlKSAqIGRlbmFsaS0+ZGV2bnVtICsKLQkJCQkJCWVycl9kZXZp
Y2U7Ci0JCQkJaWYgKG9mZnNldCA8IGRlbmFsaS0+bXRkLndyaXRlc2l6ZSkgeworCQkJCSAqIHNl
Y3RvciBudW1iZXIgKiBzZWN0b3Igc2l6ZSArIG9mZnNldCBpbgorCQkJCSAqIHNlY3RvciArIGVy
cl9kZXZpY2UKKwkJCQkgKiBJZiBlcnJfYnl0ZSBpcyBsYXJnZXIgdGhhbiBFQ0NfU0VDVE9SX1NJ
WkUsCisJCQkJICogbWVhbnMgZXJyb3IgaGFwcGVuZCBpbiBPT0IsIHNvIHdlIGlnbm9yZQorCQkJ
CSAqIGl0LiBJdCdzIG5vIG5lZWQgZm9yIHVzIHRvIGNvcnJlY3QgaXQKKwkJCQkgKiAqLworCQkJ
CWlmIChlcnJfYnl0ZSA8IEVDQ19TRUNUT1JfU0laRSkgeworCQkJCQlpbnQgb2Zmc2V0OworCQkJ
CQlvZmZzZXQgPSAoZXJyX3NlY3RvciAqCisJCQkJCQkJRUNDX1NFQ1RPUl9TSVpFICsKKwkJCQkJ
CQllcnJfYnl0ZSkgKgorCQkJCQkJCWRlbmFsaS0+ZGV2bnVtICsKKwkJCQkJCQllcnJfZGV2aWNl
OwogCQkJCQkvKiBjb3JyZWN0IHRoZSBFQ0MgZXJyb3IgKi8KIAkJCQkJYnVmW29mZnNldF0gXj0g
ZXJyX2NvcnJlY3Rpb25fdmFsdWU7CiAJCQkJCWRlbmFsaS0+bXRkLmVjY19zdGF0cy5jb3JyZWN0
ZWQrKzsKQEAgLTE2MDQsNyArMTYxMCw3IEBAIHN0YXRpYyBpbnQgZGVuYWxpX3JlYWRfcGFnZShz
dHJ1Y3QgbXRkX2luZm8gKm10ZCwgc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwKIAogCW1lbWNweShi
dWYsIGRlbmFsaS0+YnVmLmJ1ZiwgbXRkLT53cml0ZXNpemUpOwogCi0JY2hlY2tfZXJhc2VkX3Bh
Z2UgPSBoYW5kbGVfZWNjKGRlbmFsaSwgYnVmLCBjaGlwLT5vb2JfcG9pLCBpcnFfc3RhdHVzKTsK
KwljaGVja19lcmFzZWRfcGFnZSA9IGhhbmRsZV9lY2MoZGVuYWxpLCBidWYsIGlycV9zdGF0dXMp
OwogCWRlbmFsaV9lbmFibGVfZG1hKGRlbmFsaSwgZmFsc2UpOwogCiAJaWYgKGNoZWNrX2VyYXNl
ZF9wYWdlKSB7Ci0tIAoxLjYuNi4xCgo=

--_002_5D8008F58939784290FAB48F549751981D09B718B6shsmsx502ccrc_--


From chuanxiao.dong at intel.com  Mon Jun 21 06:34:30 2010
From: chuanxiao.dong at intel.com (Chuanxiao Dong)
Date: Mon, 21 Jun 2010 18:34:30 +0800
Subject: [PATCH 3/5] [MTD/denali] enabled multi connected NAND feature
Message-ID: <mailman.70.1278936651.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Chuanxiao Dong <chuanxiao.dong at intel.com>
---
 drivers/mtd/nand/denali.c |   28 +++++++++++++++++++++++++---
 drivers/mtd/nand/denali.h |    2 ++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index fbdd9f0..57818eb 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1415,8 +1415,9 @@ static bool handle_ecc(struct denali_nand_info *denal=
i, uint8_t *buf,
 				   sector number * sector size + offset in
 				   sector
 				 */
-				int offset =3D err_sector * ECC_SECTOR_SIZE +
-								err_byte;
+				int offset =3D (err_sector * ECC_SECTOR_SIZE +
+						err_byte) * denali->devnum +
+						err_device;
 				if (offset < denali->mtd.writesize) {
 					/* correct the ECC error */
 					buf[offset] ^=3D err_correction_value;
@@ -2032,6 +2033,27 @@ static int denali_pci_probe(struct pci_dev *dev, con=
st struct pci_device_id *id)
 		goto failed_nand;
 	}
=20
+	/* support for multi nand
+	 * MTD known nothing about multi nand,
+	 * so we should tell it the real pagesize
+	 * and anything necessery,
+	 * Some NAND chip has a spectial OOB size, so here do
+	 * a recheck */
+	denali->mtd.oobsize =3D ioread32(denali->flash_reg +
+						DEVICE_SPARE_AREA_SIZE);
+	denali->devnum =3D ioread32(denali->flash_reg + DEVICES_CONNECTED);
+	denali->nand.chipsize <<=3D (denali->devnum - 1);
+	denali->nand.page_shift +=3D (denali->devnum - 1);
+	denali->nand.pagemask =3D (denali->nand.chipsize >>
+						denali->nand.page_shift) - 1;
+	denali->nand.bbt_erase_shift +=3D (denali->devnum - 1);
+	denali->nand.phys_erase_shift =3D denali->nand.bbt_erase_shift;
+	denali->nand.chip_shift +=3D (denali->devnum - 1);
+	denali->mtd.writesize <<=3D (denali->devnum - 1);
+	denali->mtd.oobsize <<=3D (denali->devnum - 1);
+	denali->mtd.erasesize <<=3D (denali->devnum - 1);
+	denali->mtd.size =3D denali->nand.numchips * denali->nand.chipsize;
+
 	/* second stage of the NAND scan
 	 * this stage requires information regarding ECC and
 	 * bad block management. */
@@ -2060,7 +2082,7 @@ static int denali_pci_probe(struct pci_dev *dev, cons=
t struct pci_device_id *id)
 	denali->nand.ecc.hwctl =3D denali_ecc_hwctl;
=20
 	/* override the default read operations */
-	denali->nand.ecc.size =3D denali->mtd.writesize;
+	denali->nand.ecc.size =3D denali->mtd.writesize * denali->devnum;
 	denali->nand.ecc.read_page =3D denali_read_page;
 	denali->nand.ecc.read_page_raw =3D denali_read_page_raw;
 	denali->nand.ecc.write_page =3D denali_write_page;
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index fc6be39..2bee4cb 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -802,6 +802,8 @@ struct denali_nand_info {
 	uint32_t irq_status;
 	int irq_debug_array[32];
 	int idx;
+
+	uint32_t devnum;	/* represent how many nands connected */
 };
=20
 #endif /*_LLD_NAND_*/
--=20
1.6.6.1


--_002_5D8008F58939784290FAB48F549751981D09B718B5shsmsx502ccrc_
Content-Type: application/octet-stream;
	name="0003-MTD-denali-enabled-multi-connected-NAND-feature.patch"
Content-Description: 0003-MTD-denali-enabled-multi-connected-NAND-feature.patch
Content-Disposition: attachment;
	filename="0003-MTD-denali-enabled-multi-connected-NAND-feature.patch";
	size=3098; creation-date="Mon, 21 Jun 2010 18:56:23 GMT";
	modification-date="Mon, 21 Jun 2010 18:56:23 GMT"
Content-Transfer-Encoding: base64

[encoded data, 4158 characters]
QU5EXyovCi0tIAoxLjYuNi4xCgo=

--_002_5D8008F58939784290FAB48F549751981D09B718B5shsmsx502ccrc_--


From chuanxiao.dong at intel.com  Mon Jun 21 06:51:19 2010
From: chuanxiao.dong at intel.com (Chuanxiao Dong)
Date: Mon, 21 Jun 2010 18:51:19 +0800
Subject: [PATCH 5/5] [MTD/denali] remove set_ecc_config
 	This function only need to set ECC_CORRECTION reg
 	so remove it and set this reg in probe function.
 	For denali nand controller only support 15bits and
 	8bits ecc correction on MRST, here use 15bits ecc
 	correction for MLC NAND and 8bits ecc correction for
 	SLC NAND.
Message-ID: <mailman.71.1278936653.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Chuanxiao Dong <chuanxiao.dong at intel.com>
---
 drivers/mtd/nand/denali.c |   44 ++---------------------------------------=
---
 1 files changed, 2 insertions(+), 42 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 1555921..d143b0b 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -354,46 +354,6 @@ static void nand_onfi_timing_set(struct denali_nand_in=
fo *denali,
 	denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT);
 }
=20
-/* configures the initial ECC settings for the controller */
-static void set_ecc_config(struct denali_nand_info *denali)
-{
-#if SUPPORT_8BITECC
-	if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) < 4096) ||
-		(ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) <=3D 128))
-		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
-
-	if ((ioread32(denali->flash_reg + ECC_CORRECTION) &
-				ECC_CORRECTION__VALUE) =3D=3D 1) {
-		denali->dev_info.wECCBytesPerSector =3D 4;
-		denali->dev_info.wECCBytesPerSector *=3D
-			denali->dev_info.wDevicesConnected;
-		denali->dev_info.wNumPageSpareFlag =3D
-			denali->dev_info.wPageSpareSize -
-			denali->dev_info.wPageDataSize /
-			(ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) *
-			denali->dev_info.wECCBytesPerSector
-			- denali->dev_info.wSpareSkipBytes;
-	} else {
-		denali->dev_info.wECCBytesPerSector =3D
-			(ioread32(denali->flash_reg + ECC_CORRECTION) &
-			ECC_CORRECTION__VALUE) * 13 / 8;
-		if ((denali->dev_info.wECCBytesPerSector) % 2 =3D=3D 0)
-			denali->dev_info.wECCBytesPerSector +=3D 2;
-		else
-			denali->dev_info.wECCBytesPerSector +=3D 1;
-
-		denali->dev_info.wECCBytesPerSector *=3D
-			denali->dev_info.wDevicesConnected;
-		denali->dev_info.wNumPageSpareFlag =3D
-			denali->dev_info.wPageSpareSize -
-			denali->dev_info.wPageDataSize /
-			(ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) *
-			denali->dev_info.wECCBytesPerSector
-			- denali->dev_info.wSpareSkipBytes;
-	}
-}
-
 /* queries the NAND device to see what ONFI modes it supports. */
 static uint16_t get_onfi_nand_para(struct denali_nand_info *denali)
 {
@@ -900,8 +860,6 @@ static uint16_t denali_nand_timing_set(struct denali_na=
nd_info *denali)
 	denali->dev_info.nBitsInBlockDataSize =3D
 		ilog2(denali->dev_info.wBlockDataSize);
=20
-	set_ecc_config(denali);
-
 	no_of_planes =3D ioread32(denali->flash_reg + NUMBER_OF_PLANES) &
 		NUMBER_OF_PLANES__VALUE;
=20
@@ -2075,9 +2033,11 @@ static int denali_pci_probe(struct pci_dev *dev, con=
st struct pci_device_id *id)
 	if (denali->dev_info.MLCDevice) {
 		denali->nand.ecc.layout =3D &nand_oob_mlc_14bit;
 		denali->nand.ecc.bytes =3D ECC_BYTES_MLC;
+		denali_write32(15, denali->flash_reg + ECC_CORRECTION);
 	} else { /* SLC */
 		denali->nand.ecc.layout =3D &nand_oob_slc;
 		denali->nand.ecc.bytes =3D ECC_BYTES_SLC;
+		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
 	}
=20
 	/* These functions are required by the NAND core framework, otherwise,
--=20
1.6.6.1


--_002_5D8008F58939784290FAB48F549751981D09B718B7shsmsx502ccrc_
Content-Type: application/octet-stream;
	name="0005-MTD-denali-remove-set_ecc_config.patch"
Content-Description: 0005-MTD-denali-remove-set_ecc_config.patch
Content-Disposition: attachment;
	filename="0005-MTD-denali-remove-set_ecc_config.patch"; size=3545;
	creation-date="Mon, 21 Jun 2010 18:56:23 GMT";
	modification-date="Mon, 21 Jun 2010 19:11:43 GMT"
Content-Transfer-Encoding: base64

[encoded data, 4774 characters]
MS42LjYuMQ0KDQo=

--_002_5D8008F58939784290FAB48F549751981D09B718B7shsmsx502ccrc_--


From bogus@does.not.exist.com  Sun Jun  6 12:36:48 2010
From: bogus@does.not.exist.com ()
Date: Sun, 06 Jun 2010 16:36:48 -0000
Subject: No subject
Message-ID: <mailman.75.1279191728.27306.linux-mtd@lists.infradead.org>

+       timeo =3D jiffies + usecs_to_jiffies(100);
+       do {
+               ecc_state =3D (davinci_nand_readl(info,
+                               NANDFSR_OFFSET) >> 8) & 0x0f;
+               cpu_relax();
+       } while ((ecc_state < 4) && time_before(jiffies, timeo));
+       spin_unlock_irqrestore(&ecc_spin_lock, flags);

To something like:

+       timeo =3D 0;
+       do {
+               ecc_state =3D (davinci_nand_readl(info,
+                               NANDFSR_OFFSET) >> 8) & 0x0f;
+               if (!timeo)
+                       timeo =3D jiffies + usecs_to_jiffies(100);
+               cpu_relax();
+       } while ((ecc_state < 4) && time_before(jiffies, timeo));

Sorry if my mailer has messed up the formatting. Hopefuly readable.

--
Jon Povey
jon.povey at racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 274=
3719 .
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Buc=
ks, MK18 1TB .

The information contained in this electronic mail transmission is intended =
by Racelogic Ltd for the use of the named individual or entity to which it =
is directed and may contain information that is confidential or privileged.=
 If you have received this electronic mail transmission in error, please de=
lete it from your system without copying or forwarding it, and notify the s=
ender of the error by reply email so that the sender's address records can =
be corrected. The views expressed by the sender of this communication do no=
t necessarily represent those of Racelogic Ltd. Please note that Racelogic =
reserves the right to monitor e-mail communications passing through its net=
work




From leiwen at marvell.com  Tue Jun 22 08:19:35 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 20:19:35 +0800
Subject: [PATCH 02/29] pxa3xx_nand: fix compile warning
Message-ID: <mailman.96.1280296594.27306.linux-mtd@lists.infradead.org>

The compile output as below:
WARNING: modpost: Found 1 section mismatch(es).

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 3ffcbcd..52cec28 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1069,7 +1069,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->chip_delay = 25;
 }

-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 08:20:16 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 20:20:16 +0800
Subject: [PATCH 03/29] pxa3xx_nand: introduce default timing to reduce
Message-ID: <mailman.97.1280296597.27306.linux-mtd@lists.infradead.org>

read id times

We certainly don't need to send read id command times by times, since
we already know what the id is after the first read id...

So create a default timing which could ensure it would successfully read
id out all supported chip. Then follow the build-in table to reconfigure
the timing.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   56 ++++++++++++++++++---------------------
 1 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 52cec28..b605147 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -190,15 +190,18 @@ static struct pxa3xx_nand_cmdset default_cmdset = {
 };

 static struct pxa3xx_nand_timing __devinitdata timing[] = {
-	{ 10,  0, 20, 40, 30, 40, 11123, 110, 10, },
-	{ 10, 25, 15, 25, 15, 30, 25000,  60, 10, },
-	{ 10, 35, 15, 25, 15, 25, 25000,  60, 10, },
+	{ 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
+	{ 10,  0, 20,  40, 30,  40, 11123, 110, 10, },
+	{ 10, 25, 15,  25, 15,  30, 25000,  60, 10, },
+	{ 10, 35, 15,  25, 15,  25, 25000,  60, 10, },
 };

-#define NAND_SETTING_SAMSUNG     &default_cmdset, &timing[0]
-#define NAND_SETTING_MICRON      &default_cmdset, &timing[1]
-#define NAND_SETTING_ST          &default_cmdset, &timing[2]
+#define NAND_SETTING_DEFAULT     &default_cmdset, &timing[0]
+#define NAND_SETTING_SAMSUNG     &default_cmdset, &timing[1]
+#define NAND_SETTING_MICRON      &default_cmdset, &timing[2]
+#define NAND_SETTING_ST          &default_cmdset, &timing[3]
 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
+	{      0,   0, 2048,  8,  8,    0, NAND_SETTING_DEFAULT, },
 	{ 0x46ec,  32,  512, 16, 16, 4096, NAND_SETTING_SAMSUNG, },
 	{ 0xdaec,  64, 2048,  8,  8, 2048, NAND_SETTING_SAMSUNG, },
 	{ 0xd7ec, 128, 4096,  8,  8, 8192, NAND_SETTING_SAMSUNG, },
@@ -948,36 +951,29 @@ static int pxa3xx_nand_detect_flash(struct
pxa3xx_nand_info *info,
 		if (pxa3xx_nand_detect_config(info) == 0)
 			return 0;

-	for (i = 0; i<pdata->num_flash; ++i) {
-		f = pdata->flash + i;
-
-		if (pxa3xx_nand_config_flash(info, f))
-			continue;
-
-		if (__readid(info, &id))
-			continue;
-
-		if (id == f->chip_id)
-			return 0;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
-
-		f = &builtin_flash_types[i];
-
-		if (pxa3xx_nand_config_flash(info, f))
-			continue;
-
-		if (__readid(info, &id))
-			continue;
-
-		if (id == f->chip_id)
+	/* we use default timing to detect id */
+	f = &builtin_flash_types[0];
+	pxa3xx_nand_config_flash(info, f);
+	if (__readid(info, &id))
+		goto fail_detect;
+
+	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
+		/* we first choose the flash definition from platfrom */
+		if (i < pdata->num_flash)
+			f = pdata->flash + i;
+		else
+			f = &builtin_flash_types[i - pdata->num_flash + 1];
+		if (f->chip_id == id) {
+			dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
+			pxa3xx_nand_config_flash(info, f);
 			return 0;
+		}
 	}

 	dev_warn(&info->pdev->dev,
 		 "failed to detect configured nand flash; found %04x instead of\n",
 		 id);
+fail_detect:
 	return -ENODEV;
 }

-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 08:28:19 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 20:28:19 +0800
Subject: [PATCH 04/29] pxa3xx_nand: remove the flash info in driver structure
Message-ID: <mailman.99.1280296612.27306.linux-mtd@lists.infradead.org>

After probe, all info already transfer to driver structure.
There is no need to keep the original flash info.
So that we could safely free the flash info in memory, which may grows
larger when more flash is suported.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  116 +++++++++++++++-------------------------
 1 files changed, 44 insertions(+), 72 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index b605147..50e08db 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -117,7 +117,7 @@ struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;

 	struct platform_device	 *pdev;
-	const struct pxa3xx_nand_flash *flash_info;
+	struct pxa3xx_nand_cmdset *cmdset;

 	struct clk		*clk;
 	void __iomem		*mmio_base;
@@ -131,6 +131,7 @@ struct pxa3xx_nand_info {
 	int			drcmr_cmd;

 	unsigned char		*data_buff;
+	unsigned char		*oob_buff;
 	dma_addr_t 		data_buff_phys;
 	size_t			data_buff_size;
 	int 			data_dma_ch;
@@ -149,7 +150,8 @@ struct pxa3xx_nand_info {
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */

-	size_t			data_size;	/* data size in FIFO */
+	unsigned int		page_size;	/* page size of attached chip */
+	unsigned int		data_size;	/* data size in FIFO */
 	int 			retcode;
 	struct completion 	cmd_complete;

@@ -158,6 +160,10 @@ struct pxa3xx_nand_info {
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;

+	/* timing calcuted from setting */
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
+
 	/* calculated from pxa3xx_nand_flash data */
 	size_t		oob_size;
 	size_t		read_id_bytes;
@@ -174,8 +180,6 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data
transfering to/from NAND HW");
  * Default NAND flash controller configuration setup by the
  * bootloader. This configuration is used only when pdata->keep_config is set
  */
-static struct pxa3xx_nand_timing default_timing;
-static struct pxa3xx_nand_flash default_flash;
 static struct pxa3xx_nand_cmdset default_cmdset = {
 	.read1		= 0x3000,
 	.read2		= 0x0050,
@@ -223,23 +227,9 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 #define NDTR1_tWHR(c)	(min((c), 15) << 4)
 #define NDTR1_tAR(c)	(min((c), 15) << 0)

-#define tCH_NDTR0(r)	(((r) >> 19) & 0x7)
-#define tCS_NDTR0(r)	(((r) >> 16) & 0x7)
-#define tWH_NDTR0(r)	(((r) >> 11) & 0x7)
-#define tWP_NDTR0(r)	(((r) >> 8) & 0x7)
-#define tRH_NDTR0(r)	(((r) >> 3) & 0x7)
-#define tRP_NDTR0(r)	(((r) >> 0) & 0x7)
-
-#define tR_NDTR1(r)	(((r) >> 16) & 0xffff)
-#define tWHR_NDTR1(r)	(((r) >> 4) & 0xf)
-#define tAR_NDTR1(r)	(((r) >> 0) & 0xf)
-
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)(((ns) * (clk / 1000000) / 1000) - 1)

-/* convert nand flash controller clock cycles to nano-seconds */
-#define cycle2ns(c, clk)	((((c) + 1) * 1000000 + clk / 500) / (clk / 1000))
-
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
 {
@@ -257,6 +247,8 @@ static void pxa3xx_nand_set_timing(struct
pxa3xx_nand_info *info,
 		NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
 		NDTR1_tAR(ns2cycle(t->tAR, nand_clk));

+	info->ndtr0cs0 = ndtr0;
+	info->ndtr1cs0 = ndtr1;
 	nand_writel(info, NDTR0CS0, ndtr0);
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
@@ -280,23 +272,24 @@ static int wait_for_event(struct
pxa3xx_nand_info *info, uint32_t event)
 	return -ETIMEDOUT;
 }

-static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
-			uint16_t cmd, int column, int page_addr)
+static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-	const struct pxa3xx_nand_flash *f = info->flash_info;
-	const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
-
 	/* calculate data size */
-	switch (f->page_size) {
+	switch (info->page_size) {
 	case 2048:
 		info->data_size = (info->use_ecc) ? 2088 : 2112;
 		break;
 	case 512:
 		info->data_size = (info->use_ecc) ? 520 : 528;
 		break;
-	default:
-		return -EINVAL;
 	}
+}
+
+static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
+		uint16_t cmd, int column, int page_addr)
+{
+	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
+	pxa3xx_set_datasize(info);

 	/* generate values for NDCBx registers */
 	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
@@ -335,7 +328,7 @@ static int prepare_erase_cmd(struct pxa3xx_nand_info *info,

 static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
 {
-	const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
+	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;

 	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
 	info->ndcb1 = 0;
@@ -421,6 +414,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 	case STATE_PIO_READING:
 		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
 				DIV_ROUND_UP(info->data_size, 4));
+
 		break;
 	default:
 		printk(KERN_ERR "%s: invalid state %d\n", __func__,
@@ -572,8 +566,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 				int column, int page_addr)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	const struct pxa3xx_nand_flash *flash_info = info->flash_info;
-	const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
+	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
 	int ret;

 	info->use_dma = (use_dma) ? 1 : 0;
@@ -797,8 +790,7 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,

 static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
 {
-	const struct pxa3xx_nand_flash *f = info->flash_info;
-	const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
+	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
 	uint32_t ndcr;
 	uint8_t  id_buff[8];

@@ -840,6 +832,9 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 		return -EINVAL;

 	/* calculate flash information */
+	info->cmdset = f->cmdset;
+	info->page_size = f->page_size;
+	info->oob_buff = info->data_buff + f->page_size;
 	info->oob_size = (f->page_size == 2048) ? 64 : 16;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

@@ -864,44 +859,20 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	info->reg_ndcr = ndcr;

 	pxa3xx_nand_set_timing(info, f->timing);
-	info->flash_info = f;
 	return 0;
 }

-static void pxa3xx_nand_detect_timing(struct pxa3xx_nand_info *info,
-				      struct pxa3xx_nand_timing *t)
-{
-	unsigned long nand_clk = clk_get_rate(info->clk);
-	uint32_t ndtr0 = nand_readl(info, NDTR0CS0);
-	uint32_t ndtr1 = nand_readl(info, NDTR1CS0);
-
-	t->tCH = cycle2ns(tCH_NDTR0(ndtr0), nand_clk);
-	t->tCS = cycle2ns(tCS_NDTR0(ndtr0), nand_clk);
-	t->tWH = cycle2ns(tWH_NDTR0(ndtr0), nand_clk);
-	t->tWP = cycle2ns(tWP_NDTR0(ndtr0), nand_clk);
-	t->tRH = cycle2ns(tRH_NDTR0(ndtr0), nand_clk);
-	t->tRP = cycle2ns(tRP_NDTR0(ndtr0), nand_clk);
-
-	t->tR = cycle2ns(tR_NDTR1(ndtr1), nand_clk);
-	t->tWHR = cycle2ns(tWHR_NDTR1(ndtr1), nand_clk);
-	t->tAR = cycle2ns(tAR_NDTR1(ndtr1), nand_clk);
-}
-
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
 	uint32_t ndcr = nand_readl(info, NDCR);
 	struct nand_flash_dev *type = NULL;
-	uint32_t id = -1;
+	uint32_t id = -1, page_per_block, num_blocks;
 	int i;

-	default_flash.page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
-	default_flash.page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8;
-	default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8;
-
+	page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
+	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
 	/* set info fields needed to __readid */
-	info->flash_info = &default_flash;
-	info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2;
+	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;

 	if (__readid(info, &id))
@@ -920,22 +891,22 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
 		return -ENODEV;

 	/* fill the missing flash information */
-	i = __ffs(default_flash.page_per_block * default_flash.page_size);
-	default_flash.num_blocks = type->chipsize << (20 - i);
+	i = __ffs(page_per_block * info->page_size);
+	num_blocks = type->chipsize << (20 - i);

-	info->oob_size = (default_flash.page_size == 2048) ? 64 : 16;
+	info->oob_size = (info->page_size == 2048) ? 64 : 16;

 	/* calculate addressing information */
-	info->col_addr_cycles = (default_flash.page_size == 2048) ? 2 : 1;
+	info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;

-	if (default_flash.num_blocks * default_flash.page_per_block > 65536)
+	if (num_blocks * page_per_block > 65536)
 		info->row_addr_cycles = 3;
 	else
 		info->row_addr_cycles = 2;

-	pxa3xx_nand_detect_timing(info, &default_timing);
-	default_flash.timing = &default_timing;
-	default_flash.cmdset = &default_cmdset;
+	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	info->cmdset = &default_cmdset;

 	return 0;
 }
@@ -1036,10 +1007,9 @@ static struct nand_ecclayout hw_largepage_ecclayout = {
 static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 				 struct pxa3xx_nand_info *info)
 {
-	const struct pxa3xx_nand_flash *f = info->flash_info;
 	struct nand_chip *this = &info->nand_chip;

-	this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
+	this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;

 	this->waitfunc		= pxa3xx_nand_waitfunc;
 	this->select_chip	= pxa3xx_nand_select_chip;
@@ -1055,9 +1025,9 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
 	this->ecc.calculate	= pxa3xx_nand_ecc_calculate;
 	this->ecc.correct	= pxa3xx_nand_ecc_correct;
-	this->ecc.size		= f->page_size;
+	this->ecc.size		= info->page_size;

-	if (f->page_size == 2048)
+	if (info->page_size == 2048)
 		this->ecc.layout = &hw_largepage_ecclayout;
 	else
 		this->ecc.layout = &hw_smallpage_ecclayout;
@@ -1264,9 +1234,11 @@ static int pxa3xx_nand_resume(struct
platform_device *pdev)
 	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
 	struct pxa3xx_nand_info *info = mtd->priv;

+	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
 	clk_enable(info->clk);

-	return pxa3xx_nand_config_flash(info, info->flash_info);
+	return 0;
 }
 #else
 #define pxa3xx_nand_suspend	NULL
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:01:04 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:01:04 +0800
Subject: [PATCH 05/29] pxa3xx_nand: set oob length in the runtime
Message-ID: <mailman.102.1280296640.27306.linux-mtd@lists.infradead.org>

For different command need different oob requirement, set the proper
oob length by different cmd.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   25 ++++++++++++++++++-------
 1 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 50e08db..26c0286 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -274,13 +274,20 @@ static int wait_for_event(struct
pxa3xx_nand_info *info, uint32_t event)

 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-	/* calculate data size */
+	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+
+	info->data_size = info->page_size;
+	if (!oob_enable) {
+		info->oob_size = 0;
+		return;
+	}
+
 	switch (info->page_size) {
 	case 2048:
-		info->data_size = (info->use_ecc) ? 2088 : 2112;
+		info->oob_size = (info->use_ecc) ? 40 : 64;
 		break;
 	case 512:
-		info->data_size = (info->use_ecc) ? 520 : 528;
+		info->oob_size = (info->use_ecc) ? 8 : 16;
 		break;
 	}
 }
@@ -334,6 +341,7 @@ static int prepare_other_cmd(struct
pxa3xx_nand_info *info, uint16_t cmd)
 	info->ndcb1 = 0;
 	info->ndcb2 = 0;

+	info->oob_size = 0;
 	if (cmd == cmdset->read_id) {
 		info->ndcb0 |= NDCB0_CMD_TYPE(3);
 		info->data_size = 8;
@@ -402,6 +410,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 	case STATE_PIO_WRITING:
 		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
 				DIV_ROUND_UP(info->data_size, 4));
+		if (info->oob_size > 0)
+			__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
+					DIV_ROUND_UP(info->oob_size, 4));

 		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);

@@ -414,6 +425,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 	case STATE_PIO_READING:
 		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
 				DIV_ROUND_UP(info->data_size, 4));
+		if (info->oob_size > 0)
+			__raw_readsl(info->mmio_base + NDDB, info->oob_buff,
+					DIV_ROUND_UP(info->oob_size, 4));

 		break;
 	default:
@@ -429,7 +443,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
 {
 	struct pxa_dma_desc *desc = info->data_desc;
-	int dma_len = ALIGN(info->data_size, 32);
+	int dma_len = ALIGN(info->data_size + info->oob_size, 32);

 	desc->ddadr = DDADR_STOP;
 	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
@@ -835,7 +849,6 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	info->cmdset = f->cmdset;
 	info->page_size = f->page_size;
 	info->oob_buff = info->data_buff + f->page_size;
-	info->oob_size = (f->page_size == 2048) ? 64 : 16;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

 	/* calculate addressing information */
@@ -894,8 +907,6 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
 	i = __ffs(page_per_block * info->page_size);
 	num_blocks = type->chipsize << (20 - i);

-	info->oob_size = (info->page_size == 2048) ? 64 : 16;
-
 	/* calculate addressing information */
 	info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;

-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:01:27 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:01:27 +0800
Subject: [PATCH 06/29] pxa3xx_nand: make scan procedure more clear
Message-ID: <mailman.103.1280296642.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   88 ++++++++++++++++++++++-----------------
 1 files changed, 50 insertions(+), 38 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 26c0286..8d030ec 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -126,6 +126,7 @@ struct pxa3xx_nand_info {
 	unsigned int 		buf_start;
 	unsigned int		buf_count;

+	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
@@ -1046,21 +1047,13 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->chip_delay = 25;
 }

-static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
+static int alloc_nand_resource(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_platform_data *pdata;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct pxa3xx_nand_info *info;
-	struct nand_chip *this;
 	struct mtd_info *mtd;
 	struct resource *r;
-	int ret = 0, irq;
-
-	pdata = pdev->dev.platform_data;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -ENODEV;
-	}
+	int ret, irq;

 	mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
 			GFP_KERNEL);
@@ -1072,8 +1065,8 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 	info = (struct pxa3xx_nand_info *)(&mtd[1]);
 	info->pdev = pdev;

-	this = &info->nand_chip;
 	mtd->priv = info;
+	info->mtd = mtd;
 	mtd->owner = THIS_MODULE;

 	info->clk = clk_get(&pdev->dev, NULL);
@@ -1151,27 +1144,9 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 	}

 	pxa3xx_nand_init_mtd(mtd, info);
+	platform_set_drvdata(pdev, info);

-	platform_set_drvdata(pdev, mtd);
-
-	if (nand_scan(mtd, 1)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
-		ret = -ENXIO;
-		goto fail_free_irq;
-	}
-
-	if (mtd_has_cmdlinepart()) {
-		static const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
-
-		nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
-
-		if (nr_parts)
-			return add_mtd_partitions(mtd, parts, nr_parts);
-	}
-
-	return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+	return 0;

 fail_free_irq:
 	free_irq(irq, info);
@@ -1196,8 +1171,8 @@ fail_free_mtd:

 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
-	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
 	struct resource *r;
 	int irq;

@@ -1226,11 +1201,48 @@ static int pxa3xx_nand_remove(struct
platform_device *pdev)
 	return 0;
 }

+static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
+{
+	struct pxa3xx_nand_platform_data *pdata;
+	struct pxa3xx_nand_info *info;
+	int ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -ENODEV;
+	}
+
+	ret = alloc_nand_resource(pdev);
+	if (ret)
+		return ret;
+
+	info = platform_get_drvdata(pdev);
+	if (nand_scan(info->mtd, 1)) {
+		dev_err(&pdev->dev, "failed to scan nand\n");
+		pxa3xx_nand_remove(pdev);
+		return -ENODEV;
+	}
+
+	if (mtd_has_cmdlinepart()) {
+		static const char *probes[] = { "cmdlinepart", NULL };
+		struct mtd_partition *parts;
+		int nr_parts;
+
+		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+
+		if (nr_parts)
+			return add_mtd_partitions(info->mtd, parts, nr_parts);
+	}
+
+	return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
+}
+
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev,
pm_message_t state)
 {
-	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;

 	if (info->state != STATE_READY) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
@@ -1242,8 +1254,8 @@ static int pxa3xx_nand_suspend(struct
platform_device *pdev, pm_message_t state)

 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
-	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;

 	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
 	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:19:40 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:19:40 +0800
Subject: [PATCH 07/29] pxa3xx_nand: rework irq logic
Message-ID: <mailman.106.1280296673.27306.linux-mtd@lists.infradead.org>

Enable all irq when we start the nand controller, and
put all the transaction logic in the pxa3xx_nand_irq.

By doing this way, we could dramatically increase the
performance by avoid unnecessary delay.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  308 ++++++++++++++++++----------------------
 1 files changed, 140 insertions(+), 168 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 8d030ec..0d97463 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -27,6 +27,7 @@
 #include <plat/pxa3xx_nand.h>

 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
+#define NAND_STOP_DELAY		(2 * HZ/50)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -49,6 +50,7 @@
 #define NDCR_DWIDTH_M		(0x1 << 26)
 #define NDCR_PAGE_SZ		(0x1 << 24)
 #define NDCR_NCSX		(0x1 << 23)
+#define NDCR_STOP_ON_UNCOR	(0x1 << 22)
 #define NDCR_ND_MODE		(0x3 << 21)
 #define NDCR_NAND_MODE   	(0x0)
 #define NDCR_CLR_PG_CNT		(0x1 << 20)
@@ -59,9 +61,11 @@
 #define NDCR_RA_START		(0x1 << 15)
 #define NDCR_PG_PER_BLK		(0x1 << 14)
 #define NDCR_ND_ARB_EN		(0x1 << 12)
+#define NDCR_INT_MASK           (0xFFF)

 #define NDSR_MASK		(0xfff)
-#define NDSR_RDY		(0x1 << 11)
+#define NDSR_RDY                (0x1 << 12)
+#define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED		(0x1 << 10)
 #define NDSR_CS1_PAGED		(0x1 << 9)
 #define NDSR_CS0_CMDD		(0x1 << 8)
@@ -104,13 +108,14 @@ enum {
 };

 enum {
-	STATE_READY	= 0,
-	STATE_CMD_HANDLE,
-	STATE_DMA_READING,
-	STATE_DMA_WRITING,
-	STATE_DMA_DONE,
-	STATE_PIO_READING,
-	STATE_PIO_WRITING,
+	STATE_CMD_WAIT_DONE	= 1,
+	STATE_DATA_PROCESSING	= (1 << 1),
+	STATE_DATA_DONE		= (1 << 2),
+	STATE_PAGE_DONE		= (1 << 3),
+	STATE_CMD_DONE		= (1 << 4),
+	STATE_READY		= (1 << 5),
+	STATE_CMD_PREPARED	= (1 << 6),
+	STATE_IS_WRITE		= (1 << 7),
 };

 struct pxa3xx_nand_info {
@@ -293,7 +298,47 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 	}
 }

-static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
+/**
+ * NOTE: it is a must to set ND_RUN firstly, then write
+ * command buffer, otherwise, it does not work.
+ * We enable all the interrupt at the same time, and
+ * let pxa3xx_nand_irq to handle all logic.
+ */
+static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
+{
+	uint32_t ndcr;
+
+	ndcr = info->reg_ndcr;
+	ndcr |= NDCR_ECC_EN;
+	ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
+	ndcr |= NDCR_ND_RUN;
+
+	/* clear status bits and run */
+	nand_writel(info, NDCR, 0);
+	nand_writel(info, NDSR, NDSR_MASK);
+	nand_writel(info, NDCR, ndcr);
+}
+
+static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
+{
+	uint32_t ndcr;
+	int timeout = NAND_STOP_DELAY;
+
+	/* wait RUN bit in NDCR become 0 */
+	do {
+		/* clear status bits */
+		nand_writel(info, NDSR, NDSR_MASK);
+		ndcr = nand_readl(info, NDCR);
+		udelay(1);
+	} while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0));
+
+	if (timeout <= 0) {
+		ndcr &= ~(NDCR_ND_RUN);
+		nand_writel(info, NDCR, ndcr);
+	}
+}
+
+static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
 		uint16_t cmd, int column, int page_addr)
 {
 	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
@@ -320,21 +365,18 @@ static int prepare_read_prog_cmd(struct
pxa3xx_nand_info *info,

 	if (cmd == cmdset->program)
 		info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
-
-	return 0;
 }

-static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
+static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
 			uint16_t cmd, int page_addr)
 {
 	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
 	info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
 	info->ndcb1 = page_addr;
 	info->ndcb2 = 0;
-	return 0;
 }

-static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
+static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
 {
 	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;

@@ -352,10 +394,7 @@ static int prepare_other_cmd(struct
pxa3xx_nand_info *info, uint16_t cmd)
 	} else if (cmd == cmdset->reset || cmd == cmdset->lock ||
 		   cmd == cmdset->unlock) {
 		info->ndcb0 |= NDCB0_CMD_TYPE(5);
-	} else
-		return -EINVAL;
-
-	return 0;
+	}
 }

 static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
@@ -403,42 +442,23 @@ static int write_cmd(struct pxa3xx_nand_info *info)
 	return 0;
 }

-static int handle_data_pio(struct pxa3xx_nand_info *info)
+static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
-	int ret, timeout = CHIP_DELAY_TIMEOUT;
-
-	switch (info->state) {
-	case STATE_PIO_WRITING:
+	if (info->state & STATE_IS_WRITE) {
 		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
 				DIV_ROUND_UP(info->data_size, 4));
 		if (info->oob_size > 0)
 			__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
 					DIV_ROUND_UP(info->oob_size, 4));

-		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-
-		ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-		if (!ret) {
-			printk(KERN_ERR "program command time out\n");
-			return -1;
-		}
-		break;
-	case STATE_PIO_READING:
+	}
+	else {
 		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
 				DIV_ROUND_UP(info->data_size, 4));
 		if (info->oob_size > 0)
 			__raw_readsl(info->mmio_base + NDDB, info->oob_buff,
 					DIV_ROUND_UP(info->oob_size, 4));
-
-		break;
-	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
-				info->state);
-		return -EINVAL;
 	}
-
-	info->state = STATE_READY;
-	return 0;
 }

 static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
@@ -474,93 +494,59 @@ static void pxa3xx_nand_data_dma_irq(int
channel, void *data)

 	if (dcsr & DCSR_BUSERR) {
 		info->retcode = ERR_DMABUSERR;
-		complete(&info->cmd_complete);
 	}

-	if (info->state == STATE_DMA_WRITING) {
-		info->state = STATE_DMA_DONE;
-		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-	} else {
-		info->state = STATE_READY;
-		complete(&info->cmd_complete);
-	}
+	enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
 }

 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand_info *info = devid;
-	unsigned int status;
+	unsigned int status, is_completed = 0;

 	status = nand_readl(info, NDSR);

-	if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) {
-		if (status & NDSR_DBERR)
-			info->retcode = ERR_DBERR;
-		else if (status & NDSR_SBERR)
-			info->retcode = ERR_SBERR;
-
-		disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
+	if (status & NDSR_DBERR)
+		info->retcode = ERR_DBERR;
+	if (status & NDSR_SBERR)
+		info->retcode = ERR_SBERR;
+	if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {

+		info->state |= STATE_DATA_PROCESSING;
+		/* whether use dma to transfer data */
 		if (info->use_dma) {
-			info->state = STATE_DMA_READING;
+			disable_int(info, NDSR_WRDREQ);
 			start_data_dma(info, 0);
-		} else {
-			info->state = STATE_PIO_READING;
-			complete(&info->cmd_complete);
-		}
-	} else if (status & NDSR_WRDREQ) {
-		disable_int(info, NDSR_WRDREQ);
-		if (info->use_dma) {
-			info->state = STATE_DMA_WRITING;
-			start_data_dma(info, 1);
-		} else {
-			info->state = STATE_PIO_WRITING;
-			complete(&info->cmd_complete);
-		}
-	} else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
-		if (status & NDSR_CS0_BBD)
-			info->retcode = ERR_BBERR;
+			goto NORMAL_IRQ_EXIT;
+		} else
+			handle_data_pio(info);

-		disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-		info->state = STATE_READY;
-		complete(&info->cmd_complete);
+		info->state |= STATE_DATA_DONE;
 	}
-	nand_writel(info, NDSR, status);
-	return IRQ_HANDLED;
-}
-
-static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
-{
-	uint32_t ndcr;
-	int ret, timeout = CHIP_DELAY_TIMEOUT;
-
-	if (write_cmd(info)) {
-		info->retcode = ERR_SENDCMD;
-		goto fail_stop;
+	if (status & NDSR_CS0_CMDD) {
+		info->state |= STATE_CMD_DONE;
+		is_completed = 1;
 	}
-
-	info->state = STATE_CMD_HANDLE;
-
-	enable_int(info, event);
-
-	ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-	if (!ret) {
-		printk(KERN_ERR "command execution timed out\n");
-		info->retcode = ERR_SENDCMD;
-		goto fail_stop;
+	if (status & NDSR_FLASH_RDY)
+		info->state |= STATE_READY;
+	if (status & NDSR_CS0_PAGED)
+		info->state |= STATE_PAGE_DONE;
+
+	if (status & NDSR_WRCMDREQ) {
+		nand_writel(info, NDSR, NDSR_WRCMDREQ);
+		status &= ~NDSR_WRCMDREQ;
+		info->state |= STATE_CMD_WAIT_DONE;
+		nand_writel(info, NDCB0, info->ndcb0);
+		nand_writel(info, NDCB0, info->ndcb1);
+		nand_writel(info, NDCB0, info->ndcb2);
 	}

-	if (info->use_dma == 0 && info->data_size > 0)
-		if (handle_data_pio(info))
-			goto fail_stop;
-
-	return 0;
-
-fail_stop:
-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-	udelay(10);
-	return -ETIMEDOUT;
+	/* clear NDSR to let the controller exit the IRQ */
+	nand_writel(info, NDSR, status);
+	if (is_completed)
+		complete(&info->cmd_complete);
+NORMAL_IRQ_EXIT:
+	return IRQ_HANDLED;
 }

 static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
@@ -582,14 +568,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
 	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	int ret;
+	int ret, exec_cmd = 0;

 	info->use_dma = (use_dma) ? 1 : 0;
 	info->use_ecc = 0;
 	info->data_size = 0;
-	info->state = STATE_READY;
-
-	init_completion(&info->cmd_complete);
+	info->state = 0;

 	switch (command) {
 	case NAND_CMD_READOOB:
@@ -598,14 +582,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		info->buf_start = mtd->writesize + column;
 		memset(info->data_buff, 0xFF, info->buf_count);

-		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
+		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
 		/* We only are OOB, so if the data has error, does not matter */
 		if (info->retcode == ERR_DBERR)
 			info->retcode = ERR_NONE;
+
+		exec_cmd = 1;
 		break;

 	case NAND_CMD_READ0:
@@ -615,11 +597,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		info->buf_count = mtd->writesize + mtd->oobsize;
 		memset(info->data_buff, 0xFF, info->buf_count);

-		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
+		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
 		if (info->retcode == ERR_DBERR) {
 			/* for blank page (all 0xff), HW will calculate its ECC as
 			 * 0, which is different from the ECC information within
@@ -628,6 +606,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 			if (is_buf_blank(info->data_buff, mtd->writesize))
 				info->retcode = ERR_NONE;
 		}
+
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_SEQIN:
 		info->buf_start = column;
@@ -641,17 +621,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 	case NAND_CMD_PAGEPROG:
 		info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;

-		if (prepare_read_prog_cmd(info, cmdset->program,
-				info->seqin_column, info->seqin_page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
+		prepare_read_prog_cmd(info, cmdset->program,
+				info->seqin_column, info->seqin_page_addr);
+		info->state |= STATE_IS_WRITE;
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_ERASE1:
-		if (prepare_erase_cmd(info, cmdset->erase, page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+		prepare_erase_cmd(info, cmdset->erase, page_addr);
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_ERASE2:
 		break;
@@ -662,39 +639,37 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		info->buf_count = (command == NAND_CMD_READID) ?
 				info->read_id_bytes : 1;

-		if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
-				cmdset->read_id : cmdset->read_status))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
+		prepare_other_cmd(info, (command == NAND_CMD_READID) ?
+				cmdset->read_id : cmdset->read_status);
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_RESET:
-		if (prepare_other_cmd(info, cmdset->reset))
-			break;
-
-		ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
-		if (ret == 0) {
-			int timeout = 2;
-			uint32_t ndcr;
-
-			while (timeout--) {
-				if (nand_readl(info, NDSR) & NDSR_RDY)
-					break;
-				msleep(10);
-			}
-
-			ndcr = nand_readl(info, NDCR);
-			nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-		}
+		prepare_other_cmd(info, cmdset->reset);
+		exec_cmd = 1;
 		break;
 	default:
 		printk(KERN_ERR "non-supported command.\n");
 		break;
 	}

-	if (info->retcode == ERR_DBERR) {
-		printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
-		info->retcode = ERR_NONE;
+	if (exec_cmd) {
+		init_completion(&info->cmd_complete);
+		info->state |= STATE_CMD_PREPARED;
+		pxa3xx_nand_start(info);
+
+		ret = wait_for_completion_timeout(&info->cmd_complete,
+				CHIP_DELAY_TIMEOUT);
+		if (!ret) {
+			printk(KERN_ERR "Wait time out!!!\n");
+		}
+		/* Stop State Machine for next command cycle */
+		pxa3xx_nand_stop(info);
+		disable_int(info, NDCR_INT_MASK);
+		info->state &= ~STATE_CMD_PREPARED;
+		if (info->retcode == ERR_DBERR) {
+			printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
+			info->retcode = ERR_NONE;
+		}
 	}
 }

@@ -809,10 +784,7 @@ static int __readid(struct pxa3xx_nand_info
*info, uint32_t *id)
 	uint32_t ndcr;
 	uint8_t  id_buff[8];

-	if (prepare_other_cmd(info, cmdset->read_id)) {
-		printk(KERN_ERR "failed to prepare command\n");
-		return -EINVAL;
-	}
+	prepare_other_cmd(info, cmdset->read_id);

 	/* Send command */
 	if (write_cmd(info))
@@ -889,11 +861,12 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;

-	if (__readid(info, &id))
+	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));
+	if (id == 0)
 		return -ENODEV;

 	/* Lookup the flash id */
-	id = (id >> 8) & 0xff;		/* device id is byte 2 */
 	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
 		if (id == nand_flash_ids[i].id) {
 			type =  &nand_flash_ids[i];
@@ -937,8 +910,8 @@ static int pxa3xx_nand_detect_flash(struct
pxa3xx_nand_info *info,
 	/* we use default timing to detect id */
 	f = &builtin_flash_types[0];
 	pxa3xx_nand_config_flash(info, f);
-	if (__readid(info, &id))
-		goto fail_detect;
+	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));

 	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
 		/* we first choose the flash definition from platfrom */
@@ -956,7 +929,6 @@ static int pxa3xx_nand_detect_flash(struct
pxa3xx_nand_info *info,
 	dev_warn(&info->pdev->dev,
 		 "failed to detect configured nand flash; found %04x instead of\n",
 		 id);
-fail_detect:
 	return -ENODEV;
 }

@@ -1244,7 +1216,7 @@ static int pxa3xx_nand_suspend(struct
platform_device *pdev, pm_message_t state)
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
 	struct mtd_info *mtd = info->mtd;

-	if (info->state != STATE_READY) {
+	if (info->state & STATE_CMD_PREPARED) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
 		return -EAGAIN;
 	}
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:20:47 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:20:47 +0800
Subject: [PATCH 08/29] pxa3xx_nand: discard wait_for_event, write_cmd,
Message-ID: <mailman.107.1280296676.27306.linux-mtd@lists.infradead.org>

__readid function

Since we have rework the irq process, we don't need additional
delay in wait_for_event. Also write_cmd and __readid is also
discarded for the same reason.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   77 +---------------------------------------
 1 files changed, 1 insertions(+), 76 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 0d97463..5dd03ea 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -259,25 +259,6 @@ static void pxa3xx_nand_set_timing(struct
pxa3xx_nand_info *info,
 	nand_writel(info, NDTR1CS0, ndtr1);
 }

-#define WAIT_EVENT_TIMEOUT	10
-
-static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
-{
-	int timeout = WAIT_EVENT_TIMEOUT;
-	uint32_t ndsr;
-
-	while (timeout--) {
-		ndsr = nand_readl(info, NDSR) & NDSR_MASK;
-		if (ndsr & event) {
-			nand_writel(info, NDSR, ndsr);
-			return 0;
-		}
-		udelay(10);
-	}
-
-	return -ETIMEDOUT;
-}
-
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
@@ -413,35 +394,6 @@ static void disable_int(struct pxa3xx_nand_info
*info, uint32_t int_mask)
 	nand_writel(info, NDCR, ndcr | int_mask);
 }

-/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
- * otherwise, it does not work
- */
-static int write_cmd(struct pxa3xx_nand_info *info)
-{
-	uint32_t ndcr;
-
-	/* clear status bits and run */
-	nand_writel(info, NDSR, NDSR_MASK);
-
-	ndcr = info->reg_ndcr;
-
-	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
-	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
-	ndcr |= NDCR_ND_RUN;
-
-	nand_writel(info, NDCR, ndcr);
-
-	if (wait_for_event(info, NDSR_WRCMDREQ)) {
-		printk(KERN_ERR "timed out writing command\n");
-		return -ETIMEDOUT;
-	}
-
-	nand_writel(info, NDCB0, info->ndcb0);
-	nand_writel(info, NDCB0, info->ndcb1);
-	nand_writel(info, NDCB0, info->ndcb2);
-	return 0;
-}
-
 static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
 	if (info->state & STATE_IS_WRITE) {
@@ -778,33 +730,6 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
 	return 0;
 }

-static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
-{
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	uint32_t ndcr;
-	uint8_t  id_buff[8];
-
-	prepare_other_cmd(info, cmdset->read_id);
-
-	/* Send command */
-	if (write_cmd(info))
-		goto fail_timeout;
-
-	/* Wait for CMDDM(command done successfully) */
-	if (wait_for_event(info, NDSR_RDDREQ))
-		goto fail_timeout;
-
-	__raw_readsl(info->mmio_base + NDDB, id_buff, 2);
-	*id = id_buff[0] | (id_buff[1] << 8);
-	return 0;
-
-fail_timeout:
-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-	udelay(10);
-	return -ETIMEDOUT;
-}
-
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 				    const struct pxa3xx_nand_flash *f)
 {
@@ -857,7 +782,7 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)

 	page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	/* set info fields needed to __readid */
+	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;

-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:32:09 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:32:09 +0800
Subject: [PATCH 09/29] pxa3xx_nand: unify prepare command
Message-ID: <mailman.108.1280296678.27306.linux-mtd@lists.infradead.org>

Make the interface simpler which could make both debug
and enhancement easier.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  261 +++++++++++++++++++++-------------------
 1 files changed, 135 insertions(+), 126 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 5dd03ea..e7b54dd 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -28,6 +28,7 @@

 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
 #define NAND_STOP_DELAY		(2 * HZ/50)
+#define PAGE_CHUNK_SIZE		(2048)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -78,6 +79,7 @@
 #define NDSR_RDDREQ		(0x1 << 1)
 #define NDSR_WRCMDREQ		(0x1)

+#define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS		(0x1 << 25)
 #define NDCB0_CSEL		(0x1 << 24)
 #define NDCB0_CMD_TYPE_MASK	(0x7 << 21)
@@ -290,7 +292,7 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 	uint32_t ndcr;

 	ndcr = info->reg_ndcr;
-	ndcr |= NDCR_ECC_EN;
+	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
 	ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
 	ndcr |= NDCR_ND_RUN;

@@ -319,65 +321,6 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
 	}
 }

-static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
-		uint16_t cmd, int column, int page_addr)
-{
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	pxa3xx_set_datasize(info);
-
-	/* generate values for NDCBx registers */
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb1 = 0;
-	info->ndcb2 = 0;
-	info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
-
-	if (info->col_addr_cycles == 2) {
-		/* large block, 2 cycles for column address
-		 * row address starts from 3rd cycle
-		 */
-		info->ndcb1 |= page_addr << 16;
-		if (info->row_addr_cycles == 3)
-			info->ndcb2 = (page_addr >> 16) & 0xff;
-	} else
-		/* small block, 1 cycles for column address
-		 * row address starts from 2nd cycle
-		 */
-		info->ndcb1 = page_addr << 8;
-
-	if (cmd == cmdset->program)
-		info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
-}
-
-static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
-			uint16_t cmd, int page_addr)
-{
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
-	info->ndcb1 = page_addr;
-	info->ndcb2 = 0;
-}
-
-static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
-{
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb1 = 0;
-	info->ndcb2 = 0;
-
-	info->oob_size = 0;
-	if (cmd == cmdset->read_id) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(3);
-		info->data_size = 8;
-	} else if (cmd == cmdset->read_status) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(4);
-		info->data_size = 8;
-	} else if (cmd == cmdset->reset || cmd == cmdset->lock ||
-		   cmd == cmdset->unlock) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(5);
-	}
-}
-
 static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 {
 	uint32_t ndcr;
@@ -515,95 +458,165 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
 	return 1;
 }

-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
-				int column, int page_addr)
+static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+		uint16_t column, int page_addr)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	int ret, exec_cmd = 0;
+	uint16_t cmd;
+	int addr_cycle, exec_cmd, ndcb0;
+	struct mtd_info *mtd = info->mtd;

-	info->use_dma = (use_dma) ? 1 : 0;
-	info->use_ecc = 0;
-	info->data_size = 0;
-	info->state = 0;
+	ndcb0 = 0;
+	addr_cycle = 0;
+	exec_cmd = 1;
+
+	/* reset data and oob column point to handle data */
+	info->buf_start		= 0;
+	info->buf_count		= 0;
+	info->oob_size		= 0;
+	info->use_ecc		= 0;

 	switch (command) {
+	case NAND_CMD_READ0:
+	case NAND_CMD_PAGEPROG:
+		info->use_ecc = 1;
 	case NAND_CMD_READOOB:
-		/* disable HW ECC to get all the OOB data */
-		info->buf_count = mtd->writesize + mtd->oobsize;
-		info->buf_start = mtd->writesize + column;
-		memset(info->data_buff, 0xFF, info->buf_count);
-
-		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
-		/* We only are OOB, so if the data has error, does not matter */
-		if (info->retcode == ERR_DBERR)
-			info->retcode = ERR_NONE;
-
-		exec_cmd = 1;
+		pxa3xx_set_datasize(info);
+		break;
+	case NAND_CMD_SEQIN:
+		exec_cmd = 0;
+		break;
+	default:
+		info->ndcb1 = 0;
+		info->ndcb2 = 0;
 		break;
+	}
+
+	info->ndcb0 = ndcb0;
+	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
+			+ info->col_addr_cycles);

+	switch (command) {
+	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		info->use_ecc = 1;
-		info->retcode = ERR_NONE;
-		info->buf_start = column;
-		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xFF, info->buf_count);
+		cmd  = info->cmdset->read1;
+		if (command == NAND_CMD_READOOB)
+			info->buf_start = mtd->writesize + column;
+		else
+			info->buf_start = column;

-		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
-		if (info->retcode == ERR_DBERR) {
-			/* for blank page (all 0xff), HW will calculate its ECC as
-			 * 0, which is different from the ECC information within
-			 * OOB, ignore such double bit errors
-			 */
-			if (is_buf_blank(info->data_buff, mtd->writesize))
-				info->retcode = ERR_NONE;
-		}
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+					| addr_cycle
+					| (cmd & NDCB0_CMD1_MASK);
+		else
+			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+					| NDCB0_DBC
+					| addr_cycle
+					| cmd;

-		exec_cmd = 1;
-		break;
 	case NAND_CMD_SEQIN:
-		info->buf_start = column;
+		/* small page addr setting */
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+					| (column & 0xFF);
+
+			info->ndcb2 = 0;
+		}
+		else {
+			info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+					| (column & 0xFFFF);
+
+			if (page_addr & 0xFF0000)
+				info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+			else
+				info->ndcb2 = 0;
+		}
+
 		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xff, info->buf_count);
+		memset(info->data_buff, 0xFF, info->buf_count);

-		/* save column/page_addr for next CMD_PAGEPROG */
-		info->seqin_column = column;
-		info->seqin_page_addr = page_addr;
 		break;
+
 	case NAND_CMD_PAGEPROG:
-		info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
+		if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) {
+			exec_cmd = 0;
+			break;
+		}

-		prepare_read_prog_cmd(info, cmdset->program,
-				info->seqin_column, info->seqin_page_addr);
+		cmd = info->cmdset->program;
 		info->state |= STATE_IS_WRITE;
-		exec_cmd = 1;
-		break;
-	case NAND_CMD_ERASE1:
-		prepare_erase_cmd(info, cmdset->erase, page_addr);
-		exec_cmd = 1;
-		break;
-	case NAND_CMD_ERASE2:
+		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+				| NDCB0_AUTO_RS
+				| NDCB0_ST_ROW_EN
+				| NDCB0_DBC
+				| cmd
+				| addr_cycle;
 		break;
+
 	case NAND_CMD_READID:
+		cmd = info->cmdset->read_id;
+		info->buf_count = info->read_id_bytes;
+		info->ndcb0 |= NDCB0_CMD_TYPE(3)
+				| NDCB0_ADDR_CYC(1)
+				| cmd;
+
+		info->data_size = 8;
+		break;
 	case NAND_CMD_STATUS:
-		info->use_dma = 0;	/* force PIO read */
-		info->buf_start = 0;
-		info->buf_count = (command == NAND_CMD_READID) ?
-				info->read_id_bytes : 1;
-
-		prepare_other_cmd(info, (command == NAND_CMD_READID) ?
-				cmdset->read_id : cmdset->read_status);
-		exec_cmd = 1;
+		cmd = info->cmdset->read_status;
+		info->buf_count = 1;
+		info->ndcb0 |= NDCB0_CMD_TYPE(4)
+				| NDCB0_ADDR_CYC(1)
+				| cmd;
+
+		info->data_size = 8;
+		break;
+
+	case NAND_CMD_ERASE1:
+		cmd = info->cmdset->erase;
+		info->ndcb0 |= NDCB0_CMD_TYPE(2)
+				| NDCB0_AUTO_RS
+				| NDCB0_ADDR_CYC(3)
+				| NDCB0_DBC
+				| cmd;
+		info->ndcb1 = page_addr;
+		info->ndcb2 = 0;
+
 		break;
 	case NAND_CMD_RESET:
-		prepare_other_cmd(info, cmdset->reset);
-		exec_cmd = 1;
+		cmd = info->cmdset->reset;
+		info->ndcb0 |= NDCB0_CMD_TYPE(5)
+				| cmd;
+
+		break;
+
+	case NAND_CMD_ERASE2:
+		exec_cmd = 0;
 		break;
+
 	default:
-		printk(KERN_ERR "non-supported command.\n");
+		exec_cmd = 0;
+		printk(KERN_ERR "pxa3xx-nand: non-supported command %x\n", command);
 		break;
 	}

+	return exec_cmd;
+}
+
+static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+		int column, int page_addr)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	int ret, exec_cmd;
+
+	/* if this is a x16 device ,then convert the input
+	 * "byte" address into a "word" address appropriate
+	 * for indexing a word-oriented device
+	 */
+	if (info->reg_ndcr & NDCR_DWIDTH_M)
+		column /= 2;
+
+	exec_cmd = prepare_command_pool(info, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&info->cmd_complete);
 		info->state |= STATE_CMD_PREPARED;
@@ -618,10 +631,6 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		pxa3xx_nand_stop(info);
 		disable_int(info, NDCR_INT_MASK);
 		info->state &= ~STATE_CMD_PREPARED;
-		if (info->retcode == ERR_DBERR) {
-			printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
-			info->retcode = ERR_NONE;
-		}
 	}
 }

-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:32:46 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:32:46 +0800
Subject: [PATCH 10/29] pxa3xx_nand: mtd scan id process could be
Message-ID: <mailman.110.1280296696.27306.linux-mtd@lists.infradead.org>

defined by driver itself

Different NAND driver may require its unique detection. For pxa3xx_nand,
it use its self id database to get the necessary info.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  253 ++++++++++++++++++++++++++--------------
 1 files changed, 163 insertions(+), 90 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index e7b54dd..617bc69 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -123,6 +123,7 @@ enum {
 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;

+	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
 	struct pxa3xx_nand_cmdset *cmdset;

@@ -224,6 +225,8 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 	{ 0xba20,  64, 2048, 16, 16, 2048, NAND_SETTING_ST, },
 };

+static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -830,42 +833,6 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
 	return 0;
 }

-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
-				    const struct pxa3xx_nand_platform_data *pdata)
-{
-	const struct pxa3xx_nand_flash *f;
-	uint32_t id = -1;
-	int i;
-
-	if (pdata->keep_config)
-		if (pxa3xx_nand_detect_config(info) == 0)
-			return 0;
-
-	/* we use default timing to detect id */
-	f = &builtin_flash_types[0];
-	pxa3xx_nand_config_flash(info, f);
-	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-
-	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
-		/* we first choose the flash definition from platfrom */
-		if (i < pdata->num_flash)
-			f = pdata->flash + i;
-		else
-			f = &builtin_flash_types[i - pdata->num_flash + 1];
-		if (f->chip_id == id) {
-			dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
-			pxa3xx_nand_config_flash(info, f);
-			return 0;
-		}
-	}
-
-	dev_warn(&info->pdev->dev,
-		 "failed to detect configured nand flash; found %04x instead of\n",
-		 id);
-	return -ENODEV;
-}
-
 /* the maximum possible buffer size for large page with OOB data
  * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
  * data buffer and the DMA descriptor
@@ -907,56 +874,153 @@ static int pxa3xx_nand_init_buff(struct
pxa3xx_nand_info *info)
 	return 0;
 }

-static struct nand_ecclayout hw_smallpage_ecclayout = {
-	.eccbytes = 6,
-	.eccpos = {8, 9, 10, 11, 12, 13 },
-	.oobfree = { {2, 6} }
-};
+static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, uint8_t *buf, int page)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;

-static struct nand_ecclayout hw_largepage_ecclayout = {
-	.eccbytes = 24,
-	.eccpos = {
-		40, 41, 42, 43, 44, 45, 46, 47,
-		48, 49, 50, 51, 52, 53, 54, 55,
-		56, 57, 58, 59, 60, 61, 62, 63},
-	.oobfree = { {2, 38} }
-};
+	chip->read_buf(mtd, buf, mtd->writesize);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (info->retcode == ERR_SBERR) {
+		switch (info->use_ecc) {
+			case 1:
+				mtd->ecc_stats.corrected ++;
+				break;
+
+			case 0:
+			default:
+				break;
+		}
+	}
+	else if (info->retcode == ERR_DBERR) {
+		int buf_blank;
+
+		buf_blank = is_buf_blank(buf, mtd->writesize);
+		if (!buf_blank)
+			mtd->ecc_stats.failed++;
+	}
+
+	return 0;
+}
+
+static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, const uint8_t *buf)
+{
+	chip->write_buf(mtd, buf, mtd->writesize);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	/* Send commands to erase a block */
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+}

-static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
-				 struct pxa3xx_nand_info *info)
+static int __devinit pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct nand_chip *this = &info->nand_chip;
-
-	this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
-
-	this->waitfunc		= pxa3xx_nand_waitfunc;
-	this->select_chip	= pxa3xx_nand_select_chip;
-	this->dev_ready		= pxa3xx_nand_dev_ready;
-	this->cmdfunc		= pxa3xx_nand_cmdfunc;
-	this->read_word		= pxa3xx_nand_read_word;
-	this->read_byte		= pxa3xx_nand_read_byte;
-	this->read_buf		= pxa3xx_nand_read_buf;
-	this->write_buf		= pxa3xx_nand_write_buf;
-	this->verify_buf	= pxa3xx_nand_verify_buf;
-
-	this->ecc.mode		= NAND_ECC_HW;
-	this->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
-	this->ecc.calculate	= pxa3xx_nand_ecc_calculate;
-	this->ecc.correct	= pxa3xx_nand_ecc_correct;
-	this->ecc.size		= info->page_size;
-
-	if (info->page_size == 2048)
-		this->ecc.layout = &hw_largepage_ecclayout;
+	struct mtd_info *mtd = info->mtd;
+	struct nand_chip *chip = mtd->priv;
+
+	/* use the common timing to make a try */
+	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+	if (info->state & STATE_READY)
+		return 1;
 	else
-		this->ecc.layout = &hw_smallpage_ecclayout;
+		return 0;
+}

-	this->chip_delay = 25;
+static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	const struct pxa3xx_nand_flash *f = NULL;
+	struct nand_chip *chip = mtd->priv;
+	uint32_t id = -1;
+	int i, ret;
+
+	if (pdata->keep_config)
+		if (pxa3xx_nand_detect_config(info) == 0)
+			return 0;
+
+	ret = pxa3xx_nand_sensing(info);
+	if (!ret) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_INFO "There is no nand chip on cs 0!\n");
+
+		return -EINVAL;
+	}
+
+	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));
+	if (id != 0)
+		printk(KERN_INFO "Detect a flash id %x\n", id);
+	else {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
+
+		return -EINVAL;
+	}
+
+	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
+		if (i < pdata->num_flash)
+			f = pdata->flash + i;
+		else
+			f = &builtin_flash_types[i - pdata->num_flash + 1];
+
+		/* find the chip in default list */
+		if (f->chip_id == id) {
+			pxa3xx_nand_config_flash(info, f);
+			mtd->writesize = f->page_size;
+			mtd->writesize_shift = ffs(mtd->writesize) - 1;
+			mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
+			mtd->oobsize = mtd->writesize / 32;
+			mtd->erasesize = f->page_size * f->page_per_block;
+			mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
+			mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
+
+			mtd->name = mtd_names[0];
+			break;
+		}
+	}
+
+	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+
+		return -EINVAL;
+	}
+
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = f->page_size;
+	chip->chipsize 	= (uint64_t)f->num_blocks * f->page_per_block
+				* f->page_size;
+	mtd->size = chip->chipsize;
+
+	/* Calculate the address shift from the page size */
+	chip->page_shift = ffs(mtd->writesize) - 1;
+	chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
+	chip->numchips = 1;
+	chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
+
+	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
+	chip->options |= NAND_NO_AUTOINCR;
+	chip->options |= NAND_NO_READRDY;
+	chip->options |= NAND_USE_FLASH_BBT;
+
+	return nand_scan_tail(mtd);
 }

 static int alloc_nand_resource(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct pxa3xx_nand_info *info;
+	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct resource *r;
 	int ret, irq;
@@ -969,12 +1033,31 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	}

 	info = (struct pxa3xx_nand_info *)(&mtd[1]);
+	chip = (struct nand_chip *)(&mtd[1]);
 	info->pdev = pdev;
-
-	mtd->priv = info;
 	info->mtd = mtd;
+	mtd->priv = info;
 	mtd->owner = THIS_MODULE;

+	chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+	chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+	chip->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
+	chip->ecc.calculate	= pxa3xx_nand_ecc_calculate;
+	chip->ecc.correct	= pxa3xx_nand_ecc_correct;
+	chip->controller        = &info->controller;
+	chip->waitfunc		= pxa3xx_nand_waitfunc;
+	chip->select_chip	= pxa3xx_nand_select_chip;
+	chip->dev_ready		= pxa3xx_nand_dev_ready;
+	chip->cmdfunc		= pxa3xx_nand_cmdfunc;
+	chip->read_word		= pxa3xx_nand_read_word;
+	chip->read_byte		= pxa3xx_nand_read_byte;
+	chip->read_buf		= pxa3xx_nand_read_buf;
+	chip->write_buf		= pxa3xx_nand_write_buf;
+	chip->verify_buf	= pxa3xx_nand_verify_buf;
+	chip->erase_cmd		= pxa3xx_nand_erase_cmd;
+
+	spin_lock_init(&chip->controller->lock);
+	init_waitqueue_head(&chip->controller->wq);
 	info->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
@@ -1042,21 +1125,11 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		goto fail_free_buf;
 	}

-	ret = pxa3xx_nand_detect_flash(info, pdata);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to detect flash\n");
-		ret = -ENODEV;
-		goto fail_free_irq;
-	}
-
-	pxa3xx_nand_init_mtd(mtd, info);
 	platform_set_drvdata(pdev, info);
-
 	return 0;

-fail_free_irq:
-	free_irq(irq, info);
 fail_free_buf:
+	free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
 		dma_free_coherent(&pdev->dev, info->data_buff_size,
@@ -1124,7 +1197,7 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 		return ret;

 	info = platform_get_drvdata(pdev);
-	if (nand_scan(info->mtd, 1)) {
+	if (pxa3xx_nand_scan(info->mtd)) {
 		dev_err(&pdev->dev, "failed to scan nand\n");
 		pxa3xx_nand_remove(pdev);
 		return -ENODEV;
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:41:47 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:41:47 +0800
Subject: [PATCH 12/29] pxa3xx_nand: clean the keep configure code
Message-ID: <mailman.114.1280296730.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    1 +
 drivers/mtd/nand/pxa3xx_nand.c               |  107 +++++++++-----------------
 2 files changed, 38 insertions(+), 70 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 0bf1bcf..6d9212b 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -30,6 +30,7 @@ struct pxa3xx_nand_cmdset {
 };

 struct pxa3xx_nand_flash {
+	char		*name;
 	uint32_t	chip_id;
 	uint16_t	page_per_block; /* Pages per block (PG_PER_BLK) */
 	uint16_t 	page_size;	/* Page size in bytes (PAGE_SZ) */
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 617bc69..d4e34aa 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -214,15 +214,15 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 #define NAND_SETTING_MICRON      &default_cmdset, &timing[2]
 #define NAND_SETTING_ST          &default_cmdset, &timing[3]
 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-	{      0,   0, 2048,  8,  8,    0, NAND_SETTING_DEFAULT, },
-	{ 0x46ec,  32,  512, 16, 16, 4096, NAND_SETTING_SAMSUNG, },
-	{ 0xdaec,  64, 2048,  8,  8, 2048, NAND_SETTING_SAMSUNG, },
-	{ 0xd7ec, 128, 4096,  8,  8, 8192, NAND_SETTING_SAMSUNG, },
-	{ 0xa12c,  64, 2048,  8,  8, 1024, NAND_SETTING_MICRON, },
-	{ 0xb12c,  64, 2048, 16, 16, 1024, NAND_SETTING_MICRON, },
-	{ 0xdc2c,  64, 2048,  8,  8, 4096, NAND_SETTING_MICRON, },
-	{ 0xcc2c,  64, 2048, 16, 16, 4096, NAND_SETTING_MICRON, },
-	{ 0xba20,  64, 2048, 16, 16, 2048, NAND_SETTING_ST, },
+{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, NAND_SETTING_DEFAULT, },
+{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, NAND_SETTING_SAMSUNG, },
+{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, NAND_SETTING_SAMSUNG, },
+{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, NAND_SETTING_SAMSUNG, },
+{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, NAND_SETTING_MICRON, },
+{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, NAND_SETTING_MICRON, },
+{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, NAND_SETTING_MICRON, },
+{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, NAND_SETTING_MICRON, },
+{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, NAND_SETTING_ST, },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
@@ -758,7 +758,6 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	/* calculate flash information */
 	info->cmdset = f->cmdset;
 	info->page_size = f->page_size;
-	info->oob_buff = info->data_buff + f->page_size;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

 	/* calculate addressing information */
@@ -788,44 +787,12 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
 	uint32_t ndcr = nand_readl(info, NDCR);
-	struct nand_flash_dev *type = NULL;
-	uint32_t id = -1, page_per_block, num_blocks;
-	int i;

-	page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
 	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;

-	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-	if (id == 0)
-		return -ENODEV;
-
-	/* Lookup the flash id */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if (id == nand_flash_ids[i].id) {
-			type =  &nand_flash_ids[i];
-			break;
-		}
-	}
-
-	if (!type)
-		return -ENODEV;
-
-	/* fill the missing flash information */
-	i = __ffs(page_per_block * info->page_size);
-	num_blocks = type->chipsize << (20 - i);
-
-	/* calculate addressing information */
-	info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;
-
-	if (num_blocks * page_per_block > 65536)
-		info->row_addr_cycles = 3;
-	else
-		info->row_addr_cycles = 2;
-
 	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 	info->cmdset = &default_cmdset;
@@ -937,14 +904,17 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 	struct pxa3xx_nand_info *info = mtd->priv;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
 	uint32_t id = -1;
+	uint64_t chipsize;
 	int i, ret;

-	if (pdata->keep_config)
+	if (pdata->keep_config) {
 		if (pxa3xx_nand_detect_config(info) == 0)
-			return 0;
+			goto KEEP_CONFIG;
+	}

 	ret = pxa3xx_nand_sensing(info);
 	if (!ret) {
@@ -974,22 +944,11 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 			f = &builtin_flash_types[i - pdata->num_flash + 1];

 		/* find the chip in default list */
-		if (f->chip_id == id) {
-			pxa3xx_nand_config_flash(info, f);
-			mtd->writesize = f->page_size;
-			mtd->writesize_shift = ffs(mtd->writesize) - 1;
-			mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
-			mtd->oobsize = mtd->writesize / 32;
-			mtd->erasesize = f->page_size * f->page_per_block;
-			mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
-			mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
-
-			mtd->name = mtd_names[0];
+		if (f->chip_id == id)
 			break;
-		}
 	}

-	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
 		kfree(mtd);
 		info->mtd = NULL;
 		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
@@ -997,20 +956,28 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 		return -EINVAL;
 	}

+	pxa3xx_nand_config_flash(info, f);
+	pxa3xx_flash_ids[0].name = f->name;
+	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+	pxa3xx_flash_ids[0].pagesize = f->page_size;
+	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
+	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
+	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
+	pxa3xx_flash_ids[0].options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
+KEEP_CONFIG:
+	if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+		return -ENODEV;
+	/* calculate addressing information */
+	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	info->oob_buff = info->data_buff + mtd->writesize;
+	if ((mtd->size >> chip->page_shift) > 65536)
+		info->row_addr_cycles = 3;
+	else
+		info->row_addr_cycles = 2;
+	mtd->name = mtd_names[0];
 	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = f->page_size;
-	chip->chipsize 	= (uint64_t)f->num_blocks * f->page_per_block
-				* f->page_size;
-	mtd->size = chip->chipsize;
-
-	/* Calculate the address shift from the page size */
-	chip->page_shift = ffs(mtd->writesize) - 1;
-	chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
-	chip->numchips = 1;
-	chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
-
-	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
-	chip->options |= NAND_NO_AUTOINCR;
+	chip->ecc.size = mtd->writesize;
+	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16: 0;
 	chip->options |= NAND_NO_READRDY;
 	chip->options |= NAND_USE_FLASH_BBT;

-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:46:47 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:46:47 +0800
Subject: [PATCH 13/29] pxa3xx_nand: add two chip select
Message-ID: <mailman.117.1280296766.27306.linux-mtd@lists.infradead.org>

Current pxa3xx_nand controller has two chip select which
both be workable. This patch enable this feature.

Update platform driver to support this feature.

Another notice should be taken that:
When you want to use this feature, you should not enable the
keep configuration feature, for two chip select could be
attached with different nand chip. The different page size
and timing requirement make the keep configuration impossible.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c                 |    4 +-
 arch/arm/mach-mmp/avengers_lite.c            |   50 ++
 arch/arm/mach-pxa/cm-x300.c                  |    4 +-
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    4 +-
 arch/arm/mach-pxa/littleton.c                |    4 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    8 +-
 arch/arm/mach-pxa/raumfeld.c                 |    4 +-
 arch/arm/mach-pxa/zylonite.c                 |    4 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    5 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  770 +++++++++++++-------------
 10 files changed, 463 insertions(+), 394 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 244655d..81ad58d 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -126,8 +126,8 @@ static struct mtd_partition aspenite_nand_partitions[] = {

 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= aspenite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(aspenite_nand_partitions),
+	.parts[0]	= aspenite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(aspenite_nand_partitions),
 };

 static struct i2c_board_info aspenite_i2c_info[] __initdata = {
diff --git a/arch/arm/mach-mmp/avengers_lite.c
b/arch/arm/mach-mmp/avengers_lite.c
index 8c3fa5d..a828b1c 100644
--- a/arch/arm/mach-mmp/avengers_lite.c
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -32,12 +32,62 @@ static unsigned long
avengers_lite_pin_config_V16F[] __initdata = {
 	GPIO89_UART2_RXD,
 };

+static struct mtd_partition avengers_nand_partitions_0[] = {
+	{
+		.name		= "bootloader",
+		.offset		= 0,
+		.size		= SZ_1M,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= (SZ_2M + SZ_1M),
+	}, {
+		.name		= "mass0",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_48M,
+	}
+};
+
+static struct mtd_partition avengers_nand_partitions_1[] = {
+	{
+		.name		= "reserved",
+		.offset		= 0,
+		.size		= SZ_2M,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "filesystem",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_512M,
+	}, {
+		.name		= "mass1",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_16M,
+	}, {
+		.name		= "mass2",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_256M,
+	}
+};
+
+static struct pxa3xx_nand_platform_data avengers_nand_info;
+static void __init avengers_init_flash(void)
+{
+	avengers_nand_info.parts[0] = avengers_nand_partitions_0;
+	avengers_nand_info.nr_parts[0] = ARRAY_SIZE(avengers_nand_partitions_0);
+	avengers_nand_info.parts[1] = avengers_nand_partitions_1;
+	avengers_nand_info.nr_parts[1] = ARRAY_SIZE(avengers_nand_partitions_1);
+	avengers_nand_info.enable_arbiter = 1;
+	pxa168_add_nand(&avengers_nand_info);
+}
+
 static void __init avengers_lite_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(avengers_lite_pin_config_V16F));

 	/* on-chip devices */
 	pxa168_add_uart(2);
+	avengers_init_flash();
 }

 MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index fdda6be..ce1f6d3 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -419,8 +419,8 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= cm_x300_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(cm_x300_nand_partitions),
+	.parts[0]	= cm_x300_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(cm_x300_nand_partitions),
 };

 static void __init cm_x300_init_nand(void)
diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c
b/arch/arm/mach-pxa/colibri-pxa3xx.c
index 199afa2..b33559c 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -188,8 +188,8 @@ static struct mtd_partition colibri_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= colibri_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(colibri_nand_partitions),
+	.parts[0]	= colibri_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(colibri_nand_partitions),
 };

 void __init colibri_pxa3xx_init_nand(void)
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 9b90461..717cf92 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -325,8 +325,8 @@ static struct mtd_partition littleton_nand_partitions[] = {

 static struct pxa3xx_nand_platform_data littleton_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= littleton_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(littleton_nand_partitions),
+	.parts[0]	= littleton_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(littleton_nand_partitions),
 };

 static void __init littleton_init_nand(void)
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index 462167a..66c2086 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,10 +389,10 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-	.enable_arbiter = 1,
-	.keep_config = 1,
-	.parts = mxm_8x10_nand_partitions,
-	.nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions)
+	.enable_arbiter	= 1,
+	.keep_config	= 1,
+	.parts[0]	= mxm_8x10_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(mxm_8x10_nand_partitions)
 };

 static void __init mxm_8x10_nand_init(void)
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index d4b61b3..df75d4d 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -350,8 +350,8 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= raumfeld_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(raumfeld_nand_partitions),
+	.parts[0]	= raumfeld_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(raumfeld_nand_partitions),
 };

 /**
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index c479cbe..9e5c6cd 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -356,8 +356,8 @@ static struct mtd_partition zylonite_nand_partitions[] = {

 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= zylonite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(zylonite_nand_partitions),
+	.parts[0]	= zylonite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(zylonite_nand_partitions),
 };

 static void __init zylonite_init_nand(void)
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 6d9212b..cf42f97 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -41,6 +41,7 @@ struct pxa3xx_nand_flash {
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };

+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {

 	/* the data flash bus is shared between the Static Memory
@@ -52,8 +53,8 @@ struct pxa3xx_nand_platform_data {
 	/* allow platform code to keep OBM/bootloader defined NFC config */
 	int	keep_config;

-	const struct mtd_partition		*parts;
-	unsigned int				nr_parts;
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];

 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index d4e34aa..3dea0fe 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -51,11 +51,9 @@
 #define NDCR_DWIDTH_M		(0x1 << 26)
 #define NDCR_PAGE_SZ		(0x1 << 24)
 #define NDCR_NCSX		(0x1 << 23)
-#define NDCR_STOP_ON_UNCOR	(0x1 << 22)
 #define NDCR_ND_MODE		(0x3 << 21)
-#define NDCR_NAND_MODE   	(0x0)
 #define NDCR_CLR_PG_CNT		(0x1 << 20)
-#define NDCR_CLR_ECC		(0x1 << 19)
+#define NDCR_STOP_ON_UNCOR	(0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK	(0x7 << 16)
 #define NDCR_RD_ID_CNT(x)	(((x) << 16) & NDCR_RD_ID_CNT_MASK)

@@ -98,6 +96,8 @@

 #define nand_readl(info, off)		\
 	__raw_readl((info)->mmio_base + (off))
+#define get_mtd_by_info(info)		\
+	(struct mtd_info *)((void *)info - sizeof(struct mtd_info))

 /* error code and state */
 enum {
@@ -122,63 +122,64 @@ enum {

 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;
-
-	struct nand_hw_control	controller;
-	struct platform_device	 *pdev;
 	struct pxa3xx_nand_cmdset *cmdset;
+	/* page size of attached chip */
+	uint16_t		page_size;
+	uint8_t			chip_select;
+	uint8_t			use_ecc;
+
+	/* calculated from pxa3xx_nand_flash data */
+	uint8_t			col_addr_cycles;
+	uint8_t			row_addr_cycles;
+	uint8_t			read_id_bytes;
+
+	/* cached register value */
+	uint32_t		reg_ndcr;
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;

+	void			*nand_data;
+};
+
+struct pxa3xx_nand {
 	struct clk		*clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
+	struct nand_hw_control	controller;
+	struct completion 	cmd_complete;
+	struct platform_device	 *pdev;

-	unsigned int 		buf_start;
-	unsigned int		buf_count;
-
-	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
-
-	unsigned char		*data_buff;
-	unsigned char		*oob_buff;
-	dma_addr_t 		data_buff_phys;
-	size_t			data_buff_size;
 	int 			data_dma_ch;
-	struct pxa_dma_desc	*data_desc;
+	dma_addr_t 		data_buff_phys;
 	dma_addr_t 		data_desc_addr;
+	struct pxa_dma_desc	*data_desc;

-	uint32_t		reg_ndcr;
-
-	/* saved column/page_addr during CMD_SEQIN */
-	int			seqin_column;
-	int			seqin_page_addr;
+	struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
+	uint32_t		command;
+	uint16_t		data_size;	/* data size in FIFO */
+	uint16_t		oob_size;
+	uint32_t		bad_count;
+	unsigned char		*dma_buff;
+	unsigned char		*data_buff;
+	unsigned char		*oob_buff;
+	uint32_t		buf_start;
+	uint32_t		buf_count;
+	uint8_t			total_cmds;

 	/* relate to the command */
+	uint8_t			chip_select;
 	unsigned int		state;
-
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
-
-	unsigned int		page_size;	/* page size of attached chip */
-	unsigned int		data_size;	/* data size in FIFO */
 	int 			retcode;
-	struct completion 	cmd_complete;

 	/* generated NDCBx register values */
 	uint32_t		ndcb0;
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;
-
-	/* timing calcuted from setting */
-	uint32_t		ndtr0cs0;
-	uint32_t		ndtr1cs0;
-
-	/* calculated from pxa3xx_nand_flash data */
-	size_t		oob_size;
-	size_t		read_id_bytes;
-
-	unsigned int	col_addr_cycles;
-	unsigned int	row_addr_cycles;
 };

 static int use_dma = 1;
@@ -217,6 +218,7 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 { "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, NAND_SETTING_DEFAULT, },
 { "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, NAND_SETTING_SAMSUNG, },
 { "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, NAND_SETTING_SAMSUNG, },
+{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, 4096, NAND_SETTING_SAMSUNG, },
 { "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, NAND_SETTING_SAMSUNG, },
 { "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, NAND_SETTING_MICRON, },
 { "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, NAND_SETTING_MICRON, },
@@ -225,7 +227,7 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 { "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, NAND_SETTING_ST, },
 };

-static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};

 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
@@ -244,9 +246,11 @@ static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
 {
-	unsigned long nand_clk = clk_get_rate(info->clk);
+	struct pxa3xx_nand *nand = info->nand_data;
+	unsigned long nand_clk;
 	uint32_t ndtr0, ndtr1;

+	nand_clk = clk_get_rate(nand->clk);
 	ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
 		NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
 		NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
@@ -260,26 +264,27 @@ static void pxa3xx_nand_set_timing(struct
pxa3xx_nand_info *info,

 	info->ndtr0cs0 = ndtr0;
 	info->ndtr1cs0 = ndtr1;
-	nand_writel(info, NDTR0CS0, ndtr0);
-	nand_writel(info, NDTR1CS0, ndtr1);
+	nand_writel(nand, NDTR0CS0, ndtr0);
+	nand_writel(nand, NDTR1CS0, ndtr1);
 }

 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
+	struct pxa3xx_nand *nand = info->nand_data;
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;

-	info->data_size = info->page_size;
+	nand->data_size = info->page_size;
 	if (!oob_enable) {
-		info->oob_size = 0;
+		nand->oob_size = 0;
 		return;
 	}

 	switch (info->page_size) {
 	case 2048:
-		info->oob_size = (info->use_ecc) ? 40 : 64;
+		nand->oob_size = (nand->use_ecc) ? 40 : 64;
 		break;
 	case 512:
-		info->oob_size = (info->use_ecc) ? 8 : 16;
+		nand->oob_size = (nand->use_ecc) ? 8 : 16;
 		break;
 	}
 }
@@ -290,22 +295,24 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
  * We enable all the interrupt at the same time, and
  * let pxa3xx_nand_irq to handle all logic.
  */
-static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
+static void pxa3xx_nand_start(struct pxa3xx_nand *nand)
 {
+	struct pxa3xx_nand_info *info;
 	uint32_t ndcr;

+	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
-	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
-	ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
+	ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
+	ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
 	ndcr |= NDCR_ND_RUN;

 	/* clear status bits and run */
-	nand_writel(info, NDCR, 0);
-	nand_writel(info, NDSR, NDSR_MASK);
-	nand_writel(info, NDCR, ndcr);
+	nand_writel(nand, NDCR, 0);
+	nand_writel(nand, NDSR, NDSR_MASK);
+	nand_writel(nand, NDCR, ndcr);
 }

-static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
+static void pxa3xx_nand_stop(struct pxa3xx_nand *nand)
 {
 	uint32_t ndcr;
 	int timeout = NAND_STOP_DELAY;
@@ -313,146 +320,149 @@ static void pxa3xx_nand_stop(struct
pxa3xx_nand_info *info)
 	/* wait RUN bit in NDCR become 0 */
 	do {
 		/* clear status bits */
-		nand_writel(info, NDSR, NDSR_MASK);
-		ndcr = nand_readl(info, NDCR);
+		nand_writel(nand, NDSR, NDSR_MASK);
+		ndcr = nand_readl(nand, NDCR);
 		udelay(1);
 	} while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0));

 	if (timeout <= 0) {
 		ndcr &= ~(NDCR_ND_RUN);
-		nand_writel(info, NDCR, ndcr);
+		nand_writel(nand, NDCR, ndcr);
 	}
 }

-static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
+static void enable_int(struct pxa3xx_nand *nand, uint32_t int_mask)
 {
 	uint32_t ndcr;

-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~int_mask);
+	ndcr = nand_readl(nand, NDCR);
+	nand_writel(nand, NDCR, ndcr & ~int_mask);
 }

-static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
+static void disable_int(struct pxa3xx_nand *nand, uint32_t int_mask)
 {
 	uint32_t ndcr;

-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr | int_mask);
+	ndcr = nand_readl(nand, NDCR);
+	nand_writel(nand, NDCR, ndcr | int_mask);
 }

-static void handle_data_pio(struct pxa3xx_nand_info *info)
+static void handle_data_pio(struct pxa3xx_nand *nand)
 {
-	if (info->state & STATE_IS_WRITE) {
-		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
-				DIV_ROUND_UP(info->data_size, 4));
-		if (info->oob_size > 0)
-			__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
-					DIV_ROUND_UP(info->oob_size, 4));
+	if (nand->state & STATE_IS_WRITE) {
+		__raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
+				DIV_ROUND_UP(nand->data_size, 4));
+		if (nand->oob_size > 0)
+			__raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
+					DIV_ROUND_UP(nand->oob_size, 4));

 	}
 	else {
-		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
-				DIV_ROUND_UP(info->data_size, 4));
-		if (info->oob_size > 0)
-			__raw_readsl(info->mmio_base + NDDB, info->oob_buff,
-					DIV_ROUND_UP(info->oob_size, 4));
+		__raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
+				DIV_ROUND_UP(nand->data_size, 4));
+		if (nand->oob_size > 0)
+			__raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
+					DIV_ROUND_UP(nand->oob_size, 4));
 	}
 }

-static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
+static void start_data_dma(struct pxa3xx_nand *nand, int dir_out)
 {
-	struct pxa_dma_desc *desc = info->data_desc;
-	int dma_len = ALIGN(info->data_size + info->oob_size, 32);
+	struct pxa_dma_desc *desc = nand->data_desc;
+	int dma_len = ALIGN(nand->data_size + nand->oob_size, 32);

 	desc->ddadr = DDADR_STOP;
 	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;

 	if (dir_out) {
-		desc->dsadr = info->data_buff_phys;
-		desc->dtadr = info->mmio_phys + NDDB;
+		desc->dsadr = nand->data_buff_phys;
+		desc->dtadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
 	} else {
-		desc->dtadr = info->data_buff_phys;
-		desc->dsadr = info->mmio_phys + NDDB;
+		desc->dtadr = nand->data_buff_phys;
+		desc->dsadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
 	}

-	DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
-	DDADR(info->data_dma_ch) = info->data_desc_addr;
-	DCSR(info->data_dma_ch) |= DCSR_RUN;
+	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
+	DDADR(nand->data_dma_ch) = nand->data_desc_addr;
+	DCSR(nand->data_dma_ch) |= DCSR_RUN;
 }

 static void pxa3xx_nand_data_dma_irq(int channel, void *data)
 {
-	struct pxa3xx_nand_info *info = data;
+	struct pxa3xx_nand *nand = data;
 	uint32_t dcsr;

 	dcsr = DCSR(channel);
 	DCSR(channel) = dcsr;

 	if (dcsr & DCSR_BUSERR) {
-		info->retcode = ERR_DMABUSERR;
+		nand->retcode = ERR_DMABUSERR;
 	}

-	enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+	enable_int(nand, NDCR_INT_MASK);
+	nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }

 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
-	struct pxa3xx_nand_info *info = devid;
-	unsigned int status, is_completed = 0;
+	struct pxa3xx_nand *nand = devid;
+	struct pxa3xx_nand_info *info;
+	unsigned int status, is_completed = 0, cs;
+	unsigned int ready, cmd_done, page_done, badblock_detect;

-	status = nand_readl(info, NDSR);
+	cs		= nand->chip_select;
+	ready           = (cs) ? NDSR_RDY : NDSR_FLASH_RDY;
+	cmd_done        = (cs) ? NDSR_CS1_CMDD : NDSR_CS0_CMDD;
+	page_done       = (cs) ? NDSR_CS1_PAGED : NDSR_CS0_PAGED;
+	badblock_detect = (cs) ? NDSR_CS1_BBD : NDSR_CS0_BBD;
+	info            = nand->info[cs];

+	status = nand_readl(nand, NDSR);
 	if (status & NDSR_DBERR)
-		info->retcode = ERR_DBERR;
+		nand->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
-		info->retcode = ERR_SBERR;
+		nand->retcode = ERR_SBERR;
 	if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {

-		info->state |= STATE_DATA_PROCESSING;
+		nand->state |= STATE_DATA_PROCESSING;
 		/* whether use dma to transfer data */
-		if (info->use_dma) {
-			disable_int(info, NDSR_WRDREQ);
-			start_data_dma(info, 0);
+		if (nand->use_dma) {
+			disable_int(nand, NDCR_INT_MASK);
+			start_data_dma(nand, nand->state & STATE_IS_WRITE);
 			goto NORMAL_IRQ_EXIT;
 		} else
-			handle_data_pio(info);
+			handle_data_pio(nand);

-		info->state |= STATE_DATA_DONE;
+		nand->state |= STATE_DATA_DONE;
 	}
-	if (status & NDSR_CS0_CMDD) {
-		info->state |= STATE_CMD_DONE;
+	if (status & cmd_done) {
+		nand->state |= STATE_CMD_DONE;
 		is_completed = 1;
 	}
-	if (status & NDSR_FLASH_RDY)
-		info->state |= STATE_READY;
-	if (status & NDSR_CS0_PAGED)
-		info->state |= STATE_PAGE_DONE;
+	if (status & ready)
+		nand->state |= STATE_READY;
+	if (status & page_done)
+		nand->state |= STATE_PAGE_DONE;

 	if (status & NDSR_WRCMDREQ) {
-		nand_writel(info, NDSR, NDSR_WRCMDREQ);
+		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
 		status &= ~NDSR_WRCMDREQ;
-		info->state |= STATE_CMD_WAIT_DONE;
-		nand_writel(info, NDCB0, info->ndcb0);
-		nand_writel(info, NDCB0, info->ndcb1);
-		nand_writel(info, NDCB0, info->ndcb2);
+		nand->state |= STATE_CMD_WAIT_DONE;
+		nand_writel(nand, NDCB0, nand->ndcb0);
+		nand_writel(nand, NDCB0, nand->ndcb1);
+		nand_writel(nand, NDCB0, nand->ndcb2);
 	}

 	/* clear NDSR to let the controller exit the IRQ */
-	nand_writel(info, NDSR, status);
+	nand_writel(nand, NDSR, status);
 	if (is_completed)
-		complete(&info->cmd_complete);
+		complete(&nand->cmd_complete);
 NORMAL_IRQ_EXIT:
 	return IRQ_HANDLED;
 }

-static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
-{
-	struct pxa3xx_nand_info *info = mtd->priv;
-	return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0;
-}
-
 static inline int is_buf_blank(uint8_t *buf, size_t len)
 {
 	for (; len > 0; len--)
@@ -461,40 +471,48 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
 	return 1;
 }

-static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+static int prepare_command_pool(struct pxa3xx_nand *nand, int command,
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
 	int addr_cycle, exec_cmd, ndcb0;
-	struct mtd_info *mtd = info->mtd;
+	struct mtd_info *mtd;
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];

-	ndcb0 = 0;
+	mtd = get_mtd_by_info(info);
+	ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;;
 	addr_cycle = 0;
 	exec_cmd = 1;

 	/* reset data and oob column point to handle data */
-	info->buf_start		= 0;
-	info->buf_count		= 0;
-	info->oob_size		= 0;
-	info->use_ecc		= 0;
+	nand->buf_start		= 0;
+	nand->buf_count		= 0;
+	nand->ndcb0		= ndcb0;
+	nand->data_size		= 0;
+	nand->oob_size		= 0;
+	nand->use_ecc		= 0;
+	nand->use_dma		= 0;
+	nand->state		= 0;
+	nand->command		= command;

 	switch (command) {
 	case NAND_CMD_READ0:
 	case NAND_CMD_PAGEPROG:
-		info->use_ecc = 1;
+		nand->use_ecc = 1;
 	case NAND_CMD_READOOB:
 		pxa3xx_set_datasize(info);
+		nand->oob_buff = nand->data_buff + nand->data_size;
+		nand->use_dma = use_dma;
 		break;
 	case NAND_CMD_SEQIN:
 		exec_cmd = 0;
 		break;
 	default:
-		info->ndcb1 = 0;
-		info->ndcb2 = 0;
+		nand->ndcb1 = 0;
+		nand->ndcb2 = 0;
 		break;
 	}

-	info->ndcb0 = ndcb0;
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);

@@ -503,16 +521,16 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,
 	case NAND_CMD_READ0:
 		cmd  = info->cmdset->read1;
 		if (command == NAND_CMD_READOOB)
-			info->buf_start = mtd->writesize + column;
+			nand->buf_start = mtd->writesize + column;
 		else
-			info->buf_start = column;
+			nand->buf_start = column;

 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
 		else
-			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| NDCB0_DBC
 					| addr_cycle
 					| cmd;
@@ -520,35 +538,35 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,
 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
-			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);

-			info->ndcb2 = 0;
+			nand->ndcb2 = 0;
 		}
 		else {
-			info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
 					| (column & 0xFFFF);

 			if (page_addr & 0xFF0000)
-				info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
 			else
-				info->ndcb2 = 0;
+				nand->ndcb2 = 0;
 		}

-		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xFF, info->buf_count);
+		nand->buf_count = mtd->writesize + mtd->oobsize;
+		memset(nand->data_buff, 0xFF, nand->buf_count);

 		break;

 	case NAND_CMD_PAGEPROG:
-		if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) {
+		if (is_buf_blank(nand->data_buff, (mtd->writesize + mtd->oobsize))) {
 			exec_cmd = 0;
 			break;
 		}

 		cmd = info->cmdset->program;
-		info->state |= STATE_IS_WRITE;
-		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+		nand->state |= STATE_IS_WRITE;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
 				| NDCB0_AUTO_RS
 				| NDCB0_ST_ROW_EN
 				| NDCB0_DBC
@@ -558,37 +576,37 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,

 	case NAND_CMD_READID:
 		cmd = info->cmdset->read_id;
-		info->buf_count = info->read_id_bytes;
-		info->ndcb0 |= NDCB0_CMD_TYPE(3)
+		nand->buf_count = info->read_id_bytes;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

-		info->data_size = 8;
+		nand->data_size = 8;
 		break;
 	case NAND_CMD_STATUS:
 		cmd = info->cmdset->read_status;
-		info->buf_count = 1;
-		info->ndcb0 |= NDCB0_CMD_TYPE(4)
+		nand->buf_count = 1;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

-		info->data_size = 8;
+		nand->data_size = 8;
 		break;

 	case NAND_CMD_ERASE1:
 		cmd = info->cmdset->erase;
-		info->ndcb0 |= NDCB0_CMD_TYPE(2)
+		nand->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
 				| NDCB0_DBC
 				| cmd;
-		info->ndcb1 = page_addr;
-		info->ndcb2 = 0;
+		nand->ndcb1 = page_addr;
+		nand->ndcb2 = 0;

 		break;
 	case NAND_CMD_RESET:
 		cmd = info->cmdset->reset;
-		info->ndcb0 |= NDCB0_CMD_TYPE(5)
+		nand->ndcb0 |= NDCB0_CMD_TYPE(5)
 				| cmd;

 		break;
@@ -599,7 +617,7 @@ static int prepare_command_pool(struct
pxa3xx_nand_info *info, int command,

 	default:
 		exec_cmd = 0;
-		printk(KERN_ERR "pxa3xx-nand: non-supported command %x\n", command);
+		dev_err(&nand->pdev->dev, "non-supported command %x\n", command);
 		break;
 	}

@@ -610,6 +628,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		int column, int page_addr)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	int ret, exec_cmd;

 	/* if this is a x16 device ,then convert the input
@@ -619,32 +638,40 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 	if (info->reg_ndcr & NDCR_DWIDTH_M)
 		column /= 2;

-	exec_cmd = prepare_command_pool(info, command, column, page_addr);
+	/* reset timing */
+	if (nand->chip_select != info->chip_select) {
+		nand->chip_select = info->chip_select;
+		nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
+		nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
+	}
+
+	exec_cmd = prepare_command_pool(nand, command, column, page_addr);
 	if (exec_cmd) {
-		init_completion(&info->cmd_complete);
-		info->state |= STATE_CMD_PREPARED;
-		pxa3xx_nand_start(info);
+		init_completion(&nand->cmd_complete);
+		nand->state |= STATE_CMD_PREPARED;
+		pxa3xx_nand_start(nand);

-		ret = wait_for_completion_timeout(&info->cmd_complete,
+		ret = wait_for_completion_timeout(&nand->cmd_complete,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
-			printk(KERN_ERR "Wait time out!!!\n");
+			dev_err(&nand->pdev->dev, "Wait time out!!!\n");
 		}
 		/* Stop State Machine for next command cycle */
-		pxa3xx_nand_stop(info);
-		disable_int(info, NDCR_INT_MASK);
-		info->state &= ~STATE_CMD_PREPARED;
+		pxa3xx_nand_stop(nand);
+		disable_int(nand, NDCR_INT_MASK);
+		nand->state &= ~STATE_CMD_PREPARED;
 	}
 }

 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	char retval = 0xFF;

-	if (info->buf_start < info->buf_count)
+	if (nand->buf_start < nand->buf_count)
 		/* Has just send a new command? */
-		retval = info->data_buff[info->buf_start++];
+		retval = nand->data_buff[nand->buf_start++];

 	return retval;
 }
@@ -652,11 +679,12 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	u16 retval = 0xFFFF;

-	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
-		retval = *((u16 *)(info->data_buff+info->buf_start));
-		info->buf_start += 2;
+	if (!(nand->buf_start & 0x01) && nand->buf_start < nand->buf_count) {
+		retval = *((u16 *)(nand->data_buff+nand->buf_start));
+		nand->buf_start += 2;
 	}
 	return retval;
 }
@@ -664,20 +692,22 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+	struct pxa3xx_nand *nand = info->nand_data;
+	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);

-	memcpy(buf, info->data_buff + info->buf_start, real_len);
-	info->buf_start += real_len;
+	memcpy(buf, nand->data_buff + nand->buf_start, real_len);
+	nand->buf_start += real_len;
 }

 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+	struct pxa3xx_nand *nand = info->nand_data;
+	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);

-	memcpy(info->data_buff + info->buf_start, buf, real_len);
-	info->buf_start += real_len;
+	memcpy(nand->data_buff + nand->buf_start, buf, real_len);
+	nand->buf_start += real_len;
 }

 static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
@@ -694,10 +724,11 @@ static void pxa3xx_nand_select_chip(struct
mtd_info *mtd, int chip)
 static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;

 	/* pxa3xx_nand_send_command has waited for command complete */
 	if (this->state == FL_WRITING || this->state == FL_ERASING) {
-		if (info->retcode == ERR_NONE)
+		if (nand->retcode == ERR_NONE)
 			return 0;
 		else {
 			/*
@@ -711,41 +742,11 @@ static int pxa3xx_nand_waitfunc(struct mtd_info
*mtd, struct nand_chip *this)
 	return 0;
 }

-static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
-{
-	return;
-}
-
-static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd,
-		const uint8_t *dat, uint8_t *ecc_code)
-{
-	return 0;
-}
-
-static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
-		uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
-{
-	struct pxa3xx_nand_info *info = mtd->priv;
-	/*
-	 * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
-	 * consider it as a ecc error which will tell the caller the
-	 * read fail We have distinguish all the errors, but the
-	 * nand_read_ecc only check this function return value
-	 *
-	 * Corrected (single-bit) errors must also be noted.
-	 */
-	if (info->retcode == ERR_SBERR)
-		return 1;
-	else if (info->retcode != ERR_NONE)
-		return -1;
-
-	return 0;
-}
-
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 				    const struct pxa3xx_nand_flash *f)
 {
-	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand *nand = info->nand_data;
+	struct platform_device *pdev = nand->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	uint32_t ndcr = 0x00000FFF; /* disable all interrupts */

@@ -779,22 +780,28 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */

 	info->reg_ndcr = ndcr;
+	info->use_ecc = 1;

 	pxa3xx_nand_set_timing(info, f->timing);
 	return 0;
 }

-static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_detect_config(struct pxa3xx_nand *nand)
 {
-	uint32_t ndcr = nand_readl(info, NDCR);
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
+	uint32_t ndcr = nand_readl(nand, NDCR);

+	if (nand->chip_select > 0) {
+		printk(KERN_ERR "We could not detect configure if two cs is supported!!\n");
+		BUG();
+	}
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
 	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;

-	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
+	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
 	info->cmdset = &default_cmdset;

 	return 0;
@@ -805,62 +812,40 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand_info *info)
  * data buffer and the DMA descriptor
  */
 #define MAX_BUFF_SIZE	PAGE_SIZE
-
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
-	struct platform_device *pdev = info->pdev;
-	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
-
-	if (use_dma == 0) {
-		info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
-		if (info->data_buff == NULL)
-			return -ENOMEM;
-		return 0;
-	}
-
-	info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
-				&info->data_buff_phys, GFP_KERNEL);
-	if (info->data_buff == NULL) {
-		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
-		return -ENOMEM;
-	}
-
-	info->data_buff_size = MAX_BUFF_SIZE;
-	info->data_desc = (void *)info->data_buff + data_desc_offset;
-	info->data_desc_addr = info->data_buff_phys + data_desc_offset;
+	struct pxa3xx_nand *nand;
+	struct mtd_info *mtd;

-	info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
-				pxa3xx_nand_data_dma_irq, info);
-	if (info->data_dma_ch < 0) {
-		dev_err(&pdev->dev, "failed to request data dma\n");
-		dma_free_coherent(&pdev->dev, info->data_buff_size,
-				info->data_buff, info->data_buff_phys);
-		return info->data_dma_ch;
-	}
+	if (!info)
+		return;

-	return 0;
+	nand = info->nand_data;
+	mtd = get_mtd_by_info(info);
+	kfree(mtd);
+	nand->info[cs] = NULL;
 }

 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 		struct nand_chip *chip, uint8_t *buf, int page)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;

 	chip->read_buf(mtd, buf, mtd->writesize);
 	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);

-	if (info->retcode == ERR_SBERR) {
-		switch (info->use_ecc) {
+	if (nand->retcode == ERR_SBERR) {
+		switch (nand->use_ecc) {
 			case 1:
-				mtd->ecc_stats.corrected ++;
+				mtd->ecc_stats.corrected++;
 				break;

 			case 0:
 			default:
 				break;
 		}
-	}
-	else if (info->retcode == ERR_DBERR) {
+	} else if (nand->retcode == ERR_DBERR) {
 		int buf_blank;

 		buf_blank = is_buf_blank(buf, mtd->writesize);
@@ -880,20 +865,19 @@ static void pxa3xx_nand_write_page_hwecc(struct
mtd_info *mtd,

 static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
 {
-	struct nand_chip *chip = mtd->priv;
 	/* Send commands to erase a block */
-	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
 }

-static int __devinit pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+static int __devinit pxa3xx_nand_sensing(struct pxa3xx_nand *nand)
 {
-	struct mtd_info *mtd = info->mtd;
-	struct nand_chip *chip = mtd->priv;
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
+	struct mtd_info *mtd = get_mtd_by_info(info);

 	/* use the common timing to make a try */
 	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
-	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
-	if (info->state & STATE_READY)
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+	if (nand->state & STATE_READY)
 		return 1;
 	else
 		return 0;
@@ -902,7 +886,8 @@ static int __devinit pxa3xx_nand_sensing(struct
pxa3xx_nand_info *info)
 static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand *nand = info->nand_data;
+	struct platform_device *pdev = nand->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
 	const struct pxa3xx_nand_flash *f = NULL;
@@ -912,28 +897,23 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 	int i, ret;

 	if (pdata->keep_config) {
-		if (pxa3xx_nand_detect_config(info) == 0)
+		if (pxa3xx_nand_detect_config(nand) == 0)
 			goto KEEP_CONFIG;
 	}

-	ret = pxa3xx_nand_sensing(info);
+	ret = pxa3xx_nand_sensing(nand);
 	if (!ret) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_INFO "There is no nand chip on cs 0!\n");
-
+		free_cs_resource(info, nand->chip_select);
 		return -EINVAL;
 	}

 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
+	id = *((uint16_t *)(nand->data_buff));
 	if (id != 0)
-		printk(KERN_INFO "Detect a flash id %x\n", id);
+		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id);
 	else {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
-
+		dev_warn(&nand->pdev->dev, "Read out ID 0, potential timing set wrong!!\n");
+		free_cs_resource(info, nand->chip_select);
 		return -EINVAL;
 	}

@@ -949,10 +929,8 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 	}

 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
-
+		dev_err(&nand->pdev->dev, "ERROR!! flash not defined!!!\n");
+		free_cs_resource(info, nand->chip_select);
 		return -EINVAL;
 	}

@@ -969,15 +947,15 @@ KEEP_CONFIG:
 		return -ENODEV;
 	/* calculate addressing information */
 	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
-	info->oob_buff = info->data_buff + mtd->writesize;
 	if ((mtd->size >> chip->page_shift) > 65536)
 		info->row_addr_cycles = 3;
 	else
 		info->row_addr_cycles = 2;
-	mtd->name = mtd_names[0];
+	info->page_size = mtd->writesize;
+	mtd->name = mtd_names[nand->chip_select];
 	chip->ecc.mode = NAND_ECC_HW;
 	chip->ecc.size = mtd->writesize;
-	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16: 0;
+	chip->options |= (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16: 0;
 	chip->options |= NAND_NO_READRDY;
 	chip->options |= NAND_USE_FLASH_BBT;

@@ -989,49 +967,25 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	struct pxa3xx_nand_info *info;
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
+	struct pxa3xx_nand *nand;
 	struct resource *r;
-	int ret, irq;
+	int ret, irq, cs;
+	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);

-	mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
-			GFP_KERNEL);
-	if (!mtd) {
+	nand = kzalloc(sizeof(struct pxa3xx_nand), GFP_KERNEL);
+	if (!nand) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
 		return -ENOMEM;
 	}

-	info = (struct pxa3xx_nand_info *)(&mtd[1]);
-	chip = (struct nand_chip *)(&mtd[1]);
-	info->pdev = pdev;
-	info->mtd = mtd;
-	mtd->priv = info;
-	mtd->owner = THIS_MODULE;
-
-	chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
-	chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
-	chip->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
-	chip->ecc.calculate	= pxa3xx_nand_ecc_calculate;
-	chip->ecc.correct	= pxa3xx_nand_ecc_correct;
-	chip->controller        = &info->controller;
-	chip->waitfunc		= pxa3xx_nand_waitfunc;
-	chip->select_chip	= pxa3xx_nand_select_chip;
-	chip->dev_ready		= pxa3xx_nand_dev_ready;
-	chip->cmdfunc		= pxa3xx_nand_cmdfunc;
-	chip->read_word		= pxa3xx_nand_read_word;
-	chip->read_byte		= pxa3xx_nand_read_byte;
-	chip->read_buf		= pxa3xx_nand_read_buf;
-	chip->write_buf		= pxa3xx_nand_write_buf;
-	chip->verify_buf	= pxa3xx_nand_verify_buf;
-	chip->erase_cmd		= pxa3xx_nand_erase_cmd;
-
-	spin_lock_init(&chip->controller->lock);
-	init_waitqueue_head(&chip->controller->wq);
-	info->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(info->clk)) {
+	nand->pdev = pdev;
+	nand->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(nand->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
-		ret = PTR_ERR(info->clk);
-		goto fail_free_mtd;
+		ret = PTR_ERR(nand->clk);
+		goto fail_alloc;
 	}
-	clk_enable(info->clk);
+	clk_enable(nand->clk);

 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (r == NULL) {
@@ -1039,7 +993,7 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		ret = -ENXIO;
 		goto fail_put_clk;
 	}
-	info->drcmr_dat = r->start;
+	nand->drcmr_dat = r->start;

 	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
 	if (r == NULL) {
@@ -1047,14 +1001,7 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		ret = -ENXIO;
 		goto fail_put_clk;
 	}
-	info->drcmr_cmd = r->start;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no IRQ resource defined\n");
-		ret = -ENXIO;
-		goto fail_put_clk;
-	}
+	nand->drcmr_cmd = r->start;

 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
@@ -1070,80 +1017,142 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		goto fail_put_clk;
 	}

-	info->mmio_base = ioremap(r->start, resource_size(r));
-	if (info->mmio_base == NULL) {
+	nand->mmio_base = ioremap(r->start, resource_size(r));
+	if (nand->mmio_base == NULL) {
 		dev_err(&pdev->dev, "ioremap() failed\n");
 		ret = -ENODEV;
 		goto fail_free_res;
 	}
-	info->mmio_phys = r->start;
-
-	ret = pxa3xx_nand_init_buff(info);
-	if (ret)
-		goto fail_free_io;
+	nand->mmio_phys = r->start;

 	/* initialize all interrupts to be disabled */
-	disable_int(info, NDSR_MASK);
+	disable_int(nand, NDSR_MASK);
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ resource defined\n");
+		ret = -ENXIO;
+		goto fail_put_clk;
+	}

 	ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED,
-			  pdev->name, info);
+			  pdev->name, nand);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
+		ret = -ENXIO;
+		goto fail_free_irq;
+	}
+
+	platform_set_drvdata(pdev, nand);
+	spin_lock_init(&nand->controller.lock);
+	init_waitqueue_head(&nand->controller.wq);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		mtd = kzalloc(sizeof(struct mtd_info)
+				+ sizeof(struct pxa3xx_nand_info),
+				GFP_KERNEL);
+		if (!mtd) {
+			dev_err(&pdev->dev, "failed to allocate memory\n");
+			ret = -ENOMEM;
+			goto fail_free_irq;
+		}
+
+		info = (struct pxa3xx_nand_info *)(&mtd[1]);
+		info->nand_data = nand;
+		info->chip_select = cs;
+		mtd->priv = info;
+		mtd->owner = THIS_MODULE;
+		nand->info[cs] = info;
+
+		chip = (struct nand_chip *)(&mtd[1]);
+		chip->controller        = &nand->controller;
+		chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+		chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+		chip->waitfunc		= pxa3xx_nand_waitfunc;
+		chip->select_chip	= pxa3xx_nand_select_chip;
+		chip->cmdfunc		= pxa3xx_nand_cmdfunc;
+		chip->read_word		= pxa3xx_nand_read_word;
+		chip->read_byte		= pxa3xx_nand_read_byte;
+		chip->read_buf		= pxa3xx_nand_read_buf;
+		chip->write_buf		= pxa3xx_nand_write_buf;
+		chip->verify_buf	= pxa3xx_nand_verify_buf;
+		chip->erase_cmd		= pxa3xx_nand_erase_cmd;
+	}
+
+	if (use_dma == 0) {
+		nand->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+		if (nand->data_buff == NULL) {
+			ret = -ENOMEM;
+			goto fail_free_buf;
+		}
+		goto success_exit;
+	}
+
+	nand->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
+			&nand->data_buff_phys, GFP_KERNEL);
+	if (nand->data_buff == NULL) {
+		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
+		ret = -ENOMEM;
 		goto fail_free_buf;
 	}

-	platform_set_drvdata(pdev, info);
+	nand->data_desc = (void *)nand->data_buff + data_desc_offset;
+	nand->data_desc_addr = nand->data_buff_phys + data_desc_offset;
+	nand->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
+			pxa3xx_nand_data_dma_irq, nand);
+	if (nand->data_dma_ch < 0) {
+		dev_err(&pdev->dev, "failed to request data dma\n");
+		ret = -ENXIO;
+		goto fail_free_buf;
+	}
+success_exit:
 	return 0;

 fail_free_buf:
-	free_irq(irq, info);
-	if (use_dma) {
-		pxa_free_dma(info->data_dma_ch);
-		dma_free_coherent(&pdev->dev, info->data_buff_size,
-			info->data_buff, info->data_buff_phys);
-	} else
-		kfree(info->data_buff);
-fail_free_io:
-	iounmap(info->mmio_base);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		info = nand->info[cs];
+		free_cs_resource(info, cs);
+	}
+fail_free_irq:
+	free_irq(irq, nand);
+	iounmap(nand->mmio_base);
 fail_free_res:
 	release_mem_region(r->start, resource_size(r));
 fail_put_clk:
-	clk_disable(info->clk);
-	clk_put(info->clk);
-fail_free_mtd:
-	kfree(mtd);
+	clk_disable(nand->clk);
+	clk_put(nand->clk);
+fail_alloc:
+	kfree(nand);
 	return ret;
 }

 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand *nand = platform_get_drvdata(pdev);
+	struct pxa3xx_nand_info *info;
+	struct mtd_info *mtd;
 	struct resource *r;
-	int irq;
+	int irq, cs;

 	platform_set_drvdata(pdev, NULL);

-	del_mtd_device(mtd);
-	del_mtd_partitions(mtd);
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0)
-		free_irq(irq, info);
-	if (use_dma) {
-		pxa_free_dma(info->data_dma_ch);
-		dma_free_writecombine(&pdev->dev, info->data_buff_size,
-				info->data_buff, info->data_buff_phys);
-	} else
-		kfree(info->data_buff);
-
-	iounmap(info->mmio_base);
+		free_irq(irq, nand);
+
+	iounmap(nand->mmio_base);
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(r->start, resource_size(r));
-
-	clk_disable(info->clk);
-	clk_put(info->clk);
-
-	kfree(mtd);
+	clk_disable(nand->clk);
+	clk_put(nand->clk);
+
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		info = nand->info[cs];
+		if (!info)
+			continue;
+		mtd = get_mtd_by_info(info);
+		del_mtd_partitions(mtd);
+		del_mtd_device(mtd);
+		free_cs_resource(info, cs);
+	}
 	return 0;
 }

@@ -1151,7 +1160,11 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
-	int ret;
+	struct pxa3xx_nand *nand;
+	struct mtd_info *mtd;
+	static const char *probes[] = { "cmdlinepart", NULL };
+	struct mtd_partition *parts;
+	int nr_parts, ret, cs, probe_success = 0;

 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1163,25 +1176,30 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 	if (ret)
 		return ret;

-	info = platform_get_drvdata(pdev);
-	if (pxa3xx_nand_scan(info->mtd)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
-		pxa3xx_nand_remove(pdev);
-		return -ENODEV;
-	}
-
-	if (mtd_has_cmdlinepart()) {
-		static const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
-
-		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
-
-		if (nr_parts)
-			return add_mtd_partitions(info->mtd, parts, nr_parts);
+	nand = platform_get_drvdata(pdev);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+		info = nand->info[cs];
+		mtd = get_mtd_by_info(info);
+		if (pxa3xx_nand_scan(mtd)) {
+			dev_err(&pdev->dev, "failed to scan cs#%d nand\n", cs);
+			continue;
+		}
+		nr_parts = 0;
+		if (mtd_has_cmdlinepart()) {
+			nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
+			if (nr_parts)
+				ret = add_mtd_partitions(mtd, parts, nr_parts);
+		}
+		if (!nr_parts)
+			ret = add_mtd_partitions(mtd, pdata->parts[cs],
+					pdata->nr_parts[cs]);
+		if (!ret)
+			probe_success = 1;
 	}

-	return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
+	if (!probe_success)
+		pxa3xx_nand_remove(pdev);
+	return ret;
 }

 #ifdef CONFIG_PM
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 09:52:09 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 21:52:09 +0800
Subject: [PATCH 14/29] pxa3xx_nand: add bch ecc support
Message-ID: <mailman.119.1280296784.27306.linux-mtd@lists.infradead.org>

Enable the controller internal bch ecc engine when need.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   11 ++-
 drivers/mtd/nand/pxa3xx_nand.c               |  119 ++++++++++++++++++-------
 2 files changed, 94 insertions(+), 36 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index cf42f97..9b1f9df 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -3,6 +3,12 @@

 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+/* error code and state */
+enum {
+	ECC_NONE = 0,
+	ECC_HAMMIN,
+	ECC_BCH,
+};

 struct pxa3xx_nand_timing {
 	unsigned int	tCH;  /* Enable signal hold time */
@@ -32,10 +38,11 @@ struct pxa3xx_nand_cmdset {
 struct pxa3xx_nand_flash {
 	char		*name;
 	uint32_t	chip_id;
-	uint16_t	page_per_block; /* Pages per block (PG_PER_BLK) */
-	uint16_t 	page_size;	/* Page size in bytes (PAGE_SZ) */
+	uint16_t	page_per_block; /* Pages per block */
+	uint16_t 	page_size;	/* Page size in bytes */
 	uint8_t		flash_width;	/* Width of Flash memory (DWIDTH_M) */
 	uint8_t 	dfc_width;	/* Width of flash controller(DWIDTH_C) */
+	uint8_t		ecc_type;	/* Which ECC is applied */
 	uint32_t	num_blocks;	/* Number of physical blocks in Flash */
 	struct pxa3xx_nand_cmdset *cmdset;	/* NAND command set */
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 3dea0fe..94df2bd 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -29,6 +29,7 @@
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
 #define NAND_STOP_DELAY		(2 * HZ/50)
 #define PAGE_CHUNK_SIZE		(2048)
+#define BCH_THRESHOLD           (8)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -38,12 +39,15 @@
 #define NDPCR		(0x18) /* Page Count Register */
 #define NDBDR0		(0x1C) /* Bad Block Register 0 */
 #define NDBDR1		(0x20) /* Bad Block Register 1 */
+#define NDECCCTRL	(0x28) /* ECC Control Register */
 #define NDDB		(0x40) /* Data Buffer */
 #define NDCB0		(0x48) /* Command Buffer0 */
 #define NDCB1		(0x4C) /* Command Buffer1 */
 #define NDCB2		(0x50) /* Command Buffer2 */

 #define NDCR_SPARE_EN		(0x1 << 31)
+#define NDSR_ERR_CNT_MASK       (0x1F << 16)
+#define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
 #define NDCR_ECC_EN		(0x1 << 30)
 #define NDCR_DMA_EN		(0x1 << 29)
 #define NDCR_ND_RUN		(0x1 << 28)
@@ -90,6 +94,13 @@
 #define NDCB0_CMD1_MASK		(0xff)
 #define NDCB0_ADDR_CYC_SHIFT	(16)

+/* ECC Control Register */
+#define NDECCCTRL_ECC_SPARE_MSK (0xFF << 7)
+#define NDECCCTRL_ECC_SPARE(x)  (((x) << 7) & NDECCCTRL_ECC_SPARE_MSK)
+#define NDECCCTRL_ECC_THR_MSK   (0x3F << 1)
+#define NDECCCTRL_ECC_THRESH(x) (((x) << 1) & NDECCCTRL_ECC_THR_MSK)
+#define NDECCCTRL_BCH_EN        (0x1)
+
 /* macros for registers read/write */
 #define nand_writel(info, off, val)	\
 	__raw_writel((val), (info)->mmio_base + (off))
@@ -215,16 +226,16 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 #define NAND_SETTING_MICRON      &default_cmdset, &timing[2]
 #define NAND_SETTING_ST          &default_cmdset, &timing[3]
 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, NAND_SETTING_DEFAULT, },
-{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, NAND_SETTING_SAMSUNG, },
-{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, NAND_SETTING_SAMSUNG, },
-{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, 4096, NAND_SETTING_SAMSUNG, },
-{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, NAND_SETTING_SAMSUNG, },
-{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, NAND_SETTING_MICRON, },
-{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, NAND_SETTING_MICRON, },
-{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, NAND_SETTING_MICRON, },
-{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, NAND_SETTING_MICRON, },
-{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, NAND_SETTING_ST, },
+{ "DEFAULT FLASH",      0,   0, 2048,  8,  8, ECC_NONE,      0,
NAND_SETTING_DEFAULT, },
+{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, ECC_HAMMIN, 4096,
NAND_SETTING_SAMSUNG, },
+{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, ECC_HAMMIN, 2048,
NAND_SETTING_SAMSUNG, },
+{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, ECC_BCH,    4096,
NAND_SETTING_SAMSUNG, },
+{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, ECC_BCH,    8192,
NAND_SETTING_SAMSUNG, },
+{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, ECC_HAMMIN, 1024,
NAND_SETTING_MICRON, },
+{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, ECC_HAMMIN, 1024,
NAND_SETTING_MICRON, },
+{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, ECC_HAMMIN, 4096,
NAND_SETTING_MICRON, },
+{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, ECC_HAMMIN, 4096,
NAND_SETTING_MICRON, },
+{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, ECC_HAMMIN, 2048,
NAND_SETTING_ST, },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
@@ -273,19 +284,43 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 	struct pxa3xx_nand *nand = info->nand_data;
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;

-	nand->data_size = info->page_size;
-	if (!oob_enable) {
-		nand->oob_size = 0;
-		return;
-	}
+	if (info->page_size >= PAGE_CHUNK_SIZE) {
+		nand->data_size = PAGE_CHUNK_SIZE;
+		if (!oob_enable) {
+			nand->oob_size = 0;
+			return;
+		}

-	switch (info->page_size) {
-	case 2048:
-		nand->oob_size = (nand->use_ecc) ? 40 : 64;
-		break;
-	case 512:
-		nand->oob_size = (nand->use_ecc) ? 8 : 16;
-		break;
+		switch (nand->use_ecc) {
+		case ECC_HAMMIN:
+			nand->oob_size = 40;
+			break;
+		case ECC_BCH:
+			nand->oob_size = 32;
+			break;
+		default:
+			nand->oob_size = 64;
+			break;
+		}
+	} else {
+		nand->data_size = 512;
+		if (!oob_enable) {
+			nand->oob_size = 0;
+			return;
+		}
+
+		switch (nand->use_ecc) {
+		case ECC_HAMMIN:
+			nand->oob_size = 8;
+			break;
+		case ECC_BCH:
+			printk("Don't support BCH on small page device!!!\n");
+			BUG();
+			break;
+		default:
+			nand->oob_size = 16;
+			break;
+		}
 	}
 }

@@ -298,16 +333,26 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 static void pxa3xx_nand_start(struct pxa3xx_nand *nand)
 {
 	struct pxa3xx_nand_info *info;
-	uint32_t ndcr;
+	uint32_t ndcr, ndeccctrl = 0;

 	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
-	ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
 	ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
 	ndcr |= NDCR_ND_RUN;

+	switch (nand->use_ecc) {
+	case ECC_BCH:
+		ndeccctrl |= NDECCCTRL_BCH_EN;
+		ndeccctrl |= NDECCCTRL_ECC_THRESH(BCH_THRESHOLD);
+	case ECC_HAMMIN:
+		ndcr |= NDCR_ECC_EN;
+	default:
+		break;
+	}
+
 	/* clear status bits and run */
 	nand_writel(nand, NDCR, 0);
+	nand_writel(nand, NDECCCTRL, ndeccctrl);
 	nand_writel(nand, NDSR, NDSR_MASK);
 	nand_writel(nand, NDCR, ndcr);
 }
@@ -420,6 +465,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	info            = nand->info[cs];

 	status = nand_readl(nand, NDSR);
+	nand->bad_count = (status & NDSR_ERR_CNT_MASK) >> 16;
 	if (status & NDSR_DBERR)
 		nand->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
@@ -498,7 +544,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	switch (command) {
 	case NAND_CMD_READ0:
 	case NAND_CMD_PAGEPROG:
-		nand->use_ecc = 1;
+		nand->use_ecc = info->use_ecc;
 	case NAND_CMD_READOOB:
 		pxa3xx_set_datasize(info);
 		nand->oob_buff = nand->data_buff + nand->data_size;
@@ -757,6 +803,7 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 		return -EINVAL;

 	/* calculate flash information */
+	info->use_ecc = f->ecc_type;
 	info->cmdset = f->cmdset;
 	info->page_size = f->page_size;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
@@ -780,7 +827,6 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */

 	info->reg_ndcr = ndcr;
-	info->use_ecc = 1;

 	pxa3xx_nand_set_timing(info, f->timing);
 	return 0;
@@ -790,6 +836,7 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)
 {
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
 	uint32_t ndcr = nand_readl(nand, NDCR);
+	uint32_t ndeccctrl = nand_readl(nand, NDECCCTRL);

 	if (nand->chip_select > 0) {
 		printk(KERN_ERR "We could not detect configure if two cs is supported!!\n");
@@ -802,6 +849,7 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)

 	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
+	info->use_ecc = (ndeccctrl & NDECCCTRL_BCH_EN) ? ECC_BCH : ECC_HAMMIN;
 	info->cmdset = &default_cmdset;

 	return 0;
@@ -837,13 +885,16 @@ static int pxa3xx_nand_read_page_hwecc(struct
mtd_info *mtd,

 	if (nand->retcode == ERR_SBERR) {
 		switch (nand->use_ecc) {
-			case 1:
-				mtd->ecc_stats.corrected++;
-				break;
-
-			case 0:
-			default:
-				break;
+		case ECC_BCH:
+			if (nand->bad_count > BCH_THRESHOLD)
+				mtd->ecc_stats.corrected +=
+					(nand->bad_count - BCH_THRESHOLD);
+			break;
+		case ECC_HAMMIN:
+			mtd->ecc_stats.corrected ++;
+		case ECC_NONE:
+		default:
+			break;
 		}
 	} else if (nand->retcode == ERR_DBERR) {
 		int buf_blank;
@@ -1026,8 +1077,8 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	nand->mmio_phys = r->start;

 	/* initialize all interrupts to be disabled */
-	disable_int(nand, NDSR_MASK);
 	irq = platform_get_irq(pdev, 0);
+	disable_int(nand, NDCR_INT_MASK);
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		ret = -ENXIO;
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 10:08:13 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 22:08:13 +0800
Subject: [PATCH 15/29] pxa3xx_nand: add more attribute that platform
Message-ID: <mailman.120.1280296786.27306.linux-mtd@lists.infradead.org>

could choose from

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c                 |    3 ++-
 arch/arm/mach-mmp/avengers_lite.c            |    3 ++-
 arch/arm/mach-pxa/cm-x300.c                  |    3 +--
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    3 +--
 arch/arm/mach-pxa/littleton.c                |    2 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    3 +--
 arch/arm/mach-pxa/raumfeld.c                 |    3 +--
 arch/arm/mach-pxa/zylonite.c                 |    2 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   23 +++++++++++++----------
 drivers/mtd/nand/pxa3xx_nand.c               |   11 +++++++----
 10 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 81ad58d..8d739d1 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -125,7 +125,8 @@ static struct mtd_partition aspenite_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
-	.enable_arbiter	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_NAKED_CMD_EN | PXA3XX_DMA_EN
+				| PXA3XX_ADV_TIME_TUNING | PXA3XX_TWO_CHIP_EN,
 	.parts[0]	= aspenite_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(aspenite_nand_partitions),
 };
diff --git a/arch/arm/mach-mmp/avengers_lite.c
b/arch/arm/mach-mmp/avengers_lite.c
index a828b1c..3a07613 100644
--- a/arch/arm/mach-mmp/avengers_lite.c
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -77,7 +77,8 @@ static void __init avengers_init_flash(void)
 	avengers_nand_info.nr_parts[0] = ARRAY_SIZE(avengers_nand_partitions_0);
 	avengers_nand_info.parts[1] = avengers_nand_partitions_1;
 	avengers_nand_info.nr_parts[1] = ARRAY_SIZE(avengers_nand_partitions_1);
-	avengers_nand_info.enable_arbiter = 1;
+	avengers_nand_info.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_NAKED_CMD_EN
+		| PXA3XX_DMA_EN | PXA3XX_ADV_TIME_TUNING | PXA3XX_TWO_CHIP_EN;
 	pxa168_add_nand(&avengers_nand_info);
 }

diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index ce1f6d3..9f0282b 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -417,8 +417,7 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= cm_x300_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(cm_x300_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c
b/arch/arm/mach-pxa/colibri-pxa3xx.c
index b33559c..627b289 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -186,8 +186,7 @@ static struct mtd_partition colibri_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data colibri_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= colibri_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(colibri_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 717cf92..e63451c 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -324,7 +324,7 @@ static struct mtd_partition littleton_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data littleton_nand_info = {
-	.enable_arbiter	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN,
 	.parts[0]	= littleton_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(littleton_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index 66c2086..baca736 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,8 +389,7 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= mxm_8x10_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(mxm_8x10_nand_partitions)
 };
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index df75d4d..8761775 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -348,8 +348,7 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
-	.enable_arbiter	= 1,
-	.keep_config	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN | PXA3XX_KEEP_CONFIG,
 	.parts[0]	= raumfeld_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(raumfeld_nand_partitions),
 };
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 9e5c6cd..5cf3d10 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -355,7 +355,7 @@ static struct mtd_partition zylonite_nand_partitions[] = {
 };

 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
-	.enable_arbiter	= 1,
+	.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_DMA_EN,
 	.parts[0]	= zylonite_nand_partitions,
 	.nr_parts[0]	= ARRAY_SIZE(zylonite_nand_partitions),
 };
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 9b1f9df..ed7d623 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -49,17 +49,20 @@ struct pxa3xx_nand_flash {
 };

 #define NUM_CHIP_SELECT		(2)
+/* the data flash bus is shared between the Static Memory
+ * Controller and the Data Flash Controller,  the arbiter
+ * controls the ownership of the bus
+ */
+#define PXA3XX_ARBI_EN		(1)
+#define PXA3XX_NAKED_CMD_EN	(1 << 1)
+#define PXA3XX_TWO_CHIP_EN	(1 << 2)
+#define PXA3XX_DMA_EN		(1 << 3)
+/* for newer controller support more precise timing tuning, only
+ * enable such tuning for those platform which support it */
+#define PXA3XX_ADV_TIME_TUNING	(1 << 4)
+#define PXA3XX_KEEP_CONFIG	(1 << 5)
 struct pxa3xx_nand_platform_data {
-
-	/* the data flash bus is shared between the Static Memory
-	 * Controller and the Data Flash Controller,  the arbiter
-	 * controls the ownership of the bus
-	 */
-	int	enable_arbiter;
-
-	/* allow platform code to keep OBM/bootloader defined NFC config */
-	int	keep_config;
-
+	unsigned int				controller_attrs;
 	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
 	unsigned int				nr_parts[NUM_CHIP_SELECT];

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 94df2bd..204c9d6 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -816,7 +816,7 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	else
 		info->row_addr_cycles = 2;

-	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
+	ndcr |= (pdata->controller_attrs & PXA3XX_ARBI_EN) ? NDCR_ND_ARB_EN : 0;
 	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
 	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
@@ -947,7 +947,7 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret;

-	if (pdata->keep_config) {
+	if (pdata->controller_attrs & PXA3XX_KEEP_CONFIG) {
 		if (pxa3xx_nand_detect_config(nand) == 0)
 			goto KEEP_CONFIG;
 	}
@@ -1215,7 +1215,7 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 	struct mtd_info *mtd;
 	static const char *probes[] = { "cmdlinepart", NULL };
 	struct mtd_partition *parts;
-	int nr_parts, ret, cs, probe_success = 0;
+	int nr_parts, ret, cs, probe_success = 0, cs_to_scan;

 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1223,12 +1223,15 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 		return -ENODEV;
 	}

+	if (!(pdata->controller_attrs & PXA3XX_DMA_EN))
+		use_dma = 0;
 	ret = alloc_nand_resource(pdev);
 	if (ret)
 		return ret;

 	nand = platform_get_drvdata(pdev);
-	for (cs = 0; cs < NUM_CHIP_SELECT; cs++) {
+	cs_to_scan = (pdata->controller_attrs & PXA3XX_TWO_CHIP_EN)? 2 : 1;
+	for (cs = 0; cs < cs_to_scan; cs++) {
 		info = nand->info[cs];
 		mtd = get_mtd_by_info(info);
 		if (pxa3xx_nand_scan(mtd)) {
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 10:29:21 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 22:29:21 +0800
Subject: [PATCH 16/29] pxa3xx_nand: enable 4k page operation
Message-ID: <mailman.122.1280296804.27306.linux-mtd@lists.infradead.org>

For limitation of our controller, we only could do large page
nand chip by dividing the original page size into what we could
afford. We call one divide operation as chunk.

The divide operation need naked command support, which may not
be existed in so old version. You should check it first before
you want to use this feature.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  363 +++++++++++++++++++++++++++++++---------
 1 files changed, 284 insertions(+), 79 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 204c9d6..45c9660 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -29,7 +29,10 @@
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
 #define NAND_STOP_DELAY		(2 * HZ/50)
 #define PAGE_CHUNK_SIZE		(2048)
+#define OOB_CHUNK_SIZE		(64)
 #define BCH_THRESHOLD           (8)
+#define CMD_POOL_SIZE           (5)
+#define READ_ID_BYTES		(4)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -39,33 +42,50 @@
 #define NDPCR		(0x18) /* Page Count Register */
 #define NDBDR0		(0x1C) /* Bad Block Register 0 */
 #define NDBDR1		(0x20) /* Bad Block Register 1 */
+#define NDREDEL		(0x24) /* Read Enable Return Delay Register */
 #define NDECCCTRL	(0x28) /* ECC Control Register */
+#define NDBZCNT		(0x2C) /* Timer for NDRnB0 and NDRnB1 */
 #define NDDB		(0x40) /* Data Buffer */
 #define NDCB0		(0x48) /* Command Buffer0 */
 #define NDCB1		(0x4C) /* Command Buffer1 */
 #define NDCB2		(0x50) /* Command Buffer2 */

 #define NDCR_SPARE_EN		(0x1 << 31)
-#define NDSR_ERR_CNT_MASK       (0x1F << 16)
-#define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
 #define NDCR_ECC_EN		(0x1 << 30)
 #define NDCR_DMA_EN		(0x1 << 29)
 #define NDCR_ND_RUN		(0x1 << 28)
 #define NDCR_DWIDTH_C		(0x1 << 27)
 #define NDCR_DWIDTH_M		(0x1 << 26)
-#define NDCR_PAGE_SZ		(0x1 << 24)
-#define NDCR_NCSX		(0x1 << 23)
-#define NDCR_ND_MODE		(0x3 << 21)
+#define NDCR_PAGE_SZ_MASK	(0x3 << 24)
+#define NDCR_PAGE_SZ(x)		(((x) << 24) & NDCR_PAGE_SZ_MASK)
+#define NDCR_SEQ_DIS		(0x1 << 23)
+#define NDCR_ND_STOP		(0x1 << 22)
+#define NDCR_FORCE_CSX		(0x1 << 21)
 #define NDCR_CLR_PG_CNT		(0x1 << 20)
 #define NDCR_STOP_ON_UNCOR	(0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK	(0x7 << 16)
 #define NDCR_RD_ID_CNT(x)	(((x) << 16) & NDCR_RD_ID_CNT_MASK)

 #define NDCR_RA_START		(0x1 << 15)
-#define NDCR_PG_PER_BLK		(0x1 << 14)
+#define NDCR_PG_PER_BLK_MASK	(0x3 << 13)
+#define NDCR_PG_PER_BLK(x)	(((x) << 13) & NDCR_PG_PER_BLK_MASK)
 #define NDCR_ND_ARB_EN		(0x1 << 12)
 #define NDCR_INT_MASK           (0xFFF)
+#define NDCR_RDYM               (0x1 << 11)
+#define NDCR_CS0_PAGEDM         (0x1 << 10)
+#define NDCR_CS1_PAGEDM         (0x1 << 9)
+#define NDCR_CS0_CMDDM          (0x1 << 8)
+#define NDCR_CS1_CMDDM          (0x1 << 7)
+#define NDCR_CS0_BBDM           (0x1 << 6)
+#define NDCR_CS1_BBDM           (0x1 << 5)
+#define NDCR_UNCERRM            (0x1 << 4)
+#define NDCR_CORERRM            (0x1 << 3)
+#define NDCR_WRDREQM            (0x1 << 2)
+#define NDCR_RDDREQM            (0x1 << 1)
+#define NDCR_WRCMDREQM          (0x1)

+#define NDSR_ERR_CNT_MASK       (0x1F << 16)
+#define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
 #define NDSR_MASK		(0xfff)
 #define NDSR_RDY                (0x1 << 12)
 #define NDSR_FLASH_RDY          (0x1 << 11)
@@ -81,6 +101,8 @@
 #define NDSR_RDDREQ		(0x1 << 1)
 #define NDSR_WRCMDREQ		(0x1)

+#define NDCB0_CMD_XTYPE_MASK    (0x7 << 29)
+#define NDCB0_CMD_XTYPE(x)      (((x) << 29) & NDCB0_CMD_XTYPE_MASK)
 #define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS		(0x1 << 25)
 #define NDCB0_CSEL		(0x1 << 24)
@@ -110,6 +132,7 @@
 #define get_mtd_by_info(info)		\
 	(struct mtd_info *)((void *)info - sizeof(struct mtd_info))

+#define STATE_MASK		(0x3f)
 /* error code and state */
 enum {
 	ERR_NONE	= 0,
@@ -142,7 +165,6 @@ struct pxa3xx_nand_info {
 	/* calculated from pxa3xx_nand_flash data */
 	uint8_t			col_addr_cycles;
 	uint8_t			row_addr_cycles;
-	uint8_t			read_id_bytes;

 	/* cached register value */
 	uint32_t		reg_ndcr;
@@ -178,7 +200,8 @@ struct pxa3xx_nand {
 	unsigned char		*oob_buff;
 	uint32_t		buf_start;
 	uint32_t		buf_count;
-	uint8_t			total_cmds;
+	uint16_t		data_column;
+	uint16_t		oob_column;

 	/* relate to the command */
 	uint8_t			chip_select;
@@ -187,8 +210,11 @@ struct pxa3xx_nand {
 	int			use_dma;	/* use DMA ? */
 	int 			retcode;

-	/* generated NDCBx register values */
-	uint32_t		ndcb0;
+	/* cached register value */
+	uint8_t			cmd_seqs;
+	uint8_t			total_cmds;
+	uint8_t			wait_ready[CMD_POOL_SIZE];
+	uint32_t		ndcb0[CMD_POOL_SIZE];
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;
 };
@@ -235,6 +261,7 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 { "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, ECC_HAMMIN, 1024,
NAND_SETTING_MICRON, },
 { "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, ECC_HAMMIN, 4096,
NAND_SETTING_MICRON, },
 { "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, ECC_HAMMIN, 4096,
NAND_SETTING_MICRON, },
+{ "1GiB 8-bit",    0x382c, 128, 4096,  8,  8, ECC_BCH,    2048,
NAND_SETTING_MICRON },
 { "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, ECC_HAMMIN, 2048,
NAND_SETTING_ST, },
 };

@@ -392,41 +419,98 @@ static void disable_int(struct pxa3xx_nand
*nand, uint32_t int_mask)
 	nand_writel(nand, NDCR, ndcr | int_mask);
 }

+static void nand_error_dump(struct pxa3xx_nand *nand)
+{
+	int i;
+
+	printk(KERN_ERR "NAND controller state wrong!!!\n");
+	printk(KERN_ERR "command %x, state %x, current seqs %d, errcode %x,
bad count %d\n",
+			nand->command, nand->state, nand->cmd_seqs,
+			nand->retcode, nand->bad_count);
+	printk(KERN_ERR "Totally %d command for sending\n",
+			nand->total_cmds);
+	for (i = 0; i < nand->total_cmds; i ++)
+		printk(KERN_ERR "NDCB0:%d: %x\n",
+				i, nand->ndcb0[i]);
+	printk(KERN_ERR "NDCB1: %x; NDCB2 %x\n", nand->ndcb1, nand->ndcb2);
+
+	printk(KERN_ERR "\nRegister DUMPing ##############\n");
+	printk(KERN_ERR "NDCR %x\n"
+			"NDSR %x\n"
+			"NDCB0 %x\n"
+			"NDCB1 %x\n"
+			"NDCB2 %x\n"
+			"NDTR0CS0 %x\n"
+			"NDTR1CS0 %x\n"
+			"NDBDR0 %x\n"
+			"NDBDR1 %x\n"
+			"NDREDEL %x\n"
+			"NDECCCTRL %x\n"
+			"NDBZCNT %x\n\n",
+			nand_readl(nand, NDCR),
+			nand_readl(nand, NDSR),
+			nand_readl(nand, NDCB0),
+			nand_readl(nand, NDCB1),
+			nand_readl(nand, NDCB2),
+			nand_readl(nand, NDTR0CS0),
+			nand_readl(nand, NDTR1CS0),
+			nand_readl(nand, NDBDR0),
+			nand_readl(nand, NDBDR1),
+			nand_readl(nand, NDREDEL),
+			nand_readl(nand, NDECCCTRL),
+			nand_readl(nand, NDBZCNT));
+}
+
 static void handle_data_pio(struct pxa3xx_nand *nand)
 {
+	unsigned int data_size, oob_size;
+
+	data_size = DIV_ROUND_UP(nand->data_size, 4);
+	oob_size = DIV_ROUND_UP(nand->oob_size, 4);
 	if (nand->state & STATE_IS_WRITE) {
-		__raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
-				DIV_ROUND_UP(nand->data_size, 4));
+		__raw_writesl(nand->mmio_base + NDDB,
+				nand->data_buff + nand->data_column, data_size);
 		if (nand->oob_size > 0)
-			__raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
-					DIV_ROUND_UP(nand->oob_size, 4));
-
+			__raw_writesl(nand->mmio_base + NDDB,
+				nand->oob_buff + nand->oob_column, oob_size);
 	}
 	else {
-		__raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
-				DIV_ROUND_UP(nand->data_size, 4));
+		__raw_readsl(nand->mmio_base + NDDB,
+				nand->data_buff + nand->data_column, data_size);
 		if (nand->oob_size > 0)
-			__raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
-					DIV_ROUND_UP(nand->oob_size, 4));
+			__raw_readsl(nand->mmio_base + NDDB,
+				nand->oob_buff + nand->oob_column, oob_size);
 	}
+	nand->data_column += (data_size << 2);
+	nand->oob_column += (oob_size << 2);
 }

 static void start_data_dma(struct pxa3xx_nand *nand, int dir_out)
 {
+	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
 	struct pxa_dma_desc *desc = nand->data_desc;
-	int dma_len = ALIGN(nand->data_size + nand->oob_size, 32);
-
-	desc->ddadr = DDADR_STOP;
-	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
+	struct pxa_dma_desc *desc_oob = nand->data_desc + 1;
+	unsigned int data_len = ALIGN(nand->data_size, 32);
+	unsigned int oob_len = ALIGN(nand->oob_size, 32);

+	desc_oob->ddadr = desc->ddadr = DDADR_STOP;
+	desc_oob->dcmd = desc->dcmd = DCMD_WIDTH4 | DCMD_BURST32;
 	if (dir_out) {
-		desc->dsadr = nand->data_buff_phys;
+		desc->dsadr = nand->data_buff_phys + nand->data_column;
 		desc->dtadr = nand->mmio_phys + NDDB;
-		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
+		desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG |
(data_len + oob_len);
 	} else {
-		desc->dtadr = nand->data_buff_phys;
-		desc->dsadr = nand->mmio_phys + NDDB;
-		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+		if (nand->oob_size > 0) {
+			desc_oob->dtadr = nand->data_buff_phys
+					+ info->page_size + nand->oob_column;
+			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | oob_len;
+			desc->ddadr = nand->data_desc_addr + sizeof(struct pxa_dma_desc);
+			desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
+		}
+		else
+			desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
+		desc->dtadr = nand->data_buff_phys + nand->data_column;
+		desc_oob->dsadr = desc->dsadr = nand->mmio_phys + NDDB;
 	}

 	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
@@ -446,6 +530,8 @@ static void pxa3xx_nand_data_dma_irq(int channel,
void *data)
 		nand->retcode = ERR_DMABUSERR;
 	}

+	nand->data_column += nand->data_size;
+	nand->oob_column += nand->oob_size;
 	enable_int(nand, NDCR_INT_MASK);
 	nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }
@@ -454,7 +540,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand *nand = devid;
 	struct pxa3xx_nand_info *info;
-	unsigned int status, is_completed = 0, cs;
+	unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2;
 	unsigned int ready, cmd_done, page_done, badblock_detect;

 	cs		= nand->chip_select;
@@ -463,13 +549,14 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	page_done       = (cs) ? NDSR_CS1_PAGED : NDSR_CS0_PAGED;
 	badblock_detect = (cs) ? NDSR_CS1_BBD : NDSR_CS0_BBD;
 	info            = nand->info[cs];
+	cmd_seqs	= nand->cmd_seqs;

 	status = nand_readl(nand, NDSR);
 	nand->bad_count = (status & NDSR_ERR_CNT_MASK) >> 16;
-	if (status & NDSR_DBERR)
-		nand->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
 		nand->retcode = ERR_SBERR;
+	if (status & NDSR_DBERR)
+		nand->retcode = ERR_DBERR;
 	if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {

 		nand->state |= STATE_DATA_PROCESSING;
@@ -483,24 +570,51 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)

 		nand->state |= STATE_DATA_DONE;
 	}
+	if (status & page_done)
+		nand->state |= STATE_PAGE_DONE;
+	if (status & ready) {
+		nand->state |= STATE_READY;
+		if (nand->wait_ready[cmd_seqs]) {
+			enable_int(nand, NDCR_WRCMDREQM);
+			if (cmd_seqs == nand->total_cmds)
+				is_completed = 1;
+		}
+	}
 	if (status & cmd_done) {
 		nand->state |= STATE_CMD_DONE;
-		is_completed = 1;
+		if (cmd_seqs == nand->total_cmds && !nand->wait_ready[cmd_seqs])
+			is_completed = 1;
 	}
-	if (status & ready)
-		nand->state |= STATE_READY;
-	if (status & page_done)
-		nand->state |= STATE_PAGE_DONE;

 	if (status & NDSR_WRCMDREQ) {
-		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
 		status &= ~NDSR_WRCMDREQ;
-		nand->state |= STATE_CMD_WAIT_DONE;
-		nand_writel(nand, NDCB0, nand->ndcb0);
-		nand_writel(nand, NDCB0, nand->ndcb1);
-		nand_writel(nand, NDCB0, nand->ndcb2);
+		if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) {
+			disable_int(nand, NDCR_WRCMDREQM);
+			goto IRQ_FORCE_EXIT;
+		}
+
+		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
+		if (cmd_seqs < nand->total_cmds) {
+			nand->cmd_seqs ++;
+			if (cmd_seqs == 0) {
+				ndcb1 = nand->ndcb1;
+				ndcb2 = nand->ndcb2;
+			}
+			else {
+				ndcb1 = 0;
+				ndcb2 = 0;
+			}
+			nand->state &= ~STATE_MASK;
+			nand->state |= STATE_CMD_WAIT_DONE;
+			nand_writel(nand, NDCB0, nand->ndcb0[cmd_seqs]);
+			nand_writel(nand, NDCB0, ndcb1);
+			nand_writel(nand, NDCB0, ndcb2);
+		}
+		else
+			is_completed = 1;
 	}

+IRQ_FORCE_EXIT:
 	/* clear NDSR to let the controller exit the IRQ */
 	nand_writel(nand, NDSR, status);
 	if (is_completed)
@@ -521,7 +635,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
-	int addr_cycle, exec_cmd, ndcb0;
+	int addr_cycle, exec_cmd, ndcb0, i, chunks = 0;
 	struct mtd_info *mtd;
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];

@@ -531,14 +645,19 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	exec_cmd = 1;

 	/* reset data and oob column point to handle data */
+	nand->data_column	= 0;
+	nand->oob_column	= 0;
 	nand->buf_start		= 0;
 	nand->buf_count		= 0;
-	nand->ndcb0		= ndcb0;
+	nand->total_cmds	= 1;
+	nand->cmd_seqs		= 0;
 	nand->data_size		= 0;
 	nand->oob_size		= 0;
 	nand->use_ecc		= 0;
 	nand->use_dma		= 0;
 	nand->state		= 0;
+	nand->bad_count		= 0;
+	nand->retcode		= ERR_NONE;
 	nand->command		= command;

 	switch (command) {
@@ -549,6 +668,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		pxa3xx_set_datasize(info);
 		nand->oob_buff = nand->data_buff + nand->data_size;
 		nand->use_dma = use_dma;
+		chunks = info->page_size / nand->data_size;
 		break;
 	case NAND_CMD_SEQIN:
 		exec_cmd = 0;
@@ -559,6 +679,11 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		break;
 	}

+	/* clear the command buffer */
+	for (i = 0; i < CMD_POOL_SIZE; i ++) {
+		nand->ndcb0[i] = ndcb0;
+		nand->wait_ready[i] = 0;
+	}
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);

@@ -572,14 +697,37 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 			nand->buf_start = column;

 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
-		else
-			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
-					| NDCB0_DBC
-					| addr_cycle
-					| cmd;
+		else {
+			if (chunks == 1)
+				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
+						| NDCB0_DBC
+						| addr_cycle
+						| cmd;
+			else {
+				nand->total_cmds = chunks + 1;
+				nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
+						| NDCB0_CMD_TYPE(0)
+						| NDCB0_DBC
+						| NDCB0_NC
+						| addr_cycle
+						| cmd;
+
+				nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
+						| NDCB0_NC
+						| addr_cycle;
+
+				for (i = 2; i <= chunks; i ++)
+					nand->ndcb0[i] = nand->ndcb0[1];
+
+				nand->ndcb0[chunks] &= ~NDCB0_NC;
+				/* we should wait RnB go high again
+				 * before read out data*/
+				nand->wait_ready[1] = 1;
+			}
+		}

 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
@@ -612,18 +760,46 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 		cmd = info->cmdset->program;
 		nand->state |= STATE_IS_WRITE;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
-				| NDCB0_AUTO_RS
-				| NDCB0_ST_ROW_EN
-				| NDCB0_DBC
-				| cmd
-				| addr_cycle;
+		if (chunks == 1)
+			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0x1)
+					| NDCB0_AUTO_RS
+					| NDCB0_ST_ROW_EN
+					| NDCB0_DBC
+					| cmd
+					| addr_cycle;
+		else {
+			nand->total_cmds = chunks + 1;
+			nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x4)
+					| NDCB0_CMD_TYPE(0x1)
+					| NDCB0_NC
+					| NDCB0_AUTO_RS
+					| (cmd & NDCB0_CMD1_MASK)
+					| addr_cycle;
+
+			for (i = 1; i < chunks; i ++)
+				nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_CMD_TYPE(0x1)
+						| addr_cycle;
+
+			nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
+						| NDCB0_CMD_TYPE(0x1)
+						| NDCB0_ST_ROW_EN
+						| NDCB0_DBC
+						| (cmd & NDCB0_CMD2_MASK)
+						| NDCB0_CMD1_MASK
+						| addr_cycle;
+			/* we should wait for RnB goes high which
+			 * indicate the data has been written succesfully*/
+			nand->wait_ready[nand->total_cmds] = 1;
+		}
 		break;

 	case NAND_CMD_READID:
 		cmd = info->cmdset->read_id;
-		nand->buf_count = info->read_id_bytes;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(3)
+		nand->buf_count = READ_ID_BYTES;
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

@@ -632,7 +808,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	case NAND_CMD_STATUS:
 		cmd = info->cmdset->read_status;
 		nand->buf_count = 1;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(4)
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;

@@ -641,7 +817,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,

 	case NAND_CMD_ERASE1:
 		cmd = info->cmdset->erase;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(2)
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
 				| NDCB0_DBC
@@ -652,7 +828,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		break;
 	case NAND_CMD_RESET:
 		cmd = info->cmdset->reset;
-		nand->ndcb0 |= NDCB0_CMD_TYPE(5)
+		nand->ndcb0[0] |= NDCB0_CMD_TYPE(5)
 				| cmd;

 		break;
@@ -701,10 +877,10 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
 			dev_err(&nand->pdev->dev, "Wait time out!!!\n");
+			nand_error_dump(nand);
+			/* Stop State Machine for next command cycle */
+			pxa3xx_nand_stop(nand);
 		}
-		/* Stop State Machine for next command cycle */
-		pxa3xx_nand_stop(nand);
-		disable_int(nand, NDCR_INT_MASK);
 		nand->state &= ~STATE_CMD_PREPARED;
 	}
 }
@@ -796,20 +972,25 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	uint32_t ndcr = 0x00000FFF; /* disable all interrupts */

-	if (f->page_size != 2048 && f->page_size != 512)
+	if (f->page_size != 4096 && f->page_size != 2048 && f->page_size != 512)
 		return -EINVAL;

 	if (f->flash_width != 16 && f->flash_width != 8)
 		return -EINVAL;

+	if (f->page_size > PAGE_CHUNK_SIZE
+			&& !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
+		printk(KERN_ERR "Your controller don't support 4k or larger "
+			       "page NAND for don't support naked command\n");
+		return -EINVAL;
+	}
 	/* calculate flash information */
 	info->use_ecc = f->ecc_type;
 	info->cmdset = f->cmdset;
 	info->page_size = f->page_size;
-	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;

 	/* calculate addressing information */
-	info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+	info->col_addr_cycles = (f->page_size >= 2048) ? 2 : 1;

 	if (f->num_blocks * f->page_per_block > 65536)
 		info->row_addr_cycles = 3;
@@ -818,16 +999,39 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,

 	ndcr |= (pdata->controller_attrs & PXA3XX_ARBI_EN) ? NDCR_ND_ARB_EN : 0;
 	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
-	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
-	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
 	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
 	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	switch (f->page_per_block) {
+	case 32:
+		ndcr |= NDCR_PG_PER_BLK(0x0);
+		break;
+	case 128:
+		ndcr |= NDCR_PG_PER_BLK(0x1);
+		break;
+	case 256:
+		ndcr |= NDCR_PG_PER_BLK(0x3);
+		break;
+	case 64:
+	default:
+		ndcr |= NDCR_PG_PER_BLK(0x2);
+		break;
+	}

-	ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
+	switch (f->page_size) {
+	case 512:
+		ndcr |= NDCR_PAGE_SZ(0x0);
+		break;
+	case 2048:
+	default:
+		ndcr |= NDCR_PAGE_SZ(0x1);
+		ndcr |= NDCR_FORCE_CSX;
+		break;
+	}
+
+	ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */

 	info->reg_ndcr = ndcr;
-
 	pxa3xx_nand_set_timing(info, f->timing);
 	return 0;
 }
@@ -842,9 +1046,8 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)
 		printk(KERN_ERR "We could not detect configure if two cs is supported!!\n");
 		BUG();
 	}
-	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
+	info->page_size = ndcr & NDCR_PAGE_SZ_MASK ? 2048 : 512;
 	/* set info fields needed to read id */
-	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;

 	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
@@ -855,11 +1058,10 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)
 	return 0;
 }

-/* the maximum possible buffer size for large page with OOB data
- * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
- * data buffer and the DMA descriptor
+/* the max buff size should be large than the largest size
+ * of page of NAND flash that currently controller support
  */
-#define MAX_BUFF_SIZE	PAGE_SIZE
+#define MAX_BUFF_SIZE	((PAGE_CHUNK_SIZE + OOB_CHUNK_SIZE) * 2) +
sizeof(struct pxa_dma_desc) * 2
 static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
 	struct pxa3xx_nand *nand;
@@ -926,7 +1128,8 @@ static int __devinit pxa3xx_nand_sensing(struct
pxa3xx_nand *nand)
 	struct mtd_info *mtd = get_mtd_by_info(info);

 	/* use the common timing to make a try */
-	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	if (pxa3xx_nand_config_flash(info, &builtin_flash_types[0]))
+		return 0;
 	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	if (nand->state & STATE_READY)
 		return 1;
@@ -947,6 +1150,7 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret;

+	nand->chip_select = info->chip_select;
 	if (pdata->controller_attrs & PXA3XX_KEEP_CONFIG) {
 		if (pxa3xx_nand_detect_config(nand) == 0)
 			goto KEEP_CONFIG;
@@ -985,7 +1189,8 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd)
 		return -EINVAL;
 	}

-	pxa3xx_nand_config_flash(info, f);
+	if (pxa3xx_nand_config_flash(info, f))
+		return -EINVAL;
 	pxa3xx_flash_ids[0].name = f->name;
 	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
@@ -1021,7 +1226,7 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 	struct pxa3xx_nand *nand;
 	struct resource *r;
 	int ret, irq, cs;
-	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
+	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc) * 2;

 	nand = kzalloc(sizeof(struct pxa3xx_nand), GFP_KERNEL);
 	if (!nand) {
-- 
1.7.0.4


From leiwen at marvell.com  Thu Jun  3 03:46:50 2010
From: leiwen at marvell.com (Lei Wen)
Date: Thu, 3 Jun 2010 15:46:50 +0800
Subject: [PATCH 17/29] mmp: correct nand clock setting for pxa168 and pxa910
Message-ID: <mailman.123.1280296807.27306.linux-mtd@lists.infradead.org>

There is no clock setting at 208Mhz for nand on pxa168 and pxa910
platform. Set correct register and lock the clock at
156MHZ.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/pxa168.c |    2 +-
 arch/arm/mach-mmp/pxa910.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 652ae66..70d2231 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -78,7 +78,7 @@ static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
 static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
 static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);

-static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(nand, NAND, 0x19B, 156000000);

 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 46f2d69..96f2b61 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -110,7 +110,7 @@ static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
 static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
 static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);

-static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(nand, NAND, 0x19B, 156000000);

 /* device and clock bindings */
 static struct clk_lookup pxa910_clkregs[] = {
-- 
1.7.0.4


From leiwen at marvell.com  Thu Jun  3 04:21:04 2010
From: leiwen at marvell.com (Lei Wen)
Date: Thu, 3 Jun 2010 16:21:04 +0800
Subject: [PATCH 18/29] mmp: add nand support to mmp2
Message-ID: <mailman.125.1280296868.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/configs/mmp2_defconfig       |    4 +-
 arch/arm/mach-mmp/include/mach/mmp2.h |    6 ++++
 arch/arm/mach-mmp/jasper.c            |   52 +++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index 4b55dcb..e63dec3 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -469,7 +469,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
 #
 # User Modules And Translation Layers
 #
-# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
@@ -525,7 +525,7 @@ CONFIG_MTD_NAND=y
 # CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_PXA3xx is not set
+CONFIG_MTD_NAND_PXA3xx=y
 # CONFIG_MTD_NAND_NANDSIM is not set
 # CONFIG_MTD_NAND_PLATFORM is not set
 CONFIG_MTD_ONENAND=y
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h
b/arch/arm/mach-mmp/include/mach/mmp2.h
index fec220b..d68890b 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -4,6 +4,7 @@
 #include <linux/i2c.h>
 #include <mach/devices.h>
 #include <plat/i2c.h>
+#include <plat/pxa3xx_nand.h>

 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
@@ -15,6 +16,7 @@ extern struct pxa_device_desc mmp2_device_twsi3;
 extern struct pxa_device_desc mmp2_device_twsi4;
 extern struct pxa_device_desc mmp2_device_twsi5;
 extern struct pxa_device_desc mmp2_device_twsi6;
+extern struct pxa_device_desc mmp2_device_nand;

 static inline int mmp2_add_uart(int id)
 {
@@ -56,5 +58,9 @@ static inline int mmp2_add_twsi(int id, struct
i2c_pxa_platform_data *data,
 	return pxa_register_device(d, data, sizeof(*data));
 }

+static inline int mmp2_add_nand(struct pxa3xx_nand_platform_data *data)
+{
+	return pxa_register_device(&mmp2_device_nand, data, sizeof(*data));
+}
 #endif /* __ASM_MACH_MMP2_H */

diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index d77dd41..5d055f3 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -67,6 +67,57 @@ static unsigned long jasper_pin_config[] __initdata = {
 	PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
 };

+static struct mtd_partition jasper_nand_partitions[] = {
+	[0] = {
+		.name		= "Bootloader",
+		.offset		= 0,
+		.size		= 0x100000,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[1] = {
+		.name		= "Reserve",
+		.offset		= 0x100000,
+		.size		= 0x080000,
+	},
+	[2] = {
+		.name		= "Reserve",
+		.offset		= 0x180000,
+		.size		= 0x800000,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[3] = {
+		.name		= "Kernel",
+		.offset		= 0x980000,
+		.size		= 0x300000,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[4] = {
+		.name		= "system",
+		.offset		= 0x0c80000,
+		.size		= 0x7000000,
+	},
+	[5] = {
+		.name		= "userdata",
+		.offset		= 0x7c80000,
+		.size		= 0x7000000,
+	},
+	[6] = {
+		.name		= "filesystem",
+		.offset		= 0x0ec80000,
+		.size		= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct pxa3xx_nand_platform_data jasper_nand_info;
+static void __init jasper_init_flash(void)
+{
+	jasper_nand_info.controller_attrs = PXA3XX_ARBI_EN | PXA3XX_NAKED_CMD_EN
+		| PXA3XX_DMA_EN | PXA3XX_ADV_TIME_TUNING | PXA3XX_TWO_CHIP_EN;
+	jasper_nand_info.parts[0] = jasper_nand_partitions;
+	jasper_nand_info.nr_parts[0] = ARRAY_SIZE(jasper_nand_partitions);
+	mmp2_add_nand(&jasper_nand_info);
+}
+
 static struct regulator_consumer_supply max8649_supply[] = {
 	REGULATOR_SUPPLY("vcc_core", NULL),
 };
@@ -128,6 +179,7 @@ static void __init jasper_init(void)
 	/* on-chip devices */
 	mmp2_add_uart(1);
 	mmp2_add_uart(3);
+	jasper_init_flash();
 	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(jasper_twsi1_info));

 	regulator_has_full_constraints();
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 10:32:54 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 22:32:54 +0800
Subject: [PATCH 19/29] pxa3xx_nand: update ns2cycle calculation method
Message-ID: <mailman.126.1280296872.27306.linux-mtd@lists.infradead.org>

For the original method change from plus 1 to minus 1,
this way make the default timing like tCS become 0 after calculation,
although we set the timing as 0xa...

Change the method to no plus and minus, and make the result
closer to what the timing specified in the NAND chip spec.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 45c9660..50f653b 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -279,7 +279,7 @@ static const char *mtd_names[] = {"pxa3xx_nand-0",
"pxa3xx_nand-1", NULL};
 #define NDTR1_tAR(c)	(min((c), 15) << 0)

 /* convert nano-seconds to nand flash controller clock cycles */
-#define ns2cycle(ns, clk)	(int)(((ns) * (clk / 1000000) / 1000) - 1)
+#define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)

 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 10:47:13 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 22:47:13 +0800
Subject: [PATCH 20/29] pxa3xx_nand: use the buff passed from upper
Message-ID: <mailman.127.1280296875.27306.linux-mtd@lists.infradead.org>

layer if not use dma

For dma enabling case, we couldn't avoid the memcpy, for the buffer
in the upper layer may not be the physical consecutive.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  297 ++++++++++++++++++++++++----------------
 1 files changed, 181 insertions(+), 116 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 50f653b..048b576 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -158,6 +158,7 @@ struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;
 	struct pxa3xx_nand_cmdset *cmdset;
 	/* page size of attached chip */
+	int			page_addr;
 	uint16_t		page_size;
 	uint8_t			chip_select;
 	uint8_t			use_ecc;
@@ -186,8 +187,8 @@ struct pxa3xx_nand {
 	int			drcmr_dat;
 	int			drcmr_cmd;
 	int 			data_dma_ch;
-	dma_addr_t 		data_buff_phys;
-	dma_addr_t 		data_desc_addr;
+	dma_addr_t 		dma_buff_phys;
+	dma_addr_t 		dma_desc_addr;
 	struct pxa_dma_desc	*data_desc;

 	struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
@@ -496,25 +497,25 @@ static void start_data_dma(struct pxa3xx_nand
*nand, int dir_out)
 	desc_oob->ddadr = desc->ddadr = DDADR_STOP;
 	desc_oob->dcmd = desc->dcmd = DCMD_WIDTH4 | DCMD_BURST32;
 	if (dir_out) {
-		desc->dsadr = nand->data_buff_phys + nand->data_column;
+		desc->dsadr = nand->dma_buff_phys + nand->data_column;
 		desc->dtadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG |
(data_len + oob_len);
 	} else {
 		if (nand->oob_size > 0) {
-			desc_oob->dtadr = nand->data_buff_phys
+			desc_oob->dtadr = nand->dma_buff_phys
 					+ info->page_size + nand->oob_column;
 			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | oob_len;
-			desc->ddadr = nand->data_desc_addr + sizeof(struct pxa_dma_desc);
+			desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc);
 			desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
 		}
 		else
 			desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
-		desc->dtadr = nand->data_buff_phys + nand->data_column;
+		desc->dtadr = nand->dma_buff_phys + nand->data_column;
 		desc_oob->dsadr = desc->dsadr = nand->mmio_phys + NDDB;
 	}

 	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
-	DDADR(nand->data_dma_ch) = nand->data_desc_addr;
+	DDADR(nand->data_dma_ch) = nand->dma_desc_addr;
 	DCSR(nand->data_dma_ch) |= DCSR_RUN;
 }

@@ -638,6 +639,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	int addr_cycle, exec_cmd, ndcb0, i, chunks = 0;
 	struct mtd_info *mtd;
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
+	struct platform_device *pdev = nand->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;

 	mtd = get_mtd_by_info(info);
 	ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;;
@@ -647,8 +650,6 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	/* reset data and oob column point to handle data */
 	nand->data_column	= 0;
 	nand->oob_column	= 0;
-	nand->buf_start		= 0;
-	nand->buf_count		= 0;
 	nand->total_cmds	= 1;
 	nand->cmd_seqs		= 0;
 	nand->data_size		= 0;
@@ -658,26 +659,25 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	nand->state		= 0;
 	nand->bad_count		= 0;
 	nand->retcode		= ERR_NONE;
-	nand->command		= command;
+	nand->buf_start		= column;

 	switch (command) {
-	case NAND_CMD_READ0:
 	case NAND_CMD_PAGEPROG:
-		nand->use_ecc = info->use_ecc;
-	case NAND_CMD_READOOB:
+	case NAND_CMD_RNDOUT:
 		pxa3xx_set_datasize(info);
-		nand->oob_buff = nand->data_buff + nand->data_size;
 		nand->use_dma = use_dma;
 		chunks = info->page_size / nand->data_size;
 		break;
-	case NAND_CMD_SEQIN:
-		exec_cmd = 0;
-		break;
 	default:
 		nand->ndcb1 = 0;
 		nand->ndcb2 = 0;
+		nand->use_ecc = ECC_NONE;
 		break;
 	}
+	if (nand->use_dma) {
+		nand->data_buff = nand->dma_buff;
+		nand->oob_buff = nand->dma_buff + mtd->writesize;
+	}

 	/* clear the command buffer */
 	for (i = 0; i < CMD_POOL_SIZE; i ++) {
@@ -688,68 +688,67 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 			+ info->col_addr_cycles);

 	switch (command) {
-	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		cmd  = info->cmdset->read1;
-		if (command == NAND_CMD_READOOB)
-			nand->buf_start = mtd->writesize + column;
-		else
-			nand->buf_start = column;
-
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
-					| addr_cycle
-					| (cmd & NDCB0_CMD1_MASK);
-		else {
-			if (chunks == 1)
-				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
-						| NDCB0_DBC
-						| addr_cycle
-						| cmd;
-			else {
-				nand->total_cmds = chunks + 1;
-				nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
-						| NDCB0_CMD_TYPE(0)
-						| NDCB0_DBC
-						| NDCB0_NC
-						| addr_cycle
-						| cmd;
-
-				nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
-						| NDCB0_NC
-						| addr_cycle;
-
-				for (i = 2; i <= chunks; i ++)
-					nand->ndcb0[i] = nand->ndcb0[1];
-
-				nand->ndcb0[chunks] &= ~NDCB0_NC;
-				/* we should wait RnB go high again
-				 * before read out data*/
-				nand->wait_ready[1] = 1;
-			}
-		}
-
 	case NAND_CMD_SEQIN:
+		nand->use_ecc = info->use_ecc;
+	case NAND_CMD_READOOB:
+		memset(nand->data_buff, 0xff, column);
+		nand->buf_count = mtd->writesize + mtd->oobsize;
+		exec_cmd = 0;
+		info->page_addr = page_addr;
 		/* small page addr setting */
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
 			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
-
-			nand->ndcb2 = 0;
-		}
 		else {
 			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
 					| (column & 0xFFFF);

 			if (page_addr & 0xFF0000)
 				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
+		}
+		break;
+
+	case NAND_CMD_RNDOUT:
+		cmd = info->cmdset->read1;
+		if (nand->command == NAND_CMD_READOOB) {
+			nand->buf_start = mtd->writesize + column;
+			nand->buf_count = mtd->oobsize;
+		}
+
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)
+			|| !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
+			if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
+						| addr_cycle
+						| (cmd & NDCB0_CMD1_MASK);
 			else
-				nand->ndcb2 = 0;
+				nand->ndcb0[0] |= NDCB0_CMD_TYPE(0)
+						| NDCB0_DBC
+						| addr_cycle
+						| cmd;
+			break;
 		}

-		nand->buf_count = mtd->writesize + mtd->oobsize;
-		memset(nand->data_buff, 0xFF, nand->buf_count);
+		nand->total_cmds = chunks + 1;
+		nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
+				| NDCB0_CMD_TYPE(0)
+				| NDCB0_DBC
+				| NDCB0_NC
+				| addr_cycle
+				| cmd;
+
+		nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
+				| NDCB0_NC
+				| addr_cycle;
+
+		for (i = 2; i <= chunks; i ++)
+			nand->ndcb0[i] = nand->ndcb0[1];

+		nand->ndcb0[chunks] &= ~NDCB0_NC;
+		/* we should wait RnB go high again
+		 * before read out data*/
+		nand->wait_ready[1] = 1;
 		break;

 	case NAND_CMD_PAGEPROG:
@@ -760,40 +759,42 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 		cmd = info->cmdset->program;
 		nand->state |= STATE_IS_WRITE;
-		if (chunks == 1)
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)
+			|| !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
 			nand->ndcb0[0] |= NDCB0_CMD_TYPE(0x1)
 					| NDCB0_AUTO_RS
 					| NDCB0_ST_ROW_EN
 					| NDCB0_DBC
 					| cmd
 					| addr_cycle;
-		else {
-			nand->total_cmds = chunks + 1;
-			nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x4)
-					| NDCB0_CMD_TYPE(0x1)
+			break;
+		}
+
+		nand->total_cmds = chunks + 1;
+		nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x4)
+				| NDCB0_CMD_TYPE(0x1)
+				| NDCB0_NC
+				| NDCB0_AUTO_RS
+				| (cmd & NDCB0_CMD1_MASK)
+				| addr_cycle;
+
+		for (i = 1; i < chunks; i ++)
+			nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
 					| NDCB0_NC
 					| NDCB0_AUTO_RS
-					| (cmd & NDCB0_CMD1_MASK)
+					| NDCB0_CMD_TYPE(0x1)
 					| addr_cycle;

-			for (i = 1; i < chunks; i ++)
-				nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
-						| NDCB0_NC
-						| NDCB0_AUTO_RS
-						| NDCB0_CMD_TYPE(0x1)
-						| addr_cycle;
-
-			nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
-						| NDCB0_CMD_TYPE(0x1)
-						| NDCB0_ST_ROW_EN
-						| NDCB0_DBC
-						| (cmd & NDCB0_CMD2_MASK)
-						| NDCB0_CMD1_MASK
-						| addr_cycle;
-			/* we should wait for RnB goes high which
-			 * indicate the data has been written succesfully*/
-			nand->wait_ready[nand->total_cmds] = 1;
-		}
+		nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
+				| NDCB0_CMD_TYPE(0x1)
+				| NDCB0_ST_ROW_EN
+				| NDCB0_DBC
+				| (cmd & NDCB0_CMD2_MASK)
+				| NDCB0_CMD1_MASK
+				| addr_cycle;
+		/* we should wait for RnB goes high which
+		 * indicate the data has been written succesfully*/
+		nand->wait_ready[nand->total_cmds] = 1;
 		break;

 	case NAND_CMD_READID:
@@ -807,6 +808,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		break;
 	case NAND_CMD_STATUS:
 		cmd = info->cmdset->read_status;
+		nand->data_buff = nand->dma_buff;
 		nand->buf_count = 1;
 		nand->ndcb0[0] |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
@@ -843,6 +845,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		break;
 	}

+	nand->command = command;
 	return exec_cmd;
 }

@@ -1076,44 +1079,104 @@ static void free_cs_resource(struct
pxa3xx_nand_info *info, int cs)
 	nand->info[cs] = NULL;
 }

-static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
-		struct nand_chip *chip, uint8_t *buf, int page)
+static void pxa3xx_read_page(struct mtd_info *mtd, uint8_t *buf)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	struct pxa3xx_nand *nand = info->nand_data;
+	int buf_blank;

-	chip->read_buf(mtd, buf, mtd->writesize);
-	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-	if (nand->retcode == ERR_SBERR) {
+	nand->data_buff = buf;
+	nand->oob_buff = chip->oob_poi;
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RNDOUT, 0, info->page_addr);
+	switch (nand->retcode) {
+	case ERR_SBERR:
 		switch (nand->use_ecc) {
 		case ECC_BCH:
 			if (nand->bad_count > BCH_THRESHOLD)
 				mtd->ecc_stats.corrected +=
 					(nand->bad_count - BCH_THRESHOLD);
 			break;
+
 		case ECC_HAMMIN:
 			mtd->ecc_stats.corrected ++;
+			break;
+
 		case ECC_NONE:
 		default:
 			break;
 		}
-	} else if (nand->retcode == ERR_DBERR) {
-		int buf_blank;
-
-		buf_blank = is_buf_blank(buf, mtd->writesize);
+		break;
+	case ERR_DBERR:
+		buf_blank = is_buf_blank(nand->data_buff, mtd->writesize);
 		if (!buf_blank)
 			mtd->ecc_stats.failed++;
+		break;
+	case ERR_NONE:
+		break;
+	default:
+		mtd->ecc_stats.failed++;
+		break;
+	}
+}
+
+static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, uint8_t *buf, int page)
+{
+	pxa3xx_read_page(mtd, buf);
+	if (use_dma) {
+		chip->read_buf(mtd, buf, mtd->writesize);
+		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 	}
+	return 0;
+}

+static int pxa3xx_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+		int page, int sndcmd)
+{
+	if (sndcmd) {
+		pxa3xx_nand_cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+		pxa3xx_read_page(mtd, chip->oob_poi);
+	}
+	if (use_dma)
+		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 	return 0;
 }

 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 		struct nand_chip *chip, const uint8_t *buf)
 {
-	chip->write_buf(mtd, buf, mtd->writesize);
-	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
+	if (use_dma) {
+		chip->write_buf(mtd, buf, mtd->writesize);
+		chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	}
+	else {
+		nand->data_buff = (uint8_t *)buf;
+		nand->oob_buff = chip->oob_poi;
+	}
+}
+
+static int pxa3xx_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+			      int page)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
+	int status = 0;
+
+	nand->data_buff = nand->dma_buff;
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	if (use_dma)
+		chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	else
+		nand->oob_buff = chip->oob_poi;
+	/* Send command to program the OOB data */
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	status = chip->waitfunc(mtd, chip);
+
+	return status & NAND_STATUS_FAIL ? -EIO : 0;
 }

 static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
@@ -1162,8 +1225,8 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 		return -EINVAL;
 	}

+	nand->data_buff = (unsigned char *)&id;
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(nand->data_buff));
 	if (id != 0)
 		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id);
 	else {
@@ -1321,7 +1384,11 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		chip = (struct nand_chip *)(&mtd[1]);
 		chip->controller        = &nand->controller;
 		chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+		chip->ecc.read_page_raw = pxa3xx_nand_read_page_hwecc;
+		chip->ecc.read_oob      = pxa3xx_nand_read_oob;
 		chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+		chip->ecc.write_page_raw= pxa3xx_nand_write_page_hwecc;
+		chip->ecc.write_oob     = pxa3xx_nand_write_oob;
 		chip->waitfunc		= pxa3xx_nand_waitfunc;
 		chip->select_chip	= pxa3xx_nand_select_chip;
 		chip->cmdfunc		= pxa3xx_nand_cmdfunc;
@@ -1333,25 +1400,16 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		chip->erase_cmd		= pxa3xx_nand_erase_cmd;
 	}

-	if (use_dma == 0) {
-		nand->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
-		if (nand->data_buff == NULL) {
-			ret = -ENOMEM;
-			goto fail_free_buf;
-		}
-		goto success_exit;
-	}
-
-	nand->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
-			&nand->data_buff_phys, GFP_KERNEL);
-	if (nand->data_buff == NULL) {
+	nand->dma_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
+			&nand->dma_buff_phys, GFP_KERNEL);
+	if (nand->dma_buff == NULL) {
 		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
 		ret = -ENOMEM;
 		goto fail_free_buf;
 	}

-	nand->data_desc = (void *)nand->data_buff + data_desc_offset;
-	nand->data_desc_addr = nand->data_buff_phys + data_desc_offset;
+	nand->data_desc = (void *)nand->dma_buff + data_desc_offset;
+	nand->dma_desc_addr = nand->dma_buff_phys + data_desc_offset;
 	nand->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
 			pxa3xx_nand_data_dma_irq, nand);
 	if (nand->data_dma_ch < 0) {
@@ -1359,7 +1417,6 @@ static int alloc_nand_resource(struct
platform_device *pdev)
 		ret = -ENXIO;
 		goto fail_free_buf;
 	}
-success_exit:
 	return 0;

 fail_free_buf:
@@ -1409,6 +1466,14 @@ static int pxa3xx_nand_remove(struct
platform_device *pdev)
 		del_mtd_device(mtd);
 		free_cs_resource(info, cs);
 	}
+	if (nand->dma_buff_phys) {
+		if (nand->data_dma_ch >= 0)
+			pxa_free_dma(nand->data_dma_ch);
+		if (nand->dma_buff)
+			dma_free_coherent(&nand->pdev->dev, MAX_BUFF_SIZE,
+					nand->dma_buff, nand->dma_buff_phys);
+		nand->dma_buff_phys = 0;
+	}
 	return 0;
 }

-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 10:57:04 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 22:57:04 +0800
Subject: [PATCH 21/29] pxa3xx_nand: add ext id check
Message-ID: <mailman.128.1280296879.27306.linux-mtd@lists.infradead.org>

For K9LBG08U0M and K9LBG08UXD two nand chip, they have the same chip id
as
0xd7ec. So we should use the ext id to distinguish them.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    3 +-
 drivers/mtd/nand/pxa3xx_nand.c               |   32 +++++++++++++-------------
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index ed7d623..c20ac35 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -37,7 +37,8 @@ struct pxa3xx_nand_cmdset {

 struct pxa3xx_nand_flash {
 	char		*name;
-	uint32_t	chip_id;
+	uint16_t	chip_id;	/* chip id */
+	uint16_t	ext_id;		/* Extend id */
 	uint16_t	page_per_block; /* Pages per block */
 	uint16_t 	page_size;	/* Page size in bytes */
 	uint8_t		flash_width;	/* Width of Flash memory (DWIDTH_M) */
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 048b576..b0a0ccf 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -253,17 +253,17 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 #define NAND_SETTING_MICRON      &default_cmdset, &timing[2]
 #define NAND_SETTING_ST          &default_cmdset, &timing[3]
 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-{ "DEFAULT FLASH",      0,   0, 2048,  8,  8, ECC_NONE,      0,
NAND_SETTING_DEFAULT, },
-{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, ECC_HAMMIN, 4096,
NAND_SETTING_SAMSUNG, },
-{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, ECC_HAMMIN, 2048,
NAND_SETTING_SAMSUNG, },
-{ "1GiB 8-bit",    0xd3ec, 128, 2048,  8,  8, ECC_BCH,    4096,
NAND_SETTING_SAMSUNG, },
-{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, ECC_BCH,    8192,
NAND_SETTING_SAMSUNG, },
-{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, ECC_HAMMIN, 1024,
NAND_SETTING_MICRON, },
-{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, ECC_HAMMIN, 1024,
NAND_SETTING_MICRON, },
-{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, ECC_HAMMIN, 4096,
NAND_SETTING_MICRON, },
-{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, ECC_HAMMIN, 4096,
NAND_SETTING_MICRON, },
-{ "1GiB 8-bit",    0x382c, 128, 4096,  8,  8, ECC_BCH,    2048,
NAND_SETTING_MICRON },
-{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, ECC_HAMMIN, 2048,
NAND_SETTING_ST, },
+{ "DEFAULT FLASH",      0,       0,  0, 2048,  8,  8, ECC_NONE,
0, NAND_SETTING_DEFAULT, },
+{ "64MiB 16-bit",  0x46ec, 0xffff,  32,  512, 16, 16, ECC_HAMMIN,
4096, NAND_SETTING_SAMSUNG, },
+{ "256MiB 8-bit",  0xdaec, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
2048, NAND_SETTING_SAMSUNG, },
+{ "1GiB 8-bit",    0xd3ec, 0xffff, 128, 2048,  8,  8, ECC_BCH,
4096, NAND_SETTING_SAMSUNG, },
+{ "4GiB 8-bit",    0xd7ec, 0x29d5, 128, 4096,  8,  8, ECC_BCH,
8192, NAND_SETTING_SAMSUNG, },
+{ "128MiB 8-bit",  0xa12c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
1024, NAND_SETTING_MICRON, },
+{ "128MiB 16-bit", 0xb12c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
1024, NAND_SETTING_MICRON, },
+{ "512MiB 8-bit",  0xdc2c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
4096, NAND_SETTING_MICRON, },
+{ "512MiB 16-bit", 0xcc2c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
4096, NAND_SETTING_MICRON, },
+{ "1GiB 8-bit",    0x382c, 0xffff, 128, 4096,  8,  8, ECC_BCH,
2048, NAND_SETTING_MICRON },
+{ "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
2048, NAND_SETTING_ST, },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
@@ -1209,7 +1209,7 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 	struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
-	uint32_t id = -1;
+	uint16_t id[2];
 	uint64_t chipsize;
 	int i, ret;

@@ -1225,10 +1225,10 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 		return -EINVAL;
 	}

-	nand->data_buff = (unsigned char *)&id;
+	nand->data_buff = (unsigned char *)id;
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	if (id != 0)
-		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id);
+	if (id[0] != 0)
+		dev_info(&nand->pdev->dev, "Detect a flash id %x\n", id[0]);
 	else {
 		dev_warn(&nand->pdev->dev, "Read out ID 0, potential timing set wrong!!\n");
 		free_cs_resource(info, nand->chip_select);
@@ -1242,7 +1242,7 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)
 			f = &builtin_flash_types[i - pdata->num_flash + 1];

 		/* find the chip in default list */
-		if (f->chip_id == id)
+		if ((f->chip_id == id[0]) && ((f->ext_id & id[1]) == id[1]))
 			break;
 	}

-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 11:06:01 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 23:06:01 +0800
Subject: [PATCH 22/29] pxa3xx_nand: support ecc requirement higher
Message-ID: <mailman.130.1280296897.27306.linux-mtd@lists.infradead.org>

than 4bit per 512 bytes

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    2 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  117 +++++++++++++++----------
 2 files changed, 71 insertions(+), 48 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index c20ac35..2f1a1cf 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -43,7 +43,7 @@ struct pxa3xx_nand_flash {
 	uint16_t 	page_size;	/* Page size in bytes */
 	uint8_t		flash_width;	/* Width of Flash memory (DWIDTH_M) */
 	uint8_t 	dfc_width;	/* Width of flash controller(DWIDTH_C) */
-	uint8_t		ecc_type;	/* Which ECC is applied */
+	uint8_t		ecc_strength;	/* How strong a ecc should be applied */
 	uint32_t	num_blocks;	/* Number of physical blocks in Flash */
 	struct pxa3xx_nand_cmdset *cmdset;	/* NAND command set */
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index b0a0ccf..8f7ab2d 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -33,6 +33,8 @@
 #define BCH_THRESHOLD           (8)
 #define CMD_POOL_SIZE           (5)
 #define READ_ID_BYTES		(4)
+#define BCH_STRENGTH		(4)
+#define HAMMING_STRENGTH	(1)

 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -84,9 +86,9 @@
 #define NDCR_RDDREQM            (0x1 << 1)
 #define NDCR_WRCMDREQM          (0x1)

+#define NDSR_MASK		(0xffffffff)
 #define NDSR_ERR_CNT_MASK       (0x1F << 16)
 #define NDSR_ERR_CNT(x)         (((x) << 16) & NDSR_ERR_CNT_MASK)
-#define NDSR_MASK		(0xfff)
 #define NDSR_RDY                (0x1 << 12)
 #define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED		(0x1 << 10)
@@ -103,6 +105,7 @@

 #define NDCB0_CMD_XTYPE_MASK    (0x7 << 29)
 #define NDCB0_CMD_XTYPE(x)      (((x) << 29) & NDCB0_CMD_XTYPE_MASK)
+#define NDCB0_LEN_OVRD		(0x1 << 28)
 #define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS		(0x1 << 25)
 #define NDCB0_CSEL		(0x1 << 24)
@@ -161,7 +164,7 @@ struct pxa3xx_nand_info {
 	int			page_addr;
 	uint16_t		page_size;
 	uint8_t			chip_select;
-	uint8_t			use_ecc;
+	uint8_t			ecc_strength;

 	/* calculated from pxa3xx_nand_flash data */
 	uint8_t			col_addr_cycles;
@@ -206,8 +209,8 @@ struct pxa3xx_nand {

 	/* relate to the command */
 	uint8_t			chip_select;
+	uint8_t			ecc_strength;
 	unsigned int		state;
-	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
 	int 			retcode;

@@ -218,6 +221,7 @@ struct pxa3xx_nand {
 	uint32_t		ndcb0[CMD_POOL_SIZE];
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;
+	uint32_t		ndcb3[CMD_POOL_SIZE];
 };

 static int use_dma = 1;
@@ -253,17 +257,17 @@ static struct pxa3xx_nand_timing __devinitdata
timing[] = {
 #define NAND_SETTING_MICRON      &default_cmdset, &timing[2]
 #define NAND_SETTING_ST          &default_cmdset, &timing[3]
 static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = {
-{ "DEFAULT FLASH",      0,       0,  0, 2048,  8,  8, ECC_NONE,
0, NAND_SETTING_DEFAULT, },
-{ "64MiB 16-bit",  0x46ec, 0xffff,  32,  512, 16, 16, ECC_HAMMIN,
4096, NAND_SETTING_SAMSUNG, },
-{ "256MiB 8-bit",  0xdaec, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
2048, NAND_SETTING_SAMSUNG, },
-{ "1GiB 8-bit",    0xd3ec, 0xffff, 128, 2048,  8,  8, ECC_BCH,
4096, NAND_SETTING_SAMSUNG, },
-{ "4GiB 8-bit",    0xd7ec, 0x29d5, 128, 4096,  8,  8, ECC_BCH,
8192, NAND_SETTING_SAMSUNG, },
-{ "128MiB 8-bit",  0xa12c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
1024, NAND_SETTING_MICRON, },
-{ "128MiB 16-bit", 0xb12c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
1024, NAND_SETTING_MICRON, },
-{ "512MiB 8-bit",  0xdc2c, 0xffff,  64, 2048,  8,  8, ECC_HAMMIN,
4096, NAND_SETTING_MICRON, },
-{ "512MiB 16-bit", 0xcc2c, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
4096, NAND_SETTING_MICRON, },
-{ "1GiB 8-bit",    0x382c, 0xffff, 128, 4096,  8,  8, ECC_BCH,
2048, NAND_SETTING_MICRON },
-{ "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, ECC_HAMMIN,
2048, NAND_SETTING_ST, },
+{ "DEFAULT FLASH",      0,       0,  0, 2048,  8,  8, 0,    0,
NAND_SETTING_DEFAULT, },
+{ "64MiB 16-bit",  0x46ec, 0xffff,  32,  512, 16, 16, 1, 4096,
NAND_SETTING_SAMSUNG, },
+{ "256MiB 8-bit",  0xdaec, 0xffff,  64, 2048,  8,  8, 1, 2048,
NAND_SETTING_SAMSUNG, },
+{ "1GiB 8-bit",    0xd3ec, 0xffff, 128, 2048,  8,  8, 4, 4096,
NAND_SETTING_SAMSUNG, },
+{ "4GiB 8-bit",    0xd7ec, 0x29d5, 128, 4096,  8,  8, 8, 8192,
NAND_SETTING_SAMSUNG, },
+{ "128MiB 8-bit",  0xa12c, 0xffff,  64, 2048,  8,  8, 1, 1024,
NAND_SETTING_MICRON, },
+{ "128MiB 16-bit", 0xb12c, 0xffff,  64, 2048, 16, 16, 1, 1024,
NAND_SETTING_MICRON, },
+{ "512MiB 8-bit",  0xdc2c, 0xffff,  64, 2048,  8,  8, 1, 4096,
NAND_SETTING_MICRON, },
+{ "512MiB 16-bit", 0xcc2c, 0xffff,  64, 2048, 16, 16, 1, 4096,
NAND_SETTING_MICRON, },
+{ "1GiB 8-bit",    0x382c, 0xffff, 128, 4096,  8,  8, 4, 2048,
NAND_SETTING_MICRON },
+{ "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, 1, 2048,
NAND_SETTING_ST, },
 };

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
@@ -319,16 +323,15 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 			return;
 		}

-		switch (nand->use_ecc) {
-		case ECC_HAMMIN:
-			nand->oob_size = 40;
+		switch (nand->ecc_strength) {
+		case 0:
+			nand->oob_size = 64;
 			break;
-		case ECC_BCH:
-			nand->oob_size = 32;
+		case HAMMING_STRENGTH:
+			nand->oob_size = 40;
 			break;
 		default:
-			nand->oob_size = 64;
-			break;
+			nand->oob_size = 32;
 		}
 	} else {
 		nand->data_size = 512;
@@ -337,17 +340,16 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 			return;
 		}

-		switch (nand->use_ecc) {
-		case ECC_HAMMIN:
+		switch (nand->ecc_strength) {
+		case 0:
+			nand->oob_size = 16;
+			break;
+		case HAMMING_STRENGTH:
 			nand->oob_size = 8;
 			break;
-		case ECC_BCH:
+		default:
 			printk("Don't support BCH on small page device!!!\n");
 			BUG();
-			break;
-		default:
-			nand->oob_size = 16;
-			break;
 		}
 	}
 }
@@ -365,16 +367,16 @@ static void pxa3xx_nand_start(struct pxa3xx_nand *nand)

 	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
-	ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR;
+	ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
 	ndcr |= NDCR_ND_RUN;

-	switch (nand->use_ecc) {
-	case ECC_BCH:
+	switch (nand->ecc_strength) {
+	default:
 		ndeccctrl |= NDECCCTRL_BCH_EN;
 		ndeccctrl |= NDECCCTRL_ECC_THRESH(BCH_THRESHOLD);
-	case ECC_HAMMIN:
+	case HAMMING_STRENGTH:
 		ndcr |= NDCR_ECC_EN;
-	default:
+	case 0:
 		break;
 	}

@@ -610,6 +612,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 			nand_writel(nand, NDCB0, nand->ndcb0[cmd_seqs]);
 			nand_writel(nand, NDCB0, ndcb1);
 			nand_writel(nand, NDCB0, ndcb2);
+			if (nand->ndcb3[cmd_seqs])
+				nand_writel(nand, NDCB0, nand->ndcb3[cmd_seqs]);
 		}
 		else
 			is_completed = 1;
@@ -654,7 +658,6 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	nand->cmd_seqs		= 0;
 	nand->data_size		= 0;
 	nand->oob_size		= 0;
-	nand->use_ecc		= 0;
 	nand->use_dma		= 0;
 	nand->state		= 0;
 	nand->bad_count		= 0;
@@ -667,11 +670,23 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		pxa3xx_set_datasize(info);
 		nand->use_dma = use_dma;
 		chunks = info->page_size / nand->data_size;
+		if (info->ecc_strength > BCH_STRENGTH) {
+			i = info->ecc_strength / BCH_STRENGTH;
+			nand->data_size /= i;
+			ndcb0 |= NDCB0_LEN_OVRD;
+			chunks *= i;
+		}
 		break;
+	case NAND_CMD_READOOB:
+		if (info->ecc_strength > BCH_STRENGTH) {
+			printk(KERN_ERR "we don't support oob command if use"
+				     " 8bit per 512bytes ecc feature!!\n");
+			BUG();
+		}
 	default:
 		nand->ndcb1 = 0;
 		nand->ndcb2 = 0;
-		nand->use_ecc = ECC_NONE;
+		nand->ecc_strength = 0;
 		break;
 	}
 	if (nand->use_dma) {
@@ -683,6 +698,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	for (i = 0; i < CMD_POOL_SIZE; i ++) {
 		nand->ndcb0[i] = ndcb0;
 		nand->wait_ready[i] = 0;
+		nand->ndcb3[i] = (ndcb0 & NDCB0_LEN_OVRD)? nand->data_size : 0;
 	}
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);
@@ -690,7 +706,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 	switch (command) {
 	case NAND_CMD_READ0:
 	case NAND_CMD_SEQIN:
-		nand->use_ecc = info->use_ecc;
+		nand->ecc_strength = info->ecc_strength;
 	case NAND_CMD_READOOB:
 		memset(nand->data_buff, 0xff, column);
 		nand->buf_count = mtd->writesize + mtd->oobsize;
@@ -737,7 +753,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 				| NDCB0_NC
 				| addr_cycle
 				| cmd;
-
+		nand->ndcb0[0] &= ~NDCB0_LEN_OVRD;
+		nand->ndcb3[0] = 0;
 		nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
 				| NDCB0_NC
 				| addr_cycle;
@@ -792,6 +809,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 				| (cmd & NDCB0_CMD2_MASK)
 				| NDCB0_CMD1_MASK
 				| addr_cycle;
+		nand->ndcb0[chunks] &= ~NDCB0_LEN_OVRD;
+		nand->ndcb3[chunks] = 0;
 		/* we should wait for RnB goes high which
 		 * indicate the data has been written succesfully*/
 		nand->wait_ready[nand->total_cmds] = 1;
@@ -988,7 +1007,12 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 		return -EINVAL;
 	}
 	/* calculate flash information */
-	info->use_ecc = f->ecc_type;
+	if (f->ecc_strength != 0 && f->ecc_strength != HAMMING_STRENGTH
+	    && (f->ecc_strength % BCH_STRENGTH != 0)) {
+		printk(KERN_ERR "ECC strength definition error, please recheck!!\n");
+		return -EINVAL;
+	}
+	info->ecc_strength = f->ecc_strength;
 	info->cmdset = f->cmdset;
 	info->page_size = f->page_size;

@@ -1032,7 +1056,9 @@ static int pxa3xx_nand_config_flash(struct
pxa3xx_nand_info *info,
 	}

 	ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
-	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
+	/* only enable spare area when ecc is lower than 8bits per 512 bytes */
+	if (f->ecc_strength <= BCH_STRENGTH)
+		ndcr |= NDCR_SPARE_EN;

 	info->reg_ndcr = ndcr;
 	pxa3xx_nand_set_timing(info, f->timing);
@@ -1055,7 +1081,7 @@ static int pxa3xx_nand_detect_config(struct
pxa3xx_nand *nand)

 	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
-	info->use_ecc = (ndeccctrl & NDECCCTRL_BCH_EN) ? ECC_BCH : ECC_HAMMIN;
+	info->ecc_strength = (ndeccctrl & NDECCCTRL_BCH_EN) ? BCH_STRENGTH :
HAMMING_STRENGTH;
 	info->cmdset = &default_cmdset;

 	return 0;
@@ -1091,19 +1117,16 @@ static void pxa3xx_read_page(struct mtd_info
*mtd, uint8_t *buf)
 	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RNDOUT, 0, info->page_addr);
 	switch (nand->retcode) {
 	case ERR_SBERR:
-		switch (nand->use_ecc) {
-		case ECC_BCH:
+		switch (nand->ecc_strength) {
+		default:
 			if (nand->bad_count > BCH_THRESHOLD)
 				mtd->ecc_stats.corrected +=
 					(nand->bad_count - BCH_THRESHOLD);
 			break;

-		case ECC_HAMMIN:
+		case HAMMING_STRENGTH:
 			mtd->ecc_stats.corrected ++;
-			break;
-
-		case ECC_NONE:
-		default:
+		case 0:
 			break;
 		}
 		break;
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 11:09:03 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 23:09:03 +0800
Subject: [PATCH 23/29] pxa3xx_nand: add advanced timing tuning feature
Message-ID: <mailman.132.1280296918.27306.linux-mtd@lists.infradead.org>

For new controller, it has more power at more precise timing
tuning.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    2 +
 drivers/mtd/nand/pxa3xx_nand.c               |   91 ++++++++++++++++++--------
 2 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 2f1a1cf..f7c16d3 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -11,6 +11,7 @@ enum {
 };

 struct pxa3xx_nand_timing {
+	unsigned int	tADL; /* Adress to Write Data delay */
 	unsigned int	tCH;  /* Enable signal hold time */
 	unsigned int	tCS;  /* Enable signal setup time */
 	unsigned int	tWH;  /* ND_nWE high duration */
@@ -18,6 +19,7 @@ struct pxa3xx_nand_timing {
 	unsigned int	tRH;  /* ND_nRE high duration */
 	unsigned int	tRP;  /* ND_nRE pulse width */
 	unsigned int	tR;   /* ND_nWE high to ND_nRE low for read */
+	unsigned int	tRHW; /* delay for next command issue */
 	unsigned int	tWHR; /* ND_nWE high to ND_nRE low for status read */
 	unsigned int	tAR;  /* ND_ALE low to ND_nRE low delay */
 };
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 8f7ab2d..9a37517 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -246,10 +246,10 @@ static struct pxa3xx_nand_cmdset default_cmdset = {
 };

 static struct pxa3xx_nand_timing __devinitdata timing[] = {
-	{ 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
-	{ 10,  0, 20,  40, 30,  40, 11123, 110, 10, },
-	{ 10, 25, 15,  25, 15,  30, 25000,  60, 10, },
-	{ 10, 35, 15,  25, 15,  25, 25000,  60, 10, },
+	{   0, 40, 80, 60, 100, 80, 100, 90000,  0, 400, 40, },
+	{ 200, 10,  0, 20,  40, 30,  40, 11123, 20, 110, 10, },
+	{   0, 10, 25, 15,  25, 15,  30, 25000,  0,  60, 10, },
+	{   0, 10, 35, 15,  25, 15,  25, 25000,  0,  60, 10, },
 };

 #define NAND_SETTING_DEFAULT     &default_cmdset, &timing[0]
@@ -272,16 +272,20 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {

 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};

-#define NDTR0_tCH(c)	(min((c), 7) << 19)
-#define NDTR0_tCS(c)	(min((c), 7) << 16)
-#define NDTR0_tWH(c)	(min((c), 7) << 11)
-#define NDTR0_tWP(c)	(min((c), 7) << 8)
-#define NDTR0_tRH(c)	(min((c), 7) << 3)
-#define NDTR0_tRP(c)	(min((c), 7) << 0)
-
-#define NDTR1_tR(c)	(min((c), 65535) << 16)
-#define NDTR1_tWHR(c)	(min((c), 15) << 4)
-#define NDTR1_tAR(c)	(min((c), 15) << 0)
+#define NDTR0_tADL(c)		(min_t(uint32_t, (c), 31) << 27)
+#define NDTR0_tCH(c)		(min_t(uint32_t, (c), 7) << 19)
+#define NDTR0_tCS(c)		(min_t(uint32_t, (c), 7) << 16)
+#define NDTR0_tWH(c)		(min_t(uint32_t, (c), 7) << 11)
+#define NDTR0_tWP(c)		(min_t(uint32_t, (c), 7) << 8)
+#define NDTR0_ETRP		(0x1 << 6)
+#define NDTR0_tRH(c)		(min_t(uint32_t, (c), 7) << 3)
+#define NDTR0_tRP(c)		(min_t(uint32_t, (c), 7) << 0)
+
+#define NDTR1_tR(c)		(min_t(uint32_t, (c), 65535) << 16)
+#define NDTR1_PRESCALE		(0x1 << 14)
+#define NDTR1_tRHW(c)		(min_t(uint32_t, (c), 3) << 8)
+#define NDTR1_tWHR(c)		(min_t(uint32_t, (c), 15) << 4)
+#define NDTR1_tAR(c)		(min_t(uint32_t, (c), 15) << 0)

 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
@@ -290,20 +294,51 @@ static void pxa3xx_nand_set_timing(struct
pxa3xx_nand_info *info,
 				   const struct pxa3xx_nand_timing *t)
 {
 	struct pxa3xx_nand *nand = info->nand_data;
-	unsigned long nand_clk;
-	uint32_t ndtr0, ndtr1;
-
-	nand_clk = clk_get_rate(nand->clk);
-	ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
-		NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
-		NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
-		NDTR0_tWP(ns2cycle(t->tWP, nand_clk)) |
-		NDTR0_tRH(ns2cycle(t->tRH, nand_clk)) |
-		NDTR0_tRP(ns2cycle(t->tRP, nand_clk));
-
-	ndtr1 = NDTR1_tR(ns2cycle(t->tR, nand_clk)) |
-		NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
-		NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
+	struct platform_device *pdev = nand->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	unsigned long nand_clk = clk_get_rate(nand->clk);
+	uint32_t ndtr0, ndtr1, tRP, tR, tRHW, tADL;
+
+	tR = ns2cycle(t->tR, nand_clk);
+	tRP = ns2cycle(t->tRP, nand_clk);
+	tRHW = tADL = ndtr0 = ndtr1 = 0;
+	if (pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)
+		tR = 0;
+	if (pdata->controller_attrs & PXA3XX_ADV_TIME_TUNING) {
+		if (tRP > 0x7) {
+			ndtr0 |= NDTR0_ETRP;
+			tRP -= 0x7;
+		}
+		if (tR > 0xffff) {
+			ndtr1 |= NDTR1_PRESCALE;
+			tR /= 16;
+		}
+		if (t->tRHW > 0) {
+			tRHW = ns2cycle(t->tRHW, nand_clk);
+			if (tRHW < 16)
+				tRHW = 1;
+			else {
+				if (tRHW < 32)
+					tRHW = 2;
+				else
+					tRHW = 3;
+			}
+		}
+		tADL = ns2cycle(t->tADL, nand_clk);
+	}
+
+	ndtr0 |= NDTR0_tADL(tADL)
+		| NDTR0_tCH(ns2cycle(t->tCH, nand_clk))
+		| NDTR0_tCS(ns2cycle(t->tCS, nand_clk))
+		| NDTR0_tWH(ns2cycle(t->tWH, nand_clk))
+		| NDTR0_tWP(ns2cycle(t->tWP, nand_clk))
+		| NDTR0_tRH(ns2cycle(t->tRH, nand_clk))
+		| NDTR0_tRP(tRP);
+
+	ndtr1 |= NDTR1_tR(tR)
+		| NDTR1_tRHW(tRHW)
+		| NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk))
+		| NDTR1_tAR(ns2cycle(t->tAR, nand_clk));

 	info->ndtr0cs0 = ndtr0;
 	info->ndtr1cs0 = ndtr1;
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 11:10:42 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 23:10:42 +0800
Subject: [PATCH 24/29] pxa3xx_nand: add polling mode support
Message-ID: <mailman.139.1280297047.27306.linux-mtd@lists.infradead.org>

Add polling mode to facilitate debugging.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    1 +
 drivers/mtd/nand/pxa3xx_nand.c               |   58 ++++++++++++++++++++------
 2 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index f7c16d3..9e00267 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -64,6 +64,7 @@ struct pxa3xx_nand_flash {
  * enable such tuning for those platform which support it */
 #define PXA3XX_ADV_TIME_TUNING	(1 << 4)
 #define PXA3XX_KEEP_CONFIG	(1 << 5)
+#define PXA3XX_POOLING_MODE	(1 << 6)
 struct pxa3xx_nand_platform_data {
 	unsigned int				controller_attrs;
 	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 9a37517..fbe455e 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -228,10 +228,9 @@ static int use_dma = 1;
 module_param(use_dma, bool, 0444);
 MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");

-/*
- * Default NAND flash controller configuration setup by the
- * bootloader. This configuration is used only when pdata->keep_config is set
- */
+static int use_polling = 0;
+module_param(use_polling, bool, 0444);
+MODULE_PARM_DESC(use_polling, "Use full polling mode");
 static struct pxa3xx_nand_cmdset default_cmdset = {
 	.read1		= 0x3000,
 	.read2		= 0x0050,
@@ -403,6 +402,7 @@ static void pxa3xx_nand_start(struct pxa3xx_nand *nand)
 	info = nand->info[nand->chip_select];
 	ndcr = info->reg_ndcr;
 	ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
+	ndcr |= use_polling ? NDCR_INT_MASK : 0;
 	ndcr |= NDCR_ND_RUN;

 	switch (nand->ecc_strength) {
@@ -574,9 +574,8 @@ static void pxa3xx_nand_data_dma_irq(int channel,
void *data)
 	nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }

-static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
+static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand)
 {
-	struct pxa3xx_nand *nand = devid;
 	struct pxa3xx_nand_info *info;
 	unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2;
 	unsigned int ready, cmd_done, page_done, badblock_detect;
@@ -613,13 +612,20 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	if (status & ready) {
 		nand->state |= STATE_READY;
 		if (nand->wait_ready[cmd_seqs]) {
-			enable_int(nand, NDCR_WRCMDREQM);
+			if (!use_polling)
+				enable_int(nand, NDCR_WRCMDREQM | NDCR_CS0_CMDDM
+						| NDCR_CS1_CMDDM);
 			if (cmd_seqs == nand->total_cmds)
 				is_completed = 1;
 		}
 	}
 	if (status & cmd_done) {
 		nand->state |= STATE_CMD_DONE;
+		if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) {
+			status &= ~cmd_done;
+			if (!use_polling)
+				disable_int(nand, NDCR_CS0_CMDDM | NDCR_CS1_CMDDM);
+		}
 		if (cmd_seqs == nand->total_cmds && !nand->wait_ready[cmd_seqs])
 			is_completed = 1;
 	}
@@ -627,7 +633,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	if (status & NDSR_WRCMDREQ) {
 		status &= ~NDSR_WRCMDREQ;
 		if (nand->wait_ready[cmd_seqs] && !(nand->state & STATE_READY)) {
-			disable_int(nand, NDCR_WRCMDREQM);
+			if (!use_polling)
+				disable_int(nand, NDCR_WRCMDREQM);
 			goto IRQ_FORCE_EXIT;
 		}

@@ -657,12 +664,32 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 IRQ_FORCE_EXIT:
 	/* clear NDSR to let the controller exit the IRQ */
 	nand_writel(nand, NDSR, status);
-	if (is_completed)
-		complete(&nand->cmd_complete);
 NORMAL_IRQ_EXIT:
+	return is_completed;
+}
+
+static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
+{
+	struct pxa3xx_nand *nand = devid;
+	if (pxa3xx_nand_transaction(nand))
+		complete(&nand->cmd_complete);
 	return IRQ_HANDLED;
 }

+static int pxa3xx_nand_polling(struct pxa3xx_nand *nand, unsigned long timeout)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < timeout; i++) {
+		ret = pxa3xx_nand_transaction(nand);
+		if (ret)
+			break;
+		udelay(10);
+	}
+
+	return ret;
+}
+
 static inline int is_buf_blank(uint8_t *buf, size_t len)
 {
 	for (; len > 0; len--)
@@ -930,8 +957,11 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		nand->state |= STATE_CMD_PREPARED;
 		pxa3xx_nand_start(nand);

-		ret = wait_for_completion_timeout(&nand->cmd_complete,
-				CHIP_DELAY_TIMEOUT);
+		if (!use_polling)
+			ret = wait_for_completion_timeout(&nand->cmd_complete,
+					CHIP_DELAY_TIMEOUT);
+		else
+			ret = pxa3xx_nand_polling(nand, CHIP_DELAY_TIMEOUT);
 		if (!ret) {
 			dev_err(&nand->pdev->dev, "Wait time out!!!\n");
 			nand_error_dump(nand);
@@ -1551,7 +1581,9 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 		return -ENODEV;
 	}

-	if (!(pdata->controller_attrs & PXA3XX_DMA_EN))
+	if (pdata->controller_attrs & PXA3XX_POOLING_MODE)
+		use_polling = 1;
+	if (!(pdata->controller_attrs & PXA3XX_DMA_EN) || use_polling)
 		use_dma = 0;
 	ret = alloc_nand_resource(pdev);
 	if (ret)
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 11:13:05 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 23:13:05 +0800
Subject: [PATCH 25/29] pxa3xx_nand: reimplement the read oob logic
Message-ID: <mailman.140.1280297050.27306.linux-mtd@lists.infradead.org>

For readoob command only need the content of oob part, it certainly
don't need the controller transfer the data part, which greatly
downgrade the performance.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |  182 +++++++++++++++++++++-------------------
 1 files changed, 96 insertions(+), 86 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index fbe455e..ba15baf 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -198,30 +198,28 @@ struct pxa3xx_nand {
 	uint32_t		command;
 	uint16_t		data_size;	/* data size in FIFO */
 	uint16_t		oob_size;
-	uint32_t		bad_count;
 	unsigned char		*dma_buff;
 	unsigned char		*data_buff;
 	unsigned char		*oob_buff;
+	uint8_t			chip_select;
+	uint8_t			total_cmds;
 	uint32_t		buf_start;
 	uint32_t		buf_count;
+
+	uint32_t		state;
+	uint32_t		bad_count;
 	uint16_t		data_column;
 	uint16_t		oob_column;
-
-	/* relate to the command */
-	uint8_t			chip_select;
-	uint8_t			ecc_strength;
-	unsigned int		state;
 	int			use_dma;	/* use DMA ? */
 	int 			retcode;
+	uint8_t			ecc_strength;

 	/* cached register value */
 	uint8_t			cmd_seqs;
-	uint8_t			total_cmds;
 	uint8_t			wait_ready[CMD_POOL_SIZE];
 	uint32_t		ndcb0[CMD_POOL_SIZE];
-	uint32_t		ndcb1;
+	uint32_t		ndcb1[CMD_POOL_SIZE];
 	uint32_t		ndcb2;
-	uint32_t		ndcb3[CMD_POOL_SIZE];
 };

 static int use_dma = 1;
@@ -350,8 +348,8 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)
 	struct pxa3xx_nand *nand = info->nand_data;
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;

-	if (info->page_size >= PAGE_CHUNK_SIZE) {
-		nand->data_size = PAGE_CHUNK_SIZE;
+	if (info->page_size < PAGE_CHUNK_SIZE) {
+		nand->data_size = 512;
 		if (!oob_enable) {
 			nand->oob_size = 0;
 			return;
@@ -359,32 +357,54 @@ static void pxa3xx_set_datasize(struct
pxa3xx_nand_info *info)

 		switch (nand->ecc_strength) {
 		case 0:
-			nand->oob_size = 64;
+			nand->oob_size = 16;
 			break;
 		case HAMMING_STRENGTH:
-			nand->oob_size = 40;
+			nand->oob_size = 8;
 			break;
 		default:
-			nand->oob_size = 32;
-		}
-	} else {
-		nand->data_size = 512;
-		if (!oob_enable) {
-			nand->oob_size = 0;
-			return;
+			printk("Don't support BCH on small page device!!!\n");
+			BUG();
 		}
+		return;
+	}
+	nand->data_size = PAGE_CHUNK_SIZE;
+	if (!oob_enable) {
+		nand->oob_size = 0;
+		return;
+	}

-		switch (nand->ecc_strength) {
-		case 0:
-			nand->oob_size = 16;
-			break;
+	if (nand->command == NAND_CMD_READOOB) {
+		switch (info->ecc_strength) {
 		case HAMMING_STRENGTH:
-			nand->oob_size = 8;
+			nand->ndcb1[3] = 2 * PAGE_CHUNK_SIZE + OOB_CHUNK_SIZE;
+			nand->data_size = 40;
+			break;
+		case BCH_STRENGTH:
+			nand->ndcb1[3] = 2 * PAGE_CHUNK_SIZE + OOB_CHUNK_SIZE - 2;
+			nand->data_size = 32;
 			break;
 		default:
-			printk("Don't support BCH on small page device!!!\n");
 			BUG();
 		}
+		if (info->reg_ndcr & NDCR_DWIDTH_M) {
+			nand->ndcb1[1] = PAGE_CHUNK_SIZE / 2;
+			nand->ndcb1[3] /= 2;
+		}
+		else
+			nand->ndcb1[1] = PAGE_CHUNK_SIZE;
+		nand->oob_size = 0;
+		return;
+	}
+	switch (nand->ecc_strength) {
+	case 0:
+		nand->oob_size = 64;
+		break;
+	case HAMMING_STRENGTH:
+		nand->oob_size = 40;
+		break;
+	default:
+		nand->oob_size = 32;
 	}
 }

@@ -468,9 +488,8 @@ static void nand_error_dump(struct pxa3xx_nand *nand)
 	printk(KERN_ERR "Totally %d command for sending\n",
 			nand->total_cmds);
 	for (i = 0; i < nand->total_cmds; i ++)
-		printk(KERN_ERR "NDCB0:%d: %x\n",
-				i, nand->ndcb0[i]);
-	printk(KERN_ERR "NDCB1: %x; NDCB2 %x\n", nand->ndcb1, nand->ndcb2);
+		printk(KERN_ERR "%d::NDCB0: %x, NDCB1: %x, NDCB2: %x\n",
+			i, nand->ndcb0[i], nand->ndcb1[i], nand->ndcb2);

 	printk(KERN_ERR "\nRegister DUMPing ##############\n");
 	printk(KERN_ERR "NDCR %x\n"
@@ -577,8 +596,8 @@ static void pxa3xx_nand_data_dma_irq(int channel,
void *data)
 static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand)
 {
 	struct pxa3xx_nand_info *info;
-	unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2;
-	unsigned int ready, cmd_done, page_done, badblock_detect;
+	unsigned int status, is_completed = 0, cs, cmd_seqs;
+	unsigned int ready, cmd_done, page_done, badblock_detect, ndcb2;

 	cs		= nand->chip_select;
 	ready           = (cs) ? NDSR_RDY : NDSR_FLASH_RDY;
@@ -640,22 +659,19 @@ static int pxa3xx_nand_transaction(struct
pxa3xx_nand *nand)

 		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
 		if (cmd_seqs < nand->total_cmds) {
-			nand->cmd_seqs ++;
-			if (cmd_seqs == 0) {
-				ndcb1 = nand->ndcb1;
+			if (cmd_seqs == 0)
 				ndcb2 = nand->ndcb2;
-			}
-			else {
-				ndcb1 = 0;
+			else
 				ndcb2 = 0;
-			}
+			nand->cmd_seqs ++;
 			nand->state &= ~STATE_MASK;
 			nand->state |= STATE_CMD_WAIT_DONE;
 			nand_writel(nand, NDCB0, nand->ndcb0[cmd_seqs]);
-			nand_writel(nand, NDCB0, ndcb1);
+			nand_writel(nand, NDCB0, nand->ndcb1[cmd_seqs]);
 			nand_writel(nand, NDCB0, ndcb2);
-			if (nand->ndcb3[cmd_seqs])
-				nand_writel(nand, NDCB0, nand->ndcb3[cmd_seqs]);
+			if (nand->ndcb0[cmd_seqs] & NDCB0_LEN_OVRD)
+				nand_writel(nand, NDCB0, nand->data_size
+						+ nand->oob_size);
 		}
 		else
 			is_completed = 1;
@@ -714,24 +730,15 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	exec_cmd = 1;

 	/* reset data and oob column point to handle data */
-	nand->data_column	= 0;
-	nand->oob_column	= 0;
-	nand->total_cmds	= 1;
-	nand->cmd_seqs		= 0;
-	nand->data_size		= 0;
-	nand->oob_size		= 0;
-	nand->use_dma		= 0;
-	nand->state		= 0;
-	nand->bad_count		= 0;
-	nand->retcode		= ERR_NONE;
-	nand->buf_start		= column;
+	nand->total_cmds = 1;
+	nand->buf_start	= column;

 	switch (command) {
 	case NAND_CMD_PAGEPROG:
 	case NAND_CMD_RNDOUT:
 		pxa3xx_set_datasize(info);
 		nand->use_dma = use_dma;
-		chunks = info->page_size / nand->data_size;
+		chunks = info->page_size / PAGE_CHUNK_SIZE;
 		if (info->ecc_strength > BCH_STRENGTH) {
 			i = info->ecc_strength / BCH_STRENGTH;
 			nand->data_size /= i;
@@ -746,9 +753,8 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 			BUG();
 		}
 	default:
-		nand->ndcb1 = 0;
-		nand->ndcb2 = 0;
-		nand->ecc_strength = 0;
+		i = (uint32_t)(&nand->state) - (uint32_t)nand;
+		memset(&nand->state, 0, sizeof(struct pxa3xx_nand) - i);
 		break;
 	}
 	if (nand->use_dma) {
@@ -757,11 +763,8 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	}

 	/* clear the command buffer */
-	for (i = 0; i < CMD_POOL_SIZE; i ++) {
+	for (i = 0; i < CMD_POOL_SIZE; i ++)
 		nand->ndcb0[i] = ndcb0;
-		nand->wait_ready[i] = 0;
-		nand->ndcb3[i] = (ndcb0 & NDCB0_LEN_OVRD)? nand->data_size : 0;
-	}
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 			+ info->col_addr_cycles);

@@ -776,10 +779,10 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		info->page_addr = page_addr;
 		/* small page addr setting */
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+			nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
 		else {
-			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
+			nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16)
 					| (column & 0xFFFF);

 			if (page_addr & 0xFF0000)
@@ -789,11 +792,6 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 	case NAND_CMD_RNDOUT:
 		cmd = info->cmdset->read1;
-		if (nand->command == NAND_CMD_READOOB) {
-			nand->buf_start = mtd->writesize + column;
-			nand->buf_count = mtd->oobsize;
-		}
-
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)
 			|| !(pdata->controller_attrs & PXA3XX_NAKED_CMD_EN)) {
 			if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
@@ -805,10 +803,18 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 						| NDCB0_DBC
 						| addr_cycle
 						| cmd;
+			if (nand->command == NAND_CMD_READOOB) {
+				nand->buf_start = mtd->writesize + column;
+				nand->buf_count = mtd->oobsize;
+			}
 			break;
 		}

-		nand->total_cmds = chunks + 1;
+		if (nand->command == NAND_CMD_READOOB)
+			nand->total_cmds = 2 * chunks + 1;
+		else
+			nand->total_cmds = chunks + 1;
+
 		nand->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6)
 				| NDCB0_CMD_TYPE(0)
 				| NDCB0_DBC
@@ -816,15 +822,23 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 				| addr_cycle
 				| cmd;
 		nand->ndcb0[0] &= ~NDCB0_LEN_OVRD;
-		nand->ndcb3[0] = 0;
-		nand->ndcb0[1] |= NDCB0_CMD_XTYPE(0x5)
-				| NDCB0_NC
-				| addr_cycle;

-		for (i = 2; i <= chunks; i ++)
-			nand->ndcb0[i] = nand->ndcb0[1];
+		for (i = 1; i <= nand->total_cmds - 1;) {
+			if (nand->command == NAND_CMD_READOOB) {
+				nand->ndcb0[i ++] |= NDCB0_CMD_XTYPE(0x6)
+						| NDCB0_CMD_TYPE(0)
+						| NDCB0_ADDR_CYC(info->col_addr_cycles)
+						| NDCB0_DBC
+						| NDCB0_NC
+						| (NAND_CMD_RNDOUTSTART << 8)
+						| NAND_CMD_RNDOUT;
+				nand->ndcb0[i] |= NDCB0_LEN_OVRD;
+			}
+			nand->ndcb0[i ++] |= NDCB0_CMD_XTYPE(0x5)
+					| NDCB0_NC;
+		}

-		nand->ndcb0[chunks] &= ~NDCB0_NC;
+		nand->ndcb0[nand->total_cmds - 1] &= ~NDCB0_NC;
 		/* we should wait RnB go high again
 		 * before read out data*/
 		nand->wait_ready[1] = 1;
@@ -861,18 +875,15 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 			nand->ndcb0[i] |= NDCB0_CMD_XTYPE(0x5)
 					| NDCB0_NC
 					| NDCB0_AUTO_RS
-					| NDCB0_CMD_TYPE(0x1)
-					| addr_cycle;
+					| NDCB0_CMD_TYPE(0x1);

 		nand->ndcb0[chunks] |= NDCB0_CMD_XTYPE(0x3)
-				| NDCB0_CMD_TYPE(0x1)
-				| NDCB0_ST_ROW_EN
-				| NDCB0_DBC
-				| (cmd & NDCB0_CMD2_MASK)
-				| NDCB0_CMD1_MASK
-				| addr_cycle;
+					| NDCB0_CMD_TYPE(0x1)
+					| NDCB0_ST_ROW_EN
+					| NDCB0_DBC
+					| (cmd & NDCB0_CMD2_MASK)
+					| NDCB0_CMD1_MASK;
 		nand->ndcb0[chunks] &= ~NDCB0_LEN_OVRD;
-		nand->ndcb3[chunks] = 0;
 		/* we should wait for RnB goes high which
 		 * indicate the data has been written succesfully*/
 		nand->wait_ready[nand->total_cmds] = 1;
@@ -905,8 +916,7 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 				| NDCB0_ADDR_CYC(3)
 				| NDCB0_DBC
 				| cmd;
-		nand->ndcb1 = page_addr;
-		nand->ndcb2 = 0;
+		nand->ndcb1[0] = page_addr;

 		break;
 	case NAND_CMD_RESET:
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 11:14:21 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 23:14:21 +0800
Subject: [PATCH 26/29] pxa3xx_nand: fix reset timeout on mmp2
Message-ID: <mailman.141.1280297054.27306.linux-mtd@lists.infradead.org>

For mmp2 board, reset command would always have timeout when enable
the IRQ processing. The command done would comes after exit the IRQ
processing whatever the timeout value is set.

Change reset command use polling mode fix the issue.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index ba15baf..cad97df 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -920,6 +920,10 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,

 		break;
 	case NAND_CMD_RESET:
+		/* on some platform, it is stranger that when issue reset command,
+		 * cmd done would not come till timeout cause irq exit.
+		 * Force polling mode for reset command*/
+		use_polling = 1;
 		cmd = info->cmdset->reset;
 		nand->ndcb0[0] |= NDCB0_CMD_TYPE(5)
 				| cmd;
@@ -945,7 +949,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
 	struct pxa3xx_nand *nand = info->nand_data;
-	int ret, exec_cmd;
+	int ret, exec_cmd, polling_mode;

 	/* if this is a x16 device ,then convert the input
 	 * "byte" address into a "word" address appropriate
@@ -961,6 +965,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
 	}

+	polling_mode = use_polling;
 	exec_cmd = prepare_command_pool(nand, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&nand->cmd_complete);
@@ -980,6 +985,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info
*mtd, unsigned command,
 		}
 		nand->state &= ~STATE_CMD_PREPARED;
 	}
+	use_polling = polling_mode;
 }

 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 11:16:58 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 23:16:58 +0800
Subject: [PATCH 27/29] pxa3xx_nand: fix write oob bug
Message-ID: <mailman.142.1280297069.27306.linux-mtd@lists.infradead.org>

For column addressing is only used to subpage and oob operation,
and the fact that our controller is performing poor at such two
operations, disable the column addressing in writing the ndcb1.

If not add this patch, write_oob function would fail.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   42 +++++++++++++++++++++++++++++++--------
 1 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index cad97df..65cf54c 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -267,6 +267,20 @@ static struct pxa3xx_nand_flash __devinitdata
builtin_flash_types[] = {
 { "256MiB 16-bit", 0xba20, 0xffff,  64, 2048, 16, 16, 1, 2048,
NAND_SETTING_ST, },
 };

+static struct nand_ecclayout nand_oob_128_BCH = {
+	.eccbytes = 64,
+	.eccpos = {
+		64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+		76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+		88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+		100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+		110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127},
+	.oobfree = {
+		{.offset = 2,
+		.length = 62}}
+};
+
 static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};

 #define NDTR0_tADL(c)		(min_t(uint32_t, (c), 31) << 27)
@@ -553,13 +567,19 @@ static void start_data_dma(struct pxa3xx_nand
*nand, int dir_out)
 	desc_oob->ddadr = desc->ddadr = DDADR_STOP;
 	desc_oob->dcmd = desc->dcmd = DCMD_WIDTH4 | DCMD_BURST32;
 	if (dir_out) {
+		if (nand->oob_size > 0) {
+			desc_oob->dsadr = nand->dma_buff_phys + info->page_size + nand->oob_column;
+			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG | oob_len;
+			desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc);
+			desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG | data_len;
+		}
+		else
+			desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG | data_len;
 		desc->dsadr = nand->dma_buff_phys + nand->data_column;
-		desc->dtadr = nand->mmio_phys + NDDB;
-		desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG |
(data_len + oob_len);
+		desc_oob->dtadr = desc->dtadr = nand->mmio_phys + NDDB;
 	} else {
 		if (nand->oob_size > 0) {
-			desc_oob->dtadr = nand->dma_buff_phys
-					+ info->page_size + nand->oob_column;
+			desc_oob->dtadr = nand->dma_buff_phys + info->page_size + nand->oob_column;
 			desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | oob_len;
 			desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc);
 			desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len;
@@ -720,11 +740,13 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 	uint16_t cmd;
 	int addr_cycle, exec_cmd, ndcb0, i, chunks = 0;
 	struct mtd_info *mtd;
+	struct nand_chip *chip;
 	struct pxa3xx_nand_info *info = nand->info[nand->chip_select];
 	struct platform_device *pdev = nand->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;

 	mtd = get_mtd_by_info(info);
+	chip = mtd->priv;
 	ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;;
 	addr_cycle = 0;
 	exec_cmd = 1;
@@ -779,11 +801,9 @@ static int prepare_command_pool(struct
pxa3xx_nand *nand, int command,
 		info->page_addr = page_addr;
 		/* small page addr setting */
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8)
-					| (column & 0xFF);
+			nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8);
 		else {
-			nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16)
-					| (column & 0xFFFF);
+			nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16);

 			if (page_addr & 0xFF0000)
 				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
@@ -845,7 +865,9 @@ static int prepare_command_pool(struct pxa3xx_nand
*nand, int command,
 		break;

 	case NAND_CMD_PAGEPROG:
-		if (is_buf_blank(nand->data_buff, (mtd->writesize + mtd->oobsize))) {
+		if (is_buf_blank(nand->data_buff, mtd->writesize) &&
+		    is_buf_blank(nand->oob_buff + chip->ecc.layout->oobfree[0].offset,
+			    chip->ecc.layout->oobfree[0].length)) {
 			exec_cmd = 0;
 			break;
 		}
@@ -1358,6 +1380,8 @@ static int __devinit pxa3xx_nand_scan(struct
mtd_info *mtd)

 	if (pxa3xx_nand_config_flash(info, f))
 		return -EINVAL;
+	if (f->page_size == 4096 && f->ecc_strength == 4)
+		chip->ecc.layout = &nand_oob_128_BCH;
 	pxa3xx_flash_ids[0].name = f->name;
 	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 11:17:36 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 23:17:36 +0800
Subject: [PATCH 28/29] pxa3xx_nand: fix power management support
Message-ID: <mailman.143.1280297072.27306.linux-mtd@lists.infradead.org>

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   48 +++++++++++++++++++++++++++++++--------
 1 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 65cf54c..bc2f56d 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1659,26 +1659,54 @@ static int __devinit pxa3xx_nand_probe(struct
platform_device *pdev)
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev,
pm_message_t state)
 {
-	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand *nand= platform_get_drvdata(pdev);
+	struct pxa3xx_nand_info *info;
+	struct mtd_info *mtd;
+	int ret = 0;
+	uint8_t cs;

-	if (info->state & STATE_CMD_PREPARED) {
-		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
+	if (nand->state & STATE_CMD_PREPARED) {
+		dev_err(&pdev->dev, "driver busy, state = %d\n", nand->state);
 		return -EAGAIN;
 	}

-	return 0;
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs ++) {
+		info = nand->info[cs];
+		if (!info)
+			continue;
+		mtd = get_mtd_by_info(info);
+		ret = mtd->suspend(mtd);
+	}
+
+	return ret;
 }

 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand *nand= platform_get_drvdata(pdev);
+	struct pxa3xx_nand_info *info;
+	struct mtd_info *mtd;
+	uint8_t cs;

-	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
-	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
-	clk_enable(info->clk);
+	for (cs = 0; cs < NUM_CHIP_SELECT; cs ++) {
+		info = nand->info[cs];
+		if (!info)
+			continue;
+		nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
+		nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
+		nand->chip_select = cs;
+		/* Sometimes nand chip would raise a ready interrupt
+		 * when resume, reset the by start and stop to prevent
+		 * it damage driver's state machine */
+		pxa3xx_nand_start(nand);
+		pxa3xx_nand_stop(nand);
+		mtd = get_mtd_by_info(info);
+		mtd->resume(mtd);
+	}

+	/* set the controller cs to a invalid num to let driver
+	 * reconfigure the timing when it call the cmdfunc */
+	nand->chip_select = 0xff;
 	return 0;
 }
 #else
-- 
1.7.0.4


From leiwen at marvell.com  Tue Jun 22 08:19:35 2010
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 22 Jun 2010 20:19:35 +0800
Subject: [PATCH 03/06] pxa3xx_nand: fix compile warning
Message-ID: <mailman.187.1282048210.27306.linux-mtd@lists.infradead.org>

The compile output as below:
WARNING: modpost: Found 1 section mismatch(es).

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 02a4466..e3061bc 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1066,7 +1066,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->chip_delay = 25;
 }

-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static int __devinit pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
-- 
1.7.0.4

--000e0ce043362ad62d048e041b32
Content-Type: text/x-patch; charset=US-ASCII; 
	name="0003-pxa3xx_nand-fix-compile-warning.patch"
Content-Disposition: attachment; 
	filename="0003-pxa3xx_nand-fix-compile-warning.patch"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_gcyq3hvh0

RnJvbSBmNjZkNDU4MTg3MTJhOTQ5OTQ1OGI0OWI1ZmMwZGRhOTM1NzAyZjUyIE1vbiBTZXAgMTcg
MDA6MDA6MDAgMjAwMQpGcm9tOiBMZWkgV2VuIDxsZWl3ZW5AbWFydmVsbC5jb20+CkRhdGU6IFR1
ZSwgMjIgSnVuIDIwMTAgMjA6MTk6MzUgKzA4MDAKU3ViamVjdDogW1BBVENIIDAzLzEyXSBweGEz
eHhfbmFuZDogZml4IGNvbXBpbGUgd2FybmluZwoKVGhlIGNvbXBpbGUgb3V0cHV0IGFzIGJlbG93
OgpXQVJOSU5HOiBtb2Rwb3N0OiBGb3VuZCAxIHNlY3Rpb24gbWlzbWF0Y2goZXMpLgoKU2lnbmVk
LW9mZi1ieTogTGVpIFdlbiA8bGVpd2VuQG1hcnZlbGwuY29tPgotLS0KIGRyaXZlcnMvbXRkL25h
bmQvcHhhM3h4X25hbmQuYyB8ICAgIDIgKy0KIDEgZmlsZXMgY2hhbmdlZCwgMSBpbnNlcnRpb25z
KCspLCAxIGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvbXRkL25hbmQvcHhhM3h4
X25hbmQuYyBiL2RyaXZlcnMvbXRkL25hbmQvcHhhM3h4X25hbmQuYwppbmRleCAwMmE0NDY2Li5l
MzA2MWJjIDEwMDY0NAotLS0gYS9kcml2ZXJzL210ZC9uYW5kL3B4YTN4eF9uYW5kLmMKKysrIGIv
ZHJpdmVycy9tdGQvbmFuZC9weGEzeHhfbmFuZC5jCkBAIC0xMDY2LDcgKzEwNjYsNyBAQCBzdGF0
aWMgdm9pZCBweGEzeHhfbmFuZF9pbml0X210ZChzdHJ1Y3QgbXRkX2luZm8gKm10ZCwKIAl0aGlz
LT5jaGlwX2RlbGF5ID0gMjU7CiB9CiAKLXN0YXRpYyBpbnQgcHhhM3h4X25hbmRfcHJvYmUoc3Ry
dWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3N0YXRpYyBpbnQgX19kZXZpbml0IHB4YTN4eF9u
YW5kX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiB7CiAJc3RydWN0IHB4YTN4
eF9uYW5kX3BsYXRmb3JtX2RhdGEgKnBkYXRhOwogCXN0cnVjdCBweGEzeHhfbmFuZF9pbmZvICpp
bmZvOwotLSAKMS43LjAuNAoK
--000e0ce043362ad62d048e041b32--


From bogus@does.not.exist.com  Sun Jun  6 12:36:48 2010
From: bogus@does.not.exist.com ()
Date: Sun, 06 Jun 2010 16:36:48 -0000
Subject: No subject
Message-ID: <mailman.218.1283367475.27306.linux-mtd@lists.infradead.org>

to reproduce this. Since I do not have your HW I cannot reproduce this,
so the only thing I can do is to ask you to reproduce the problem with
various debugging patches.

CCing Adrian - may be he has ideas.

-- 
Best Regards,
Artem Bityutskiy (???????????????? ??????????)



From bogus@does.not.exist.com  Sun Jun  6 12:36:48 2010
From: bogus@does.not.exist.com ()
Date: Sun, 06 Jun 2010 16:36:48 -0000
Subject: No subject
Message-ID: <mailman.231.1283515979.27306.linux-mtd@lists.infradead.org>

owner of this part of filetree.
Or did I misused the -r option?

I hope you can give me a comment or some feedback, how to change this behaviour.

Best regards
Arno


From stanley.miao at windriver.com  Fri Jun 18 06:20:39 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 18 Jun 2010 10:20:39 -0000
Subject: [v3 1/3] clean up the legacy interfaces in nandwrite.c
In-Reply-To: <1276857173-10848-1-git-send-email-stanley.miao@windriver.com>
References: <1276857173-10848-1-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276857173-10848-2-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update nandwrite to use the new ioctl command ECCGETLAYOUT. In order to
keep compatible with the old linux kernel, a linux version detection function
is added.

YAFFS and JFFS2 has updated and we don't need the arguments "forcelegacy",
"forcejffs2", "forceyaffs" anymore. Now clean them up.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 nandwrite.c |  224 +++++++++++++++--------------------------------------------
 1 files changed, 57 insertions(+), 167 deletions(-)

diff --git a/nandwrite.c b/nandwrite.c
index 1b4ca3d..eadca54 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <getopt.h>
 
 #include <asm/types.h>
@@ -45,26 +46,7 @@
 #define MAX_PAGE_SIZE	4096
 #define MAX_OOB_SIZE	128
 
-// oob layouts to pass into the kernel as default
-static struct nand_oobinfo none_oobinfo = {
-	.useecc = MTD_NANDECC_OFF,
-};
-
-static struct nand_oobinfo jffs2_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 0, 1, 2, 3, 6, 7 }
-};
-
-static struct nand_oobinfo yaffs_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_oobinfo autoplace_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE
-};
+#define LINUX_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
 
 static void display_help (void)
 {
@@ -72,13 +54,7 @@ static void display_help (void)
 "Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
 "Writes to the specified MTD device.\n"
 "\n"
-"  -a, --autoplace         Use auto oob layout\n"
-"  -j, --jffs2             Force jffs2 oob layout (legacy support)\n"
-"  -y, --yaffs             Force yaffs oob layout (legacy support)\n"
-"  -f, --forcelegacy       Force legacy support on autoplacement-enabled mtd\n"
-"                          device\n"
 "  -m, --markbad           Mark blocks bad if write fails\n"
-"  -n, --noecc             Write without ecc\n"
 "  -o, --oob               Image contains oob data\n"
 "  -r, --raw               Image contains the raw oob data dumped by nanddump\n"
 "  -s addr, --start=addr   Set start address (default is 0)\n"
@@ -112,37 +88,49 @@ static int		mtdoffset = 0;
 static bool		quiet = false;
 static bool		writeoob = false;
 static bool		rawoob = false;
-static bool		autoplace = false;
 static bool		markbad = false;
-static bool		forcejffs2 = false;
-static bool		forceyaffs = false;
-static bool		forcelegacy = false;
-static bool		noecc = false;
 static bool		pad = false;
 static int		blockalign = 1; /*default to using 16K block size */
 
+static int get_linux_version(void)
+{
+	int a, b, c, ret, err = 0;
+	struct utsname buf;
+
+	ret = uname(&buf);
+	if (ret == 0) {
+		ret = sscanf(buf.release, "%d.%d.%d", &a, &b, &c);
+		if (ret != 3)
+			err = 1;
+	} else
+		err = 1;
+
+	if (err) {
+		a = b = c = 0xff;
+		fprintf(stderr, "Warning: Can't get linux kernel version."
+				"Set the default version to the latest version.\n");
+	}
+
+	return LINUX_VERSION(a, b, c);
+}
+
 static void process_options (int argc, char * const argv[])
 {
 	int error = 0;
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "ab:fjmnopqrs:y";
+		static const char *short_options = "b:mopqrs:";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
-			{"autoplace", no_argument, 0, 'a'},
 			{"blockalign", required_argument, 0, 'b'},
-			{"forcelegacy", no_argument, 0, 'f'},
-			{"jffs2", no_argument, 0, 'j'},
 			{"markbad", no_argument, 0, 'm'},
-			{"noecc", no_argument, 0, 'n'},
 			{"oob", no_argument, 0, 'o'},
 			{"pad", no_argument, 0, 'p'},
 			{"quiet", no_argument, 0, 'q'},
 			{"raw", no_argument, 0, 'r'},
 			{"start", required_argument, 0, 's'},
-			{"yaffs", no_argument, 0, 'y'},
 			{0, 0, 0, 0},
 		};
 
@@ -166,21 +154,6 @@ static void process_options (int argc, char * const argv[])
 			case 'q':
 				quiet = true;
 				break;
-			case 'a':
-				autoplace = true;
-				break;
-			case 'j':
-				forcejffs2 = true;
-				break;
-			case 'y':
-				forceyaffs = true;
-				break;
-			case 'f':
-				forcelegacy = true;
-				break;
-			case 'n':
-				noecc = true;
-				break;
 			case 'm':
 				markbad = true;
 				break;
@@ -258,8 +231,7 @@ int main(int argc, char * const argv[])
 	struct mtd_oob_buf oob;
 	loff_t offs;
 	int ret;
-	int oobinfochanged = 0;
-	struct nand_oobinfo old_oobinfo;
+	struct nand_ecclayout ecclayout;
 	bool failed = true;
 	// contains all the data read from the file so far for the current eraseblock
 	unsigned char *filebuf = NULL;
@@ -316,86 +288,30 @@ int main(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (autoplace) {
-		/* Read the current oob info */
-		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMGETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-
-		// autoplace ECC ?
-		if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
-
-			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
-				perror ("MEMSETOOBSEL");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-			oobinfochanged = 1;
-		}
-	}
-
-	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
-		if (ret == 0) {
-			oobinfochanged = 2;
-		} else {
-			switch (errno) {
-			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				oobinfochanged = 1;
-				break;
-			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-		}
-	}
-
-	/*
-	 * force oob layout for jffs2 or yaffs ?
-	 * Legacy support
-	 */
-	if (forcejffs2 || forceyaffs) {
-		struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
 
-		if (autoplace) {
-			fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n");
-			goto restoreoob;
-		}
-		if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) {
-			fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n");
-			goto restoreoob;
-		}
-		if (meminfo.oobsize == 8) {
-			if (forceyaffs) {
-				fprintf (stderr, "YAFSS cannot operate on 256 Byte page size");
-				goto restoreoob;
-			}
-			/* Adjust number of ecc bytes */
-			jffs2_oobinfo.eccbytes = 3;
+	oob.length = meminfo.oobsize;
+	oob.ptr =  oobbuf;
+
+	memset(&ecclayout, 0, sizeof(ecclayout));
+	if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+		if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+			perror("ECCGETLAYOUT");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
+	} else {
+		struct nand_oobinfo oi;
 
-		if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) {
-			perror ("MEMSETOOBSEL");
-			goto restoreoob;
+		if (ioctl(fd, MEMGETOOBSEL, &oi) != 0) {
+			perror("MEMGETOOBSEL");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
+		memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+		memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+		ecclayout.eccbytes = oi.eccbytes;
 	}
 
-	oob.length = meminfo.oobsize;
-	oob.ptr = noecc ? oobreadbuf : oobbuf;
-
 	/* Determine if we are reading from standard input or from a file. */
 	if (strcmp(img, standard_input) == 0) {
 		ifd = STDIN_FILENO;
@@ -559,6 +475,8 @@ int main(int argc, char * const argv[])
 		}
 
 		if (writeoob) {
+			int i, start, len;
+			int tags_pos = 0;
 			oobreadbuf = writebuf + meminfo.writesize;
 
 			// Read more data for the OOB from the input if there isn't enough in the buffer
@@ -595,40 +513,19 @@ int main(int argc, char * const argv[])
 				}
 			}
 
-			if (noecc) {
-				oob.ptr = oobreadbuf;
-			} else {
-				int i, start, len;
-				int tags_pos = 0;
-				/*
-				 *  We use autoplacement and have the oobinfo with the autoplacement
-				 * information from the kernel available
-				 *
-				 * Modified to support out of order oobfree segments,
-				 * such as the layout used by diskonchip.c
-				 */
-				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
-					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
-						/* Set the reserved bytes to 0xff */
-						start = old_oobinfo.oobfree[i][0];
-						len = old_oobinfo.oobfree[i][1];
-						if (rawoob)
-							memcpy(oobbuf + start,
-									oobreadbuf + start, len);
-						else
-							memcpy(oobbuf + start,
-									oobreadbuf + tags_pos, len);
-						tags_pos += len;
-					}
-				} else {
-					/* Set at least the ecc byte positions to 0xff */
-					start = old_oobinfo.eccbytes;
-					len = meminfo.oobsize - start;
+			for (i = 0; ecclayout.oobfree[i].length; i++) {
+				/* Set the reserved bytes to 0xff */
+				start = ecclayout.oobfree[i].offset;
+				len = ecclayout.oobfree[i].length;
+				if (rawoob)
 					memcpy(oobbuf + start,
-							oobreadbuf + start,
-							len);
-				}
+							oobreadbuf + start, len);
+				else
+					memcpy(oobbuf + start,
+							oobreadbuf + tags_pos, len);
+				tags_pos += len;
 			}
+
 			/* Write OOB data first, as ecc will be placed in there*/
 			oob.start = mtdoffset;
 			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
@@ -687,13 +584,6 @@ closeall:
 	close(ifd);
 
 restoreoob:
-	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-	}
 
 	close(fd);
 
-- 
1.5.4.3



From stanley.miao at windriver.com  Fri Jun 18 06:20:42 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 18 Jun 2010 10:20:42 -0000
Subject: [v3 3/3] Place the cleanmarker in OOB area according to the mode
	MTD_OOB_AUTO
In-Reply-To: <1276857173-10848-3-git-send-email-stanley.miao@windriver.com>
References: <1276857173-10848-1-git-send-email-stanley.miao@windriver.com>
	<1276857173-10848-2-git-send-email-stanley.miao@windriver.com>
	<1276857173-10848-3-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276857173-10848-4-git-send-email-stanley.miao@windriver.com>

The jffs2 filesystem writes the cleanmarker according to the mode
MTD_OOB_AUTO, so flash_eraseall should arrange the layout of the
cleanmarker according to the mode MTD_OOB_AUTO too.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   40 ++++++++++++++++++++++------------------
 1 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index b8068c0..374edd7 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -34,7 +34,7 @@
 #include <time.h>
 #include <getopt.h>
 #include <sys/ioctl.h>
-#include <sys/mount.h>
+#include <sys/param.h>
 #include <sys/utsname.h>
 #include "crc32.h"
 
@@ -83,9 +83,11 @@ static int get_linux_version(void)
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
-	int fd, clmpos = 0, clmlen = 8;
+	int fd;
 	erase_info_t erase;
 	int isNAND, bbtest = 1;
+	unsigned char oobbuf[128];
+	memset(oobbuf, 0xFF, 128);
 
 	process_options(argc, argv);
 
@@ -106,11 +108,18 @@ int main (int argc, char *argv[])
 	if (jffs2) {
 		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
 		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-		if (!isNAND)
+		if (!isNAND) {
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
-		else {
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+		} else {
+			int already_read, num, i, start;
 			struct nand_ecclayout ecclayout;
 
+			cleanmarker.totlen = cpu_to_je32(8);
+			cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, \
+						sizeof(struct jffs2_unknown_node) - 4));
+
 			memset(&ecclayout, 0, sizeof(ecclayout));
 			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
 				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
@@ -130,19 +139,14 @@ int main (int argc, char *argv[])
 				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
 				ecclayout.eccbytes = oi.eccbytes;
 			}
-
-			/* Get the position of the free bytes */
-			if (!ecclayout.oobfree[0].length) {
-				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
-				return 1;
+			already_read = 0;
+			for (i = 0; (already_read < 8) && ecclayout.oobfree[i].length; i++) {
+				num = MIN(8 - already_read, ecclayout.oobfree[i].length);
+				start = ecclayout.oobfree[i].offset;
+				memcpy(oobbuf + start, (unsigned char *)&cleanmarker + already_read, num);
+				already_read += num;
 			}
-			clmpos = ecclayout.oobfree[0].offset;
-			clmlen = ecclayout.oobfree[0].length;
-			if (clmlen > 8)
-				clmlen = 8;
-			cleanmarker.totlen = cpu_to_je32(8);
 		}
-		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
 	}
 
 	for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) {
@@ -182,9 +186,9 @@ int main (int argc, char *argv[])
 		/* write cleanmarker */
 		if (isNAND) {
 			struct mtd_oob_buf oob;
-			oob.ptr = (unsigned char *) &cleanmarker;
-			oob.start = erase.start + clmpos;
-			oob.length = clmlen;
+			oob.ptr = oobbuf;
+			oob.start = erase.start;
+			oob.length = meminfo.oobsize;
 			if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
 				fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
 				continue;
-- 
1.5.4.3



From stanley.miao at windriver.com  Fri Jun 18 06:20:40 2010
From: stanley.miao at windriver.com (Stanley.Miao)
Date: Fri, 18 Jun 2010 10:20:40 -0000
Subject: [v3 2/3] Discard the legacy interface MEMGETOOBSEL in flash_eraseall
In-Reply-To: <1276857173-10848-2-git-send-email-stanley.miao@windriver.com>
References: <1276857173-10848-1-git-send-email-stanley.miao@windriver.com>
	<1276857173-10848-2-git-send-email-stanley.miao@windriver.com>
Message-ID: <1276857173-10848-3-git-send-email-stanley.miao@windriver.com>

The "struct nand_oobinfo" is able to record only 32 ECC code positions,which
is not enough for many big NAND chips. Therefore, this structure is replaced
by "struct nand_ecclayout" in linux kernel from the version 2.6.17.
Consequently, the ioctl command changed from MEMGETOOBSEL to ECCGETLAYOUT.

Now update flash_eraseall to use the new ioctl command ECCGETLAYOUT. In order
to keep compatible with the old linux kernel, a linux version detection
function is added.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 flash_eraseall.c |   79 ++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/flash_eraseall.c b/flash_eraseall.c
index a22fc49..b8068c0 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -35,6 +35,7 @@
 #include <getopt.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
+#include <sys/utsname.h>
 #include "crc32.h"
 
 #include <mtd/mtd-user.h>
@@ -43,6 +44,8 @@
 #define PROGRAM "flash_eraseall"
 #define VERSION "$Revision: 1.22 $"
 
+#define LINUX_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
+
 static const char *exe_name;
 static const char *mtd_device;
 static int quiet;		/* true -- don't output progress */
@@ -55,6 +58,28 @@ static void display_version (void);
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
 
+static int get_linux_version(void)
+{
+	int a, b, c, ret, err = 0;
+	struct utsname buf;
+
+	ret = uname(&buf);
+	if (ret == 0) {
+		ret = sscanf(buf.release, "%d.%d.%d", &a, &b, &c);
+		if (ret != 3)
+			err = 1;
+	} else
+		err = 1;
+
+	if (err) {
+		a = b = c = 0xff;
+		fprintf(stderr, "Warning: Can't get linux kernel version."
+				"Set the default version to the latest version.\n");
+	}
+
+	return LINUX_VERSION(a, b, c);
+}
+
 int main (int argc, char *argv[])
 {
 	mtd_info_t meminfo;
@@ -84,41 +109,37 @@ int main (int argc, char *argv[])
 		if (!isNAND)
 			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
 		else {
-			struct nand_oobinfo oobinfo;
-
-			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
-				fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", exe_name, mtd_device);
-				return 1;
-			}
+			struct nand_ecclayout ecclayout;
 
-			/* Check for autoplacement */
-			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
-				/* Get the position of the free bytes */
-				if (!oobinfo.oobfree[0][1]) {
-					fprintf (stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+			memset(&ecclayout, 0, sizeof(ecclayout));
+			if (get_linux_version() > LINUX_VERSION(2, 6, 17)) {
+				if (ioctl(fd, ECCGETLAYOUT, &ecclayout) != 0) {
+					fprintf(stderr,	"%s: %s: unable to get NAND oob layout\n", \
+							exe_name, mtd_device);
 					return 1;
 				}
-				clmpos = oobinfo.oobfree[0][0];
-				clmlen = oobinfo.oobfree[0][1];
-				if (clmlen > 8)
-					clmlen = 8;
 			} else {
-				/* Legacy mode */
-				switch (meminfo.oobsize) {
-					case 8:
-						clmpos = 6;
-						clmlen = 2;
-						break;
-					case 16:
-						clmpos = 8;
-						clmlen = 8;
-						break;
-					case 64:
-						clmpos = 16;
-						clmlen = 8;
-						break;
+				struct nand_oobinfo oi;
+
+				if (ioctl(fd, MEMGETOOBSEL, &oi) != 0) {
+					fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", \
+							exe_name, mtd_device);
+					return 1;
 				}
+				memcpy(&ecclayout.eccpos, &oi.eccpos, sizeof(oi.eccpos));
+				memcpy(&ecclayout.oobfree, &oi.oobfree, sizeof(oi.oobfree));
+				ecclayout.eccbytes = oi.eccbytes;
+			}
+
+			/* Get the position of the free bytes */
+			if (!ecclayout.oobfree[0].length) {
+				fprintf(stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
+				return 1;
 			}
+			clmpos = ecclayout.oobfree[0].offset;
+			clmlen = ecclayout.oobfree[0].length;
+			if (clmlen > 8)
+				clmlen = 8;
 			cleanmarker.totlen = cpu_to_je32(8);
 		}
 		cleanmarker.hdr_crc =  cpu_to_je32 (crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
-- 
1.5.4.3



