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