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