diff options
author | Vipin Kumar <vipin.kumar@st.com> | 2012-03-14 02:17:17 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-03-26 20:00:14 -0400 |
commit | 604e75444fa82cfdcba339e3bd4da1dfd6947539 (patch) | |
tree | 44e3c2dd6ce4e9ef871ca5dd9f74fa197f655b2d /drivers/mtd | |
parent | 712c4add03277197168210bb628b8273e36adf76 (diff) |
mtd: nand/fsmc: Access the NAND device word by word whenever possible
The default way of accessing nand device is using the nand width. This means
that 8bit devices are using u8 * and 16bit devices are accessed using u16 *.
This results in a non-optimal performance since the FSMC is designed to
translate the normal word accesses into device width based accesses. This patch
implements read_buf and write_buf callbacks using word by word accesses.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Reviewed-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/fsmc_nand.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index c41f45faa09e..81fc8e6b8cb8 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -524,6 +524,52 @@ static int count_written_bits(uint8_t *buff, int size, int max_bits) | |||
524 | } | 524 | } |
525 | 525 | ||
526 | /* | 526 | /* |
527 | * fsmc_write_buf - write buffer to chip | ||
528 | * @mtd: MTD device structure | ||
529 | * @buf: data buffer | ||
530 | * @len: number of bytes to write | ||
531 | */ | ||
532 | static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | ||
533 | { | ||
534 | int i; | ||
535 | struct nand_chip *chip = mtd->priv; | ||
536 | |||
537 | if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) && | ||
538 | IS_ALIGNED(len, sizeof(uint32_t))) { | ||
539 | uint32_t *p = (uint32_t *)buf; | ||
540 | len = len >> 2; | ||
541 | for (i = 0; i < len; i++) | ||
542 | writel(p[i], chip->IO_ADDR_W); | ||
543 | } else { | ||
544 | for (i = 0; i < len; i++) | ||
545 | writeb(buf[i], chip->IO_ADDR_W); | ||
546 | } | ||
547 | } | ||
548 | |||
549 | /* | ||
550 | * fsmc_read_buf - read chip data into buffer | ||
551 | * @mtd: MTD device structure | ||
552 | * @buf: buffer to store date | ||
553 | * @len: number of bytes to read | ||
554 | */ | ||
555 | static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
556 | { | ||
557 | int i; | ||
558 | struct nand_chip *chip = mtd->priv; | ||
559 | |||
560 | if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) && | ||
561 | IS_ALIGNED(len, sizeof(uint32_t))) { | ||
562 | uint32_t *p = (uint32_t *)buf; | ||
563 | len = len >> 2; | ||
564 | for (i = 0; i < len; i++) | ||
565 | p[i] = readl(chip->IO_ADDR_R); | ||
566 | } else { | ||
567 | for (i = 0; i < len; i++) | ||
568 | buf[i] = readb(chip->IO_ADDR_R); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | /* | ||
527 | * fsmc_read_page_hwecc | 573 | * fsmc_read_page_hwecc |
528 | * @mtd: mtd info structure | 574 | * @mtd: mtd info structure |
529 | * @chip: nand chip info structure | 575 | * @chip: nand chip info structure |
@@ -825,6 +871,15 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
825 | if (pdata->width == FSMC_NAND_BW16) | 871 | if (pdata->width == FSMC_NAND_BW16) |
826 | nand->options |= NAND_BUSWIDTH_16; | 872 | nand->options |= NAND_BUSWIDTH_16; |
827 | 873 | ||
874 | /* | ||
875 | * use customized (word by word) version of read_buf, write_buf if | ||
876 | * access_with_dev_width is reset supported | ||
877 | */ | ||
878 | if (pdata->mode == USE_WORD_ACCESS) { | ||
879 | nand->read_buf = fsmc_read_buf; | ||
880 | nand->write_buf = fsmc_write_buf; | ||
881 | } | ||
882 | |||
828 | fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16, | 883 | fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16, |
829 | host->dev_timings); | 884 | host->dev_timings); |
830 | 885 | ||