base-files: define yes/no as valid boolean options
[openwrt.git] / target / linux / mvebu / patches-3.10 / 0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch
1 From 3677d22ed7e3a631f35e2addc4e2181f6215e4b0 Mon Sep 17 00:00:00 2001
2 From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
3 Date: Thu, 14 Nov 2013 18:25:29 -0300
4 Subject: [PATCH 143/203] mtd: nand: pxa3xx: Add driver-specific ECC BCH
5  support
6
7 This commit adds the BCH ECC support available in NFCv2 controller.
8 Depending on the detected required strength the respective ECC layout
9 is selected.
10
11 This commit adds an empty ECC layout, since support to access large
12 pages is first required. Once that support is added, a proper ECC
13 layout will be added as well.
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 | 86 +++++++++++++++++++++++++++++++++---------
20  1 file changed, 69 insertions(+), 17 deletions(-)
21
22 --- a/drivers/mtd/nand/pxa3xx_nand.c
23 +++ b/drivers/mtd/nand/pxa3xx_nand.c
24 @@ -58,6 +58,7 @@
25  #define NDPCR          (0x18) /* Page Count Register */
26  #define NDBDR0         (0x1C) /* Bad Block Register 0 */
27  #define NDBDR1         (0x20) /* Bad Block Register 1 */
28 +#define NDECCCTRL      (0x28) /* ECC control */
29  #define NDDB           (0x40) /* Data Buffer */
30  #define NDCB0          (0x48) /* Command Buffer0 */
31  #define NDCB1          (0x4C) /* Command Buffer1 */
32 @@ -198,6 +199,7 @@ struct pxa3xx_nand_info {
33  
34         int                     cs;
35         int                     use_ecc;        /* use HW ECC ? */
36 +       int                     ecc_bch;        /* using BCH ECC? */
37         int                     use_dma;        /* use DMA ? */
38         int                     use_spare;      /* use spare ? */
39         int                     need_wait;
40 @@ -205,6 +207,8 @@ struct pxa3xx_nand_info {
41         unsigned int            fifo_size;      /* max. data size in the FIFO */
42         unsigned int            data_size;      /* data to be read from FIFO */
43         unsigned int            oob_size;
44 +       unsigned int            spare_size;
45 +       unsigned int            ecc_size;
46         int                     retcode;
47  
48         /* cached register value */
49 @@ -339,19 +343,12 @@ static void pxa3xx_set_datasize(struct p
50         int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
51  
52         info->data_size = info->fifo_size;
53 -       if (!oob_enable) {
54 -               info->oob_size = 0;
55 +       if (!oob_enable)
56                 return;
57 -       }
58  
59 -       switch (info->fifo_size) {
60 -       case 2048:
61 -               info->oob_size = (info->use_ecc) ? 40 : 64;
62 -               break;
63 -       case 512:
64 -               info->oob_size = (info->use_ecc) ? 8 : 16;
65 -               break;
66 -       }
67 +       info->oob_size = info->spare_size;
68 +       if (!info->use_ecc)
69 +               info->oob_size += info->ecc_size;
70  }
71  
72  /**
73 @@ -366,10 +363,15 @@ static void pxa3xx_nand_start(struct pxa
74  
75         ndcr = info->reg_ndcr;
76  
77 -       if (info->use_ecc)
78 +       if (info->use_ecc) {
79                 ndcr |= NDCR_ECC_EN;
80 -       else
81 +               if (info->ecc_bch)
82 +                       nand_writel(info, NDECCCTRL, 0x1);
83 +       } else {
84                 ndcr &= ~NDCR_ECC_EN;
85 +               if (info->ecc_bch)
86 +                       nand_writel(info, NDECCCTRL, 0x0);
87 +       }
88  
89         if (info->use_dma)
90                 ndcr |= NDCR_DMA_EN;
91 @@ -1071,6 +1073,41 @@ static int pxa3xx_nand_sensing(struct px
92         return 0;
93  }
94  
95 +static int pxa_ecc_init(struct pxa3xx_nand_info *info,
96 +                       struct nand_ecc_ctrl *ecc,
97 +                       int strength, int page_size)
98 +{
99 +       /*
100 +        * We don't use strength here as the PXA variant
101 +        * is used with non-ONFI compliant devices.
102 +        */
103 +       if (page_size == 2048) {
104 +               info->spare_size = 40;
105 +               info->ecc_size = 24;
106 +               ecc->mode = NAND_ECC_HW;
107 +               ecc->size = 512;
108 +               ecc->strength = 1;
109 +               return 1;
110 +
111 +       } else if (page_size == 512) {
112 +               info->spare_size = 8;
113 +               info->ecc_size = 8;
114 +               ecc->mode = NAND_ECC_HW;
115 +               ecc->size = 512;
116 +               ecc->strength = 1;
117 +               return 1;
118 +       }
119 +       return 0;
120 +}
121 +
122 +static int armada370_ecc_init(struct pxa3xx_nand_info *info,
123 +                             struct nand_ecc_ctrl *ecc,
124 +                             int strength, int page_size)
125 +{
126 +       /* Unimplemented yet */
127 +       return 0;
128 +}
129 +
130  static int pxa3xx_nand_scan(struct mtd_info *mtd)
131  {
132         struct pxa3xx_nand_host *host = mtd->priv;
133 @@ -1141,13 +1178,13 @@ static int pxa3xx_nand_scan(struct mtd_i
134         pxa3xx_flash_ids[1].name = NULL;
135         def = pxa3xx_flash_ids;
136  KEEP_CONFIG:
137 -       chip->ecc.mode = NAND_ECC_HW;
138 -       chip->ecc.size = info->fifo_size;
139 -       chip->ecc.strength = 1;
140 -
141         if (info->reg_ndcr & NDCR_DWIDTH_M)
142                 chip->options |= NAND_BUSWIDTH_16;
143  
144 +       /* Device detection must be done with ECC disabled */
145 +       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
146 +               nand_writel(info, NDECCCTRL, 0x0);
147 +
148         if (nand_scan_ident(mtd, 1, def))
149                 return -ENODEV;
150  
151 @@ -1162,6 +1199,21 @@ KEEP_CONFIG:
152                 chip->bbt_md = &bbt_mirror_descr;
153         }
154  
155 +       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
156 +               ret = armada370_ecc_init(info, &chip->ecc,
157 +                                  chip->ecc_strength_ds,
158 +                                  mtd->writesize);
159 +       else
160 +               ret = pxa_ecc_init(info, &chip->ecc,
161 +                                  chip->ecc_strength_ds,
162 +                                  mtd->writesize);
163 +       if (!ret) {
164 +               dev_err(&info->pdev->dev,
165 +                       "ECC strength %d at page size %d is not supported\n",
166 +                       chip->ecc_strength_ds, mtd->writesize);
167 +               return -ENODEV;
168 +       }
169 +
170         /* calculate addressing information */
171         if (mtd->writesize >= 2048)
172                 host->col_addr_cycles = 2;