1 From 26d82e0081aa6f0c7db5e4bb5b154b7c528cb8d6 Mon Sep 17 00:00:00 2001
2 From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
3 Date: Thu, 14 Nov 2013 18:25:39 -0300
4 Subject: [PATCH 153/203] mtd: nand: pxa3xx: Add ECC BCH correctable errors
7 This commit extends the ECC correctable error detection to include
8 ECC BCH errors. The number of BCH correctable errors can be any up to 16,
9 and the actual value is exposed in the NDSR register.
11 Therefore, we change some symbol names to refer to correctable or
12 uncorrectable (instead of single-bit or double-bit as it was in the
13 Hamming case) and while at it, cleanup the detection code slightly.
15 Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
16 Tested-by: Daniel Mack <zonque@gmail.com>
17 Signed-off-by: Brian Norris <computersforpeace@gmail.com>
19 drivers/mtd/nand/pxa3xx_nand.c | 57 ++++++++++++++++++++++++++----------------
20 1 file changed, 35 insertions(+), 22 deletions(-)
22 --- a/drivers/mtd/nand/pxa3xx_nand.c
23 +++ b/drivers/mtd/nand/pxa3xx_nand.c
25 #define NDCR_INT_MASK (0xFFF)
27 #define NDSR_MASK (0xfff)
28 +#define NDSR_ERR_CNT_OFF (16)
29 +#define NDSR_ERR_CNT_MASK (0x1f)
30 +#define NDSR_ERR_CNT(sr) ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK)
31 #define NDSR_RDY (0x1 << 12)
32 #define NDSR_FLASH_RDY (0x1 << 11)
33 #define NDSR_CS0_PAGED (0x1 << 10)
35 #define NDSR_CS1_CMDD (0x1 << 7)
36 #define NDSR_CS0_BBD (0x1 << 6)
37 #define NDSR_CS1_BBD (0x1 << 5)
38 -#define NDSR_DBERR (0x1 << 4)
39 -#define NDSR_SBERR (0x1 << 3)
40 +#define NDSR_UNCORERR (0x1 << 4)
41 +#define NDSR_CORERR (0x1 << 3)
42 #define NDSR_WRDREQ (0x1 << 2)
43 #define NDSR_RDDREQ (0x1 << 1)
44 #define NDSR_WRCMDREQ (0x1)
45 @@ -135,9 +138,9 @@ enum {
57 @@ -221,6 +224,8 @@ struct pxa3xx_nand_info {
58 unsigned int oob_size;
59 unsigned int spare_size;
60 unsigned int ecc_size;
61 + unsigned int ecc_err_cnt;
62 + unsigned int max_bitflips;
65 /* cached register value */
66 @@ -571,10 +576,25 @@ static irqreturn_t pxa3xx_nand_irq(int i
68 status = nand_readl(info, NDSR);
70 - if (status & NDSR_DBERR)
71 - info->retcode = ERR_DBERR;
72 - if (status & NDSR_SBERR)
73 - info->retcode = ERR_SBERR;
74 + if (status & NDSR_UNCORERR)
75 + info->retcode = ERR_UNCORERR;
76 + if (status & NDSR_CORERR) {
77 + info->retcode = ERR_CORERR;
78 + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
80 + info->ecc_err_cnt = NDSR_ERR_CNT(status);
82 + info->ecc_err_cnt = 1;
85 + * Each chunk composing a page is corrected independently,
86 + * and we need to store maximum number of corrected bitflips
87 + * to return it to the MTD layer in ecc.read_page().
89 + info->max_bitflips = max_t(unsigned int,
93 if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
94 /* whether use dma to transfer data */
96 @@ -672,6 +692,7 @@ static void prepare_start_command(struct
99 info->retcode = ERR_NONE;
100 + info->ecc_err_cnt = 0;
104 @@ -1053,26 +1074,18 @@ static int pxa3xx_nand_read_page_hwecc(s
106 struct pxa3xx_nand_host *host = mtd->priv;
107 struct pxa3xx_nand_info *info = host->info_data;
108 - int max_bitflips = 0;
110 chip->read_buf(mtd, buf, mtd->writesize);
111 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
113 - if (info->retcode == ERR_SBERR) {
114 - switch (info->use_ecc) {
117 - mtd->ecc_stats.corrected++;
123 - } else if (info->retcode == ERR_DBERR) {
124 + if (info->retcode == ERR_CORERR && info->use_ecc) {
125 + mtd->ecc_stats.corrected += info->ecc_err_cnt;
127 + } else if (info->retcode == ERR_UNCORERR) {
129 * for blank page (all 0xff), HW will calculate its ECC as
130 * 0, which is different from the ECC information within
131 - * OOB, ignore such double bit errors
132 + * OOB, ignore such uncorrectable errors
134 if (is_buf_blank(buf, mtd->writesize))
135 info->retcode = ERR_NONE;
136 @@ -1080,7 +1093,7 @@ static int pxa3xx_nand_read_page_hwecc(s
137 mtd->ecc_stats.failed++;
140 - return max_bitflips;
141 + return info->max_bitflips;
144 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)