diff options
| author | David Brownell <david-b@pacbell.net> | 2008-07-04 02:40:16 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 09:51:21 -0400 |
| commit | 23a346ca4a5a6f50f81062456af955155f68e313 (patch) | |
| tree | d2e37dfb9bdc350aab668ee0cac9168a43cc78ea | |
| parent | 175428b2b3eeacf90dcc171d5915d6b4dc86e917 (diff) | |
[MTD] [NAND] atmel_nand speedup via {read,write}s{b,w}()
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 MiB read by 16%. ("dd" /dev/mtd0 to /dev/null, with an 8-bit
NAND using hardware ECC and 128KiB 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).
[haavard.skinnemoen@atmel.com: rebase onto atmel_nand rename]
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: HÃ¥vard Skinnemoen <haavard.skinnemoen@atmel.com>
Acked-by: Andrew Victor <linux@maxim.org.za>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
| -rw-r--r-- | 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 50700ab5a57a..4814fc9b237b 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) | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | /* | 144 | /* |
| 145 | * Minimal-overhead PIO for data access. | ||
| 146 | */ | ||
| 147 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | ||
| 148 | { | ||
| 149 | struct nand_chip *nand_chip = mtd->priv; | ||
| 150 | |||
| 151 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); | ||
| 152 | } | ||
| 153 | |||
| 154 | static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) | ||
| 155 | { | ||
| 156 | struct nand_chip *nand_chip = mtd->priv; | ||
| 157 | |||
| 158 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); | ||
| 159 | } | ||
| 160 | |||
| 161 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | ||
| 162 | { | ||
| 163 | struct nand_chip *nand_chip = mtd->priv; | ||
| 164 | |||
| 165 | __raw_writesb(nand_chip->IO_ADDR_W, buf, len); | ||
| 166 | } | ||
| 167 | |||
| 168 | static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) | ||
| 169 | { | ||
| 170 | struct nand_chip *nand_chip = mtd->priv; | ||
| 171 | |||
| 172 | __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); | ||
| 173 | } | ||
| 174 | |||
| 175 | /* | ||
| 145 | * write oob for small pages | 176 | * write oob for small pages |
| 146 | */ | 177 | */ |
| 147 | static int atmel_nand_write_oob_512(struct mtd_info *mtd, | 178 | 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) | |||
| 436 | 467 | ||
| 437 | nand_chip->chip_delay = 20; /* 20us command delay time */ | 468 | nand_chip->chip_delay = 20; /* 20us command delay time */ |
| 438 | 469 | ||
| 439 | if (host->board->bus_width_16) /* 16-bit bus width */ | 470 | if (host->board->bus_width_16) { /* 16-bit bus width */ |
| 440 | nand_chip->options |= NAND_BUSWIDTH_16; | 471 | nand_chip->options |= NAND_BUSWIDTH_16; |
| 472 | nand_chip->read_buf = atmel_read_buf16; | ||
| 473 | nand_chip->write_buf = atmel_write_buf16; | ||
| 474 | } else { | ||
| 475 | nand_chip->read_buf = atmel_read_buf; | ||
| 476 | nand_chip->write_buf = atmel_write_buf; | ||
| 477 | } | ||
| 441 | 478 | ||
| 442 | platform_set_drvdata(pdev, host); | 479 | platform_set_drvdata(pdev, host); |
| 443 | atmel_nand_enable(host); | 480 | atmel_nand_enable(host); |
| @@ -546,7 +583,7 @@ err_nand_ioremap: | |||
| 546 | /* | 583 | /* |
| 547 | * Remove a NAND device. | 584 | * Remove a NAND device. |
| 548 | */ | 585 | */ |
| 549 | static int __devexit atmel_nand_remove(struct platform_device *pdev) | 586 | static int __exit atmel_nand_remove(struct platform_device *pdev) |
| 550 | { | 587 | { |
| 551 | struct atmel_nand_host *host = platform_get_drvdata(pdev); | 588 | struct atmel_nand_host *host = platform_get_drvdata(pdev); |
| 552 | struct mtd_info *mtd = &host->mtd; | 589 | struct mtd_info *mtd = &host->mtd; |
| @@ -564,8 +601,7 @@ static int __devexit atmel_nand_remove(struct platform_device *pdev) | |||
| 564 | } | 601 | } |
| 565 | 602 | ||
| 566 | static struct platform_driver atmel_nand_driver = { | 603 | static struct platform_driver atmel_nand_driver = { |
| 567 | .probe = atmel_nand_probe, | 604 | .remove = __exit_p(atmel_nand_remove), |
| 568 | .remove = atmel_nand_remove, | ||
| 569 | .driver = { | 605 | .driver = { |
| 570 | .name = "atmel_nand", | 606 | .name = "atmel_nand", |
| 571 | .owner = THIS_MODULE, | 607 | .owner = THIS_MODULE, |
| @@ -574,7 +610,7 @@ static struct platform_driver atmel_nand_driver = { | |||
| 574 | 610 | ||
| 575 | static int __init atmel_nand_init(void) | 611 | static int __init atmel_nand_init(void) |
| 576 | { | 612 | { |
| 577 | return platform_driver_register(&atmel_nand_driver); | 613 | return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe); |
| 578 | } | 614 | } |
| 579 | 615 | ||
| 580 | 616 | ||
