aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVipin Kumar <vipin.kumar@st.com>2012-03-07 06:30:49 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-03-26 19:44:57 -0400
commit519300cfe18ee8dcf0b1e7a38564b61b70e4ee86 (patch)
treecfc6ad1320393249630ad695c5ef620109006ac0 /drivers
parent994c8409c4591983898182bfb5a0368d3daf1fc1 (diff)
mtd: fsmc: Newly erased page read algorithm implemented
A newly erased page contains ff in data as well as spare area. While reading an erased page, the read out ecc from spare area does not match the ecc generated by fsmc ecc hardware accelerator. This is because ecc of data ff ff is not ff ff. This leads to errors when file system erases and reads back the pages to ensure consistency. This patch adds a software workaround to ensure that the ecc check is not performed for erased pages. This problem is solved by checking the number of bits (in 512 byte data + 13 byte ecc) which are 0. If these number of bits are less than 8, the page is considered erased and correction algorithm is not tried on that page Signed-off-by: Vipin Kumar <vipin.kumar@st.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/fsmc_nand.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index e53b76064133..9c7d9d85f756 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -391,6 +391,20 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
391 return 0; 391 return 0;
392} 392}
393 393
394/* Count the number of 0's in buff upto a max of max_bits */
395static int count_written_bits(uint8_t *buff, int size, int max_bits)
396{
397 int k, written_bits = 0;
398
399 for (k = 0; k < size; k++) {
400 written_bits += hweight8(~buff[k]);
401 if (written_bits > max_bits)
402 break;
403 }
404
405 return written_bits;
406}
407
394/* 408/*
395 * fsmc_read_page_hwecc 409 * fsmc_read_page_hwecc
396 * @mtd: mtd info structure 410 * @mtd: mtd info structure
@@ -426,7 +440,6 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
426 uint8_t *oob = (uint8_t *)&ecc_oob[0]; 440 uint8_t *oob = (uint8_t *)&ecc_oob[0];
427 441
428 for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { 442 for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
429
430 chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); 443 chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
431 chip->ecc.hwctl(mtd, NAND_ECC_READ); 444 chip->ecc.hwctl(mtd, NAND_ECC_READ);
432 chip->read_buf(mtd, p, eccsize); 445 chip->read_buf(mtd, p, eccsize);
@@ -447,7 +460,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
447 j += len; 460 j += len;
448 } 461 }
449 462
450 memcpy(&ecc_code[i], oob, 13); 463 memcpy(&ecc_code[i], oob, chip->ecc.bytes);
451 chip->ecc.calculate(mtd, p, &ecc_calc[i]); 464 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
452 465
453 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); 466 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
@@ -475,14 +488,49 @@ static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat,
475{ 488{
476 struct fsmc_nand_data *host = container_of(mtd, 489 struct fsmc_nand_data *host = container_of(mtd,
477 struct fsmc_nand_data, mtd); 490 struct fsmc_nand_data, mtd);
491 struct nand_chip *chip = mtd->priv;
478 struct fsmc_regs *regs = host->regs_va; 492 struct fsmc_regs *regs = host->regs_va;
479 unsigned int bank = host->bank; 493 unsigned int bank = host->bank;
480 uint16_t err_idx[8]; 494 uint16_t err_idx[8];
481 uint64_t ecc_data[2]; 495 uint64_t ecc_data[2];
482 uint32_t num_err, i; 496 uint32_t num_err, i;
483 497
498 num_err = (readl(&regs->bank_regs[bank].sts) >> 10) & 0xF;
499
500 /* no bit flipping */
501 if (likely(num_err == 0))
502 return 0;
503
504 /* too many errors */
505 if (unlikely(num_err > 8)) {
506 /*
507 * This is a temporary erase check. A newly erased page read
508 * would result in an ecc error because the oob data is also
509 * erased to FF and the calculated ecc for an FF data is not
510 * FF..FF.
511 * This is a workaround to skip performing correction in case
512 * data is FF..FF
513 *
514 * Logic:
515 * For every page, each bit written as 0 is counted until these
516 * number of bits are greater than 8 (the maximum correction
517 * capability of FSMC for each 512 + 13 bytes)
518 */
519
520 int bits_ecc = count_written_bits(read_ecc, chip->ecc.bytes, 8);
521 int bits_data = count_written_bits(dat, chip->ecc.size, 8);
522
523 if ((bits_ecc + bits_data) <= 8) {
524 if (bits_data)
525 memset(dat, 0xff, chip->ecc.size);
526 return bits_data;
527 }
528
529 return -EBADMSG;
530 }
531
484 /* The calculated ecc is actually the correction index in data */ 532 /* The calculated ecc is actually the correction index in data */
485 memcpy(ecc_data, calc_ecc, 13); 533 memcpy(ecc_data, calc_ecc, chip->ecc.bytes);
486 534
487 /* 535 /*
488 * ------------------- calc_ecc[] bit wise -----------|--13 bits--| 536 * ------------------- calc_ecc[] bit wise -----------|--13 bits--|
@@ -513,7 +561,7 @@ static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat,
513 change_bit(0, (unsigned long *)&err_idx[i]); 561 change_bit(0, (unsigned long *)&err_idx[i]);
514 change_bit(1, (unsigned long *)&err_idx[i]); 562 change_bit(1, (unsigned long *)&err_idx[i]);
515 563
516 if (err_idx[i] <= 512 * 8) { 564 if (err_idx[i] <= chip->ecc.size * 8) {
517 change_bit(err_idx[i], (unsigned long *)dat); 565 change_bit(err_idx[i], (unsigned long *)dat);
518 i++; 566 i++;
519 } 567 }