2 * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
3 * Rohit Choraria <rohitkc@ti.com>
5 * SPDX-License-Identifier: GPL-2.0+
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>
19 #include <asm/arch/elm.h>
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;
29 * omap_nand_hwcontrol - Set the address pointers corretly for the
30 * following address/data/command operation
32 static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
35 register struct nand_chip *this = mtd->priv;
38 * Point the IO_ADDR to DATA and ADDRESS registers instead
42 case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
43 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
45 case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
46 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
48 case NAND_CTRL_CHANGE | NAND_NCE:
49 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
53 if (cmd != NAND_CMD_NONE)
54 writeb(cmd, this->IO_ADDR_W);
57 #ifdef CONFIG_SPL_BUILD
58 /* Check wait pin as dev ready indicator */
59 int omap_spl_dev_ready(struct mtd_info *mtd)
61 return gpmc_cfg->status & (1 << 8);
66 * omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
68 * @mtd: MTD device structure
71 static void __maybe_unused omap_hwecc_init(struct nand_chip *chip)
74 * Init ECC Control Register
75 * Clear all ECC | Enable Reg1
77 writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
78 writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL, &gpmc_cfg->ecc_size_config);
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
85 * @ecc_buf: buffer to store ecc code
87 * @return: re-formatted ECC value
89 static uint32_t gen_true_ecc(uint8_t *ecc_buf)
91 return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
92 ((ecc_buf[2] & 0x0F) << 8);
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
102 * @mtd: MTD device structure
104 * @read_ecc: ecc read from nand flash
105 * @calc_ecc: ecc read from ECC registers
107 * @return 0 if data is OK or corrected, else returns -1
109 static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
110 uint8_t *read_ecc, uint8_t *calc_ecc)
112 uint32_t orig_ecc, new_ecc, res, hm;
113 uint16_t parity_bits, byte;
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;
122 /* Get the hamming width */
124 /* Single bit errors can be corrected! */
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 */
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!
150 if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
152 printf("Error: Bad compare! failed\n");
153 /* detected 2 bit error */
161 * omap_calculate_ecc - Generate non-inverted ECC bytes.
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
173 * @ecc_code: ecc_code buffer
175 static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
176 const uint8_t *dat, uint8_t *ecc_code)
180 /* Start Reading from HW ECC1_Result = 0x200 */
181 val = readl(&gpmc_cfg->ecc1_result);
183 ecc_code[0] = val & 0xFF;
184 ecc_code[1] = (val >> 16) & 0xFF;
185 ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
188 * Stop reading anymore ECC vals and clear old results
189 * enable will be called if more reads are required
191 writel(0x000, &gpmc_cfg->ecc_config);
197 * omap_enable_ecc - This function enables the hardware ecc functionality
198 * @mtd: MTD device structure
199 * @mode: Read/Write mode
201 static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
203 struct nand_chip *chip = mtd->priv;
204 uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
209 /* Clear the ecc result registers, select ecc reg as 1 */
210 writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
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
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);
223 printf("Error: Unrecognized Mode[%d]!\n", mode);
229 * Generic BCH interface
231 struct nand_bch_priv {
235 struct bch_control *control;
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 */
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
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
257 * When some users with other BCH strength will exists this have to change!
259 static __maybe_unused struct nand_bch_priv bch_priv = {
260 .mode = NAND_ECC_HW_BCH,
262 .nibbles = ECC_BCH8_NIBBLES,
267 * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
269 * @mtd: MTD device structure
270 * @mode: Read/Write mode
273 static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
276 uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
278 uint32_t unused_length = 0;
280 uint32_t wr_mode = BCH_WRAPMODE_6;
281 struct nand_bch_priv *bch = chip->priv;
283 /* Clear the ecc result registers, select ecc reg as 1 */
284 writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
287 wr_mode = BCH_WRAPMODE_1;
289 switch (bch->nibbles) {
290 case ECC_BCH4_NIBBLES:
293 case ECC_BCH8_NIBBLES:
296 case ECC_BCH16_NIBBLES:
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.
308 /* write access only setup eccsize1 config */
309 val = ((unused_length + bch->nibbles) << 22);
315 * by default eccsize0 selected for ecc1resultsize
318 val = (bch->nibbles << 12);
319 /* eccsize1 config */
320 val |= (unused_length << 22);
325 * This ecc_size_config setting is for BCH sw library.
327 * Note: we only support BCH8 currently with BCH sw library!
328 * Should be really easy to adobt to BCH4, however some omap3 have
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)
335 val = (32 << 22) | (0 << 12);
337 /* ecc size configuration */
338 writel(val, &gpmc_cfg->ecc_size_config);
341 * Configure the ecc engine in gpmc
342 * We assume 512 Byte sector pages for access to NAND.
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);
354 * omap_enable_ecc_bch - This function enables the bch h/w ecc functionality
355 * @mtd: MTD device structure
356 * @mode: Read/Write mode
359 static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
361 struct nand_chip *chip = mtd->priv;
363 omap_hwecc_init_bch(chip, mode);
365 writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config);
369 * omap_ecc_disable - Disable H/W ECC calculation
371 * @mtd: MTD device structure
373 static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
375 writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
379 * BCH8 support (needs ELM and thus AM33xx-only)
383 * omap_read_bch8_result - Read BCH result for BCH8 level
385 * @mtd: MTD device structure
386 * @big_endian: When set read register 3 first
387 * @ecc_code: Read syndrome from BCH result registers
389 static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
396 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
397 ecc_code[i++] = readl(ptr) & 0xFF;
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;
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;
415 ecc_code[i++] = readl(ptr) & 0xFF;
416 ecc_code[i++] = 0; /* 14th byte is always zero */
421 * omap_rotate_ecc_bch - Rotate the syndrome bytes
423 * @mtd: MTD device structure
424 * @calc_ecc: ECC read from ECC registers
425 * @syndrome: Rotated syndrome will be retuned in this array
428 static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
431 struct nand_chip *chip = mtd->priv;
432 struct nand_bch_priv *bch = chip->priv;
451 for (i = 0, j = (n_bytes-1); i < n_bytes; i++, j--)
452 syndrome[i] = calc_ecc[j];
456 * omap_calculate_ecc_bch - Read BCH ECC result
458 * @mtd: MTD structure
460 * @ecc_code: ecc_code buffer
462 static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
465 struct nand_chip *chip = mtd->priv;
466 struct nand_bch_priv *bch = chip->priv;
467 uint8_t big_endian = 1;
470 if (bch->type == ECC_BCH8)
471 omap_read_bch8_result(mtd, big_endian, ecc_code);
472 else /* BCH4 and BCH16 currently not supported */
476 * Stop reading anymore ECC vals and clear old results
477 * enable will be called if more reads are required
479 omap_ecc_disable(mtd);
485 * omap_fix_errors_bch - Correct bch error in the data
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
493 static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
494 uint32_t error_count, uint32_t *error_loc)
496 struct nand_chip *chip = mtd->priv;
497 struct nand_bch_priv *bch = chip->priv;
499 uint32_t error_byte_pos;
500 uint32_t error_bit_mask;
501 uint32_t last_bit = (bch->nibbles * 4) - 1;
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;
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;
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
524 * @mtd: MTD device structure
526 * @read_ecc: ecc read from nand flash (ignored)
527 * @calc_ecc: ecc read from ECC registers
529 * @return 0 if data is OK or corrected, else returns -1
531 static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
532 uint8_t *read_ecc, uint8_t *calc_ecc)
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;
542 for (i = 0; i < chip->ecc.bytes; i++)
543 if (read_ecc[i] != 0xff)
550 elm_config((enum bch_level)(bch->type));
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.
556 omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
558 /* use elm module to check for errors */
559 if (elm_check_error(syndrome, bch->nibbles, &error_count,
561 printf("ECC: uncorrectable.\n");
565 /* correct bch error */
567 omap_fix_errors_bch(mtd, dat, error_count, error_loc);
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
581 static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
582 uint8_t *buf, int oob_required, int page)
584 int i, eccsize = chip->ecc.size;
585 int eccbytes = chip->ecc.bytes;
586 int eccsteps = chip->ecc.steps;
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;
597 oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
598 oob += chip->ecc.layout->eccpos[0];
600 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
602 chip->ecc.hwctl(mtd, NAND_ECC_READ);
604 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
605 chip->read_buf(mtd, p, eccsize);
607 /* read respective ecc from oob area */
608 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
609 chip->read_buf(mtd, oob, eccbytes);
611 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
617 for (i = 0; i < chip->ecc.total; i++)
618 ecc_code[i] = chip->oob_poi[eccpos[i]];
620 eccsteps = chip->ecc.steps;
623 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
626 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
628 mtd->ecc_stats.failed++;
630 mtd->ecc_stats.corrected += stat;
634 #endif /* CONFIG_AM33XX */
637 * OMAP3 BCH8 support (with BCH library)
639 #ifdef CONFIG_NAND_OMAP_BCH8
641 * omap_calculate_ecc_bch - Read BCH ECC result
643 * @mtd: MTD device structure
644 * @dat: The pointer to data on which ecc is computed (unused here)
645 * @ecc: The ECC output buffer
647 static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
652 unsigned long nsectors, val1, val2, val3, val4;
654 nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
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]);
664 * Add constant polynomial to remainder, in order to get an ecc
665 * sequence of 0xFFs for a buffer filled with 0xFFs.
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);
683 * Stop reading anymore ECC vals and clear old results
684 * enable will be called if more reads are required
686 omap_ecc_disable(mtd);
692 * omap_correct_data_bch - Decode received data and correct errors
693 * @mtd: MTD device structure
695 * @read_ecc: ecc read from nand flash
696 * @calc_ecc: ecc read from HW ECC registers
698 static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
699 u_char *read_ecc, u_char *calc_ecc)
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;
708 count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
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]);
719 * BCH8 have 13 bytes of ECC; BCH4 needs adoption
722 for (i = 0; i < 13; i++)
723 printf("%02x ", read_ecc[i]);
726 for (i = 0; i < 13; i++)
727 printf("%02x ", calc_ecc[i]);
731 } else if (count < 0) {
732 puts("ecc unrecoverable error\n");
738 * omap_free_bch - Release BCH ecc resources
739 * @mtd: MTD device structure
741 static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
743 struct nand_chip *chip = mtd->priv;
744 struct nand_bch_priv *chip_priv = chip->priv;
745 struct bch_control *bch = NULL;
748 bch = chip_priv->control;
752 chip_priv->control = NULL;
755 #endif /* CONFIG_NAND_OMAP_BCH8 */
757 #ifndef CONFIG_SPL_BUILD
759 * omap_nand_switch_ecc - switch the ECC operation between different engines
760 * (h/w and s/w) and different algorithms (hamming and BCHx)
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)
766 void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
768 struct nand_chip *nand;
769 struct mtd_info *mtd;
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");
778 mtd = &nand_info[nand_curr_device];
781 nand->options |= NAND_OWN_BUFFERS;
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;
794 /* Setup the ecc configurations again */
796 if (eccstrength == 1) {
797 nand->ecc.mode = NAND_ECC_HW;
798 nand->ecc.layout = &hw_nand_oob;
799 nand->ecc.size = 512;
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");
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;
813 nand->ecc.bytes = 14;
814 nand->ecc.read_page = omap_read_page_bch;
816 nand->ecc.bytes = 13;
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");
826 nand->ecc.mode = NAND_ECC_SOFT;
827 /* Use mtd default settings */
828 nand->ecc.layout = NULL;
830 printf("SW ECC selected\n");
833 /* Update NAND handling after ECC mode switch */
836 nand->options &= ~NAND_OWN_BUFFERS;
838 #endif /* CONFIG_SPL_BUILD */
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
851 * - options: various chip options. They can partly be set to inform
852 * nand_scan about special functionality. See the defines for further
855 int board_nand_init(struct nand_chip *nand)
857 int32_t gpmc_config = 0;
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
867 while (cs < GPMC_MAX_CS) {
868 /* Check if NAND type is set */
869 if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
875 if (cs >= GPMC_MAX_CS) {
876 printf("NAND: Unable to find NAND settings in "
877 "GPMC Configuration - quitting\n");
881 gpmc_config = readl(&gpmc_cfg->config);
882 /* Disable Write protect */
884 writel(gpmc_config, &gpmc_cfg->config);
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;
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;
895 nand->chip_delay = 100;
897 #if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
899 /* AM33xx uses the ELM */
900 /* required in case of BCH */
904 * Whereas other OMAP based SoC do not have the ELM, they use the BCH
907 bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */);
908 if (!bch_priv.control) {
909 puts("Could not init_bch()\n");
913 /* BCH info that will be correct for SPL or overridden otherwise. */
914 nand->priv = &bch_priv;
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;
928 nand->ecc.read_page = omap_read_page_bch;
930 omap_hwecc_init_bch(nand, NAND_ECC_READ);
932 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
933 nand->ecc.mode = NAND_ECC_SOFT;
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);
947 #ifdef CONFIG_SPL_BUILD
948 if (nand->options & NAND_BUSWIDTH_16)
949 nand->read_buf = nand_read_buf16;
951 nand->read_buf = nand_read_buf;
952 nand->dev_ready = omap_spl_dev_ready;