diff options
author | Vipin Kumar <vipin.kumar@st.com> | 2012-10-09 06:44:50 -0400 |
---|---|---|
committer | Artem Bityutskiy <artem.bityutskiy@linux.intel.com> | 2012-11-15 08:37:48 -0500 |
commit | a4742d515071b8b7889a6b608da48d36c1dfcc71 (patch) | |
tree | be7a07d746e8e1f2715421a5be9d18eafb15b70e /drivers/mtd/nand | |
parent | 928aa2aeb7269292ca1e3d0e5e2e5d08af13da3d (diff) |
mtd: fsmc_nand: use relaxed variants of io accessors
Use relaxed variants of readl/writel accessors. readl/writel io accessors use
explicit dsb instruction which causes stalls in the processor core resulting
several cycles of delay for each access
Use relaxed variants where ever possible. This also results in an improved
read/write performance.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/fsmc_nand.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 82c0371f71e8..6b592235f847 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -383,13 +383,13 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
383 | pc |= FSMC_ENABLE; | 383 | pc |= FSMC_ENABLE; |
384 | else | 384 | else |
385 | pc &= ~FSMC_ENABLE; | 385 | pc &= ~FSMC_ENABLE; |
386 | writel(pc, FSMC_NAND_REG(regs, bank, PC)); | 386 | writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC)); |
387 | } | 387 | } |
388 | 388 | ||
389 | mb(); | 389 | mb(); |
390 | 390 | ||
391 | if (cmd != NAND_CMD_NONE) | 391 | if (cmd != NAND_CMD_NONE) |
392 | writeb(cmd, this->IO_ADDR_W); | 392 | writeb_relaxed(cmd, this->IO_ADDR_W); |
393 | } | 393 | } |
394 | 394 | ||
395 | /* | 395 | /* |
@@ -426,14 +426,18 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank, | |||
426 | tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT; | 426 | tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT; |
427 | 427 | ||
428 | if (busw) | 428 | if (busw) |
429 | writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC)); | 429 | writel_relaxed(value | FSMC_DEVWID_16, |
430 | FSMC_NAND_REG(regs, bank, PC)); | ||
430 | else | 431 | else |
431 | writel(value | FSMC_DEVWID_8, FSMC_NAND_REG(regs, bank, PC)); | 432 | writel_relaxed(value | FSMC_DEVWID_8, |
433 | FSMC_NAND_REG(regs, bank, PC)); | ||
432 | 434 | ||
433 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar, | 435 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar, |
434 | FSMC_NAND_REG(regs, bank, PC)); | 436 | FSMC_NAND_REG(regs, bank, PC)); |
435 | writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, COMM)); | 437 | writel_relaxed(thiz | thold | twait | tset, |
436 | writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, ATTRIB)); | 438 | FSMC_NAND_REG(regs, bank, COMM)); |
439 | writel_relaxed(thiz | thold | twait | tset, | ||
440 | FSMC_NAND_REG(regs, bank, ATTRIB)); | ||
437 | } | 441 | } |
438 | 442 | ||
439 | /* | 443 | /* |
@@ -446,11 +450,11 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) | |||
446 | void __iomem *regs = host->regs_va; | 450 | void __iomem *regs = host->regs_va; |
447 | uint32_t bank = host->bank; | 451 | uint32_t bank = host->bank; |
448 | 452 | ||
449 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256, | 453 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256, |
450 | FSMC_NAND_REG(regs, bank, PC)); | 454 | FSMC_NAND_REG(regs, bank, PC)); |
451 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN, | 455 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN, |
452 | FSMC_NAND_REG(regs, bank, PC)); | 456 | FSMC_NAND_REG(regs, bank, PC)); |
453 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN, | 457 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN, |
454 | FSMC_NAND_REG(regs, bank, PC)); | 458 | FSMC_NAND_REG(regs, bank, PC)); |
455 | } | 459 | } |
456 | 460 | ||
@@ -470,7 +474,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, | |||
470 | unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; | 474 | unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; |
471 | 475 | ||
472 | do { | 476 | do { |
473 | if (readl(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY) | 477 | if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY) |
474 | break; | 478 | break; |
475 | else | 479 | else |
476 | cond_resched(); | 480 | cond_resched(); |
@@ -481,25 +485,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, | |||
481 | return -ETIMEDOUT; | 485 | return -ETIMEDOUT; |
482 | } | 486 | } |
483 | 487 | ||
484 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1)); | 488 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); |
485 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | 489 | ecc[0] = (uint8_t) (ecc_tmp >> 0); |
486 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | 490 | ecc[1] = (uint8_t) (ecc_tmp >> 8); |
487 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | 491 | ecc[2] = (uint8_t) (ecc_tmp >> 16); |
488 | ecc[3] = (uint8_t) (ecc_tmp >> 24); | 492 | ecc[3] = (uint8_t) (ecc_tmp >> 24); |
489 | 493 | ||
490 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC2)); | 494 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2)); |
491 | ecc[4] = (uint8_t) (ecc_tmp >> 0); | 495 | ecc[4] = (uint8_t) (ecc_tmp >> 0); |
492 | ecc[5] = (uint8_t) (ecc_tmp >> 8); | 496 | ecc[5] = (uint8_t) (ecc_tmp >> 8); |
493 | ecc[6] = (uint8_t) (ecc_tmp >> 16); | 497 | ecc[6] = (uint8_t) (ecc_tmp >> 16); |
494 | ecc[7] = (uint8_t) (ecc_tmp >> 24); | 498 | ecc[7] = (uint8_t) (ecc_tmp >> 24); |
495 | 499 | ||
496 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC3)); | 500 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3)); |
497 | ecc[8] = (uint8_t) (ecc_tmp >> 0); | 501 | ecc[8] = (uint8_t) (ecc_tmp >> 0); |
498 | ecc[9] = (uint8_t) (ecc_tmp >> 8); | 502 | ecc[9] = (uint8_t) (ecc_tmp >> 8); |
499 | ecc[10] = (uint8_t) (ecc_tmp >> 16); | 503 | ecc[10] = (uint8_t) (ecc_tmp >> 16); |
500 | ecc[11] = (uint8_t) (ecc_tmp >> 24); | 504 | ecc[11] = (uint8_t) (ecc_tmp >> 24); |
501 | 505 | ||
502 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, STS)); | 506 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS)); |
503 | ecc[12] = (uint8_t) (ecc_tmp >> 16); | 507 | ecc[12] = (uint8_t) (ecc_tmp >> 16); |
504 | 508 | ||
505 | return 0; | 509 | return 0; |
@@ -519,7 +523,7 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, | |||
519 | uint32_t bank = host->bank; | 523 | uint32_t bank = host->bank; |
520 | uint32_t ecc_tmp; | 524 | uint32_t ecc_tmp; |
521 | 525 | ||
522 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1)); | 526 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); |
523 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | 527 | ecc[0] = (uint8_t) (ecc_tmp >> 0); |
524 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | 528 | ecc[1] = (uint8_t) (ecc_tmp >> 8); |
525 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | 529 | ecc[2] = (uint8_t) (ecc_tmp >> 16); |
@@ -628,10 +632,10 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
628 | uint32_t *p = (uint32_t *)buf; | 632 | uint32_t *p = (uint32_t *)buf; |
629 | len = len >> 2; | 633 | len = len >> 2; |
630 | for (i = 0; i < len; i++) | 634 | for (i = 0; i < len; i++) |
631 | writel(p[i], chip->IO_ADDR_W); | 635 | writel_relaxed(p[i], chip->IO_ADDR_W); |
632 | } else { | 636 | } else { |
633 | for (i = 0; i < len; i++) | 637 | for (i = 0; i < len; i++) |
634 | writeb(buf[i], chip->IO_ADDR_W); | 638 | writeb_relaxed(buf[i], chip->IO_ADDR_W); |
635 | } | 639 | } |
636 | } | 640 | } |
637 | 641 | ||
@@ -651,10 +655,10 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
651 | uint32_t *p = (uint32_t *)buf; | 655 | uint32_t *p = (uint32_t *)buf; |
652 | len = len >> 2; | 656 | len = len >> 2; |
653 | for (i = 0; i < len; i++) | 657 | for (i = 0; i < len; i++) |
654 | p[i] = readl(chip->IO_ADDR_R); | 658 | p[i] = readl_relaxed(chip->IO_ADDR_R); |
655 | } else { | 659 | } else { |
656 | for (i = 0; i < len; i++) | 660 | for (i = 0; i < len; i++) |
657 | buf[i] = readb(chip->IO_ADDR_R); | 661 | buf[i] = readb_relaxed(chip->IO_ADDR_R); |
658 | } | 662 | } |
659 | } | 663 | } |
660 | 664 | ||
@@ -783,7 +787,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, | |||
783 | uint32_t num_err, i; | 787 | uint32_t num_err, i; |
784 | uint32_t ecc1, ecc2, ecc3, ecc4; | 788 | uint32_t ecc1, ecc2, ecc3, ecc4; |
785 | 789 | ||
786 | num_err = (readl(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF; | 790 | num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF; |
787 | 791 | ||
788 | /* no bit flipping */ | 792 | /* no bit flipping */ |
789 | if (likely(num_err == 0)) | 793 | if (likely(num_err == 0)) |
@@ -826,10 +830,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, | |||
826 | * uint64_t array and error offset indexes are populated in err_idx | 830 | * uint64_t array and error offset indexes are populated in err_idx |
827 | * array | 831 | * array |
828 | */ | 832 | */ |
829 | ecc1 = readl(FSMC_NAND_REG(regs, bank, ECC1)); | 833 | ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); |
830 | ecc2 = readl(FSMC_NAND_REG(regs, bank, ECC2)); | 834 | ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2)); |
831 | ecc3 = readl(FSMC_NAND_REG(regs, bank, ECC3)); | 835 | ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3)); |
832 | ecc4 = readl(FSMC_NAND_REG(regs, bank, STS)); | 836 | ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS)); |
833 | 837 | ||
834 | err_idx[0] = (ecc1 >> 0) & 0x1FFF; | 838 | err_idx[0] = (ecc1 >> 0) & 0x1FFF; |
835 | err_idx[1] = (ecc1 >> 13) & 0x1FFF; | 839 | err_idx[1] = (ecc1 >> 13) & 0x1FFF; |