]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/nand/omap_gpmc.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[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      = &omap_ecclayout;
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                 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
795                 nand->ecc.mode          = NAND_ECC_HW;
796                 nand->ecc.strength      = 1;
797                 nand->ecc.size          = SECTOR_BYTES;
798                 nand->ecc.bytes         = 3;
799                 nand->ecc.hwctl         = omap_enable_hwecc;
800                 nand->ecc.correct       = omap_correct_data;
801                 nand->ecc.calculate     = omap_calculate_ecc;
802                 /* define ecc-layout */
803                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
804                 for (i = 0; i < ecclayout->eccbytes; i++) {
805                         if (nand->options & NAND_BUSWIDTH_16)
806                                 ecclayout->eccpos[i] = i + 2;
807                         else
808                                 ecclayout->eccpos[i] = i + 1;
809                 }
810                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
811                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
812                                                 BADBLOCK_MARKER_LENGTH;
813                 bch->ecc_scheme         = OMAP_ECC_HAM1_CODE_HW;
814                 break;
815
816         case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
817 #ifdef CONFIG_BCH
818                 debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
819                 /* check ecc-scheme requirements before updating ecc info */
820                 if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
821                         printf("nand: error: insufficient OOB: require=%d\n", (
822                                 (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
823                         return -EINVAL;
824                 }
825                 /* check if BCH S/W library can be used for error detection */
826                 bch_priv.control = init_bch(13, 8, 0x201b);
827                 if (!bch_priv.control) {
828                         printf("nand: error: could not init_bch()\n");
829                         return -ENODEV;
830                 }
831                 bch_priv.type = ECC_BCH8;
832                 /* populate ecc specific fields */
833                 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
834                 nand->ecc.mode          = NAND_ECC_HW;
835                 nand->ecc.strength      = 8;
836                 nand->ecc.size          = SECTOR_BYTES;
837                 nand->ecc.bytes         = 13;
838                 nand->ecc.hwctl         = omap_enable_ecc_bch;
839                 nand->ecc.correct       = omap_correct_data_bch_sw;
840                 nand->ecc.calculate     = omap_calculate_ecc_bch_sw;
841                 /* define ecc-layout */
842                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
843                 ecclayout->eccpos[0]    = BADBLOCK_MARKER_LENGTH;
844                 for (i = 1; i < ecclayout->eccbytes; i++) {
845                         if (i % nand->ecc.bytes)
846                                 ecclayout->eccpos[i] =
847                                                 ecclayout->eccpos[i - 1] + 1;
848                         else
849                                 ecclayout->eccpos[i] =
850                                                 ecclayout->eccpos[i - 1] + 2;
851                 }
852                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
853                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
854                                                 BADBLOCK_MARKER_LENGTH;
855                 omap_hwecc_init_bch(nand, NAND_ECC_READ);
856                 bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
857                 break;
858 #else
859                 printf("nand: error: CONFIG_BCH required for ECC\n");
860                 return -EINVAL;
861 #endif
862
863         case OMAP_ECC_BCH8_CODE_HW:
864 #ifdef CONFIG_NAND_OMAP_ELM
865                 debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
866                 /* check ecc-scheme requirements before updating ecc info */
867                 if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
868                         printf("nand: error: insufficient OOB: require=%d\n", (
869                                 (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
870                         return -EINVAL;
871                 }
872                 /* intialize ELM for ECC error detection */
873                 elm_init();
874                 bch_priv.type           = ECC_BCH8;
875                 /* populate ecc specific fields */
876                 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
877                 nand->ecc.mode          = NAND_ECC_HW;
878                 nand->ecc.strength      = 8;
879                 nand->ecc.size          = SECTOR_BYTES;
880                 nand->ecc.bytes         = 14;
881                 nand->ecc.hwctl         = omap_enable_ecc_bch;
882                 nand->ecc.correct       = omap_correct_data_bch;
883                 nand->ecc.calculate     = omap_calculate_ecc_bch;
884                 nand->ecc.read_page     = omap_read_page_bch;
885                 /* define ecc-layout */
886                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
887                 for (i = 0; i < ecclayout->eccbytes; i++)
888                         ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
889                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
890                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
891                                                 BADBLOCK_MARKER_LENGTH;
892                 bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW;
893                 break;
894 #else
895                 printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
896                 return -EINVAL;
897 #endif
898
899         default:
900                 debug("nand: error: ecc scheme not enabled or supported\n");
901                 return -EINVAL;
902         }
903
904         /* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
905         if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
906                 nand->ecc.layout = ecclayout;
907
908         return 0;
909 }
910
911 #ifndef CONFIG_SPL_BUILD
912 /*
913  * omap_nand_switch_ecc - switch the ECC operation between different engines
914  * (h/w and s/w) and different algorithms (hamming and BCHx)
915  *
916  * @hardware            - true if one of the HW engines should be used
917  * @eccstrength         - the number of bits that could be corrected
918  *                        (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
919  */
920 int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
921 {
922         struct nand_chip *nand;
923         struct mtd_info *mtd;
924         int err = 0;
925
926         if (nand_curr_device < 0 ||
927             nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
928             !nand_info[nand_curr_device].name) {
929                 printf("nand: error: no NAND devices found\n");
930                 return -ENODEV;
931         }
932
933         mtd = &nand_info[nand_curr_device];
934         nand = mtd->priv;
935         nand->options |= NAND_OWN_BUFFERS;
936         /* Setup the ecc configurations again */
937         if (hardware) {
938                 if (eccstrength == 1) {
939                         err = omap_select_ecc_scheme(nand,
940                                         OMAP_ECC_HAM1_CODE_HW,
941                                         mtd->writesize, mtd->oobsize);
942                 } else if (eccstrength == 8) {
943                         err = omap_select_ecc_scheme(nand,
944                                         OMAP_ECC_BCH8_CODE_HW,
945                                         mtd->writesize, mtd->oobsize);
946                 } else {
947                         printf("nand: error: unsupported ECC scheme\n");
948                         return -EINVAL;
949                 }
950         } else {
951                 err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
952                                         mtd->writesize, mtd->oobsize);
953         }
954
955         /* Update NAND handling after ECC mode switch */
956         if (!err)
957                 err = nand_scan_tail(mtd);
958         return err;
959 }
960 #endif /* CONFIG_SPL_BUILD */
961
962 /*
963  * Board-specific NAND initialization. The following members of the
964  * argument are board-specific:
965  * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
966  * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
967  * - cmd_ctrl: hardwarespecific function for accesing control-lines
968  * - waitfunc: hardwarespecific function for accesing device ready/busy line
969  * - ecc.hwctl: function to enable (reset) hardware ecc generator
970  * - ecc.mode: mode of ecc, see defines
971  * - chip_delay: chip dependent delay for transfering data from array to
972  *   read regs (tR)
973  * - options: various chip options. They can partly be set to inform
974  *   nand_scan about special functionality. See the defines for further
975  *   explanation
976  */
977 int board_nand_init(struct nand_chip *nand)
978 {
979         int32_t gpmc_config = 0;
980         cs = 0;
981         int err = 0;
982         /*
983          * xloader/Uboot's gpmc configuration would have configured GPMC for
984          * nand type of memory. The following logic scans and latches on to the
985          * first CS with NAND type memory.
986          * TBD: need to make this logic generic to handle multiple CS NAND
987          * devices.
988          */
989         while (cs < GPMC_MAX_CS) {
990                 /* Check if NAND type is set */
991                 if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
992                         /* Found it!! */
993                         break;
994                 }
995                 cs++;
996         }
997         if (cs >= GPMC_MAX_CS) {
998                 printf("nand: error: Unable to find NAND settings in "
999                         "GPMC Configuration - quitting\n");
1000                 return -ENODEV;
1001         }
1002
1003         gpmc_config = readl(&gpmc_cfg->config);
1004         /* Disable Write protect */
1005         gpmc_config |= 0x10;
1006         writel(gpmc_config, &gpmc_cfg->config);
1007
1008         nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
1009         nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
1010         nand->priv      = &bch_priv;
1011         nand->cmd_ctrl  = omap_nand_hwcontrol;
1012         nand->options   |= NAND_NO_PADDING | NAND_CACHEPRG;
1013         /* If we are 16 bit dev, our gpmc config tells us that */
1014         if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
1015                 nand->options |= NAND_BUSWIDTH_16;
1016
1017         nand->chip_delay = 100;
1018         nand->ecc.layout = &omap_ecclayout;
1019
1020         /* select ECC scheme */
1021 #if defined(CONFIG_NAND_OMAP_ECCSCHEME)
1022         err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
1023                         CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
1024 #else
1025         /* pagesize and oobsize are not required to configure sw ecc-scheme */
1026         err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
1027                         0, 0);
1028 #endif
1029         if (err)
1030                 return err;
1031
1032 #ifdef CONFIG_SPL_BUILD
1033         if (nand->options & NAND_BUSWIDTH_16)
1034                 nand->read_buf = nand_read_buf16;
1035         else
1036                 nand->read_buf = nand_read_buf;
1037         nand->dev_ready = omap_spl_dev_ready;
1038 #endif
1039
1040         return 0;
1041 }