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 <linux/mtd/omap_gpmc.h>
13
#include <linux/mtd/nand_ecc.h>
14
#include <linux/bch.h>
15
#include <linux/compiler.h>
17
#include <linux/mtd/omap_elm.h>
19
#define BADBLOCK_MARKER_LENGTH 2
20
#define SECTOR_BYTES 512
21
#define ECCCLEAR (0x1 << 8)
22
#define ECCRESULTREG1 (0x1 << 0)
23
/* 4 bit padding to make byte aligned, 56 = 52 + 4 */
24
#define BCH4_BIT_PAD 4
27
static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
28
0x97, 0x79, 0xe5, 0x24, 0xb5};
31
static __maybe_unused struct nand_ecclayout omap_ecclayout;
34
* omap_nand_hwcontrol - Set the address pointers corretly for the
35
* following address/data/command operation
37
static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
40
register struct nand_chip *this = mtd->priv;
43
* Point the IO_ADDR to DATA and ADDRESS registers instead
47
case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
48
this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
50
case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
51
this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
53
case NAND_CTRL_CHANGE | NAND_NCE:
54
this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
58
if (cmd != NAND_CMD_NONE)
59
writeb(cmd, this->IO_ADDR_W);
62
#ifdef CONFIG_SPL_BUILD
63
/* Check wait pin as dev ready indicator */
64
int omap_spl_dev_ready(struct mtd_info *mtd)
66
return gpmc_cfg->status & (1 << 8);
72
* gen_true_ecc - This function will generate true ECC value, which
73
* can be used when correcting data read from NAND flash memory core
75
* @ecc_buf: buffer to store ecc code
77
* @return: re-formatted ECC value
79
static uint32_t gen_true_ecc(uint8_t *ecc_buf)
81
return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
82
((ecc_buf[2] & 0x0F) << 8);
86
* omap_correct_data - Compares the ecc read from nand spare area with ECC
87
* registers values and corrects one bit error if it has occured
88
* Further details can be had from OMAP TRM and the following selected links:
89
* http://en.wikipedia.org/wiki/Hamming_code
90
* http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
92
* @mtd: MTD device structure
94
* @read_ecc: ecc read from nand flash
95
* @calc_ecc: ecc read from ECC registers
97
* @return 0 if data is OK or corrected, else returns -1
99
static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
100
uint8_t *read_ecc, uint8_t *calc_ecc)
102
uint32_t orig_ecc, new_ecc, res, hm;
103
uint16_t parity_bits, byte;
106
/* Regenerate the orginal ECC */
107
orig_ecc = gen_true_ecc(read_ecc);
108
new_ecc = gen_true_ecc(calc_ecc);
109
/* Get the XOR of real ecc */
110
res = orig_ecc ^ new_ecc;
112
/* Get the hamming width */
114
/* Single bit errors can be corrected! */
116
/* Correctable data! */
117
parity_bits = res >> 16;
118
bit = (parity_bits & 0x7);
119
byte = (parity_bits >> 3) & 0x1FF;
120
/* Flip the bit to correct */
121
dat[byte] ^= (0x1 << bit);
122
} else if (hm == 1) {
123
printf("Error: Ecc is wrong\n");
124
/* ECC itself is corrupted */
128
* hm distance != parity pairs OR one, could mean 2 bit
129
* error OR potentially be on a blank page..
130
* orig_ecc: contains spare area data from nand flash.
131
* new_ecc: generated ecc while reading data area.
132
* Note: if the ecc = 0, all data bits from which it was
133
* generated are 0xFF.
134
* The 3 byte(24 bits) ecc is generated per 512byte
135
* chunk of a page. If orig_ecc(from spare area)
136
* is 0xFF && new_ecc(computed now from data area)=0x0,
137
* this means that data area is 0xFF and spare area is
138
* 0xFF. A sure sign of a erased page!
140
if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
142
printf("Error: Bad compare! failed\n");
143
/* detected 2 bit error */
151
* Generic BCH interface
153
struct nand_bch_priv {
157
struct bch_control *control;
158
enum omap_ecc ecc_scheme;
166
/* BCH nibbles for diff bch levels */
167
#define ECC_BCH4_NIBBLES 13
168
#define ECC_BCH8_NIBBLES 26
169
#define ECC_BCH16_NIBBLES 52
172
* This can be a single instance cause all current users have only one NAND
173
* with nearly the same setup (BCH8, some with ELM and others with sw BCH
175
* When some users with other BCH strength will exists this have to change!
177
static __maybe_unused struct nand_bch_priv bch_priv = {
179
.nibbles = ECC_BCH8_NIBBLES,
184
* omap_reverse_list - re-orders list elements in reverse order [internal]
185
* @list: pointer to start of list
186
* @length: length of list
188
void omap_reverse_list(u8 *list, unsigned int length)
191
unsigned int half_length = length / 2;
193
for (i = 0, j = length - 1; i < half_length; i++, j--) {
201
* omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
202
* @mtd: MTD device structure
203
* @mode: Read/Write mode
206
static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
208
struct nand_chip *nand = mtd->priv;
209
struct nand_bch_priv *bch = nand->priv;
210
unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
211
unsigned int ecc_algo = 0;
212
unsigned int bch_type = 0;
213
unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
214
u32 ecc_size_config_val = 0;
215
u32 ecc_config_val = 0;
217
/* configure GPMC for specific ecc-scheme */
218
switch (bch->ecc_scheme) {
219
case OMAP_ECC_HAM1_CODE_SW:
221
case OMAP_ECC_HAM1_CODE_HW:
228
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
229
case OMAP_ECC_BCH8_CODE_HW:
232
if (mode == NAND_ECC_WRITE) {
234
eccsize0 = 0; /* extra bits in nibbles per sector */
235
eccsize1 = 28; /* OOB bits in nibbles per sector */
238
eccsize0 = 26; /* ECC bits in nibbles per sector */
239
eccsize1 = 2; /* non-ECC bits in nibbles per sector */
245
/* Clear ecc and enable bits */
246
writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
247
/* Configure ecc size for BCH */
248
ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
249
writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
251
/* Configure device details for BCH engine */
252
ecc_config_val = ((ecc_algo << 16) | /* HAM1 | BCHx */
253
(bch_type << 12) | /* BCH4/BCH8/BCH16 */
254
(bch_wrapmode << 8) | /* wrap mode */
255
(dev_width << 7) | /* bus width */
256
(0x0 << 4) | /* number of sectors */
257
(cs << 1) | /* ECC CS */
258
(0x1)); /* enable ECC */
259
writel(ecc_config_val, &gpmc_cfg->ecc_config);
263
* omap_calculate_ecc - Read ECC result
264
* @mtd: MTD structure
266
* @ecc_code: ecc_code buffer
267
* Using noninverted ECC can be considered ugly since writing a blank
268
* page ie. padding will clear the ECC bytes. This is no problem as
269
* long nobody is trying to write data on the seemingly unused page.
270
* Reading an erased page will produce an ECC mismatch between
271
* generated and read ECC bytes that has to be dealt with separately.
272
* E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
273
* is used, the result of read will be 0x0 while the ECC offsets of the
274
* spare area will be 0xFF which will result in an ECC mismatch.
276
static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
279
struct nand_chip *chip = mtd->priv;
280
struct nand_bch_priv *bch = chip->priv;
281
uint32_t *ptr, val = 0;
284
switch (bch->ecc_scheme) {
285
case OMAP_ECC_HAM1_CODE_HW:
286
val = readl(&gpmc_cfg->ecc1_result);
287
ecc_code[0] = val & 0xFF;
288
ecc_code[1] = (val >> 16) & 0xFF;
289
ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
292
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
294
case OMAP_ECC_BCH8_CODE_HW:
295
ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
297
ecc_code[i++] = (val >> 0) & 0xFF;
299
for (j = 0; j < 3; j++) {
301
ecc_code[i++] = (val >> 24) & 0xFF;
302
ecc_code[i++] = (val >> 16) & 0xFF;
303
ecc_code[i++] = (val >> 8) & 0xFF;
304
ecc_code[i++] = (val >> 0) & 0xFF;
311
/* ECC scheme specific syndrome customizations */
312
switch (bch->ecc_scheme) {
313
case OMAP_ECC_HAM1_CODE_HW:
316
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
318
for (i = 0; i < chip->ecc.bytes; i++)
319
*(ecc_code + i) = *(ecc_code + i) ^
323
case OMAP_ECC_BCH8_CODE_HW:
324
ecc_code[chip->ecc.bytes - 1] = 0x00;
332
#ifdef CONFIG_NAND_OMAP_ELM
334
* omap_correct_data_bch - Compares the ecc read from nand spare area
335
* with ECC registers values and corrects one bit error if it has occured
337
* @mtd: MTD device structure
339
* @read_ecc: ecc read from nand flash (ignored)
340
* @calc_ecc: ecc read from ECC registers
342
* @return 0 if data is OK or corrected, else returns -1
344
static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
345
uint8_t *read_ecc, uint8_t *calc_ecc)
347
struct nand_chip *chip = mtd->priv;
348
struct nand_bch_priv *bch = chip->priv;
349
uint32_t eccbytes = chip->ecc.bytes;
350
uint32_t error_count = 0, error_max;
351
uint32_t error_loc[8];
352
uint32_t i, ecc_flag = 0;
353
uint8_t count, err = 0;
354
uint32_t byte_pos, bit_pos;
356
/* check calculated ecc */
357
for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
358
if (calc_ecc[i] != 0x00)
364
/* check for whether its a erased-page */
366
for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
367
if (read_ecc[i] != 0xff)
374
* while reading ECC result we read it in big endian.
375
* Hence while loading to ELM we have rotate to get the right endian.
377
switch (bch->ecc_scheme) {
378
case OMAP_ECC_BCH8_CODE_HW:
379
omap_reverse_list(calc_ecc, eccbytes - 1);
384
/* use elm module to check for errors */
385
elm_config((enum bch_level)(bch->type));
386
if (elm_check_error(calc_ecc, bch->nibbles, &error_count, error_loc)) {
387
printf("nand: error: uncorrectable ECC errors\n");
390
/* correct bch error */
391
for (count = 0; count < error_count; count++) {
394
/* 14th byte in ECC is reserved to match ROM layout */
395
error_max = SECTOR_BYTES + (eccbytes - 1);
400
byte_pos = error_max - (error_loc[count] / 8) - 1;
401
bit_pos = error_loc[count] % 8;
402
if (byte_pos < SECTOR_BYTES) {
403
dat[byte_pos] ^= 1 << bit_pos;
404
printf("nand: bit-flip corrected @data=%d\n", byte_pos);
405
} else if (byte_pos < error_max) {
406
read_ecc[byte_pos - SECTOR_BYTES] = 1 << bit_pos;
407
printf("nand: bit-flip corrected @oob=%d\n", byte_pos -
411
printf("nand: error: invalid bit-flip location\n");
414
return (err) ? err : error_count;
418
* omap_read_page_bch - hardware ecc based page read function
419
* @mtd: mtd info structure
420
* @chip: nand chip info structure
421
* @buf: buffer to store read data
422
* @oob_required: caller expects OOB data read to chip->oob_poi
423
* @page: page number to read
426
static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
427
uint8_t *buf, int oob_required, int page)
429
int i, eccsize = chip->ecc.size;
430
int eccbytes = chip->ecc.bytes;
431
int eccsteps = chip->ecc.steps;
433
uint8_t *ecc_calc = chip->buffers->ecccalc;
434
uint8_t *ecc_code = chip->buffers->ecccode;
435
uint32_t *eccpos = chip->ecc.layout->eccpos;
436
uint8_t *oob = chip->oob_poi;
442
oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
443
oob += chip->ecc.layout->eccpos[0];
445
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
447
chip->ecc.hwctl(mtd, NAND_ECC_READ);
449
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
450
chip->read_buf(mtd, p, eccsize);
452
/* read respective ecc from oob area */
453
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
454
chip->read_buf(mtd, oob, eccbytes);
456
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
462
for (i = 0; i < chip->ecc.total; i++)
463
ecc_code[i] = chip->oob_poi[eccpos[i]];
465
eccsteps = chip->ecc.steps;
468
for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
471
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
473
mtd->ecc_stats.failed++;
475
mtd->ecc_stats.corrected += stat;
479
#endif /* CONFIG_NAND_OMAP_ELM */
482
* OMAP3 BCH8 support (with BCH library)
486
* omap_correct_data_bch_sw - Decode received data and correct errors
487
* @mtd: MTD device structure
489
* @read_ecc: ecc read from nand flash
490
* @calc_ecc: ecc read from HW ECC registers
492
static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
493
u_char *read_ecc, u_char *calc_ecc)
496
/* cannot correct more than 8 errors */
497
unsigned int errloc[8];
498
struct nand_chip *chip = mtd->priv;
499
struct nand_bch_priv *chip_priv = chip->priv;
500
struct bch_control *bch = chip_priv->control;
502
count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
505
for (i = 0; i < count; i++) {
506
/* correct data only, not ecc bytes */
507
if (errloc[i] < 8*512)
508
data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
509
printf("corrected bitflip %u\n", errloc[i]);
513
* BCH8 have 13 bytes of ECC; BCH4 needs adoption
516
for (i = 0; i < 13; i++)
517
printf("%02x ", read_ecc[i]);
520
for (i = 0; i < 13; i++)
521
printf("%02x ", calc_ecc[i]);
525
} else if (count < 0) {
526
puts("ecc unrecoverable error\n");
532
* omap_free_bch - Release BCH ecc resources
533
* @mtd: MTD device structure
535
static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
537
struct nand_chip *chip = mtd->priv;
538
struct nand_bch_priv *chip_priv = chip->priv;
539
struct bch_control *bch = NULL;
542
bch = chip_priv->control;
546
chip_priv->control = NULL;
549
#endif /* CONFIG_BCH */
552
* omap_select_ecc_scheme - configures driver for particular ecc-scheme
553
* @nand: NAND chip device structure
554
* @ecc_scheme: ecc scheme to configure
555
* @pagesize: number of main-area bytes per page of NAND device
556
* @oobsize: number of OOB/spare bytes per page of NAND device
558
static int omap_select_ecc_scheme(struct nand_chip *nand,
559
enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
560
struct nand_bch_priv *bch = nand->priv;
561
struct nand_ecclayout *ecclayout = &omap_ecclayout;
562
int eccsteps = pagesize / SECTOR_BYTES;
565
switch (ecc_scheme) {
566
case OMAP_ECC_HAM1_CODE_SW:
567
debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
568
/* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
569
* initialized in nand_scan_tail(), so just set ecc.mode */
570
bch_priv.control = NULL;
572
nand->ecc.mode = NAND_ECC_SOFT;
573
nand->ecc.layout = NULL;
575
bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW;
578
case OMAP_ECC_HAM1_CODE_HW:
579
debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
580
/* check ecc-scheme requirements before updating ecc info */
581
if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
582
printf("nand: error: insufficient OOB: require=%d\n", (
583
(3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
586
bch_priv.control = NULL;
588
/* populate ecc specific fields */
589
memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
590
nand->ecc.mode = NAND_ECC_HW;
591
nand->ecc.strength = 1;
592
nand->ecc.size = SECTOR_BYTES;
594
nand->ecc.hwctl = omap_enable_hwecc;
595
nand->ecc.correct = omap_correct_data;
596
nand->ecc.calculate = omap_calculate_ecc;
597
/* define ecc-layout */
598
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
599
for (i = 0; i < ecclayout->eccbytes; i++) {
600
if (nand->options & NAND_BUSWIDTH_16)
601
ecclayout->eccpos[i] = i + 2;
603
ecclayout->eccpos[i] = i + 1;
605
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
606
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
607
BADBLOCK_MARKER_LENGTH;
608
bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW;
611
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
613
debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
614
/* check ecc-scheme requirements before updating ecc info */
615
if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
616
printf("nand: error: insufficient OOB: require=%d\n", (
617
(13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
620
/* check if BCH S/W library can be used for error detection */
621
bch_priv.control = init_bch(13, 8, 0x201b);
622
if (!bch_priv.control) {
623
printf("nand: error: could not init_bch()\n");
626
bch_priv.type = ECC_BCH8;
627
/* populate ecc specific fields */
628
memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
629
nand->ecc.mode = NAND_ECC_HW;
630
nand->ecc.strength = 8;
631
nand->ecc.size = SECTOR_BYTES;
632
nand->ecc.bytes = 13;
633
nand->ecc.hwctl = omap_enable_hwecc;
634
nand->ecc.correct = omap_correct_data_bch_sw;
635
nand->ecc.calculate = omap_calculate_ecc;
636
/* define ecc-layout */
637
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
638
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
639
for (i = 1; i < ecclayout->eccbytes; i++) {
640
if (i % nand->ecc.bytes)
641
ecclayout->eccpos[i] =
642
ecclayout->eccpos[i - 1] + 1;
644
ecclayout->eccpos[i] =
645
ecclayout->eccpos[i - 1] + 2;
647
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
648
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
649
BADBLOCK_MARKER_LENGTH;
650
bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
653
printf("nand: error: CONFIG_BCH required for ECC\n");
657
case OMAP_ECC_BCH8_CODE_HW:
658
#ifdef CONFIG_NAND_OMAP_ELM
659
debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
660
/* check ecc-scheme requirements before updating ecc info */
661
if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
662
printf("nand: error: insufficient OOB: require=%d\n", (
663
(14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
666
/* intialize ELM for ECC error detection */
668
bch_priv.type = ECC_BCH8;
669
/* populate ecc specific fields */
670
memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
671
nand->ecc.mode = NAND_ECC_HW;
672
nand->ecc.strength = 8;
673
nand->ecc.size = SECTOR_BYTES;
674
nand->ecc.bytes = 14;
675
nand->ecc.hwctl = omap_enable_hwecc;
676
nand->ecc.correct = omap_correct_data_bch;
677
nand->ecc.calculate = omap_calculate_ecc;
678
nand->ecc.read_page = omap_read_page_bch;
679
/* define ecc-layout */
680
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
681
for (i = 0; i < ecclayout->eccbytes; i++)
682
ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
683
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
684
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
685
BADBLOCK_MARKER_LENGTH;
686
bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW;
689
printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
694
debug("nand: error: ecc scheme not enabled or supported\n");
698
/* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
699
if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
700
nand->ecc.layout = ecclayout;
705
#ifndef CONFIG_SPL_BUILD
707
* omap_nand_switch_ecc - switch the ECC operation between different engines
708
* (h/w and s/w) and different algorithms (hamming and BCHx)
710
* @hardware - true if one of the HW engines should be used
711
* @eccstrength - the number of bits that could be corrected
712
* (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
714
int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
716
struct nand_chip *nand;
717
struct mtd_info *mtd;
720
if (nand_curr_device < 0 ||
721
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
722
!nand_info[nand_curr_device].name) {
723
printf("nand: error: no NAND devices found\n");
727
mtd = &nand_info[nand_curr_device];
729
nand->options |= NAND_OWN_BUFFERS;
730
nand->options &= ~NAND_SUBPAGE_READ;
731
/* Setup the ecc configurations again */
733
if (eccstrength == 1) {
734
err = omap_select_ecc_scheme(nand,
735
OMAP_ECC_HAM1_CODE_HW,
736
mtd->writesize, mtd->oobsize);
737
} else if (eccstrength == 8) {
738
err = omap_select_ecc_scheme(nand,
739
OMAP_ECC_BCH8_CODE_HW,
740
mtd->writesize, mtd->oobsize);
742
printf("nand: error: unsupported ECC scheme\n");
746
err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
747
mtd->writesize, mtd->oobsize);
750
/* Update NAND handling after ECC mode switch */
752
err = nand_scan_tail(mtd);
755
#endif /* CONFIG_SPL_BUILD */
758
* Board-specific NAND initialization. The following members of the
759
* argument are board-specific:
760
* - IO_ADDR_R: address to read the 8 I/O lines of the flash device
761
* - IO_ADDR_W: address to write the 8 I/O lines of the flash device
762
* - cmd_ctrl: hardwarespecific function for accesing control-lines
763
* - waitfunc: hardwarespecific function for accesing device ready/busy line
764
* - ecc.hwctl: function to enable (reset) hardware ecc generator
765
* - ecc.mode: mode of ecc, see defines
766
* - chip_delay: chip dependent delay for transfering data from array to
768
* - options: various chip options. They can partly be set to inform
769
* nand_scan about special functionality. See the defines for further
772
int board_nand_init(struct nand_chip *nand)
774
int32_t gpmc_config = 0;
778
* xloader/Uboot's gpmc configuration would have configured GPMC for
779
* nand type of memory. The following logic scans and latches on to the
780
* first CS with NAND type memory.
781
* TBD: need to make this logic generic to handle multiple CS NAND
784
while (cs < GPMC_MAX_CS) {
785
/* Check if NAND type is set */
786
if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
792
if (cs >= GPMC_MAX_CS) {
793
printf("nand: error: Unable to find NAND settings in "
794
"GPMC Configuration - quitting\n");
798
gpmc_config = readl(&gpmc_cfg->config);
799
/* Disable Write protect */
801
writel(gpmc_config, &gpmc_cfg->config);
803
nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
804
nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
805
nand->priv = &bch_priv;
806
nand->cmd_ctrl = omap_nand_hwcontrol;
807
nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
808
/* If we are 16 bit dev, our gpmc config tells us that */
809
if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
810
nand->options |= NAND_BUSWIDTH_16;
812
nand->chip_delay = 100;
813
nand->ecc.layout = &omap_ecclayout;
815
/* select ECC scheme */
816
#if defined(CONFIG_NAND_OMAP_ECCSCHEME)
817
err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
818
CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
820
/* pagesize and oobsize are not required to configure sw ecc-scheme */
821
err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
827
#ifdef CONFIG_SPL_BUILD
828
if (nand->options & NAND_BUSWIDTH_16)
829
nand->read_buf = nand_read_buf16;
831
nand->read_buf = nand_read_buf;
832
nand->dev_ready = omap_spl_dev_ready;