Commit 94f77e50d658be1d3ff23fb65e4d075a6f4ebee3

Authored by Sascha Hauer
Committed by David Woodhouse
1 parent 1bc991808d

mxc_nand: fix correct_data function

The v2 controller has a totally different mechanism to check
whether the data we read had ecc errors or not. Implement this.
The mechanism in the v2 controller happens to be identical to
the v3 controller.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

Showing 1 changed file with 40 additions and 2 deletions Side-by-side Diff

drivers/mtd/nand/mxc_nand.c
... ... @@ -94,6 +94,7 @@
94 94 struct clk *clk;
95 95 int clk_act;
96 96 int irq;
  97 + int eccsize;
97 98  
98 99 wait_queue_head_t irq_waitq;
99 100  
... ... @@ -342,7 +343,7 @@
342 343 */
343 344 }
344 345  
345   -static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
  346 +static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
346 347 u_char *read_ecc, u_char *calc_ecc)
347 348 {
348 349 struct nand_chip *nand_chip = mtd->priv;
... ... @@ -364,6 +365,40 @@
364 365 return 0;
365 366 }
366 367  
  368 +static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
  369 + u_char *read_ecc, u_char *calc_ecc)
  370 +{
  371 + struct nand_chip *nand_chip = mtd->priv;
  372 + struct mxc_nand_host *host = nand_chip->priv;
  373 + u32 ecc_stat, err;
  374 + int no_subpages = 1;
  375 + int ret = 0;
  376 + u8 ecc_bit_mask, err_limit;
  377 +
  378 + ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
  379 + err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
  380 +
  381 + no_subpages = mtd->writesize >> 9;
  382 +
  383 + ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT);
  384 +
  385 + do {
  386 + err = ecc_stat & ecc_bit_mask;
  387 + if (err > err_limit) {
  388 + printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
  389 + return -1;
  390 + } else {
  391 + ret += err;
  392 + }
  393 + ecc_stat >>= 4;
  394 + } while (--no_subpages);
  395 +
  396 + mtd->ecc_stats.corrected += ret;
  397 + pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
  398 +
  399 + return ret;
  400 +}
  401 +
367 402 static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
368 403 u_char *ecc_code)
369 404 {
... ... @@ -790,7 +825,10 @@
790 825 if (pdata->hw_ecc) {
791 826 this->ecc.calculate = mxc_nand_calculate_ecc;
792 827 this->ecc.hwctl = mxc_nand_enable_hwecc;
793   - this->ecc.correct = mxc_nand_correct_data;
  828 + if (nfc_is_v1())
  829 + this->ecc.correct = mxc_nand_correct_data_v1;
  830 + else
  831 + this->ecc.correct = mxc_nand_correct_data_v2_v3;
794 832 this->ecc.mode = NAND_ECC_HW;
795 833 } else {
796 834 this->ecc.mode = NAND_ECC_SOFT;