From: David Brownell <[email protected]> Speed up transfers between NAND and RAM by using the io{read,write}*_rep() calls to replace a more limited read-only I/O loop. On a similar arm926 board this gave a significant speedup (ISTR 16%) in a userspace "dd" benchmark.
Also add a comment explaining some key assumptions (wiring) this makes. Signed-off-by: David Brownell <[email protected]> --- drivers/mtd/nand/davinci_nand.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -356,18 +356,37 @@ static int nand_davinci_scan_bbt(struct } /* - * Read from memory register: we can read 4 bytes at a time. - * The hardware takes care of actually reading the NAND flash. + * NOTE: NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's + * how these chips are normally wired. This translates to both 8 and 16 + * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4). + * + * For now we assume that configuration, or any other one which ignores + * the two LSBs for NAND access ... so we can issue 32-bit reads/writes + * and have that transparently morphed into multiple NAND operations. */ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - int i; - int num_words = len >> 2; - u32 *p = (u32 *)buf; struct nand_chip *chip = mtd->priv; - for (i = 0; i < num_words; i++) - p[i] = readl(chip->IO_ADDR_R); + if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0) + ioread32_rep(chip->IO_ADDR_R, buf, len >> 2); + else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0) + ioread16_rep(chip->IO_ADDR_R, buf, len >> 1); + else + ioread8_rep(chip->IO_ADDR_R, buf, len); +} + +static void nand_davinci_write_buf(struct mtd_info *mtd, + const uint8_t *buf, int len) +{ + struct nand_chip *chip = mtd->priv; + + if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0) + iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2); + else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0) + iowrite16_rep(chip->IO_ADDR_R, buf, len >> 1); + else + iowrite8_rep(chip->IO_ADDR_R, buf, len); } /* @@ -565,8 +584,9 @@ static int __init nand_davinci_probe(str info->chip.cmd_ctrl = nand_davinci_hwcontrol; info->chip.dev_ready = nand_davinci_dev_ready; - /* Speed up the read buffer */ - info->chip.read_buf = nand_davinci_read_buf; + /* Speed up buffer I/O */ + info->chip.read_buf = nand_davinci_read_buf; + info->chip.write_buf = nand_davinci_write_buf; /* Speed up the creation of the bad block table */ info->chip.scan_bbt = nand_davinci_scan_bbt; _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
