public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}()
@ 2008-06-28 12:14 Haavard Skinnemoen
  2008-06-28 12:14 ` [PATCH RESEND 2/3] atmel_nand: Work around AT32AP7000 ECC errata Haavard Skinnemoen
  2008-06-30 13:06 ` [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}() Jörn Engel
  0 siblings, 2 replies; 4+ messages in thread
From: Haavard Skinnemoen @ 2008-06-28 12:14 UTC (permalink / raw)
  To: David Woodhouse
  Cc: David Brownell, Haavard Skinnemoen, David Brownell, linux-mtd,
	linux-kernel

From: David Brownell <david-b@pacbell.net>

This uses __raw_{read,write}s{b,w}() primitives to access data on NAND
chips for more efficient I/O.

On an arm926 with memory clocked at 100 MHz, this reduced the elapsed
time for a 64 MByte read by 16%.  ("dd" /dev/mtd0 to /dev/null, with
an 8-bit NAND using hardware ECC and 128KB blocksize.)

Also some minor section tweaks:

  - Use platform_driver_probe() so no pointer to probe() lingers
    after that code has been removed at run-time.

  - Use __exit and __exit_p so the remove() code will normally be
    removed by the linker.

Since these buffer read/write calls are new, this increases the runtime
code footprint (by 88 bytes on my build, after the section tweaks).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
[haavard.skinnemoen@atmel.com: rebase onto atmel_nand rename]
Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Acked-by: Andrew Victor <linux@maxim.org.za>
---
Resending the series with Andrew's ACKs added, no other changes.

 drivers/mtd/nand/atmel_nand.c |   46 ++++++++++++++++++++++++++++++++++++----
 1 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 50700ab..4814fc9 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -142,6 +142,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
 }
 
 /*
+ * Minimal-overhead PIO for data access.
+ */
+static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct nand_chip	*nand_chip = mtd->priv;
+
+	__raw_readsb(nand_chip->IO_ADDR_R, buf, len);
+}
+
+static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct nand_chip	*nand_chip = mtd->priv;
+
+	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+}
+
+static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct nand_chip	*nand_chip = mtd->priv;
+
+	__raw_writesb(nand_chip->IO_ADDR_W, buf, len);
+}
+
+static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct nand_chip	*nand_chip = mtd->priv;
+
+	__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
+}
+
+/*
  * write oob for small pages
  */
 static int atmel_nand_write_oob_512(struct mtd_info *mtd,
@@ -436,8 +467,14 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
 	nand_chip->chip_delay = 20;		/* 20us command delay time */
 
-	if (host->board->bus_width_16)		/* 16-bit bus width */
+	if (host->board->bus_width_16) {	/* 16-bit bus width */
 		nand_chip->options |= NAND_BUSWIDTH_16;
+		nand_chip->read_buf = atmel_read_buf16;
+		nand_chip->write_buf = atmel_write_buf16;
+	} else {
+		nand_chip->read_buf = atmel_read_buf;
+		nand_chip->write_buf = atmel_write_buf;
+	}
 
 	platform_set_drvdata(pdev, host);
 	atmel_nand_enable(host);
@@ -546,7 +583,7 @@ err_nand_ioremap:
 /*
  * Remove a NAND device.
  */
-static int __devexit atmel_nand_remove(struct platform_device *pdev)
+static int __exit atmel_nand_remove(struct platform_device *pdev)
 {
 	struct atmel_nand_host *host = platform_get_drvdata(pdev);
 	struct mtd_info *mtd = &host->mtd;
@@ -564,8 +601,7 @@ static int __devexit atmel_nand_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver atmel_nand_driver = {
-	.probe		= atmel_nand_probe,
-	.remove		= atmel_nand_remove,
+	.remove		= __exit_p(atmel_nand_remove),
 	.driver		= {
 		.name	= "atmel_nand",
 		.owner	= THIS_MODULE,
@@ -574,7 +610,7 @@ static struct platform_driver atmel_nand_driver = {
 
 static int __init atmel_nand_init(void)
 {
-	return platform_driver_register(&atmel_nand_driver);
+	return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe);
 }
 
 
-- 
1.5.5.4

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

* [PATCH RESEND 2/3] atmel_nand: Work around AT32AP7000 ECC errata
  2008-06-28 12:14 [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}() Haavard Skinnemoen
@ 2008-06-28 12:14 ` Haavard Skinnemoen
  2008-06-28 12:14   ` [PATCH RESEND 3/3] MTD: atmel_nand can be modular Haavard Skinnemoen
  2008-06-30 13:06 ` [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}() Jörn Engel
  1 sibling, 1 reply; 4+ messages in thread
From: Haavard Skinnemoen @ 2008-06-28 12:14 UTC (permalink / raw)
  To: David Woodhouse; +Cc: Haavard Skinnemoen, linux-mtd, linux-kernel

The ALE signal isn't correctly wired up to the ECC controller on the
AP7000, so it starts calculating ECC during the address cycles.

Work around this by resetting the ECC controller between the address and
data cycles.

Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Acked-by: Andrew Victor <linux@maxim.org.za>
---
Andrew, the comment you mentioned

   nand_chip->ecc.hwctl = at91_nand_hwctl;     /* unused */

doesn't seem to have made it into the MTD tree. So there was nothing
to remove.

 drivers/mtd/nand/atmel_nand.c |   25 +++++++++++++++++++++++--
 1 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4814fc9..99aec46 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 
 #ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
 #define hard_ecc	1
@@ -264,6 +265,19 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
 	uint8_t *ecc_pos;
 	int stat;
 
+	/*
+	 * Errata: ALE is incorrectly wired up to the ECC controller
+	 * on the AP7000, so it will include the address cycles in the
+	 * ECC calculation.
+	 *
+	 * Workaround: Reset the parity registers before reading the
+	 * actual data.
+	 */
+	if (cpu_is_at32ap7000()) {
+		struct atmel_nand_host *host = chip->priv;
+		ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
+	}
+
 	/* read the page */
 	chip->read_buf(mtd, p, eccsize);
 
@@ -377,9 +391,16 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
 }
 
 /*
- * Enable HW ECC : unsused
+ * Enable HW ECC : unused on most chips
  */
-static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { ; }
+static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+	if (cpu_is_at32ap7000()) {
+		struct nand_chip *nand_chip = mtd->priv;
+		struct atmel_nand_host *host = nand_chip->priv;
+		ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
+	}
+}
 
 #ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL };
-- 
1.5.5.4

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

* [PATCH RESEND 3/3] MTD: atmel_nand can be modular
  2008-06-28 12:14 ` [PATCH RESEND 2/3] atmel_nand: Work around AT32AP7000 ECC errata Haavard Skinnemoen
@ 2008-06-28 12:14   ` Haavard Skinnemoen
  0 siblings, 0 replies; 4+ messages in thread
From: Haavard Skinnemoen @ 2008-06-28 12:14 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Haavard Skinnemoen, David Brownell, linux-mtd, linux-kernel

From: David Brownell <dbrownell@users.sourceforge.net>

There's no reason to prevent the Atmel NAND driver from
building as a module.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Acked-by: Andrew Victor <linux@maxim.org.za>
---
 drivers/mtd/nand/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index d8c0d86..71406e5 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -272,7 +272,7 @@ config MTD_NAND_CS553X
 	  If you say "m", the module will be called "cs553x_nand.ko".
 
 config MTD_NAND_ATMEL
-	bool "Support for NAND Flash / SmartMedia on AT91 and AVR32"
+	tristate "Support for NAND Flash / SmartMedia on AT91 and AVR32"
 	depends on ARCH_AT91 || AVR32
 	help
 	  Enables support for NAND Flash / Smart Media Card interface
-- 
1.5.5.4

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

* Re: [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}()
  2008-06-28 12:14 [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}() Haavard Skinnemoen
  2008-06-28 12:14 ` [PATCH RESEND 2/3] atmel_nand: Work around AT32AP7000 ECC errata Haavard Skinnemoen
@ 2008-06-30 13:06 ` Jörn Engel
  1 sibling, 0 replies; 4+ messages in thread
From: Jörn Engel @ 2008-06-30 13:06 UTC (permalink / raw)
  To: Haavard Skinnemoen
  Cc: David Brownell, linux-mtd, David Brownell, David Woodhouse,
	linux-kernel

On Sat, 28 June 2008 14:14:06 +0200, Haavard Skinnemoen wrote:
> 
> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
> [haavard.skinnemoen@atmel.com: rebase onto atmel_nand rename]
> Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
> Acked-by: Andrew Victor <linux@maxim.org.za>

Acked-by: Joern Engel <joern@logfs.org>

Same goes for the other two patches in the series.

Jörn

-- 
Joern's library part 9:
http://www.scl.ameslab.gov/Publications/Gus/TwelveWays.html

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

end of thread, other threads:[~2008-06-30 13:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-28 12:14 [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}() Haavard Skinnemoen
2008-06-28 12:14 ` [PATCH RESEND 2/3] atmel_nand: Work around AT32AP7000 ECC errata Haavard Skinnemoen
2008-06-28 12:14   ` [PATCH RESEND 3/3] MTD: atmel_nand can be modular Haavard Skinnemoen
2008-06-30 13:06 ` [PATCH RESEND 1/3] atmel_nand speedup via {read,write}s{b,w}() Jörn Engel

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