]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/nand/omap_gpmc.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[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.
300          * Here we are using different settings for read and write access and
301          * also 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 have
326          * flaws with BCH4.
327          *
328          * Here we are using wrapping mode 6 both for reading and writing, with:
329          *  size0 = 0  (no additional protected byte in spare area)
330          *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
331          */
332         val = (32 << 22) | (0 << 12);
333         }
334         /* ecc size configuration */
335         writel(val, &gpmc_cfg->ecc_size_config);
336
337         /*
338          * Configure the ecc engine in gpmc
339          * We assume 512 Byte sector pages for access to NAND.
340          */
341         val  = (1 << 16);               /* enable BCH mode */
342         val |= (bch->type << 12);       /* setup BCH type */
343         val |= (wr_mode << 8);          /* setup wrapping mode */
344         val |= (dev_width << 7);        /* setup device width (16 or 8 bit) */
345         val |= (cs << 1);               /* setup chip select to work on */
346         debug("set ECC_CONFIG=0x%08x\n", val);
347         writel(val, &gpmc_cfg->ecc_config);
348 }
349
350 /*
351  * omap_enable_ecc_bch - This function enables the bch h/w ecc functionality
352  * @mtd:        MTD device structure
353  * @mode:       Read/Write mode
354  */
355 __maybe_unused
356 static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
357 {
358         struct nand_chip *chip = mtd->priv;
359
360         omap_hwecc_init_bch(chip, mode);
361         /* enable ecc */
362         writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config);
363 }
364
365 /*
366  * omap_ecc_disable - Disable H/W ECC calculation
367  *
368  * @mtd:        MTD device structure
369  */
370 static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
371 {
372         writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
373 }
374
375 /*
376  * BCH support using ELM module
377  */
378 #ifdef CONFIG_NAND_OMAP_ELM
379 /*
380  * omap_read_bch8_result - Read BCH result for BCH8 level
381  *
382  * @mtd:        MTD device structure
383  * @big_endian: When set read register 3 first
384  * @ecc_code:   Read syndrome from BCH result registers
385  */
386 static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
387                                 uint8_t *ecc_code)
388 {
389         uint32_t *ptr;
390         int8_t i = 0, j;
391
392         if (big_endian) {
393                 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
394                 ecc_code[i++] = readl(ptr) & 0xFF;
395                 ptr--;
396                 for (j = 0; j < 3; j++) {
397                         ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
398                         ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
399                         ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
400                         ecc_code[i++] = readl(ptr) & 0xFF;
401                         ptr--;
402                 }
403         } else {
404                 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[0];
405                 for (j = 0; j < 3; j++) {
406                         ecc_code[i++] = readl(ptr) & 0xFF;
407                         ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
408                         ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
409                         ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
410                         ptr++;
411                 }
412                 ecc_code[i++] = readl(ptr) & 0xFF;
413                 ecc_code[i++] = 0;      /* 14th byte is always zero */
414         }
415 }
416
417 /*
418  * omap_rotate_ecc_bch - Rotate the syndrome bytes
419  *
420  * @mtd:        MTD device structure
421  * @calc_ecc:   ECC read from ECC registers
422  * @syndrome:   Rotated syndrome will be retuned in this array
423  *
424  */
425 static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
426                 uint8_t *syndrome)
427 {
428         struct nand_chip *chip = mtd->priv;
429         struct nand_bch_priv *bch = chip->priv;
430         uint8_t n_bytes = 0;
431         int8_t i, j;
432
433         switch (bch->type) {
434         case ECC_BCH4:
435                 n_bytes = 8;
436                 break;
437
438         case ECC_BCH16:
439                 n_bytes = 28;
440                 break;
441
442         case ECC_BCH8:
443         default:
444                 n_bytes = 13;
445                 break;
446         }
447
448         for (i = 0, j = (n_bytes-1); i < n_bytes; i++, j--)
449                 syndrome[i] =  calc_ecc[j];
450 }
451
452 /*
453  *  omap_calculate_ecc_bch - Read BCH ECC result
454  *
455  *  @mtd:       MTD structure
456  *  @dat:       unused
457  *  @ecc_code:  ecc_code buffer
458  */
459 static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
460                                 uint8_t *ecc_code)
461 {
462         struct nand_chip *chip = mtd->priv;
463         struct nand_bch_priv *bch = chip->priv;
464         uint8_t big_endian = 1;
465         int8_t ret = 0;
466
467         if (bch->type == ECC_BCH8)
468                 omap_read_bch8_result(mtd, big_endian, ecc_code);
469         else /* BCH4 and BCH16 currently not supported */
470                 ret = -1;
471
472         /*
473          * Stop reading anymore ECC vals and clear old results
474          * enable will be called if more reads are required
475          */
476         omap_ecc_disable(mtd);
477
478         return ret;
479 }
480
481 /*
482  * omap_fix_errors_bch - Correct bch error in the data
483  *
484  * @mtd:        MTD device structure
485  * @data:       Data read from flash
486  * @error_count:Number of errors in data
487  * @error_loc:  Locations of errors in the data
488  *
489  */
490 static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
491                 uint32_t error_count, uint32_t *error_loc)
492 {
493         struct nand_chip *chip = mtd->priv;
494         struct nand_bch_priv *bch = chip->priv;
495         uint8_t count = 0;
496         uint32_t error_byte_pos;
497         uint32_t error_bit_mask;
498         uint32_t last_bit = (bch->nibbles * 4) - 1;
499
500         /* Flip all bits as specified by the error location array. */
501         /* FOR( each found error location flip the bit ) */
502         for (count = 0; count < error_count; count++) {
503                 if (error_loc[count] > last_bit) {
504                         /* Remove the ECC spare bits from correction. */
505                         error_loc[count] -= (last_bit + 1);
506                         /* Offset bit in data region */
507                         error_byte_pos = ((512 * 8) -
508                                         (error_loc[count]) - 1) / 8;
509                         /* Error Bit mask */
510                         error_bit_mask = 0x1 << (error_loc[count] % 8);
511                         /* Toggle the error bit to make the correction. */
512                         data[error_byte_pos] ^= error_bit_mask;
513                 }
514         }
515 }
516
517 /*
518  * omap_correct_data_bch - Compares the ecc read from nand spare area
519  * with ECC registers values and corrects one bit error if it has occured
520  *
521  * @mtd:        MTD device structure
522  * @dat:        page data
523  * @read_ecc:   ecc read from nand flash (ignored)
524  * @calc_ecc:   ecc read from ECC registers
525  *
526  * @return 0 if data is OK or corrected, else returns -1
527  */
528 static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
529                                 uint8_t *read_ecc, uint8_t *calc_ecc)
530 {
531         struct nand_chip *chip = mtd->priv;
532         struct nand_bch_priv *bch = chip->priv;
533         uint8_t syndrome[28];
534         uint32_t error_count = 0;
535         uint32_t error_loc[8];
536         uint32_t i, ecc_flag;
537
538         ecc_flag = 0;
539         for (i = 0; i < chip->ecc.bytes; i++)
540                 if (read_ecc[i] != 0xff)
541                         ecc_flag = 1;
542
543         if (!ecc_flag)
544                 return 0;
545
546         elm_reset();
547         elm_config((enum bch_level)(bch->type));
548
549         /*
550          * while reading ECC result we read it in big endian.
551          * Hence while loading to ELM we have rotate to get the right endian.
552          */
553         omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
554
555         /* use elm module to check for errors */
556         if (elm_check_error(syndrome, bch->nibbles, &error_count,
557                                 error_loc) != 0) {
558                 printf("ECC: uncorrectable.\n");
559                 return -1;
560         }
561
562         /* correct bch error */
563         if (error_count > 0)
564                 omap_fix_errors_bch(mtd, dat, error_count, error_loc);
565
566         return 0;
567 }
568
569 /**
570  * omap_read_page_bch - hardware ecc based page read function
571  * @mtd:        mtd info structure
572  * @chip:       nand chip info structure
573  * @buf:        buffer to store read data
574  * @oob_required: caller expects OOB data read to chip->oob_poi
575  * @page:       page number to read
576  *
577  */
578 static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
579                                 uint8_t *buf, int oob_required, int page)
580 {
581         int i, eccsize = chip->ecc.size;
582         int eccbytes = chip->ecc.bytes;
583         int eccsteps = chip->ecc.steps;
584         uint8_t *p = buf;
585         uint8_t *ecc_calc = chip->buffers->ecccalc;
586         uint8_t *ecc_code = chip->buffers->ecccode;
587         uint32_t *eccpos = chip->ecc.layout->eccpos;
588         uint8_t *oob = chip->oob_poi;
589         uint32_t data_pos;
590         uint32_t oob_pos;
591
592         data_pos = 0;
593         /* oob area start */
594         oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
595         oob += chip->ecc.layout->eccpos[0];
596
597         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
598                                 oob += eccbytes) {
599                 chip->ecc.hwctl(mtd, NAND_ECC_READ);
600                 /* read data */
601                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
602                 chip->read_buf(mtd, p, eccsize);
603
604                 /* read respective ecc from oob area */
605                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
606                 chip->read_buf(mtd, oob, eccbytes);
607                 /* read syndrome */
608                 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
609
610                 data_pos += eccsize;
611                 oob_pos += eccbytes;
612         }
613
614         for (i = 0; i < chip->ecc.total; i++)
615                 ecc_code[i] = chip->oob_poi[eccpos[i]];
616
617         eccsteps = chip->ecc.steps;
618         p = buf;
619
620         for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
621                 int stat;
622
623                 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
624                 if (stat < 0)
625                         mtd->ecc_stats.failed++;
626                 else
627                         mtd->ecc_stats.corrected += stat;
628         }
629         return 0;
630 }
631 #endif /* CONFIG_NAND_OMAP_ELM */
632
633 /*
634  * OMAP3 BCH8 support (with BCH library)
635  */
636 #ifdef CONFIG_BCH
637 /*
638  *  omap_calculate_ecc_bch_sw - Read BCH ECC result
639  *
640  *  @mtd:       MTD device structure
641  *  @dat:       The pointer to data on which ecc is computed (unused here)
642  *  @ecc:       The ECC output buffer
643  */
644 static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, const uint8_t *dat,
645                                 uint8_t *ecc)
646 {
647         int ret = 0;
648         size_t i;
649         unsigned long nsectors, val1, val2, val3, val4;
650
651         nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
652
653         for (i = 0; i < nsectors; i++) {
654                 /* Read hw-computed remainder */
655                 val1 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[0]);
656                 val2 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[1]);
657                 val3 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[2]);
658                 val4 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[3]);
659
660                 /*
661                  * Add constant polynomial to remainder, in order to get an ecc
662                  * sequence of 0xFFs for a buffer filled with 0xFFs.
663                  */
664                 *ecc++ = 0xef ^ (val4 & 0xFF);
665                 *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF);
666                 *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF);
667                 *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF);
668                 *ecc++ = 0xed ^ (val3 & 0xFF);
669                 *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF);
670                 *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF);
671                 *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
672                 *ecc++ = 0x97 ^ (val2 & 0xFF);
673                 *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF);
674                 *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
675                 *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF);
676                 *ecc++ = 0xb5 ^ (val1 & 0xFF);
677         }
678
679         /*
680          * Stop reading anymore ECC vals and clear old results
681          * enable will be called if more reads are required
682          */
683         omap_ecc_disable(mtd);
684
685         return ret;
686 }
687
688 /**
689  * omap_correct_data_bch_sw - Decode received data and correct errors
690  * @mtd: MTD device structure
691  * @data: page data
692  * @read_ecc: ecc read from nand flash
693  * @calc_ecc: ecc read from HW ECC registers
694  */
695 static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
696                                  u_char *read_ecc, u_char *calc_ecc)
697 {
698         int i, count;
699         /* cannot correct more than 8 errors */
700         unsigned int errloc[8];
701         struct nand_chip *chip = mtd->priv;
702         struct nand_bch_priv *chip_priv = chip->priv;
703         struct bch_control *bch = chip_priv->control;
704
705         count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
706         if (count > 0) {
707                 /* correct errors */
708                 for (i = 0; i < count; i++) {
709                         /* correct data only, not ecc bytes */
710                         if (errloc[i] < 8*512)
711                                 data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
712                         printf("corrected bitflip %u\n", errloc[i]);
713 #ifdef DEBUG
714                         puts("read_ecc: ");
715                         /*
716                          * BCH8 have 13 bytes of ECC; BCH4 needs adoption
717                          * here!
718                          */
719                         for (i = 0; i < 13; i++)
720                                 printf("%02x ", read_ecc[i]);
721                         puts("\n");
722                         puts("calc_ecc: ");
723                         for (i = 0; i < 13; i++)
724                                 printf("%02x ", calc_ecc[i]);
725                         puts("\n");
726 #endif
727                 }
728         } else if (count < 0) {
729                 puts("ecc unrecoverable error\n");
730         }
731         return count;
732 }
733
734 /**
735  * omap_free_bch - Release BCH ecc resources
736  * @mtd: MTD device structure
737  */
738 static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
739 {
740         struct nand_chip *chip = mtd->priv;
741         struct nand_bch_priv *chip_priv = chip->priv;
742         struct bch_control *bch = NULL;
743
744         if (chip_priv)
745                 bch = chip_priv->control;
746
747         if (bch) {
748                 free_bch(bch);
749                 chip_priv->control = NULL;
750         }
751 }
752 #endif /* CONFIG_BCH */
753
754 /**
755  * omap_select_ecc_scheme - configures driver for particular ecc-scheme
756  * @nand: NAND chip device structure
757  * @ecc_scheme: ecc scheme to configure
758  * @pagesize: number of main-area bytes per page of NAND device
759  * @oobsize: number of OOB/spare bytes per page of NAND device
760  */
761 static int omap_select_ecc_scheme(struct nand_chip *nand,
762         enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
763         struct nand_bch_priv    *bch            = nand->priv;
764         struct nand_ecclayout   *ecclayout      = nand->ecc.layout;
765         int eccsteps = pagesize / SECTOR_BYTES;
766         int i;
767
768         switch (ecc_scheme) {
769         case OMAP_ECC_HAM1_CODE_SW:
770                 debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
771                 /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
772                  * initialized in nand_scan_tail(), so just set ecc.mode */
773                 bch_priv.control        = NULL;
774                 bch_priv.type           = 0;
775                 nand->ecc.mode          = NAND_ECC_SOFT;
776                 nand->ecc.layout        = NULL;
777                 nand->ecc.size          = pagesize;
778                 bch->ecc_scheme         = OMAP_ECC_HAM1_CODE_SW;
779                 break;
780
781         case OMAP_ECC_HAM1_CODE_HW:
782                 debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
783                 /* check ecc-scheme requirements before updating ecc info */
784                 if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
785                         printf("nand: error: insufficient OOB: require=%d\n", (
786                                 (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
787                         return -EINVAL;
788                 }
789                 bch_priv.control        = NULL;
790                 bch_priv.type           = 0;
791                 /* populate ecc specific fields */
792                 nand->ecc.mode          = NAND_ECC_HW;
793                 nand->ecc.strength      = 1;
794                 nand->ecc.size          = SECTOR_BYTES;
795                 nand->ecc.bytes         = 3;
796                 nand->ecc.hwctl         = omap_enable_hwecc;
797                 nand->ecc.correct       = omap_correct_data;
798                 nand->ecc.calculate     = omap_calculate_ecc;
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_HAM1_CODE_HW;
807                 break;
808
809         case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
810 #ifdef CONFIG_BCH
811                 debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
812                 /* check ecc-scheme requirements before updating ecc info */
813                 if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
814                         printf("nand: error: insufficient OOB: require=%d\n", (
815                                 (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
816                         return -EINVAL;
817                 }
818                 /* check if BCH S/W library can be used for error detection */
819                 bch_priv.control = init_bch(13, 8, 0x201b);
820                 if (!bch_priv.control) {
821                         printf("nand: error: could not init_bch()\n");
822                         return -ENODEV;
823                 }
824                 bch_priv.type = ECC_BCH8;
825                 /* populate ecc specific fields */
826                 nand->ecc.mode          = NAND_ECC_HW;
827                 nand->ecc.strength      = 8;
828                 nand->ecc.size          = SECTOR_BYTES;
829                 nand->ecc.bytes         = 13;
830                 nand->ecc.hwctl         = omap_enable_ecc_bch;
831                 nand->ecc.correct       = omap_correct_data_bch_sw;
832                 nand->ecc.calculate     = omap_calculate_ecc_bch_sw;
833                 /* define ecc-layout */
834                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
835                 ecclayout->eccpos[0]    = BADBLOCK_MARKER_LENGTH;
836                 for (i = 1; i < ecclayout->eccbytes; i++) {
837                         if (i % nand->ecc.bytes)
838                                 ecclayout->eccpos[i] =
839                                                 ecclayout->eccpos[i - 1] + 1;
840                         else
841                                 ecclayout->eccpos[i] =
842                                                 ecclayout->eccpos[i - 1] + 2;
843                 }
844                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
845                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
846                                                 BADBLOCK_MARKER_LENGTH;
847                 omap_hwecc_init_bch(nand, NAND_ECC_READ);
848                 bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
849                 break;
850 #else
851                 printf("nand: error: CONFIG_BCH required for ECC\n");
852                 return -EINVAL;
853 #endif
854
855         case OMAP_ECC_BCH8_CODE_HW:
856 #ifdef CONFIG_NAND_OMAP_ELM
857                 debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
858                 /* check ecc-scheme requirements before updating ecc info */
859                 if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
860                         printf("nand: error: insufficient OOB: require=%d\n", (
861                                 (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
862                         return -EINVAL;
863                 }
864                 /* intialize ELM for ECC error detection */
865                 elm_init();
866                 bch_priv.type           = ECC_BCH8;
867                 /* populate ecc specific fields */
868                 nand->ecc.mode          = NAND_ECC_HW;
869                 nand->ecc.strength      = 8;
870                 nand->ecc.size          = SECTOR_BYTES;
871                 nand->ecc.bytes         = 14;
872                 nand->ecc.hwctl         = omap_enable_ecc_bch;
873                 nand->ecc.correct       = omap_correct_data_bch;
874                 nand->ecc.calculate     = omap_calculate_ecc_bch;
875                 nand->ecc.read_page     = omap_read_page_bch;
876                 /* define ecc-layout */
877                 ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
878                 for (i = 0; i < ecclayout->eccbytes; i++)
879                         ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
880                 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
881                 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
882                                                 BADBLOCK_MARKER_LENGTH;
883                 bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW;
884                 break;
885 #else
886                 printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
887                 return -EINVAL;
888 #endif
889
890         default:
891                 debug("nand: error: ecc scheme not enabled or supported\n");
892                 return -EINVAL;
893         }
894         return 0;
895 }
896
897 #ifndef CONFIG_SPL_BUILD
898 /*
899  * omap_nand_switch_ecc - switch the ECC operation between different engines
900  * (h/w and s/w) and different algorithms (hamming and BCHx)
901  *
902  * @hardware            - true if one of the HW engines should be used
903  * @eccstrength         - the number of bits that could be corrected
904  *                        (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
905  */
906 int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
907 {
908         struct nand_chip *nand;
909         struct mtd_info *mtd;
910         int err = 0;
911
912         if (nand_curr_device < 0 ||
913             nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
914             !nand_info[nand_curr_device].name) {
915                 printf("nand: error: no NAND devices found\n");
916                 return -ENODEV;
917         }
918
919         mtd = &nand_info[nand_curr_device];
920         nand = mtd->priv;
921         nand->options |= NAND_OWN_BUFFERS;
922         /* Setup the ecc configurations again */
923         if (hardware) {
924                 if (eccstrength == 1) {
925                         err = omap_select_ecc_scheme(nand,
926                                         OMAP_ECC_HAM1_CODE_HW,
927                                         mtd->writesize, mtd->oobsize);
928                 } else if (eccstrength == 8) {
929                         err = omap_select_ecc_scheme(nand,
930                                         OMAP_ECC_BCH8_CODE_HW,
931                                         mtd->writesize, mtd->oobsize);
932                 } else {
933                         printf("nand: error: unsupported ECC scheme\n");
934                         return -EINVAL;
935                 }
936         } else {
937                 err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
938                                         mtd->writesize, mtd->oobsize);
939         }
940
941         /* Update NAND handling after ECC mode switch */
942         if (!err)
943                 err = nand_scan_tail(mtd);
944         return err;
945 }
946 #endif /* CONFIG_SPL_BUILD */
947
948 /*
949  * Board-specific NAND initialization. The following members of the
950  * argument are board-specific:
951  * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
952  * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
953  * - cmd_ctrl: hardwarespecific function for accesing control-lines
954  * - waitfunc: hardwarespecific function for accesing device ready/busy line
955  * - ecc.hwctl: function to enable (reset) hardware ecc generator
956  * - ecc.mode: mode of ecc, see defines
957  * - chip_delay: chip dependent delay for transfering data from array to
958  *   read regs (tR)
959  * - options: various chip options. They can partly be set to inform
960  *   nand_scan about special functionality. See the defines for further
961  *   explanation
962  */
963 int board_nand_init(struct nand_chip *nand)
964 {
965         int32_t gpmc_config = 0;
966         cs = 0;
967         int err = 0;
968         /*
969          * xloader/Uboot's gpmc configuration would have configured GPMC for
970          * nand type of memory. The following logic scans and latches on to the
971          * first CS with NAND type memory.
972          * TBD: need to make this logic generic to handle multiple CS NAND
973          * devices.
974          */
975         while (cs < GPMC_MAX_CS) {
976                 /* Check if NAND type is set */
977                 if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
978                         /* Found it!! */
979                         break;
980                 }
981                 cs++;
982         }
983         if (cs >= GPMC_MAX_CS) {
984                 printf("nand: error: Unable to find NAND settings in "
985                         "GPMC Configuration - quitting\n");
986                 return -ENODEV;
987         }
988
989         gpmc_config = readl(&gpmc_cfg->config);
990         /* Disable Write protect */
991         gpmc_config |= 0x10;
992         writel(gpmc_config, &gpmc_cfg->config);
993
994         nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
995         nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
996         nand->priv      = &bch_priv;
997         nand->cmd_ctrl  = omap_nand_hwcontrol;
998         nand->options   |= NAND_NO_PADDING | NAND_CACHEPRG;
999         /* If we are 16 bit dev, our gpmc config tells us that */
1000         if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
1001                 nand->options |= NAND_BUSWIDTH_16;
1002
1003         nand->chip_delay = 100;
1004         nand->ecc.layout = &omap_ecclayout;
1005
1006         /* select ECC scheme */
1007 #if defined(CONFIG_NAND_OMAP_ECCSCHEME)
1008         err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
1009                         CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
1010 #else
1011         /* pagesize and oobsize are not required to configure sw ecc-scheme */
1012         err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
1013                         0, 0);
1014 #endif
1015         if (err)
1016                 return err;
1017
1018 #ifdef CONFIG_SPL_BUILD
1019         if (nand->options & NAND_BUSWIDTH_16)
1020                 nand->read_buf = nand_read_buf16;
1021         else
1022                 nand->read_buf = nand_read_buf;
1023         nand->dev_ready = omap_spl_dev_ready;
1024 #endif
1025
1026         return 0;
1027 }