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
;