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