1
2
3
4
5
6
7#include <common.h>
8#include <log.h>
9#include <asm/io.h>
10#include <linux/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/mtd/rawnand.h>
15#include <linux/bch.h>
16#include <linux/compiler.h>
17#include <nand.h>
18#include <linux/mtd/omap_elm.h>
19
20#define BADBLOCK_MARKER_LENGTH 2
21#define SECTOR_BYTES 512
22#define ECCCLEAR (0x1 << 8)
23#define ECCRESULTREG1 (0x1 << 0)
24
25#define BCH4_BIT_PAD 4
26
27#ifdef CONFIG_BCH
28static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
29 0x97, 0x79, 0xe5, 0x24, 0xb5};
30#endif
31static uint8_t cs_next;
32static __maybe_unused struct nand_ecclayout omap_ecclayout;
33
34#if defined(CONFIG_NAND_OMAP_GPMC_WSCFG)
35static const int8_t wscfg[CONFIG_SYS_MAX_NAND_DEVICE] =
36 { CONFIG_NAND_OMAP_GPMC_WSCFG };
37#else
38
39static const int8_t wscfg[CONFIG_SYS_MAX_NAND_DEVICE];
40#endif
41
42
43
44
45struct omap_nand_info {
46 struct bch_control *control;
47 enum omap_ecc ecc_scheme;
48 uint8_t cs;
49 uint8_t ws;
50};
51
52
53static struct omap_nand_info omap_nand_info[GPMC_MAX_CS];
54
55
56
57
58
59static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
60 uint32_t ctrl)
61{
62 register struct nand_chip *this = mtd_to_nand(mtd);
63 struct omap_nand_info *info = nand_get_controller_data(this);
64 int cs = info->cs;
65
66
67
68
69
70 switch (ctrl) {
71 case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
72 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
73 break;
74 case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
75 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
76 break;
77 case NAND_CTRL_CHANGE | NAND_NCE:
78 this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
79 break;
80 }
81
82 if (cmd != NAND_CMD_NONE)
83 writeb(cmd, this->IO_ADDR_W);
84}
85
86
87static int omap_dev_ready(struct mtd_info *mtd)
88{
89 register struct nand_chip *this = mtd_to_nand(mtd);
90 struct omap_nand_info *info = nand_get_controller_data(this);
91 return gpmc_cfg->status & (1 << (8 + info->ws));
92}
93
94
95
96
97
98
99
100
101
102static 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
110
111
112
113
114
115
116
117
118
119
120
121
122static 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
130 orig_ecc = gen_true_ecc(read_ecc);
131 new_ecc = gen_true_ecc(calc_ecc);
132
133 res = orig_ecc ^ new_ecc;
134 if (res) {
135
136 hm = hweight32(res);
137
138 if (hm == 12) {
139
140 parity_bits = res >> 16;
141 bit = (parity_bits & 0x7);
142 byte = (parity_bits >> 3) & 0x1FF;
143
144 dat[byte] ^= (0x1 << bit);
145 } else if (hm == 1) {
146 printf("Error: Ecc is wrong\n");
147
148 return 2;
149 } else {
150
151
152
153
154
155
156
157
158
159
160
161
162
163 if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
164 return 0;
165 printf("Error: Bad compare! failed\n");
166
167 return -EBADMSG;
168 }
169 }
170 return 0;
171}
172
173
174
175
176
177
178__maybe_unused
179static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
180{
181 struct nand_chip *nand = mtd_to_nand(mtd);
182 struct omap_nand_info *info = nand_get_controller_data(nand);
183 unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
184 unsigned int ecc_algo = 0;
185 unsigned int bch_type = 0;
186 unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
187 u32 ecc_size_config_val = 0;
188 u32 ecc_config_val = 0;
189 int cs = info->cs;
190
191
192 switch (info->ecc_scheme) {
193 case OMAP_ECC_HAM1_CODE_SW:
194 return;
195 case OMAP_ECC_HAM1_CODE_HW:
196 ecc_algo = 0x0;
197 bch_type = 0x0;
198 bch_wrapmode = 0x00;
199 eccsize0 = 0xFF;
200 eccsize1 = 0xFF;
201 break;
202 case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
203 case OMAP_ECC_BCH8_CODE_HW:
204 ecc_algo = 0x1;
205 bch_type = 0x1;
206 if (mode == NAND_ECC_WRITE) {
207 bch_wrapmode = 0x01;
208 eccsize0 = 0;
209 eccsize1 = 28;
210 } else {
211 bch_wrapmode = 0x01;
212 eccsize0 = 26;
213 eccsize1 = 2;
214 }
215 break;
216 case OMAP_ECC_BCH16_CODE_HW:
217 ecc_algo = 0x1;
218 bch_type = 0x2;
219 if (mode == NAND_ECC_WRITE) {
220 bch_wrapmode = 0x01;
221 eccsize0 = 0;
222 eccsize1 = 52;
223 } else {
224 bch_wrapmode = 0x01;
225 eccsize0 = 52;
226 eccsize1 = 0;
227 }
228 break;
229 default:
230 return;
231 }
232
233 writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
234
235 ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
236 writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
237
238
239 ecc_config_val = ((ecc_algo << 16) |
240 (bch_type << 12) |
241 (bch_wrapmode << 8) |
242 (dev_width << 7) |
243 (0x0 << 4) |
244 (cs << 1) |
245 (0x1));
246 writel(ecc_config_val, &gpmc_cfg->ecc_config);
247}
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
264 uint8_t *ecc_code)
265{
266 struct nand_chip *chip = mtd_to_nand(mtd);
267 struct omap_nand_info *info = nand_get_controller_data(chip);
268 const uint32_t *ptr;
269 uint32_t val = 0;
270 int8_t i = 0, j;
271
272 switch (info->ecc_scheme) {
273 case OMAP_ECC_HAM1_CODE_HW:
274 val = readl(&gpmc_cfg->ecc1_result);
275 ecc_code[0] = val & 0xFF;
276 ecc_code[1] = (val >> 16) & 0xFF;
277 ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
278 break;
279#ifdef CONFIG_BCH
280 case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
281#endif
282 case OMAP_ECC_BCH8_CODE_HW:
283 ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
284 val = readl(ptr);
285 ecc_code[i++] = (val >> 0) & 0xFF;
286 ptr--;
287 for (j = 0; j < 3; j++) {
288 val = readl(ptr);
289 ecc_code[i++] = (val >> 24) & 0xFF;
290 ecc_code[i++] = (val >> 16) & 0xFF;
291 ecc_code[i++] = (val >> 8) & 0xFF;
292 ecc_code[i++] = (val >> 0) & 0xFF;
293 ptr--;
294 }
295 break;
296 case OMAP_ECC_BCH16_CODE_HW:
297 val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[2]);
298 ecc_code[i++] = (val >> 8) & 0xFF;
299 ecc_code[i++] = (val >> 0) & 0xFF;
300 val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[1]);
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;
305 val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[0]);
306 ecc_code[i++] = (val >> 24) & 0xFF;
307 ecc_code[i++] = (val >> 16) & 0xFF;
308 ecc_code[i++] = (val >> 8) & 0xFF;
309 ecc_code[i++] = (val >> 0) & 0xFF;
310 for (j = 3; j >= 0; j--) {
311 val = readl(&gpmc_cfg->bch_result_0_3[0].bch_result_x[j]
312 );
313 ecc_code[i++] = (val >> 24) & 0xFF;
314 ecc_code[i++] = (val >> 16) & 0xFF;
315 ecc_code[i++] = (val >> 8) & 0xFF;
316 ecc_code[i++] = (val >> 0) & 0xFF;
317 }
318 break;
319 default:
320 return -EINVAL;
321 }
322
323 switch (info->ecc_scheme) {
324 case OMAP_ECC_HAM1_CODE_HW:
325 break;
326#ifdef CONFIG_BCH
327 case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
328
329 for (i = 0; i < chip->ecc.bytes; i++)
330 *(ecc_code + i) = *(ecc_code + i) ^
331 bch8_polynomial[i];
332 break;
333#endif
334 case OMAP_ECC_BCH8_CODE_HW:
335 ecc_code[chip->ecc.bytes - 1] = 0x00;
336 break;
337 case OMAP_ECC_BCH16_CODE_HW:
338 break;
339 default:
340 return -EINVAL;
341 }
342 return 0;
343}
344
345#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
346
347#define PREFETCH_CONFIG1_CS_SHIFT 24
348#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
349#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
350#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
351#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
352#define ENABLE_PREFETCH (1 << 7)
353
354
355
356
357
358
359
360
361static int omap_prefetch_enable(int fifo_th, unsigned int count, int is_write, int cs)
362{
363 uint32_t val;
364
365 if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX)
366 return -EINVAL;
367
368 if (readl(&gpmc_cfg->prefetch_control))
369 return -EBUSY;
370
371
372 writel(count, &gpmc_cfg->prefetch_config2);
373
374 val = (cs << PREFETCH_CONFIG1_CS_SHIFT) | (is_write & 1) |
375 PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH;
376 writel(val, &gpmc_cfg->prefetch_config1);
377
378
379 writel(1, &gpmc_cfg->prefetch_control);
380
381 return 0;
382}
383
384
385
386
387static void omap_prefetch_reset(void)
388{
389 writel(0, &gpmc_cfg->prefetch_control);
390 writel(0, &gpmc_cfg->prefetch_config1);
391}
392
393static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int len)
394{
395 int ret;
396 uint32_t cnt;
397 struct omap_nand_info *info = nand_get_controller_data(chip);
398
399 ret = omap_prefetch_enable(PREFETCH_FIFOTHRESHOLD_MAX, len, 0, info->cs);
400 if (ret < 0)
401 return ret;
402
403 do {
404 int i;
405
406 cnt = readl(&gpmc_cfg->prefetch_status);
407 cnt = PREFETCH_STATUS_FIFO_CNT(cnt);
408
409 for (i = 0; i < cnt / 4; i++) {
410 *buf++ = readl(CONFIG_SYS_NAND_BASE);
411 len -= 4;
412 }
413 } while (len);
414
415 omap_prefetch_reset();
416
417 return 0;
418}
419
420static inline void omap_nand_read(struct mtd_info *mtd, uint8_t *buf, int len)
421{
422 struct nand_chip *chip = mtd_to_nand(mtd);
423
424 if (chip->options & NAND_BUSWIDTH_16)
425 nand_read_buf16(mtd, buf, len);
426 else
427 nand_read_buf(mtd, buf, len);
428}
429
430static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len)
431{
432 int ret;
433 uint32_t head, tail;
434 struct nand_chip *chip = mtd_to_nand(mtd);
435
436
437
438
439
440 head = ((uint32_t) buf) % 4;
441 if (head) {
442 omap_nand_read(mtd, buf, head);
443 buf += head;
444 len -= head;
445 }
446
447
448
449
450
451 tail = len % 4;
452
453 ret = __read_prefetch_aligned(chip, (uint32_t *)buf, len - tail);
454 if (ret < 0) {
455
456 omap_nand_read(mtd, buf, len);
457 } else if (tail) {
458 buf += len - tail;
459 omap_nand_read(mtd, buf, tail);
460 }
461}
462#endif
463
464#ifdef CONFIG_NAND_OMAP_ELM
465
466
467
468
469
470static void omap_reverse_list(u8 *list, unsigned int length)
471{
472 unsigned int i, j;
473 unsigned int half_length = length / 2;
474 u8 tmp;
475 for (i = 0, j = length - 1; i < half_length; i++, j--) {
476 tmp = list[i];
477 list[i] = list[j];
478 list[j] = tmp;
479 }
480}
481
482
483
484
485
486
487
488
489
490
491
492
493static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
494 uint8_t *read_ecc, uint8_t *calc_ecc)
495{
496 struct nand_chip *chip = mtd_to_nand(mtd);
497 struct omap_nand_info *info = nand_get_controller_data(chip);
498 struct nand_ecc_ctrl *ecc = &chip->ecc;
499 uint32_t error_count = 0, error_max;
500 uint32_t error_loc[ELM_MAX_ERROR_COUNT];
501 enum bch_level bch_type;
502 uint32_t i, ecc_flag = 0;
503 uint8_t count;
504 uint32_t byte_pos, bit_pos;
505 int err = 0;
506
507
508 for (i = 0; i < ecc->bytes && !ecc_flag; i++) {
509 if (calc_ecc[i] != 0x00)
510 ecc_flag = 1;
511 }
512 if (!ecc_flag)
513 return 0;
514
515
516 ecc_flag = 0;
517 for (i = 0; i < ecc->bytes && !ecc_flag; i++) {
518 if (read_ecc[i] != 0xff)
519 ecc_flag = 1;
520 }
521 if (!ecc_flag)
522 return 0;
523
524
525
526
527
528 switch (info->ecc_scheme) {
529 case OMAP_ECC_BCH8_CODE_HW:
530 bch_type = BCH_8_BIT;
531 omap_reverse_list(calc_ecc, ecc->bytes - 1);
532 break;
533 case OMAP_ECC_BCH16_CODE_HW:
534 bch_type = BCH_16_BIT;
535 omap_reverse_list(calc_ecc, ecc->bytes);
536 break;
537 default:
538 return -EINVAL;
539 }
540
541 elm_config(bch_type);
542 err = elm_check_error(calc_ecc, bch_type, &error_count, error_loc);
543 if (err)
544 return err;
545
546
547 for (count = 0; count < error_count; count++) {
548 switch (info->ecc_scheme) {
549 case OMAP_ECC_BCH8_CODE_HW:
550
551 error_max = SECTOR_BYTES + (ecc->bytes - 1);
552 break;
553 case OMAP_ECC_BCH16_CODE_HW:
554 error_max = SECTOR_BYTES + ecc->bytes;
555 break;
556 default:
557 return -EINVAL;
558 }
559 byte_pos = error_max - (error_loc[count] / 8) - 1;
560 bit_pos = error_loc[count] % 8;
561 if (byte_pos < SECTOR_BYTES) {
562 dat[byte_pos] ^= 1 << bit_pos;
563 debug("nand: bit-flip corrected @data=%d\n", byte_pos);
564 } else if (byte_pos < error_max) {
565 read_ecc[byte_pos - SECTOR_BYTES] ^= 1 << bit_pos;
566 debug("nand: bit-flip corrected @oob=%d\n", byte_pos -
567 SECTOR_BYTES);
568 } else {
569 err = -EBADMSG;
570 printf("nand: error: invalid bit-flip location\n");
571 }
572 }
573 return (err) ? err : error_count;
574}
575
576
577
578
579
580
581
582
583
584
585static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
586 uint8_t *buf, int oob_required, int page)
587{
588 int i, eccsize = chip->ecc.size;
589 int eccbytes = chip->ecc.bytes;
590 int eccsteps = chip->ecc.steps;
591 uint8_t *p = buf;
592 uint8_t *ecc_calc = chip->buffers->ecccalc;
593 uint8_t *ecc_code = chip->buffers->ecccode;
594 uint32_t *eccpos = chip->ecc.layout->eccpos;
595 uint8_t *oob = chip->oob_poi;
596 uint32_t data_pos;
597 uint32_t oob_pos;
598
599 data_pos = 0;
600
601 oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
602 oob += chip->ecc.layout->eccpos[0];
603
604 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
605 oob += eccbytes) {
606 chip->ecc.hwctl(mtd, NAND_ECC_READ);
607
608 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, -1);
609 chip->read_buf(mtd, p, eccsize);
610
611
612 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
613 chip->read_buf(mtd, oob, eccbytes);
614
615 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
616
617 data_pos += eccsize;
618 oob_pos += eccbytes;
619 }
620
621 for (i = 0; i < chip->ecc.total; i++)
622 ecc_code[i] = chip->oob_poi[eccpos[i]];
623
624 eccsteps = chip->ecc.steps;
625 p = buf;
626
627 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
628 int stat;
629
630 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
631 if (stat < 0)
632 mtd->ecc_stats.failed++;
633 else
634 mtd->ecc_stats.corrected += stat;
635 }
636 return 0;
637}
638#endif
639
640
641
642
643#ifdef CONFIG_BCH
644
645
646
647
648
649
650
651static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
652 u_char *read_ecc, u_char *calc_ecc)
653{
654 int i, count;
655
656 unsigned int errloc[8];
657 struct nand_chip *chip = mtd_to_nand(mtd);
658 struct omap_nand_info *info = nand_get_controller_data(chip);
659
660 count = decode_bch(info->control, NULL, SECTOR_BYTES,
661 read_ecc, calc_ecc, NULL, errloc);
662 if (count > 0) {
663
664 for (i = 0; i < count; i++) {
665
666 if (errloc[i] < SECTOR_BYTES << 3)
667 data[errloc[i] >> 3] ^= 1 << (errloc[i] & 7);
668 debug("corrected bitflip %u\n", errloc[i]);
669#ifdef DEBUG
670 puts("read_ecc: ");
671
672
673
674
675 for (i = 0; i < 13; i++)
676 printf("%02x ", read_ecc[i]);
677 puts("\n");
678 puts("calc_ecc: ");
679 for (i = 0; i < 13; i++)
680 printf("%02x ", calc_ecc[i]);
681 puts("\n");
682#endif
683 }
684 } else if (count < 0) {
685 puts("ecc unrecoverable error\n");
686 }
687 return count;
688}
689
690
691
692
693
694static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
695{
696 struct nand_chip *chip = mtd_to_nand(mtd);
697 struct omap_nand_info *info = nand_get_controller_data(chip);
698
699 if (info->control) {
700 free_bch(info->control);
701 info->control = NULL;
702 }
703}
704#endif
705
706
707
708
709
710
711
712
713static int omap_select_ecc_scheme(struct nand_chip *nand,
714 enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
715 struct omap_nand_info *info = nand_get_controller_data(nand);
716 struct nand_ecclayout *ecclayout = &omap_ecclayout;
717 int eccsteps = pagesize / SECTOR_BYTES;
718 int i;
719
720 switch (ecc_scheme) {
721 case OMAP_ECC_HAM1_CODE_SW:
722 debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
723
724
725 info->control = NULL;
726 nand->ecc.mode = NAND_ECC_SOFT;
727 nand->ecc.layout = NULL;
728 nand->ecc.size = 0;
729 break;
730
731 case OMAP_ECC_HAM1_CODE_HW:
732 debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
733
734 if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
735 printf("nand: error: insufficient OOB: require=%d\n", (
736 (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
737 return -EINVAL;
738 }
739 info->control = NULL;
740
741 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
742 nand->ecc.mode = NAND_ECC_HW;
743 nand->ecc.strength = 1;
744 nand->ecc.size = SECTOR_BYTES;
745 nand->ecc.bytes = 3;
746 nand->ecc.hwctl = omap_enable_hwecc;
747 nand->ecc.correct = omap_correct_data;
748 nand->ecc.calculate = omap_calculate_ecc;
749
750 ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
751 for (i = 0; i < ecclayout->eccbytes; i++) {
752 if (nand->options & NAND_BUSWIDTH_16)
753 ecclayout->eccpos[i] = i + 2;
754 else
755 ecclayout->eccpos[i] = i + 1;
756 }
757 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
758 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
759 BADBLOCK_MARKER_LENGTH;
760 break;
761
762 case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
763#ifdef CONFIG_BCH
764 debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
765
766 if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
767 printf("nand: error: insufficient OOB: require=%d\n", (
768 (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
769 return -EINVAL;
770 }
771
772 info->control = init_bch(13, 8, 0x201b);
773 if (!info->control) {
774 printf("nand: error: could not init_bch()\n");
775 return -ENODEV;
776 }
777
778 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
779 nand->ecc.mode = NAND_ECC_HW;
780 nand->ecc.strength = 8;
781 nand->ecc.size = SECTOR_BYTES;
782 nand->ecc.bytes = 13;
783 nand->ecc.hwctl = omap_enable_hwecc;
784 nand->ecc.correct = omap_correct_data_bch_sw;
785 nand->ecc.calculate = omap_calculate_ecc;
786
787 ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
788 ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
789 for (i = 1; i < ecclayout->eccbytes; i++) {
790 if (i % nand->ecc.bytes)
791 ecclayout->eccpos[i] =
792 ecclayout->eccpos[i - 1] + 1;
793 else
794 ecclayout->eccpos[i] =
795 ecclayout->eccpos[i - 1] + 2;
796 }
797 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
798 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
799 BADBLOCK_MARKER_LENGTH;
800 break;
801#else
802 printf("nand: error: CONFIG_BCH required for ECC\n");
803 return -EINVAL;
804#endif
805
806 case OMAP_ECC_BCH8_CODE_HW:
807#ifdef CONFIG_NAND_OMAP_ELM
808 debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
809
810 if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
811 printf("nand: error: insufficient OOB: require=%d\n", (
812 (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
813 return -EINVAL;
814 }
815
816 elm_init();
817 info->control = NULL;
818
819 memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
820 nand->ecc.mode = NAND_ECC_HW;
821 nand->ecc.strength = 8;
822 nand->ecc.size = SECTOR_BYTES;
823 nand->ecc.bytes = 14;
824 nand->ecc.hwctl = omap_enable_hwecc;
825 nand->ecc.correct = omap_correct_data_bch;
826 nand->ecc.calculate = omap_calculate_ecc;
827 nand->ecc.read_page = omap_read_page_bch;
828
829 ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
830 for (i = 0; i < ecclayout->eccbytes; i++)
831 ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
832 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
833 ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
834 BADBLOCK_MARKER_LENGTH;
835 break;
836#else
837 printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
838 return -EINVAL;
839#endif
840
841 case OMAP_ECC_BCH16_CODE_HW:
842#ifdef CONFIG_NAND_OMAP_ELM
843 debug("nand: using OMAP_ECC_BCH16_CODE_HW\n");
844
845 if ((26 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
846 printf("nand: error: insufficient OOB: require=%d\n", (
847 (26 * eccsteps) + BADBLOCK_MARKER_LENGTH));
848 return -EINVAL;
849 }
850
851 elm_init();
852
853 nand->ecc.mode = NAND_ECC_HW;
854 nand->ecc.size = SECTOR_BYTES;
855 nand->ecc.bytes = 26;
856 nand->ecc.strength = 16;
857 nand->ecc.hwctl = omap_enable_hwecc;
858 nand->ecc.correct = omap_correct_data_bch;
859 nand->ecc.calculate = omap_calculate_ecc;
860 nand->ecc.read_page = omap_read_page_bch;
861
862 ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
863 for (i = 0; i < ecclayout->eccbytes; i++)
864 ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
865 ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
866 ecclayout->oobfree[0].length = oobsize - nand->ecc.bytes -
867 BADBLOCK_MARKER_LENGTH;
868 break;
869#else
870 printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
871 return -EINVAL;
872#endif
873 default:
874 debug("nand: error: ecc scheme not enabled or supported\n");
875 return -EINVAL;
876 }
877
878
879 if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
880 nand->ecc.layout = ecclayout;
881
882 info->ecc_scheme = ecc_scheme;
883 return 0;
884}
885
886#ifndef CONFIG_SPL_BUILD
887
888
889
890
891
892
893
894
895int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
896{
897 struct nand_chip *nand;
898 struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device);
899 int err = 0;
900
901 if (!mtd) {
902 printf("nand: error: no NAND devices found\n");
903 return -ENODEV;
904 }
905
906 nand = mtd_to_nand(mtd);
907 nand->options |= NAND_OWN_BUFFERS;
908 nand->options &= ~NAND_SUBPAGE_READ;
909
910 if (hardware) {
911 if (eccstrength == 1) {
912 err = omap_select_ecc_scheme(nand,
913 OMAP_ECC_HAM1_CODE_HW,
914 mtd->writesize, mtd->oobsize);
915 } else if (eccstrength == 8) {
916 err = omap_select_ecc_scheme(nand,
917 OMAP_ECC_BCH8_CODE_HW,
918 mtd->writesize, mtd->oobsize);
919 } else if (eccstrength == 16) {
920 err = omap_select_ecc_scheme(nand,
921 OMAP_ECC_BCH16_CODE_HW,
922 mtd->writesize, mtd->oobsize);
923 } else {
924 printf("nand: error: unsupported ECC scheme\n");
925 return -EINVAL;
926 }
927 } else {
928 if (eccstrength == 1) {
929 err = omap_select_ecc_scheme(nand,
930 OMAP_ECC_HAM1_CODE_SW,
931 mtd->writesize, mtd->oobsize);
932 } else if (eccstrength == 8) {
933 err = omap_select_ecc_scheme(nand,
934 OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
935 mtd->writesize, mtd->oobsize);
936 } else {
937 printf("nand: error: unsupported ECC scheme\n");
938 return -EINVAL;
939 }
940 }
941
942
943 if (!err)
944 err = nand_scan_tail(mtd);
945 return err;
946}
947#endif
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964int board_nand_init(struct nand_chip *nand)
965{
966 int32_t gpmc_config = 0;
967 int cs = cs_next++;
968 int err = 0;
969
970
971
972
973
974
975
976 while (cs < GPMC_MAX_CS) {
977
978 if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
979
980 break;
981 }
982 cs++;
983 }
984 if (cs >= GPMC_MAX_CS) {
985 printf("nand: error: Unable to find NAND settings in "
986 "GPMC Configuration - quitting\n");
987 return -ENODEV;
988 }
989
990 gpmc_config = readl(&gpmc_cfg->config);
991
992 gpmc_config |= 0x10;
993 writel(gpmc_config, &gpmc_cfg->config);
994
995 nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
996 nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
997 omap_nand_info[cs].control = NULL;
998 omap_nand_info[cs].cs = cs;
999 omap_nand_info[cs].ws = wscfg[cs];
1000 nand_set_controller_data(nand, &omap_nand_info[cs]);
1001 nand->cmd_ctrl = omap_nand_hwcontrol;
1002 nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
1003 nand->chip_delay = 100;
1004 nand->ecc.layout = &omap_ecclayout;
1005
1006
1007 gpmc_config = readl(&gpmc_cfg->cs[cs].config1);
1008#if defined(CONFIG_SYS_NAND_BUSWIDTH_16BIT)
1009 nand->options |= NAND_BUSWIDTH_16;
1010 writel(gpmc_config | (0x1 << 12), &gpmc_cfg->cs[cs].config1);
1011#else
1012 nand->options &= ~NAND_BUSWIDTH_16;
1013 writel(gpmc_config & ~(0x1 << 12), &gpmc_cfg->cs[cs].config1);
1014#endif
1015
1016#if defined(CONFIG_NAND_OMAP_ECCSCHEME)
1017 err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
1018 CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
1019#else
1020
1021 err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
1022 0, 0);
1023#endif
1024 if (err)
1025 return err;
1026
1027#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
1028 nand->read_buf = omap_nand_read_prefetch;
1029#else
1030 if (nand->options & NAND_BUSWIDTH_16)
1031 nand->read_buf = nand_read_buf16;
1032 else
1033 nand->read_buf = nand_read_buf;
1034#endif
1035
1036 nand->dev_ready = omap_dev_ready;
1037
1038 return 0;
1039}
1040