base-files: define yes/no as valid boolean options
[openwrt.git] / target / linux / mvebu / patches-3.10 / 0153-mtd-nand-pxa3xx-Add-ECC-BCH-correctable-errors-detec.patch
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
5  detection
6
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.
10
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.
14
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>
18 ---
19  drivers/mtd/nand/pxa3xx_nand.c | 57 ++++++++++++++++++++++++++----------------
20  1 file changed, 35 insertions(+), 22 deletions(-)
21
22 --- a/drivers/mtd/nand/pxa3xx_nand.c
23 +++ b/drivers/mtd/nand/pxa3xx_nand.c
24 @@ -85,6 +85,9 @@
25  #define NDCR_INT_MASK           (0xFFF)
26  
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)
34 @@ -93,8 +96,8 @@
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 {
46         ERR_NONE        = 0,
47         ERR_DMABUSERR   = -1,
48         ERR_SENDCMD     = -2,
49 -       ERR_DBERR       = -3,
50 +       ERR_UNCORERR    = -3,
51         ERR_BBERR       = -4,
52 -       ERR_SBERR       = -5,
53 +       ERR_CORERR      = -5,
54  };
55  
56  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;
63         int                     retcode;
64  
65         /* cached register value */
66 @@ -571,10 +576,25 @@ static irqreturn_t pxa3xx_nand_irq(int i
67  
68         status = nand_readl(info, NDSR);
69  
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 &&
79 +                   info->ecc_bch)
80 +                       info->ecc_err_cnt = NDSR_ERR_CNT(status);
81 +               else
82 +                       info->ecc_err_cnt = 1;
83 +
84 +               /*
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().
88 +                */
89 +               info->max_bitflips = max_t(unsigned int,
90 +                                          info->max_bitflips,
91 +                                          info->ecc_err_cnt);
92 +       }
93         if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
94                 /* whether use dma to transfer data */
95                 if (info->use_dma) {
96 @@ -672,6 +692,7 @@ static void prepare_start_command(struct
97         info->use_ecc           = 0;
98         info->use_spare         = 1;
99         info->retcode           = ERR_NONE;
100 +       info->ecc_err_cnt       = 0;
101         info->ndcb3             = 0;
102  
103         switch (command) {
104 @@ -1053,26 +1074,18 @@ static int pxa3xx_nand_read_page_hwecc(s
105  {
106         struct pxa3xx_nand_host *host = mtd->priv;
107         struct pxa3xx_nand_info *info = host->info_data;
108 -       int max_bitflips = 0;
109  
110         chip->read_buf(mtd, buf, mtd->writesize);
111         chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
112  
113 -       if (info->retcode == ERR_SBERR) {
114 -               switch (info->use_ecc) {
115 -               case 1:
116 -                       max_bitflips = 1;
117 -                       mtd->ecc_stats.corrected++;
118 -                       break;
119 -               case 0:
120 -               default:
121 -                       break;
122 -               }
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;
126 +
127 +       } else if (info->retcode == ERR_UNCORERR) {
128                 /*
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
133                  */
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++;
138         }
139  
140 -       return max_bitflips;
141 +       return info->max_bitflips;
142  }
143  
144  static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)