]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/nand/omap_gpmc.c
asm/omap_gpmc.h: consolidate common defines
[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  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <asm/io.h>
26 #include <asm/errno.h>
27 #include <asm/arch/mem.h>
28 #include <asm/arch/cpu.h>
29 #include <asm/omap_gpmc.h>
30 #include <linux/mtd/nand_ecc.h>
31 #include <linux/compiler.h>
32 #include <nand.h>
33 #ifdef CONFIG_AM33XX
34 #include <asm/arch/elm.h>
35 #endif
36
37 static uint8_t cs;
38 static __maybe_unused struct nand_ecclayout hw_nand_oob =
39         GPMC_NAND_HW_ECC_LAYOUT;
40
41 /*
42  * omap_nand_hwcontrol - Set the address pointers corretly for the
43  *                      following address/data/command operation
44  */
45 static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
46                                 uint32_t ctrl)
47 {
48         register struct nand_chip *this = mtd->priv;
49
50         /*
51          * Point the IO_ADDR to DATA and ADDRESS registers instead
52          * of chip address
53          */
54         switch (ctrl) {
55         case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
56                 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
57                 break;
58         case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
59                 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
60                 break;
61         case NAND_CTRL_CHANGE | NAND_NCE:
62                 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
63                 break;
64         }
65
66         if (cmd != NAND_CMD_NONE)
67                 writeb(cmd, this->IO_ADDR_W);
68 }
69
70 #ifdef CONFIG_SPL_BUILD
71 /* Check wait pin as dev ready indicator */
72 int omap_spl_dev_ready(struct mtd_info *mtd)
73 {
74         return gpmc_cfg->status & (1 << 8);
75 }
76 #endif
77
78 /*
79  * omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
80  *                   GPMC controller
81  * @mtd:        MTD device structure
82  *
83  */
84 static void __maybe_unused omap_hwecc_init(struct nand_chip *chip)
85 {
86         /*
87          * Init ECC Control Register
88          * Clear all ECC | Enable Reg1
89          */
90         writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
91         writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL, &gpmc_cfg->ecc_size_config);
92 }
93
94 /*
95  * gen_true_ecc - This function will generate true ECC value, which
96  * can be used when correcting data read from NAND flash memory core
97  *
98  * @ecc_buf:    buffer to store ecc code
99  *
100  * @return:     re-formatted ECC value
101  */
102 static uint32_t gen_true_ecc(uint8_t *ecc_buf)
103 {
104         return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
105                 ((ecc_buf[2] & 0x0F) << 8);
106 }
107
108 /*
109  * omap_correct_data - Compares the ecc read from nand spare area with ECC
110  * registers values and corrects one bit error if it has occured
111  * Further details can be had from OMAP TRM and the following selected links:
112  * http://en.wikipedia.org/wiki/Hamming_code
113  * http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
114  *
115  * @mtd:                 MTD device structure
116  * @dat:                 page data
117  * @read_ecc:            ecc read from nand flash
118  * @calc_ecc:            ecc read from ECC registers
119  *
120  * @return 0 if data is OK or corrected, else returns -1
121  */
122 static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
123                                 uint8_t *read_ecc, uint8_t *calc_ecc)
124 {
125         uint32_t orig_ecc, new_ecc, res, hm;
126         uint16_t parity_bits, byte;
127         uint8_t bit;
128
129         /* Regenerate the orginal ECC */
130         orig_ecc = gen_true_ecc(read_ecc);
131         new_ecc = gen_true_ecc(calc_ecc);
132         /* Get the XOR of real ecc */
133         res = orig_ecc ^ new_ecc;
134         if (res) {
135                 /* Get the hamming width */
136                 hm = hweight32(res);
137                 /* Single bit errors can be corrected! */
138                 if (hm == 12) {
139                         /* Correctable data! */
140                         parity_bits = res >> 16;
141                         bit = (parity_bits & 0x7);
142                         byte = (parity_bits >> 3) & 0x1FF;
143                         /* Flip the bit to correct */
144                         dat[byte] ^= (0x1 << bit);
145                 } else if (hm == 1) {
146                         printf("Error: Ecc is wrong\n");
147                         /* ECC itself is corrupted */
148                         return 2;
149                 } else {
150                         /*
151                          * hm distance != parity pairs OR one, could mean 2 bit
152                          * error OR potentially be on a blank page..
153                          * orig_ecc: contains spare area data from nand flash.
154                          * new_ecc: generated ecc while reading data area.
155                          * Note: if the ecc = 0, all data bits from which it was
156                          * generated are 0xFF.
157                          * The 3 byte(24 bits) ecc is generated per 512byte
158                          * chunk of a page. If orig_ecc(from spare area)
159                          * is 0xFF && new_ecc(computed now from data area)=0x0,
160                          * this means that data area is 0xFF and spare area is
161                          * 0xFF. A sure sign of a erased page!
162                          */
163                         if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
164                                 return 0;
165                         printf("Error: Bad compare! failed\n");
166                         /* detected 2 bit error */
167                         return -1;
168                 }
169         }
170         return 0;
171 }
172
173 /*
174  *  omap_calculate_ecc - Generate non-inverted ECC bytes.
175  *
176  *  Using noninverted ECC can be considered ugly since writing a blank
177  *  page ie. padding will clear the ECC bytes. This is no problem as
178  *  long nobody is trying to write data on the seemingly unused page.
179  *  Reading an erased page will produce an ECC mismatch between
180  *  generated and read ECC bytes that has to be dealt with separately.
181  *  E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
182  *  is used, the result of read will be 0x0 while the ECC offsets of the
183  *  spare area will be 0xFF which will result in an ECC mismatch.
184  *  @mtd:       MTD structure
185  *  @dat:       unused
186  *  @ecc_code:  ecc_code buffer
187  */
188 static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
189                 const uint8_t *dat, uint8_t *ecc_code)
190 {
191         u_int32_t val;
192
193         /* Start Reading from HW ECC1_Result = 0x200 */
194         val = readl(&gpmc_cfg->ecc1_result);
195
196         ecc_code[0] = val & 0xFF;
197         ecc_code[1] = (val >> 16) & 0xFF;
198         ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
199
200         /*
201          * Stop reading anymore ECC vals and clear old results
202          * enable will be called if more reads are required
203          */
204         writel(0x000, &gpmc_cfg->ecc_config);
205
206         return 0;
207 }
208
209 /*
210  * omap_enable_ecc - This function enables the hardware ecc functionality
211  * @mtd:        MTD device structure
212  * @mode:       Read/Write mode
213  */
214 static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
215 {
216         struct nand_chip *chip = mtd->priv;
217         uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
218
219         switch (mode) {
220         case NAND_ECC_READ:
221         case NAND_ECC_WRITE:
222                 /* Clear the ecc result registers, select ecc reg as 1 */
223                 writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
224
225                 /*
226                  * Size 0 = 0xFF, Size1 is 0xFF - both are 512 bytes
227                  * tell all regs to generate size0 sized regs
228                  * we just have a single ECC engine for all CS
229                  */
230                 writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL,
231                         &gpmc_cfg->ecc_size_config);
232                 val = (dev_width << 7) | (cs << 1) | (0x1);
233                 writel(val, &gpmc_cfg->ecc_config);
234                 break;
235         default:
236                 printf("Error: Unrecognized Mode[%d]!\n", mode);
237                 break;
238         }
239 }
240
241 /*
242  * BCH8 support (needs ELM and thus AM33xx-only)
243  */
244 #ifdef CONFIG_AM33XX
245 struct nand_bch_priv {
246         uint8_t mode;
247         uint8_t type;
248         uint8_t nibbles;
249 };
250
251 /* bch types */
252 #define ECC_BCH4        0
253 #define ECC_BCH8        1
254 #define ECC_BCH16       2
255
256 /* BCH nibbles for diff bch levels */
257 #define NAND_ECC_HW_BCH ((uint8_t)(NAND_ECC_HW_OOB_FIRST) + 1)
258 #define ECC_BCH4_NIBBLES        13
259 #define ECC_BCH8_NIBBLES        26
260 #define ECC_BCH16_NIBBLES       52
261
262 static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
263
264 static struct nand_bch_priv bch_priv = {
265         .mode = NAND_ECC_HW_BCH,
266         .type = ECC_BCH8,
267         .nibbles = ECC_BCH8_NIBBLES
268 };
269
270 /*
271  * omap_read_bch8_result - Read BCH result for BCH8 level
272  *
273  * @mtd:        MTD device structure
274  * @big_endian: When set read register 3 first
275  * @ecc_code:   Read syndrome from BCH result registers
276  */
277 static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
278                                 uint8_t *ecc_code)
279 {
280         uint32_t *ptr;
281         int8_t i = 0, j;
282
283         if (big_endian) {
284                 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
285                 ecc_code[i++] = readl(ptr) & 0xFF;
286                 ptr--;
287                 for (j = 0; j < 3; j++) {
288                         ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
289                         ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
290                         ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
291                         ecc_code[i++] = readl(ptr) & 0xFF;
292                         ptr--;
293                 }
294         } else {
295                 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[0];
296                 for (j = 0; j < 3; j++) {
297                         ecc_code[i++] = readl(ptr) & 0xFF;
298                         ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
299                         ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
300                         ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
301                         ptr++;
302                 }
303                 ecc_code[i++] = readl(ptr) & 0xFF;
304                 ecc_code[i++] = 0;      /* 14th byte is always zero */
305         }
306 }
307
308 /*
309  * omap_ecc_disable - Disable H/W ECC calculation
310  *
311  * @mtd:        MTD device structure
312  *
313  */
314 static void omap_ecc_disable(struct mtd_info *mtd)
315 {
316         writel((readl(&gpmc_cfg->ecc_config) & ~0x1),
317                 &gpmc_cfg->ecc_config);
318 }
319
320 /*
321  * omap_rotate_ecc_bch - Rotate the syndrome bytes
322  *
323  * @mtd:        MTD device structure
324  * @calc_ecc:   ECC read from ECC registers
325  * @syndrome:   Rotated syndrome will be retuned in this array
326  *
327  */
328 static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
329                 uint8_t *syndrome)
330 {
331         struct nand_chip *chip = mtd->priv;
332         struct nand_bch_priv *bch = chip->priv;
333         uint8_t n_bytes = 0;
334         int8_t i, j;
335
336         switch (bch->type) {
337         case ECC_BCH4:
338                 n_bytes = 8;
339                 break;
340
341         case ECC_BCH16:
342                 n_bytes = 28;
343                 break;
344
345         case ECC_BCH8:
346         default:
347                 n_bytes = 13;
348                 break;
349         }
350
351         for (i = 0, j = (n_bytes-1); i < n_bytes; i++, j--)
352                 syndrome[i] =  calc_ecc[j];
353 }
354
355 /*
356  *  omap_calculate_ecc_bch - Read BCH ECC result
357  *
358  *  @mtd:       MTD structure
359  *  @dat:       unused
360  *  @ecc_code:  ecc_code buffer
361  */
362 static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
363                                 uint8_t *ecc_code)
364 {
365         struct nand_chip *chip = mtd->priv;
366         struct nand_bch_priv *bch = chip->priv;
367         uint8_t big_endian = 1;
368         int8_t ret = 0;
369
370         if (bch->type == ECC_BCH8)
371                 omap_read_bch8_result(mtd, big_endian, ecc_code);
372         else /* BCH4 and BCH16 currently not supported */
373                 ret = -1;
374
375         /*
376          * Stop reading anymore ECC vals and clear old results
377          * enable will be called if more reads are required
378          */
379         omap_ecc_disable(mtd);
380
381         return ret;
382 }
383
384 /*
385  * omap_fix_errors_bch - Correct bch error in the data
386  *
387  * @mtd:        MTD device structure
388  * @data:       Data read from flash
389  * @error_count:Number of errors in data
390  * @error_loc:  Locations of errors in the data
391  *
392  */
393 static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
394                 uint32_t error_count, uint32_t *error_loc)
395 {
396         struct nand_chip *chip = mtd->priv;
397         struct nand_bch_priv *bch = chip->priv;
398         uint8_t count = 0;
399         uint32_t error_byte_pos;
400         uint32_t error_bit_mask;
401         uint32_t last_bit = (bch->nibbles * 4) - 1;
402
403         /* Flip all bits as specified by the error location array. */
404         /* FOR( each found error location flip the bit ) */
405         for (count = 0; count < error_count; count++) {
406                 if (error_loc[count] > last_bit) {
407                         /* Remove the ECC spare bits from correction. */
408                         error_loc[count] -= (last_bit + 1);
409                         /* Offset bit in data region */
410                         error_byte_pos = ((512 * 8) -
411                                         (error_loc[count]) - 1) / 8;
412                         /* Error Bit mask */
413                         error_bit_mask = 0x1 << (error_loc[count] % 8);
414                         /* Toggle the error bit to make the correction. */
415                         data[error_byte_pos] ^= error_bit_mask;
416                 }
417         }
418 }
419
420 /*
421  * omap_correct_data_bch - Compares the ecc read from nand spare area
422  * with ECC registers values and corrects one bit error if it has occured
423  *
424  * @mtd:        MTD device structure
425  * @dat:        page data
426  * @read_ecc:   ecc read from nand flash (ignored)
427  * @calc_ecc:   ecc read from ECC registers
428  *
429  * @return 0 if data is OK or corrected, else returns -1
430  */
431 static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
432                                 uint8_t *read_ecc, uint8_t *calc_ecc)
433 {
434         struct nand_chip *chip = mtd->priv;
435         struct nand_bch_priv *bch = chip->priv;
436         uint8_t syndrome[28];
437         uint32_t error_count = 0;
438         uint32_t error_loc[8];
439         uint32_t i, ecc_flag;
440
441         ecc_flag = 0;
442         for (i = 0; i < chip->ecc.bytes; i++)
443                 if (read_ecc[i] != 0xff)
444                         ecc_flag = 1;
445
446         if (!ecc_flag)
447                 return 0;
448
449         elm_reset();
450         elm_config((enum bch_level)(bch->type));
451
452         /*
453          * while reading ECC result we read it in big endian.
454          * Hence while loading to ELM we have rotate to get the right endian.
455          */
456         omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
457
458         /* use elm module to check for errors */
459         if (elm_check_error(syndrome, bch->nibbles, &error_count,
460                                 error_loc) != 0) {
461                 printf("ECC: uncorrectable.\n");
462                 return -1;
463         }
464
465         /* correct bch error */
466         if (error_count > 0)
467                 omap_fix_errors_bch(mtd, dat, error_count, error_loc);
468
469         return 0;
470 }
471 /*
472  * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
473  *                              GPMC controller
474  * @mtd:       MTD device structure
475  * @mode:       Read/Write mode
476  */
477 static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
478 {
479         uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
480         uint32_t unused_length = 0;
481         struct nand_bch_priv *bch = chip->priv;
482
483         switch (bch->nibbles) {
484         case ECC_BCH4_NIBBLES:
485                 unused_length = 3;
486                 break;
487         case ECC_BCH8_NIBBLES:
488                 unused_length = 2;
489                 break;
490         case ECC_BCH16_NIBBLES:
491                 unused_length = 0;
492                 break;
493         }
494
495         /* Clear the ecc result registers, select ecc reg as 1 */
496         writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
497
498         switch (mode) {
499         case NAND_ECC_WRITE:
500                 /* eccsize1 config */
501                 val = ((unused_length + bch->nibbles) << 22);
502                 break;
503
504         case NAND_ECC_READ:
505         default:
506                 /* by default eccsize0 selected for ecc1resultsize */
507                 /* eccsize0 config */
508                 val  = (bch->nibbles << 12);
509                 /* eccsize1 config */
510                 val |= (unused_length << 22);
511                 break;
512         }
513         /* ecc size configuration */
514         writel(val, &gpmc_cfg->ecc_size_config);
515         /* by default 512bytes sector page is selected */
516         /* set bch mode */
517         val  = (1 << 16);
518         /* bch4 / bch8 / bch16 */
519         val |= (bch->type << 12);
520         /* set wrap mode to 1 */
521         val |= (1 << 8);
522         val |= (dev_width << 7);
523         val |= (cs << 1);
524         writel(val, &gpmc_cfg->ecc_config);
525 }
526
527 /*
528  * omap_enable_ecc_bch- This function enables the bch h/w ecc functionality
529  * @mtd:        MTD device structure
530  * @mode:       Read/Write mode
531  *
532  */
533 static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
534 {
535         struct nand_chip *chip = mtd->priv;
536
537         omap_hwecc_init_bch(chip, mode);
538         /* enable ecc */
539         writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config);
540 }
541
542 /**
543  * omap_read_page_bch - hardware ecc based page read function
544  * @mtd:        mtd info structure
545  * @chip:       nand chip info structure
546  * @buf:        buffer to store read data
547  * @page:       page number to read
548  *
549  */
550 static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
551                                 uint8_t *buf, int page)
552 {
553         int i, eccsize = chip->ecc.size;
554         int eccbytes = chip->ecc.bytes;
555         int eccsteps = chip->ecc.steps;
556         uint8_t *p = buf;
557         uint8_t *ecc_calc = chip->buffers->ecccalc;
558         uint8_t *ecc_code = chip->buffers->ecccode;
559         uint32_t *eccpos = chip->ecc.layout->eccpos;
560         uint8_t *oob = chip->oob_poi;
561         uint32_t data_pos;
562         uint32_t oob_pos;
563
564         data_pos = 0;
565         /* oob area start */
566         oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
567         oob += chip->ecc.layout->eccpos[0];
568
569         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
570                                 oob += eccbytes) {
571                 chip->ecc.hwctl(mtd, NAND_ECC_READ);
572                 /* read data */
573                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
574                 chip->read_buf(mtd, p, eccsize);
575
576                 /* read respective ecc from oob area */
577                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
578                 chip->read_buf(mtd, oob, eccbytes);
579                 /* read syndrome */
580                 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
581
582                 data_pos += eccsize;
583                 oob_pos += eccbytes;
584         }
585
586         for (i = 0; i < chip->ecc.total; i++)
587                 ecc_code[i] = chip->oob_poi[eccpos[i]];
588
589         eccsteps = chip->ecc.steps;
590         p = buf;
591
592         for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
593                 int stat;
594
595                 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
596                 if (stat < 0)
597                         mtd->ecc_stats.failed++;
598                 else
599                         mtd->ecc_stats.corrected += stat;
600         }
601         return 0;
602 }
603 #endif /* CONFIG_AM33XX */
604
605 #ifndef CONFIG_SPL_BUILD
606 /*
607  * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
608  * The default is to come up on s/w ecc
609  *
610  * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
611  *
612  */
613 void omap_nand_switch_ecc(int32_t hardware)
614 {
615         struct nand_chip *nand;
616         struct mtd_info *mtd;
617
618         if (nand_curr_device < 0 ||
619             nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
620             !nand_info[nand_curr_device].name) {
621                 printf("Error: Can't switch ecc, no devices available\n");
622                 return;
623         }
624
625         mtd = &nand_info[nand_curr_device];
626         nand = mtd->priv;
627
628         nand->options |= NAND_OWN_BUFFERS;
629
630         /* Reset ecc interface */
631         nand->ecc.read_page = NULL;
632         nand->ecc.write_page = NULL;
633         nand->ecc.read_oob = NULL;
634         nand->ecc.write_oob = NULL;
635         nand->ecc.hwctl = NULL;
636         nand->ecc.correct = NULL;
637         nand->ecc.calculate = NULL;
638
639         /* Setup the ecc configurations again */
640         if (hardware == 1) {
641                 nand->ecc.mode = NAND_ECC_HW;
642                 nand->ecc.layout = &hw_nand_oob;
643                 nand->ecc.size = 512;
644                 nand->ecc.bytes = 3;
645                 nand->ecc.hwctl = omap_enable_hwecc;
646                 nand->ecc.correct = omap_correct_data;
647                 nand->ecc.calculate = omap_calculate_ecc;
648                 omap_hwecc_init(nand);
649                 printf("HW ECC selected\n");
650 #ifdef CONFIG_AM33XX
651         } else if (hardware == 2) {
652                 nand->ecc.mode = NAND_ECC_HW;
653                 nand->ecc.layout = &hw_bch8_nand_oob;
654                 nand->ecc.size = 512;
655                 nand->ecc.bytes = 14;
656                 nand->ecc.read_page = omap_read_page_bch;
657                 nand->ecc.hwctl = omap_enable_ecc_bch;
658                 nand->ecc.correct = omap_correct_data_bch;
659                 nand->ecc.calculate = omap_calculate_ecc_bch;
660                 omap_hwecc_init_bch(nand, NAND_ECC_READ);
661                 printf("HW BCH8 selected\n");
662 #endif
663         } else {
664                 nand->ecc.mode = NAND_ECC_SOFT;
665                 /* Use mtd default settings */
666                 nand->ecc.layout = NULL;
667                 nand->ecc.size = 0;
668                 printf("SW ECC selected\n");
669         }
670
671         /* Update NAND handling after ECC mode switch */
672         nand_scan_tail(mtd);
673
674         nand->options &= ~NAND_OWN_BUFFERS;
675 }
676 #endif /* CONFIG_SPL_BUILD */
677
678 /*
679  * Board-specific NAND initialization. The following members of the
680  * argument are board-specific:
681  * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
682  * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
683  * - cmd_ctrl: hardwarespecific function for accesing control-lines
684  * - waitfunc: hardwarespecific function for accesing device ready/busy line
685  * - ecc.hwctl: function to enable (reset) hardware ecc generator
686  * - ecc.mode: mode of ecc, see defines
687  * - chip_delay: chip dependent delay for transfering data from array to
688  *   read regs (tR)
689  * - options: various chip options. They can partly be set to inform
690  *   nand_scan about special functionality. See the defines for further
691  *   explanation
692  */
693 int board_nand_init(struct nand_chip *nand)
694 {
695         int32_t gpmc_config = 0;
696         cs = 0;
697
698         /*
699          * xloader/Uboot's gpmc configuration would have configured GPMC for
700          * nand type of memory. The following logic scans and latches on to the
701          * first CS with NAND type memory.
702          * TBD: need to make this logic generic to handle multiple CS NAND
703          * devices.
704          */
705         while (cs < GPMC_MAX_CS) {
706                 /* Check if NAND type is set */
707                 if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
708                         /* Found it!! */
709                         break;
710                 }
711                 cs++;
712         }
713         if (cs >= GPMC_MAX_CS) {
714                 printf("NAND: Unable to find NAND settings in "
715                         "GPMC Configuration - quitting\n");
716                 return -ENODEV;
717         }
718
719         gpmc_config = readl(&gpmc_cfg->config);
720         /* Disable Write protect */
721         gpmc_config |= 0x10;
722         writel(gpmc_config, &gpmc_cfg->config);
723
724         nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
725         nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
726
727         nand->cmd_ctrl = omap_nand_hwcontrol;
728         nand->options = NAND_NO_PADDING | NAND_CACHEPRG | NAND_NO_AUTOINCR;
729         /* If we are 16 bit dev, our gpmc config tells us that */
730         if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
731                 nand->options |= NAND_BUSWIDTH_16;
732
733         nand->chip_delay = 100;
734
735 #ifdef CONFIG_AM33XX
736         /* required in case of BCH */
737         elm_init();
738
739         /* BCH info that will be correct for SPL or overridden otherwise. */
740         nand->priv = &bch_priv;
741 #endif
742
743         /* Default ECC mode */
744 #ifdef CONFIG_AM33XX
745         nand->ecc.mode = NAND_ECC_HW;
746         nand->ecc.layout = &hw_bch8_nand_oob;
747         nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
748         nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
749         nand->ecc.hwctl = omap_enable_ecc_bch;
750         nand->ecc.correct = omap_correct_data_bch;
751         nand->ecc.calculate = omap_calculate_ecc_bch;
752         nand->ecc.read_page = omap_read_page_bch;
753         omap_hwecc_init_bch(nand, NAND_ECC_READ);
754 #else
755 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
756         nand->ecc.mode = NAND_ECC_SOFT;
757 #else
758         nand->ecc.mode = NAND_ECC_HW;
759         nand->ecc.layout = &hw_nand_oob;
760         nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
761         nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
762         nand->ecc.hwctl = omap_enable_hwecc;
763         nand->ecc.correct = omap_correct_data;
764         nand->ecc.calculate = omap_calculate_ecc;
765         omap_hwecc_init(nand);
766 #endif
767 #endif
768
769 #ifdef CONFIG_SPL_BUILD
770         if (nand->options & NAND_BUSWIDTH_16)
771                 nand->read_buf = nand_read_buf16;
772         else
773                 nand->read_buf = nand_read_buf;
774         nand->dev_ready = omap_spl_dev_ready;
775 #endif
776
777         return 0;
778 }