diff options
author | Bastian Hecht <hechtb@googlemail.com> | 2012-05-14 08:14:45 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-07-06 13:17:04 -0400 |
commit | 623c55caa37203ece6b4450daa0d2d058255da30 (patch) | |
tree | 7a97e24c5edb22845f28e3d1aa439a5a8286275c | |
parent | 50ed399cc3fbe5e16de78f7b62a39b8280f9001b (diff) |
mtd: sh_flctl: Group sector accesses into a single transfer
When we use hardware ecc, the flctl is run in so-called "sector access
mode". We can bundle 4 sector accesses when using 2KiB page sizes to read
a whole page at once and speed up things.
Signed-off-by: Bastian Hecht <hechtb@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/mtd/nand/sh_flctl.c | 44 |
1 files changed, 19 insertions, 25 deletions
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 1cc19eb1c302..96e242adda6a 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c | |||
@@ -368,25 +368,21 @@ static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) | |||
368 | struct sh_flctl *flctl = mtd_to_flctl(mtd); | 368 | struct sh_flctl *flctl = mtd_to_flctl(mtd); |
369 | int sector, page_sectors; | 369 | int sector, page_sectors; |
370 | 370 | ||
371 | if (flctl->page_size) | 371 | page_sectors = flctl->page_size ? 4 : 1; |
372 | page_sectors = 4; | 372 | |
373 | else | 373 | set_cmd_regs(mtd, NAND_CMD_READ0, |
374 | page_sectors = 1; | 374 | (NAND_CMD_READSTART << 8) | NAND_CMD_READ0); |
375 | 375 | ||
376 | writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT, | 376 | writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT, |
377 | FLCMNCR(flctl)); | 377 | FLCMNCR(flctl)); |
378 | writel(readl(FLCMDCR(flctl)) | page_sectors, FLCMDCR(flctl)); | ||
379 | writel(page_addr << 2, FLADR(flctl)); | ||
378 | 380 | ||
379 | set_cmd_regs(mtd, NAND_CMD_READ0, | 381 | empty_fifo(flctl); |
380 | (NAND_CMD_READSTART << 8) | NAND_CMD_READ0); | 382 | start_translation(flctl); |
381 | 383 | ||
382 | for (sector = 0; sector < page_sectors; sector++) { | 384 | for (sector = 0; sector < page_sectors; sector++) { |
383 | int ret; | 385 | int ret; |
384 | |||
385 | empty_fifo(flctl); | ||
386 | writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl)); | ||
387 | writel(page_addr << 2 | sector, FLADR(flctl)); | ||
388 | |||
389 | start_translation(flctl); | ||
390 | read_fiforeg(flctl, 512, 512 * sector); | 386 | read_fiforeg(flctl, 512, 512 * sector); |
391 | 387 | ||
392 | ret = read_ecfiforeg(flctl, | 388 | ret = read_ecfiforeg(flctl, |
@@ -397,8 +393,10 @@ static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) | |||
397 | flctl->hwecc_cant_correct[sector] = 1; | 393 | flctl->hwecc_cant_correct[sector] = 1; |
398 | 394 | ||
399 | writel(0x0, FL4ECCCR(flctl)); | 395 | writel(0x0, FL4ECCCR(flctl)); |
400 | wait_completion(flctl); | ||
401 | } | 396 | } |
397 | |||
398 | wait_completion(flctl); | ||
399 | |||
402 | writel(readl(FLCMNCR(flctl)) & ~(ACM_SACCES_MODE | _4ECCCORRECT), | 400 | writel(readl(FLCMNCR(flctl)) & ~(ACM_SACCES_MODE | _4ECCCORRECT), |
403 | FLCMNCR(flctl)); | 401 | FLCMNCR(flctl)); |
404 | } | 402 | } |
@@ -430,31 +428,27 @@ static void execmd_write_page_sector(struct mtd_info *mtd) | |||
430 | int i, page_addr = flctl->seqin_page_addr; | 428 | int i, page_addr = flctl->seqin_page_addr; |
431 | int sector, page_sectors; | 429 | int sector, page_sectors; |
432 | 430 | ||
433 | if (flctl->page_size) | 431 | page_sectors = flctl->page_size ? 4 : 1; |
434 | page_sectors = 4; | ||
435 | else | ||
436 | page_sectors = 1; | ||
437 | |||
438 | writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl)); | ||
439 | 432 | ||
440 | set_cmd_regs(mtd, NAND_CMD_PAGEPROG, | 433 | set_cmd_regs(mtd, NAND_CMD_PAGEPROG, |
441 | (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN); | 434 | (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN); |
442 | 435 | ||
443 | for (sector = 0; sector < page_sectors; sector++) { | 436 | empty_fifo(flctl); |
444 | empty_fifo(flctl); | 437 | writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl)); |
445 | writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl)); | 438 | writel(readl(FLCMDCR(flctl)) | page_sectors, FLCMDCR(flctl)); |
446 | writel(page_addr << 2 | sector, FLADR(flctl)); | 439 | writel(page_addr << 2, FLADR(flctl)); |
440 | start_translation(flctl); | ||
447 | 441 | ||
448 | start_translation(flctl); | 442 | for (sector = 0; sector < page_sectors; sector++) { |
449 | write_fiforeg(flctl, 512, 512 * sector); | 443 | write_fiforeg(flctl, 512, 512 * sector); |
450 | 444 | ||
451 | for (i = 0; i < 4; i++) { | 445 | for (i = 0; i < 4; i++) { |
452 | wait_wecfifo_ready(flctl); /* wait for write ready */ | 446 | wait_wecfifo_ready(flctl); /* wait for write ready */ |
453 | writel(0xFFFFFFFF, FLECFIFO(flctl)); | 447 | writel(0xFFFFFFFF, FLECFIFO(flctl)); |
454 | } | 448 | } |
455 | wait_completion(flctl); | ||
456 | } | 449 | } |
457 | 450 | ||
451 | wait_completion(flctl); | ||
458 | writel(readl(FLCMNCR(flctl)) & ~ACM_SACCES_MODE, FLCMNCR(flctl)); | 452 | writel(readl(FLCMNCR(flctl)) & ~ACM_SACCES_MODE, FLCMNCR(flctl)); |
459 | } | 453 | } |
460 | 454 | ||