mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
[platform/kernel/u-boot.git] / drivers / mtd / nand / omap_gpmc.c
1 /*
2  * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
3  * Rohit Choraria <rohitkc@ti.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <asm/io.h>
10 #include <asm/errno.h>
11 #include <asm/arch/mem.h>
12 #include <asm/arch/cpu.h>
13 #include <asm/omap_gpmc.h>
14 #include <linux/mtd/nand_ecc.h>
15 #include <linux/bch.h>
16 #include <linux/compiler.h>
17 #include <nand.h>
18 #include <asm/omap_elm.h>
19
20 #define BADBLOCK_MARKER_LENGTH  2
21 #define SECTOR_BYTES            512
22 #define ECCCLEAR                (0x1 << 8)
23 #define ECCRESULTREG1           (0x1 << 0)
24
25 static uint8_t cs;
26 static __maybe_unused struct nand_ecclayout omap_ecclayout;
27
28 /*
29  * omap_nand_hwcontrol - Set the address pointers corretly for the
30  *                      following address/data/command operation
31  */
32 static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
33                                 uint32_t ctrl)
34 {
35         register struct nand_chip *this = mtd->priv;
36
37         /*
38          * Point the IO_ADDR to DATA and ADDRESS registers instead
39          * of chip address
40          */
41         switch (ctrl) {
42         case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
43                 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
44                 break;
45         case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
46                 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
47                 break;
48         case NAND_CTRL_CHANGE | NAND_NCE:
49                 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
50                 break;
51         }
52
53         if (cmd != NAND_CMD_NONE)
54                 writeb(cmd, this->IO_ADDR_W);
55 }
56
57 #ifdef CONFIG_SPL_BUILD
58 /* Check wait pin as dev ready indicator */
59 int omap_spl_dev_ready(struct mtd_info *mtd)
60 {
61         return gpmc_cfg->status & (1 << 8);
62 }
63 #endif
64
65
66 /*
67  * gen_true_ecc - This function will generate true ECC value, which
68  * can be used when correcting data read from NAND flash memory core
69  *
70  * @ecc_buf:    buffer to store ecc code
71  *
72  * @return:     re-formatted ECC value
73  */
74 static uint32_t gen_true_ecc(uint8_t *ecc_buf)
75 {
76         return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
77                 ((ecc_buf[2] & 0x0F) << 8);
78 }
79
80 /*
81  * omap_correct_data - Compares the ecc read from nand spare area with ECC
82  * registers values and corrects one bit error if it has occured
83  * Further details can be had from OMAP TRM and the following selected links:
84  * http://en.wikipedia.org/wiki/Hamming_code
85  * http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
86  *
87  * @mtd:                 MTD device structure
88  * @dat:                 page data
89  * @read_ecc:            ecc read from nand flash
90  * @calc_ecc:            ecc read from ECC registers
91  *
92  * @return 0 if data is OK or corrected, else returns -1
93  */
94 static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
95                                 uint8_t *read_ecc, uint8_t *calc_ecc)
96 {
97         uint32_t orig_ecc, new_ecc, res, hm;
98         uint16_t parity_bits, byte;
99         uint8_t bit;
100
101         /* Regenerate the orginal ECC */
102         orig_ecc = gen_true_ecc(read_ecc);
103         new_ecc = gen_true_ecc(calc_ecc);
104         /* Get the XOR of real ecc */
105         res = orig_ecc ^ new_ecc;
106         if (res) {
107                 /* Get the hamming width */
108                 hm = hweight32(res);
109                 /* Single bit errors can be corrected! */
110                 if (hm == 12) {
111                         /* Correctable data! */
112                         parity_bits = res >> 16;
113                         bit = (parity_bits & 0x7);
114                         byte = (parity_bits >> 3) & 0x1FF;
115                         /* Flip the bit to correct */
116                         dat[byte] ^= (0x1 << bit);
117                 } else if (hm == 1) {
118                         printf("Error: Ecc is wrong\n");
119                         /* ECC itself is corrupted */
120                         return 2;
121                 } else {
122                         /*
123                          * hm distance != parity pairs OR one, could mean 2 bit
124                          * error OR potentially be on a blank page..
125                          * orig_ecc: contains spare area data from nand flash.
126                          * new_ecc: generated ecc while reading data area.
127                          * Note: if the ecc = 0, all data bits from which it was
128                          * generated are 0xFF.
129                          * The 3 byte(24 bits) ecc is generated per 512byte
130                          * chunk of a page. If orig_ecc(from spare area)
131                          * is 0xFF && new_ecc(computed now from data area)=0x0,
132                          * this means that data area is 0xFF and spare area is
133                          * 0xFF. A sure sign of a erased page!
134                          */
135                         if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
136                                 return 0;
137                         printf("Error: Bad compare! failed\n");
138                         /* detected 2 bit error */
139                         return -1;
140                 }
141         }
142         return 0;
143 }
144
145 /*
146  *  omap_calculate_ecc - Generate non-inverted ECC bytes.
147  *
148  *  Using noninverted ECC can be considered ugly since writing a blank
149  *  page ie. padding will clear the ECC bytes. This is no problem as
150  *  long nobody is trying to write data on the seemingly unused page.
151  *  Reading an erased page will produce an ECC mismatch between
152  *  generated and read ECC bytes that has to be dealt with separately.
153  *  E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
154  *  is used, the result of read will be 0x0 while the ECC offsets of the
155  *  spare area will be 0xFF which will result in an ECC mismatch.
156  *  @mtd:       MTD structure
157  *  @dat:       unused
158  *  @ecc_code:  ecc_code buffer
159  */
160 static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
161                 const uint8_t *dat, uint8_t *ecc_code)
162 {
163         u_int32_t val;
164
165         /* Start Reading from HW ECC1_Result = 0x200 */
166         val = readl(&gpmc_cfg->ecc1_result);
167
168         ecc_code[0] = val & 0xFF;
169         ecc_code[1] = (val >> 16) & 0xFF;
170         ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
171
172         /*
173          * Stop reading anymore ECC vals and clear old results
174          * enable will be called if more reads are required
175          */
176         writel(0x000, &gpmc_cfg->ecc_config);
177
178         return 0;
179 }
180
181 /*
182  * Generic BCH interface
183  */
184 struct nand_bch_priv {
185         uint8_t mode;
186         uint8_t type;
187         uint8_t nibbles;
188         struct bch_control *control;
189         enum omap_ecc ecc_scheme;
190 };
191
192 /* bch types */
193 #define ECC_BCH4        0
194 #define ECC_BCH8        1
195 #define ECC_BCH16       2
196
197 /* GPMC ecc engine settings */
198 #define BCH_WRAPMODE_1          1       /* BCH wrap mode 1 */
199 #define BCH_WRAPMODE_6          6       /* BCH wrap mode 6 */
200
201 /* BCH nibbles for diff bch levels */
202 #define NAND_ECC_HW_BCH ((uint8_t)(NAND_ECC_HW_OOB_FIRST) + 1)
203 #define ECC_BCH4_NIBBLES        13
204 #define ECC_BCH8_NIBBLES        26
205 #define ECC_BCH16_NIBBLES       52
206
207 /*
208  * This can be a single instance cause all current users have only one NAND
209  * with nearly the same setup (BCH8, some with ELM and others with sw BCH
210  * library).
211  * When some users with other BCH strength will exists this have to change!
212  */
213 static __maybe_unused struct nand_bch_priv bch_priv = {
214         .mode = NAND_ECC_HW_BCH,
215         .type = ECC_BCH8,
216         .nibbles = ECC_BCH8_NIBBLES,
217         .control = NULL
218 };
219
220 /*
221  * omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
222  * @mtd:        MTD device structure
223  * @mode:       Read/Write mode
224  */
225 __maybe_unused
226 static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
227 {
228         struct nand_chip        *nand   = mtd->priv;
229         struct nand_bch_priv    *bch    = nand->priv;
230         unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
231         unsigned int ecc_algo = 0;
232         unsigned int bch_type = 0;
233         unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
234         u32 ecc_size_config_val = 0;
235         u32 ecc_config_val = 0;
236
237         /* configure GPMC for specific ecc-scheme */
238         switch (bch->ecc_scheme) {
239         case OMAP_ECC_HAM1_CODE_SW:
240                 return;
241         case OMAP_ECC_HAM1_CODE_HW:
242                 ecc_algo = 0x0;
243                 bch_type = 0x0;
244                 bch_wrapmode = 0x00;
245                 eccsize0 = 0xFF;
246                 eccsize1 = 0xFF;
247                 break;
248         case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
249         case OMAP_ECC_BCH8_CODE_HW:
250                 ecc_algo = 0x1;
251                 bch_type = 0x1;
252                 if (mode == NAND_ECC_WRITE) {
253                         bch_wrapmode = 0x01;
254                         eccsize0 = 0;  /* extra bits in nibbles per sector */
255                         eccsize1 = 28; /* OOB bits in nibbles per sector */
256                 } else {
257                         bch_wrapmode = 0x01;
258                         eccsize0 = 26; /* ECC bits in nibbles per sector */
259                         eccsize1 = 2;  /* non-ECC bits in nibbles per sector */
260                 }
261                 break;
262         default:
263                 return;
264         }
265         /* Clear ecc and enable bits */
266         writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
267         /* Configure ecc size for BCH */
268         ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
269         writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
270
271         /* Configure device details for BCH engine */
272         ecc_config_val = ((ecc_algo << 16)      | /* HAM1 | BCHx */
273                         (bch_type << 12)        | /* BCH4/BCH8/BCH16 */
274                         (bch_wrapmode << 8)     | /* wrap mode */
275                         (dev_width << 7)        | /* bus width */
276                         (0x0 << 4)              | /* number of sectors */
277                         (cs <<  1)              | /* ECC CS */
278                         (0x1));                   /* enable ECC */
279         writel(ecc_config_val, &gpmc_cfg->ecc_config);
280 }
281
282 /*
283  * omap_ecc_disable - Disable H/W ECC calculation
284  *
285  * @mtd:        MTD device structure
286  */
287 static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
288 {
289         writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
290 }
291
292 /*
293  * BCH support using ELM module
294  */
295 #ifdef CONFIG_NAND_OMAP_ELM
296 /*
297  * omap_read_bch8_result - Read BCH result for BCH8 level
298  *
299  * @mtd:        MTD device structure
300  * @big_endian: When set read register 3 first
301  * @ecc_code:   Read syndrome from BCH result registers
302  */
303 static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
304                                 uint8_t *ecc_code)
305 {
306         uint32_t *ptr;
307         int8_t i = 0, j;
308
309         if (big_endian) {
310                 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
311                 ecc_code[i++] = readl(ptr) & 0xFF;
312                 ptr--;
313                 for (j = 0; j < 3; j++) {
314                         ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
315                         ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
316                         ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
317                         ecc_code[i++] = readl(ptr) & 0xFF;
318                         ptr--;
319                 }
320         } else {
321                 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[0];
322                 for (j = 0; j < 3; j++) {
323                         ecc_code[i++] = readl(ptr) & 0xFF;
324                         ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
325                         ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
326                         ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
327                         ptr++;
328                 }
329                 ecc_code[i++] = readl(ptr) & 0xFF;
330                 ecc_code[i++] = 0;      /* 14th byte is always zero */
331         }
332 }
333
334 /*
335  * omap_rotate_ecc_bch - Rotate the syndrome bytes
336  *
337  * @mtd:        MTD device structure
338  * @calc_ecc:   ECC read from ECC registers
339  * @syndrome:   Rotated syndrome will be retuned in this array
340  *
341  */
342 static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
343                 uint8_t *syndrome)
344 {
345         struct nand_chip *chip = mtd->priv;
346         struct nand_bch_priv *bch = chip->priv;
347         uint8_t n_bytes = 0;
348         int8_t i, j;
349
350         switch (bch->type) {
351         case ECC_BCH4:
352                 n_bytes = 8;
353                 break;
354
355         case ECC_BCH16:
356                 n_bytes = 28;
357                 break;
358
359         case ECC_BCH8:
360         default:
361                 n_bytes = 13;
362                 break;
363         }
364
365         for (i = 0, j = (n_bytes-1); i < n_bytes; i++, j--)
366                 syndrome[i] =  calc_ecc[j];
367 }
368
369 /*
370  *  omap_calculate_ecc_bch - Read BCH ECC result
371  *
372  *  @mtd:       MTD structure
373  *  @dat:       unused
374  *  @ecc_code:  ecc_code buffer
375  */
376 static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
377                                 uint8_t *ecc_code)
378 {
379         struct nand_chip *chip = mtd->priv;
380         struct nand_bch_priv *bch = chip->priv;
381         uint8_t big_endian = 1;
382         int8_t ret = 0;
383
384         if (bch->type == ECC_BCH8)
385                 omap_read_bch8_result(mtd, big_endian, ecc_code);
386         else /* BCH4 and BCH16 currently not supported */
387                 ret = -1;
388
389         /*
390          * Stop reading anymore ECC vals and clear old results
391          * enable will be called if more reads are required
392          */
393         omap_ecc_disable(mtd);
394
395         return ret;
396 }
397
398 /*
399  * omap_fix_errors_bch - Correct bch error in the data
400  *
401  * @mtd:        MTD device structure
402  * @data:       Data read from flash
403  * @error_count:Number of errors in data
404  * @error_loc:  Locations of errors in the data
405  *
406  */
407 static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
408                 uint32_t error_count, uint32_t *error_loc)
409 {
410         struct nand_chip *chip = mtd->priv;
411         struct nand_bch_priv *bch = chip->priv;
412         uint8_t count = 0;
413         uint32_t error_byte_pos;
414         uint32_t error_bit_mask;
415         uint32_t last_bit = (bch->nibbles * 4) - 1;
416
417         /* Flip all bits as specified by the error location array. */
418         /* FOR( each found error location flip the bit ) */
419         for (count = 0; count < error_count; count++) {
420                 if (error_loc[count] > last_bit) {
421                         /* Remove the ECC spare bits from correction. */
422                         error_loc[count] -= (last_bit + 1);
423                         /* Offset bit in data region */
424                         error_byte_pos = ((512 * 8) -
425                                         (error_loc[count]) - 1) / 8;
426                         /* Error Bit mask */
427                         error_bit_mask = 0x1 << (error_loc[count] % 8);
428                         /* Toggle the error bit to make the correction. */
429                         data[error_byte_pos] ^= error_bit_mask;
430                 }
431         }
432 }
433
434 /*
435  * omap_correct_data_bch - Compares the ecc read from nand spare area
436  * with ECC registers values and corrects one bit error if it has occured
437  *
438  * @mtd:        MTD device structure
439  * @dat:        page data
440  * @read_ecc:   ecc read from nand flash (ignored)
441  * @calc_ecc:   ecc read from ECC registers
442  *
443  * @return 0 if data is OK or corrected, else returns -1
444  */
445 static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
446                                 uint8_t *read_ecc, uint8_t *calc_ecc)
447 {
448         struct nand_chip *chip = mtd->priv;
449         struct nand_bch_priv *bch = chip->priv;
450         uint8_t syndrome[28];
451         uint32_t error_count = 0;
452         uint32_t error_loc[8];
453         uint32_t i, ecc_flag;
454
455         ecc_flag = 0;
456         for (i = 0; i < chip->ecc.bytes; i++)
457                 if (read_ecc[i] != 0xff)
458                         ecc_flag = 1;
459
460         if (!ecc_flag)
461                 return 0;
462
463         elm_reset();
464         elm_config((enum bch_level)(bch->type));
465
466         /*
467          * while reading ECC result we read it in big endian.
468          * Hence while loading to ELM we have rotate to get the right endian.
469          */
470         omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
471
472         /* use elm module to check for errors */
473         if (elm_check_error(syndrome, bch->nibbles, &error_count,
474                                 error_loc) != 0) {
475                 printf("ECC: uncorrectable.\n");
476                 return -1;
477         }
478
479         /* correct bch error */
480         if (error_count > 0)
481                 omap_fix_errors_bch(mtd, dat, error_count, error_loc);
482
483         return 0;
484 }
485
486 /**
487  * omap_read_page_bch - hardware ecc based page read function
488  * @mtd:        mtd info structure
489  * @chip:       nand chip info structure
490  * @buf:        buffer to store read data
491  * @oob_required: caller expects OOB data read to chip->oob_poi
492  * @page:       page number to read
493  *
494  */
495 static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
496                                 uint8_t *buf, int oob_required, int page)
497 {
498         int i, eccsize = chip->ecc.size;
499         int eccbytes = chip->ecc.bytes;
500         int eccsteps = chip->ecc.steps;
501         uint8_t *p = buf;
502         uint8_t *ecc_calc = chip->buffers->ecccalc;
503         uint8_t *ecc_code = chip->buffers->ecccode;
504         uint32_t *eccpos = chip->ecc.layout->eccpos;
505         uint8_t *oob = chip->oob_poi;
506         uint32_t data_pos;
507         uint32_t oob_pos;
508
509         data_pos = 0;
510         /* oob area start */
511         oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
512         oob += chip->ecc.layout->eccpos[0];
513
514         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
515                                 oob += eccbytes) {
516                 chip->ecc.hwctl(mtd, NAND_ECC_READ);
517                 /* read data */
518                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
519                 chip->read_buf(mtd, p, eccsize);
520
521                 /* read respective ecc from oob area */
522                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
523                 chip->read_buf(mtd, oob, eccbytes);
524                 /* read syndrome */
525                 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
526
527                 data_pos += eccsize;
528                 oob_pos += eccbytes;
529         }
530
531         for (i = 0; i < chip->ecc.total; i++)
532                 ecc_code[i] = chip->oob_poi[eccpos[i]];
533
534         eccsteps = chip->ecc.steps;
535         p = buf;
536
537         for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
538                 int stat;
539
540                 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
541                 if (stat < 0)
542                         mtd->ecc_stats.failed++;
543                 else
544                         mtd->ecc_stats.corrected += stat;
545         }
546         return 0;
547 }
548 #endif /* CONFIG_NAND_OMAP_ELM */
549
550 /*
551  * OMAP3 BCH8 support (with BCH library)
552  */
553 #ifdef CONFIG_BCH
554 /*
555  *  omap_calculate_ecc_bch_sw - Read BCH ECC result
556  *
557  *  @mtd:       MTD device structure
558  *  @dat:       The pointer to data on which ecc is computed (unused here)
559  *  @ecc:       The ECC output buffer
560  */
561 static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, const uint8_t *dat,
562                                 uint8_t *ecc)
563 {
564         int ret = 0;
565         size_t i;
566         unsigned long nsectors, val1, val2, val3, val4;
567
568         nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
569
570         for (i = 0; i < nsectors; i++) {
571                 /* Read hw-computed remainder */
572                 val1 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[0]);
573                 val2 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[1]);
574                 val3 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[2]);
575                 val4 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[3]);
576
577                 /*
578                  * Add constant polynomial to remainder, in order to get an ecc
579                  * sequence of 0xFFs for a buffer filled with 0xFFs.
580                  */
581                 *ecc++ = 0xef ^ (val4 & 0xFF);
582                 *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF);
583                 *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF);
584                 *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF);
585                 *ecc++ = 0xed ^ (val3 & 0xFF);
586                 *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF);
587                 *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF);
588                 *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
589                 *ecc++ = 0x97 ^ (val2 & 0xFF);
590                 *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF);
591                 *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
592                 *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF);
593                 *ecc++ = 0xb5 ^ (val1 & 0xFF);
594         }
595
596         /*
597          * Stop reading anymore ECC vals and clear old results
598          * enable will be called if more reads are required
599          */
600         omap_ecc_disable(mtd);
601
602         return ret;
603 }
604
605 /**
606  * omap_correct_data_bch_sw - Decode received data and correct errors
607  * @mtd: MTD device structure
608  * @data: page data
609  * @read_ecc: ecc read from nand flash
610  * @calc_ecc: ecc read from HW ECC registers
611  */
612 static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
613                                  u_char *read_ecc, u_char *calc_ecc)
614 {
615         int i, count;
616         /* cannot correct more than 8 errors */
617         unsigned int errloc[8];
618         struct nand_chip *chip = mtd->priv;
619         struct nand_bch_priv *chip_priv = chip->priv;
620         struct bch_control *bch = chip_priv->control;
621
622         count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
623         if (count > 0) {
624                 /* correct errors */
625                 for (i = 0; i < count; i++) {
626                         /* correct data only, not ecc bytes */
627                         if (errloc[i] < 8*512)
628                                 data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
629                         printf("corrected bitflip %u\n", errloc[i]);
630 #ifdef DEBUG
631                         puts("read_ecc: ");
632                         /*
633                          * BCH8 have 13 bytes of ECC; BCH4 needs adoption
634                          * here!
635                          */
636                         for (i = 0; i < 13; i++)
637                                 printf("%02x ", read_ecc[i]);
638                         puts("\n");
639                         puts("calc_ecc: ");
640                         for (i = 0; i < 13; i++)
641                                 printf("%02x ", calc_ecc[i]);
642                         puts("\n");
643 #endif
644                 }
645         } else if (count < 0) {
646                 puts("ecc unrecoverable error\n");
647         }
648         return count;
649 }
650
651 /**
652  * omap_free_bch - Release BCH ecc resources
653  * @mtd: MTD device structure
654  */
655 static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
656 {
657         struct nand_chip *chip = mtd->priv;
658         struct nand_bch_priv *chip_priv = chip->priv;
659         struct bch_control *bch = NULL;
660
661         if (chip_priv)
662                 bch = chip_priv->control;
663
664         if (bch) {
665                 free_bch(bch);
666                 chip_priv->control = NULL;
667         }
668 }
669 #endif /* CONFIG_BCH */
670
671 /**
672  * omap_select_ecc_scheme - configures driver for particular ecc-scheme
673  * @nand: NAND chip device structure
674  * @ecc_scheme: ecc scheme to configure
675  * @pagesize: number of main-area bytes per page of NAND device
676  * @oobsize: number of OOB/spare bytes per page of NAND device
677  */
678 static int omap_select_ecc_scheme(struct nand_chip *nand,
679         enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
680         struct nand_bch_priv    *bch            = nand->priv;
681         struct nand_ecclayout   *ecclayout      = &omap_ecclayout;
682         int eccsteps = pagesize / SECTOR_BYTES;
683         int i;
684
685         switch (ecc_scheme) {
686         case OMAP_ECC_HAM1_CODE_SW:
687                 debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
688                 /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
689                  * initialized in nand_scan_tail(), so just set ecc.mode */
690                 bch_priv.control        = NULL;
691                 bch_priv.type           = 0;
692                 nand->ecc.mode          = NAND_ECC_SOFT;
693                 nand->ecc.layout        = NULL;
694                 nand->ecc.size          = 0;
695                 bch->ecc_scheme         = OMAP_ECC_HAM1_CODE_SW;
696                 break;
697
698         case OMAP_ECC_HAM1_CODE_HW:
699                 debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
700                 /* check ecc-scheme requirements before updating ecc info */
701                 if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
702                         printf("nand: error: insufficient OOB: require=%d\n", (
703                                 (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
704                         return -EINVAL;
705                 }
706                 bch_priv.control        = NULL;
707                 bch_priv.type           = 0;
708                 /* populate ecc specific fields */
709                 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
710                 nand->ecc.mode          = NAND_ECC_HW;
711                 nand->ecc.strength      = 1;
712                 nand->ecc.size          = SECTOR_BYTES;
713                 nand->ecc.bytes         = 3;
714                 nand->ecc.hwctl         = omap_enable_hwecc;
715                 nand->ecc.correct       = omap_correct_data;
716                 nand->ecc.calculate     = omap_calculate_ecc;
717                 /* define ecc-layout */
718                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
719                 for (i = 0; i < ecclayout->eccbytes; i++) {
720                         if (nand->options & NAND_BUSWIDTH_16)
721                                 ecclayout->eccpos[i] = i + 2;
722                         else
723                                 ecclayout->eccpos[i] = i + 1;
724                 }
725                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
726                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
727                                                 BADBLOCK_MARKER_LENGTH;
728                 bch->ecc_scheme         = OMAP_ECC_HAM1_CODE_HW;
729                 break;
730
731         case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
732 #ifdef CONFIG_BCH
733                 debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
734                 /* check ecc-scheme requirements before updating ecc info */
735                 if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
736                         printf("nand: error: insufficient OOB: require=%d\n", (
737                                 (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
738                         return -EINVAL;
739                 }
740                 /* check if BCH S/W library can be used for error detection */
741                 bch_priv.control = init_bch(13, 8, 0x201b);
742                 if (!bch_priv.control) {
743                         printf("nand: error: could not init_bch()\n");
744                         return -ENODEV;
745                 }
746                 bch_priv.type = ECC_BCH8;
747                 /* populate ecc specific fields */
748                 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
749                 nand->ecc.mode          = NAND_ECC_HW;
750                 nand->ecc.strength      = 8;
751                 nand->ecc.size          = SECTOR_BYTES;
752                 nand->ecc.bytes         = 13;
753                 nand->ecc.hwctl         = omap_enable_hwecc;
754                 nand->ecc.correct       = omap_correct_data_bch_sw;
755                 nand->ecc.calculate     = omap_calculate_ecc_bch_sw;
756                 /* define ecc-layout */
757                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
758                 ecclayout->eccpos[0]    = BADBLOCK_MARKER_LENGTH;
759                 for (i = 1; i < ecclayout->eccbytes; i++) {
760                         if (i % nand->ecc.bytes)
761                                 ecclayout->eccpos[i] =
762                                                 ecclayout->eccpos[i - 1] + 1;
763                         else
764                                 ecclayout->eccpos[i] =
765                                                 ecclayout->eccpos[i - 1] + 2;
766                 }
767                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
768                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
769                                                 BADBLOCK_MARKER_LENGTH;
770                 bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
771                 break;
772 #else
773                 printf("nand: error: CONFIG_BCH required for ECC\n");
774                 return -EINVAL;
775 #endif
776
777         case OMAP_ECC_BCH8_CODE_HW:
778 #ifdef CONFIG_NAND_OMAP_ELM
779                 debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
780                 /* check ecc-scheme requirements before updating ecc info */
781                 if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
782                         printf("nand: error: insufficient OOB: require=%d\n", (
783                                 (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
784                         return -EINVAL;
785                 }
786                 /* intialize ELM for ECC error detection */
787                 elm_init();
788                 bch_priv.type           = ECC_BCH8;
789                 /* populate ecc specific fields */
790                 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
791                 nand->ecc.mode          = NAND_ECC_HW;
792                 nand->ecc.strength      = 8;
793                 nand->ecc.size          = SECTOR_BYTES;
794                 nand->ecc.bytes         = 14;
795                 nand->ecc.hwctl         = omap_enable_hwecc;
796                 nand->ecc.correct       = omap_correct_data_bch;
797                 nand->ecc.calculate     = omap_calculate_ecc_bch;
798                 nand->ecc.read_page     = omap_read_page_bch;
799                 /* define ecc-layout */
800                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
801                 for (i = 0; i < ecclayout->eccbytes; i++)
802                         ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
803                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
804                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
805                                                 BADBLOCK_MARKER_LENGTH;
806                 bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW;
807                 break;
808 #else
809                 printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
810                 return -EINVAL;
811 #endif
812
813         default:
814                 debug("nand: error: ecc scheme not enabled or supported\n");
815                 return -EINVAL;
816         }
817
818         /* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
819         if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
820                 nand->ecc.layout = ecclayout;
821
822         return 0;
823 }
824
825 #ifndef CONFIG_SPL_BUILD
826 /*
827  * omap_nand_switch_ecc - switch the ECC operation between different engines
828  * (h/w and s/w) and different algorithms (hamming and BCHx)
829  *
830  * @hardware            - true if one of the HW engines should be used
831  * @eccstrength         - the number of bits that could be corrected
832  *                        (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
833  */
834 int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
835 {
836         struct nand_chip *nand;
837         struct mtd_info *mtd;
838         int err = 0;
839
840         if (nand_curr_device < 0 ||
841             nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
842             !nand_info[nand_curr_device].name) {
843                 printf("nand: error: no NAND devices found\n");
844                 return -ENODEV;
845         }
846
847         mtd = &nand_info[nand_curr_device];
848         nand = mtd->priv;
849         nand->options |= NAND_OWN_BUFFERS;
850         nand->options &= ~NAND_SUBPAGE_READ;
851         /* Setup the ecc configurations again */
852         if (hardware) {
853                 if (eccstrength == 1) {
854                         err = omap_select_ecc_scheme(nand,
855                                         OMAP_ECC_HAM1_CODE_HW,
856                                         mtd->writesize, mtd->oobsize);
857                 } else if (eccstrength == 8) {
858                         err = omap_select_ecc_scheme(nand,
859                                         OMAP_ECC_BCH8_CODE_HW,
860                                         mtd->writesize, mtd->oobsize);
861                 } else {
862                         printf("nand: error: unsupported ECC scheme\n");
863                         return -EINVAL;
864                 }
865         } else {
866                 err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
867                                         mtd->writesize, mtd->oobsize);
868         }
869
870         /* Update NAND handling after ECC mode switch */
871         if (!err)
872                 err = nand_scan_tail(mtd);
873         return err;
874 }
875 #endif /* CONFIG_SPL_BUILD */
876
877 /*
878  * Board-specific NAND initialization. The following members of the
879  * argument are board-specific:
880  * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
881  * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
882  * - cmd_ctrl: hardwarespecific function for accesing control-lines
883  * - waitfunc: hardwarespecific function for accesing device ready/busy line
884  * - ecc.hwctl: function to enable (reset) hardware ecc generator
885  * - ecc.mode: mode of ecc, see defines
886  * - chip_delay: chip dependent delay for transfering data from array to
887  *   read regs (tR)
888  * - options: various chip options. They can partly be set to inform
889  *   nand_scan about special functionality. See the defines for further
890  *   explanation
891  */
892 int board_nand_init(struct nand_chip *nand)
893 {
894         int32_t gpmc_config = 0;
895         cs = 0;
896         int err = 0;
897         /*
898          * xloader/Uboot's gpmc configuration would have configured GPMC for
899          * nand type of memory. The following logic scans and latches on to the
900          * first CS with NAND type memory.
901          * TBD: need to make this logic generic to handle multiple CS NAND
902          * devices.
903          */
904         while (cs < GPMC_MAX_CS) {
905                 /* Check if NAND type is set */
906                 if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
907                         /* Found it!! */
908                         break;
909                 }
910                 cs++;
911         }
912         if (cs >= GPMC_MAX_CS) {
913                 printf("nand: error: Unable to find NAND settings in "
914                         "GPMC Configuration - quitting\n");
915                 return -ENODEV;
916         }
917
918         gpmc_config = readl(&gpmc_cfg->config);
919         /* Disable Write protect */
920         gpmc_config |= 0x10;
921         writel(gpmc_config, &gpmc_cfg->config);
922
923         nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
924         nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
925         nand->priv      = &bch_priv;
926         nand->cmd_ctrl  = omap_nand_hwcontrol;
927         nand->options   |= NAND_NO_PADDING | NAND_CACHEPRG;
928         /* If we are 16 bit dev, our gpmc config tells us that */
929         if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
930                 nand->options |= NAND_BUSWIDTH_16;
931
932         nand->chip_delay = 100;
933         nand->ecc.layout = &omap_ecclayout;
934
935         /* select ECC scheme */
936 #if defined(CONFIG_NAND_OMAP_ECCSCHEME)
937         err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
938                         CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
939 #else
940         /* pagesize and oobsize are not required to configure sw ecc-scheme */
941         err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
942                         0, 0);
943 #endif
944         if (err)
945                 return err;
946
947 #ifdef CONFIG_SPL_BUILD
948         if (nand->options & NAND_BUSWIDTH_16)
949                 nand->read_buf = nand_read_buf16;
950         else
951                 nand->read_buf = nand_read_buf;
952         nand->dev_ready = omap_spl_dev_ready;
953 #endif
954
955         return 0;
956 }