Commit 519300cfe18ee8dcf0b1e7a38564b61b70e4ee86

Authored by Vipin Kumar
Committed by David Woodhouse
1 parent 994c8409c4

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>

Showing 1 changed file with 52 additions and 4 deletions Side-by-side Diff

drivers/mtd/nand/fsmc_nand.c
... ... @@ -391,6 +391,20 @@
391 391 return 0;
392 392 }
393 393  
  394 +/* Count the number of 0's in buff upto a max of max_bits */
  395 +static 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 409 * fsmc_read_page_hwecc
396 410 * @mtd: mtd info structure
... ... @@ -426,7 +440,6 @@
426 440 uint8_t *oob = (uint8_t *)&ecc_oob[0];
427 441  
428 442 for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
429   -
430 443 chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
431 444 chip->ecc.hwctl(mtd, NAND_ECC_READ);
432 445 chip->read_buf(mtd, p, eccsize);
... ... @@ -447,7 +460,7 @@
447 460 j += len;
448 461 }
449 462  
450   - memcpy(&ecc_code[i], oob, 13);
  463 + memcpy(&ecc_code[i], oob, chip->ecc.bytes);
451 464 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
452 465  
453 466 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
454 467  
455 468  
... ... @@ -475,14 +488,49 @@
475 488 {
476 489 struct fsmc_nand_data *host = container_of(mtd,
477 490 struct fsmc_nand_data, mtd);
  491 + struct nand_chip *chip = mtd->priv;
478 492 struct fsmc_regs *regs = host->regs_va;
479 493 unsigned int bank = host->bank;
480 494 uint16_t err_idx[8];
481 495 uint64_t ecc_data[2];
482 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 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 536 * ------------------- calc_ecc[] bit wise -----------|--13 bits--|
... ... @@ -513,7 +561,7 @@
513 561 change_bit(0, (unsigned long *)&err_idx[i]);
514 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 565 change_bit(err_idx[i], (unsigned long *)dat);
518 566 i++;
519 567 }