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