1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <common.h>
23#include <watchdog.h>
24#include <linux/compat.h>
25#include <linux/mtd/mtd.h>
26#include "linux/mtd/flashchip.h"
27#include <linux/mtd/onenand.h>
28
29#include <asm/io.h>
30#include <linux/errno.h>
31#include <malloc.h>
32
33
34static void *memcpy_16(void *dst, const void *src, unsigned int len)
35{
36 void *ret = dst;
37 short *d = dst;
38 const short *s = src;
39
40 len >>= 1;
41 while (len-- > 0)
42 *d++ = *s++;
43 return ret;
44}
45
46
47
48
49
50static struct nand_ecclayout onenand_oob_128 = {
51 .eccbytes = 64,
52 .eccpos = {
53 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
54 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
55 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
56 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
57 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
58 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
59 102, 103, 104, 105
60 },
61 .oobfree = {
62 {2, 4}, {18, 4}, {34, 4}, {50, 4},
63 {66, 4}, {82, 4}, {98, 4}, {114, 4}
64 }
65};
66
67
68
69
70static struct nand_ecclayout onenand_oob_64 = {
71 .eccbytes = 20,
72 .eccpos = {
73 8, 9, 10, 11, 12,
74 24, 25, 26, 27, 28,
75 40, 41, 42, 43, 44,
76 56, 57, 58, 59, 60,
77 },
78 .oobfree = {
79 {2, 3}, {14, 2}, {18, 3}, {30, 2},
80 {34, 3}, {46, 2}, {50, 3}, {62, 2}
81 }
82};
83
84
85
86
87static struct nand_ecclayout onenand_oob_32 = {
88 .eccbytes = 10,
89 .eccpos = {
90 8, 9, 10, 11, 12,
91 24, 25, 26, 27, 28,
92 },
93 .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} }
94};
95
96
97
98
99
100
101
102static const unsigned char __aligned(2) ffchars[] = {
103 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
104 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
105 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
110 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
111 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
112 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
113 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
117 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
118 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
119};
120
121
122
123
124
125
126
127static unsigned short onenand_readw(void __iomem * addr)
128{
129 return readw(addr);
130}
131
132
133
134
135
136
137
138
139static void onenand_writew(unsigned short value, void __iomem * addr)
140{
141 writew(value, addr);
142}
143
144
145
146
147
148
149
150
151
152static int onenand_block_address(struct onenand_chip *this, int block)
153{
154
155 if (block & this->density_mask)
156 return ONENAND_DDP_CHIP1 | (block ^ this->density_mask);
157
158 return block;
159}
160
161
162
163
164
165
166
167
168
169static int onenand_bufferram_address(struct onenand_chip *this, int block)
170{
171
172 if (block & this->density_mask)
173 return ONENAND_DDP_CHIP1;
174
175 return ONENAND_DDP_CHIP0;
176}
177
178
179
180
181
182
183
184
185
186static int onenand_page_address(int page, int sector)
187{
188
189 int fpa, fsa;
190
191 fpa = page & ONENAND_FPA_MASK;
192 fsa = sector & ONENAND_FSA_MASK;
193
194 return ((fpa << ONENAND_FPA_SHIFT) | fsa);
195}
196
197
198
199
200
201
202
203
204
205
206static int onenand_buffer_address(int dataram1, int sectors, int count)
207{
208 int bsa, bsc;
209
210
211 bsa = sectors & ONENAND_BSA_MASK;
212
213 if (dataram1)
214 bsa |= ONENAND_BSA_DATARAM1;
215 else
216 bsa |= ONENAND_BSA_DATARAM0;
217
218
219 bsc = count & ONENAND_BSC_MASK;
220
221 return ((bsa << ONENAND_BSA_SHIFT) | bsc);
222}
223
224
225
226
227
228
229static unsigned int flexonenand_block(struct onenand_chip *this, loff_t addr)
230{
231 unsigned int boundary, blk, die = 0;
232
233 if (ONENAND_IS_DDP(this) && addr >= this->diesize[0]) {
234 die = 1;
235 addr -= this->diesize[0];
236 }
237
238 boundary = this->boundary[die];
239
240 blk = addr >> (this->erase_shift - 1);
241 if (blk > boundary)
242 blk = (blk + boundary + 1) >> 1;
243
244 blk += die ? this->density_mask : 0;
245 return blk;
246}
247
248unsigned int onenand_block(struct onenand_chip *this, loff_t addr)
249{
250 if (!FLEXONENAND(this))
251 return addr >> this->erase_shift;
252 return flexonenand_block(this, addr);
253}
254
255
256
257
258
259
260
261
262static loff_t flexonenand_addr(struct onenand_chip *this, int block)
263{
264 loff_t ofs = 0;
265 int die = 0, boundary;
266
267 if (ONENAND_IS_DDP(this) && block >= this->density_mask) {
268 block -= this->density_mask;
269 die = 1;
270 ofs = this->diesize[0];
271 }
272
273 boundary = this->boundary[die];
274 ofs += (loff_t) block << (this->erase_shift - 1);
275 if (block > (boundary + 1))
276 ofs += (loff_t) (block - boundary - 1)
277 << (this->erase_shift - 1);
278 return ofs;
279}
280
281loff_t onenand_addr(struct onenand_chip *this, int block)
282{
283 if (!FLEXONENAND(this))
284 return (loff_t) block << this->erase_shift;
285 return flexonenand_addr(this, block);
286}
287
288
289
290
291
292
293int flexonenand_region(struct mtd_info *mtd, loff_t addr)
294{
295 int i;
296
297 for (i = 0; i < mtd->numeraseregions; i++)
298 if (addr < mtd->eraseregions[i].offset)
299 break;
300 return i - 1;
301}
302
303
304
305
306
307
308
309static inline int onenand_get_density(int dev_id)
310{
311 int density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
312 return (density & ONENAND_DEVICE_DENSITY_MASK);
313}
314
315
316
317
318
319
320
321
322
323
324
325static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
326 size_t len)
327{
328 struct onenand_chip *this = mtd->priv;
329 int value;
330 int block, page;
331
332
333 int sectors = 0, count = 0;
334
335
336 switch (cmd) {
337 case ONENAND_CMD_UNLOCK:
338 case ONENAND_CMD_LOCK:
339 case ONENAND_CMD_LOCK_TIGHT:
340 case ONENAND_CMD_UNLOCK_ALL:
341 block = -1;
342 page = -1;
343 break;
344
345 case FLEXONENAND_CMD_PI_ACCESS:
346
347 block = addr * this->density_mask;
348 page = -1;
349 break;
350
351 case ONENAND_CMD_ERASE:
352 case ONENAND_CMD_BUFFERRAM:
353 block = onenand_block(this, addr);
354 page = -1;
355 break;
356
357 case FLEXONENAND_CMD_READ_PI:
358 cmd = ONENAND_CMD_READ;
359 block = addr * this->density_mask;
360 page = 0;
361 break;
362
363 default:
364 block = onenand_block(this, addr);
365 page = (int) (addr
366 - onenand_addr(this, block)) >> this->page_shift;
367 page &= this->page_mask;
368 break;
369 }
370
371
372 if (cmd == ONENAND_CMD_BUFFERRAM) {
373
374 value = onenand_bufferram_address(this, block);
375 this->write_word(value,
376 this->base + ONENAND_REG_START_ADDRESS2);
377
378 if (ONENAND_IS_4KB_PAGE(this))
379 ONENAND_SET_BUFFERRAM0(this);
380 else
381
382 ONENAND_SET_NEXT_BUFFERRAM(this);
383
384 return 0;
385 }
386
387 if (block != -1) {
388
389 value = onenand_block_address(this, block);
390 this->write_word(value,
391 this->base + ONENAND_REG_START_ADDRESS1);
392
393
394 value = onenand_bufferram_address(this, block);
395 this->write_word(value,
396 this->base + ONENAND_REG_START_ADDRESS2);
397 }
398
399 if (page != -1) {
400 int dataram;
401
402 switch (cmd) {
403 case FLEXONENAND_CMD_RECOVER_LSB:
404 case ONENAND_CMD_READ:
405 case ONENAND_CMD_READOOB:
406 if (ONENAND_IS_4KB_PAGE(this))
407 dataram = ONENAND_SET_BUFFERRAM0(this);
408 else
409 dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
410
411 break;
412
413 default:
414 dataram = ONENAND_CURRENT_BUFFERRAM(this);
415 break;
416 }
417
418
419 value = onenand_page_address(page, sectors);
420 this->write_word(value,
421 this->base + ONENAND_REG_START_ADDRESS8);
422
423
424 value = onenand_buffer_address(dataram, sectors, count);
425 this->write_word(value, this->base + ONENAND_REG_START_BUFFER);
426 }
427
428
429 this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT);
430
431 this->write_word(cmd, this->base + ONENAND_REG_COMMAND);
432
433 return 0;
434}
435
436
437
438
439
440static int onenand_read_ecc(struct onenand_chip *this)
441{
442 int ecc, i;
443
444 if (!FLEXONENAND(this))
445 return this->read_word(this->base + ONENAND_REG_ECC_STATUS);
446
447 for (i = 0; i < 4; i++) {
448 ecc = this->read_word(this->base
449 + ((ONENAND_REG_ECC_STATUS + i) << 1));
450 if (likely(!ecc))
451 continue;
452 if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR)
453 return ONENAND_ECC_2BIT_ALL;
454 }
455
456 return 0;
457}
458
459
460
461
462
463
464
465
466
467
468static int onenand_wait(struct mtd_info *mtd, int state)
469{
470 struct onenand_chip *this = mtd->priv;
471 unsigned int interrupt = 0;
472 unsigned int ctrl;
473
474
475 u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
476 u32 time_start = get_timer(0);
477 do {
478 WATCHDOG_RESET();
479 if (get_timer(time_start) > timeo)
480 return -EIO;
481 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
482 } while ((interrupt & ONENAND_INT_MASTER) == 0);
483
484 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
485
486 if (interrupt & ONENAND_INT_READ) {
487 int ecc = onenand_read_ecc(this);
488 if (ecc & ONENAND_ECC_2BIT_ALL) {
489 printk("onenand_wait: ECC error = 0x%04x\n", ecc);
490 return -EBADMSG;
491 }
492 }
493
494 if (ctrl & ONENAND_CTRL_ERROR) {
495 printk("onenand_wait: controller error = 0x%04x\n", ctrl);
496 if (ctrl & ONENAND_CTRL_LOCK)
497 printk("onenand_wait: it's locked error = 0x%04x\n",
498 ctrl);
499
500 return -EIO;
501 }
502
503
504 return 0;
505}
506
507
508
509
510
511
512
513
514
515static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
516{
517 struct onenand_chip *this = mtd->priv;
518
519 if (ONENAND_CURRENT_BUFFERRAM(this)) {
520 if (area == ONENAND_DATARAM)
521 return mtd->writesize;
522 if (area == ONENAND_SPARERAM)
523 return mtd->oobsize;
524 }
525
526 return 0;
527}
528
529
530
531
532
533
534
535
536
537
538
539static int onenand_read_bufferram(struct mtd_info *mtd, loff_t addr, int area,
540 unsigned char *buffer, int offset,
541 size_t count)
542{
543 struct onenand_chip *this = mtd->priv;
544 void __iomem *bufferram;
545
546 bufferram = this->base + area;
547 bufferram += onenand_bufferram_offset(mtd, area);
548
549 memcpy_16(buffer, bufferram + offset, count);
550
551 return 0;
552}
553
554
555
556
557
558
559
560
561
562
563
564static int onenand_sync_read_bufferram(struct mtd_info *mtd, loff_t addr, int area,
565 unsigned char *buffer, int offset,
566 size_t count)
567{
568 struct onenand_chip *this = mtd->priv;
569 void __iomem *bufferram;
570
571 bufferram = this->base + area;
572 bufferram += onenand_bufferram_offset(mtd, area);
573
574 this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);
575
576 memcpy_16(buffer, bufferram + offset, count);
577
578 this->mmcontrol(mtd, 0);
579
580 return 0;
581}
582
583
584
585
586
587
588
589
590
591
592
593static int onenand_write_bufferram(struct mtd_info *mtd, loff_t addr, int area,
594 const unsigned char *buffer, int offset,
595 size_t count)
596{
597 struct onenand_chip *this = mtd->priv;
598 void __iomem *bufferram;
599
600 bufferram = this->base + area;
601 bufferram += onenand_bufferram_offset(mtd, area);
602
603 memcpy_16(bufferram + offset, buffer, count);
604
605 return 0;
606}
607
608
609
610
611
612
613
614
615
616static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
617{
618 struct onenand_chip *this = mtd->priv;
619 int blockpage, block, page;
620
621
622 block = (int) (addr >> this->erase_shift) & ~1;
623
624 if (addr & this->writesize)
625 block++;
626 page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
627 blockpage = (block << 7) | page;
628
629 return blockpage;
630}
631
632
633
634
635
636
637
638
639
640static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
641{
642 struct onenand_chip *this = mtd->priv;
643 int blockpage, found = 0;
644 unsigned int i;
645
646 if (ONENAND_IS_2PLANE(this))
647 blockpage = onenand_get_2x_blockpage(mtd, addr);
648 else
649 blockpage = (int) (addr >> this->page_shift);
650
651
652 i = ONENAND_CURRENT_BUFFERRAM(this);
653 if (this->bufferram[i].blockpage == blockpage)
654 found = 1;
655 else {
656
657 i = ONENAND_NEXT_BUFFERRAM(this);
658 if (this->bufferram[i].blockpage == blockpage) {
659 ONENAND_SET_NEXT_BUFFERRAM(this);
660 found = 1;
661 }
662 }
663
664 if (found && ONENAND_IS_DDP(this)) {
665
666 int block = onenand_block(this, addr);
667 int value = onenand_bufferram_address(this, block);
668 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
669 }
670
671 return found;
672}
673
674
675
676
677
678
679
680
681
682static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
683 int valid)
684{
685 struct onenand_chip *this = mtd->priv;
686 int blockpage;
687 unsigned int i;
688
689 if (ONENAND_IS_2PLANE(this))
690 blockpage = onenand_get_2x_blockpage(mtd, addr);
691 else
692 blockpage = (int)(addr >> this->page_shift);
693
694
695 i = ONENAND_NEXT_BUFFERRAM(this);
696 if (this->bufferram[i].blockpage == blockpage)
697 this->bufferram[i].blockpage = -1;
698
699
700 i = ONENAND_CURRENT_BUFFERRAM(this);
701 if (valid)
702 this->bufferram[i].blockpage = blockpage;
703 else
704 this->bufferram[i].blockpage = -1;
705
706 return 0;
707}
708
709
710
711
712
713
714
715
716
717static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
718 unsigned int len)
719{
720 struct onenand_chip *this = mtd->priv;
721 int i;
722 loff_t end_addr = addr + len;
723
724
725 for (i = 0; i < MAX_BUFFERRAM; i++) {
726 loff_t buf_addr = this->bufferram[i].blockpage << this->page_shift;
727
728 if (buf_addr >= addr && buf_addr < end_addr)
729 this->bufferram[i].blockpage = -1;
730 }
731}
732
733
734
735
736
737
738
739
740static void onenand_get_device(struct mtd_info *mtd, int new_state)
741{
742
743}
744
745
746
747
748
749
750
751static void onenand_release_device(struct mtd_info *mtd)
752{
753
754}
755
756
757
758
759
760
761
762
763static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
764 int column, int thislen)
765{
766 struct onenand_chip *this = mtd->priv;
767 struct nand_oobfree *free;
768 int readcol = column;
769 int readend = column + thislen;
770 int lastgap = 0;
771 unsigned int i;
772 uint8_t *oob_buf = this->oob_buf;
773
774 free = this->ecclayout->oobfree;
775 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
776 i++, free++) {
777 if (readcol >= lastgap)
778 readcol += free->offset - lastgap;
779 if (readend >= lastgap)
780 readend += free->offset - lastgap;
781 lastgap = free->offset + free->length;
782 }
783 this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
784 free = this->ecclayout->oobfree;
785 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
786 i++, free++) {
787 int free_end = free->offset + free->length;
788 if (free->offset < readend && free_end > readcol) {
789 int st = max_t(int,free->offset,readcol);
790 int ed = min_t(int,free_end,readend);
791 int n = ed - st;
792 memcpy(buf, oob_buf + st, n);
793 buf += n;
794 } else if (column == 0)
795 break;
796 }
797 return 0;
798}
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
814{
815 struct onenand_chip *this = mtd->priv;
816 int i;
817
818
819 if (!FLEXONENAND(this))
820 return status;
821
822
823 if (!mtd_is_eccerr(status) && status != ONENAND_BBT_READ_ECC_ERROR)
824 return status;
825
826
827 i = flexonenand_region(mtd, addr);
828 if (mtd->eraseregions[i].erasesize < (1 << this->erase_shift))
829 return status;
830
831 printk("onenand_recover_lsb:"
832 "Attempting to recover from uncorrectable read\n");
833
834
835 this->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr, this->writesize);
836 return this->wait(mtd, FL_READING);
837}
838
839
840
841
842
843
844
845
846
847static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
848 struct mtd_oob_ops *ops)
849{
850 struct onenand_chip *this = mtd->priv;
851 struct mtd_ecc_stats stats;
852 size_t len = ops->len;
853 size_t ooblen = ops->ooblen;
854 u_char *buf = ops->datbuf;
855 u_char *oobbuf = ops->oobbuf;
856 int read = 0, column, thislen;
857 int oobread = 0, oobcolumn, thisooblen, oobsize;
858 int ret = 0, boundary = 0;
859 int writesize = this->writesize;
860
861 pr_debug("onenand_read_ops_nolock: from = 0x%08x, len = %i\n",
862 (unsigned int) from, (int) len);
863
864 if (ops->mode == MTD_OPS_AUTO_OOB)
865 oobsize = this->ecclayout->oobavail;
866 else
867 oobsize = mtd->oobsize;
868
869 oobcolumn = from & (mtd->oobsize - 1);
870
871
872 if ((from + len) > mtd->size) {
873 printk(KERN_ERR "onenand_read_ops_nolock: Attempt read beyond end of device\n");
874 ops->retlen = 0;
875 ops->oobretlen = 0;
876 return -EINVAL;
877 }
878
879 stats = mtd->ecc_stats;
880
881
882
883
884
885 if (read < len) {
886 if (!onenand_check_bufferram(mtd, from)) {
887 this->main_buf = buf;
888 this->command(mtd, ONENAND_CMD_READ, from, writesize);
889 ret = this->wait(mtd, FL_READING);
890 if (unlikely(ret))
891 ret = onenand_recover_lsb(mtd, from, ret);
892 onenand_update_bufferram(mtd, from, !ret);
893 if (ret == -EBADMSG)
894 ret = 0;
895 }
896 }
897
898 thislen = min_t(int, writesize, len - read);
899 column = from & (writesize - 1);
900 if (column + thislen > writesize)
901 thislen = writesize - column;
902
903 while (!ret) {
904
905 from += thislen;
906 if (!ONENAND_IS_4KB_PAGE(this) && read + thislen < len) {
907 this->main_buf = buf + thislen;
908 this->command(mtd, ONENAND_CMD_READ, from, writesize);
909
910
911
912
913
914 if (ONENAND_IS_DDP(this) &&
915 unlikely(from == (this->chipsize >> 1))) {
916 this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
917 boundary = 1;
918 } else
919 boundary = 0;
920 ONENAND_SET_PREV_BUFFERRAM(this);
921 }
922
923
924 this->read_bufferram(mtd, from - thislen, ONENAND_DATARAM, buf, column, thislen);
925
926
927 if (oobbuf) {
928 thisooblen = oobsize - oobcolumn;
929 thisooblen = min_t(int, thisooblen, ooblen - oobread);
930
931 if (ops->mode == MTD_OPS_AUTO_OOB)
932 onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
933 else
934 this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
935 oobread += thisooblen;
936 oobbuf += thisooblen;
937 oobcolumn = 0;
938 }
939
940 if (ONENAND_IS_4KB_PAGE(this) && (read + thislen < len)) {
941 this->command(mtd, ONENAND_CMD_READ, from, writesize);
942 ret = this->wait(mtd, FL_READING);
943 if (unlikely(ret))
944 ret = onenand_recover_lsb(mtd, from, ret);
945 onenand_update_bufferram(mtd, from, !ret);
946 if (mtd_is_eccerr(ret))
947 ret = 0;
948 }
949
950
951 read += thislen;
952 if (read == len)
953 break;
954
955 if (unlikely(boundary))
956 this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
957 if (!ONENAND_IS_4KB_PAGE(this))
958 ONENAND_SET_NEXT_BUFFERRAM(this);
959 buf += thislen;
960 thislen = min_t(int, writesize, len - read);
961 column = 0;
962
963 if (!ONENAND_IS_4KB_PAGE(this)) {
964
965 ret = this->wait(mtd, FL_READING);
966 onenand_update_bufferram(mtd, from, !ret);
967 if (mtd_is_eccerr(ret))
968 ret = 0;
969 }
970 }
971
972
973
974
975
976
977 ops->retlen = read;
978 ops->oobretlen = oobread;
979
980 if (ret)
981 return ret;
982
983 if (mtd->ecc_stats.failed - stats.failed)
984 return -EBADMSG;
985
986
987 return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0;
988}
989
990
991
992
993
994
995
996
997
998static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
999 struct mtd_oob_ops *ops)
1000{
1001 struct onenand_chip *this = mtd->priv;
1002 struct mtd_ecc_stats stats;
1003 int read = 0, thislen, column, oobsize;
1004 size_t len = ops->ooblen;
1005 unsigned int mode = ops->mode;
1006 u_char *buf = ops->oobbuf;
1007 int ret = 0, readcmd;
1008
1009 from += ops->ooboffs;
1010
1011 pr_debug("onenand_read_oob_nolock: from = 0x%08x, len = %i\n",
1012 (unsigned int) from, (int) len);
1013
1014
1015 ops->oobretlen = 0;
1016
1017 if (mode == MTD_OPS_AUTO_OOB)
1018 oobsize = this->ecclayout->oobavail;
1019 else
1020 oobsize = mtd->oobsize;
1021
1022 column = from & (mtd->oobsize - 1);
1023
1024 if (unlikely(column >= oobsize)) {
1025 printk(KERN_ERR "onenand_read_oob_nolock: Attempted to start read outside oob\n");
1026 return -EINVAL;
1027 }
1028
1029
1030 if (unlikely(from >= mtd->size ||
1031 column + len > ((mtd->size >> this->page_shift) -
1032 (from >> this->page_shift)) * oobsize)) {
1033 printk(KERN_ERR "onenand_read_oob_nolock: Attempted to read beyond end of device\n");
1034 return -EINVAL;
1035 }
1036
1037 stats = mtd->ecc_stats;
1038
1039 readcmd = ONENAND_IS_4KB_PAGE(this) ?
1040 ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1041
1042 while (read < len) {
1043 thislen = oobsize - column;
1044 thislen = min_t(int, thislen, len);
1045
1046 this->spare_buf = buf;
1047 this->command(mtd, readcmd, from, mtd->oobsize);
1048
1049 onenand_update_bufferram(mtd, from, 0);
1050
1051 ret = this->wait(mtd, FL_READING);
1052 if (unlikely(ret))
1053 ret = onenand_recover_lsb(mtd, from, ret);
1054
1055 if (ret && ret != -EBADMSG) {
1056 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
1057 break;
1058 }
1059
1060 if (mode == MTD_OPS_AUTO_OOB)
1061 onenand_transfer_auto_oob(mtd, buf, column, thislen);
1062 else
1063 this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen);
1064
1065 read += thislen;
1066
1067 if (read == len)
1068 break;
1069
1070 buf += thislen;
1071
1072
1073 if (read < len) {
1074
1075 from += mtd->writesize;
1076 column = 0;
1077 }
1078 }
1079
1080 ops->oobretlen = read;
1081
1082 if (ret)
1083 return ret;
1084
1085 if (mtd->ecc_stats.failed - stats.failed)
1086 return -EBADMSG;
1087
1088 return 0;
1089}
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1102 size_t * retlen, u_char * buf)
1103{
1104 struct mtd_oob_ops ops = {
1105 .len = len,
1106 .ooblen = 0,
1107 .datbuf = buf,
1108 .oobbuf = NULL,
1109 };
1110 int ret;
1111
1112 onenand_get_device(mtd, FL_READING);
1113 ret = onenand_read_ops_nolock(mtd, from, &ops);
1114 onenand_release_device(mtd);
1115
1116 *retlen = ops.retlen;
1117 return ret;
1118}
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128int onenand_read_oob(struct mtd_info *mtd, loff_t from,
1129 struct mtd_oob_ops *ops)
1130{
1131 int ret;
1132
1133 switch (ops->mode) {
1134 case MTD_OPS_PLACE_OOB:
1135 case MTD_OPS_AUTO_OOB:
1136 break;
1137 case MTD_OPS_RAW:
1138
1139 default:
1140 return -EINVAL;
1141 }
1142
1143 onenand_get_device(mtd, FL_READING);
1144 if (ops->datbuf)
1145 ret = onenand_read_ops_nolock(mtd, from, ops);
1146 else
1147 ret = onenand_read_oob_nolock(mtd, from, ops);
1148 onenand_release_device(mtd);
1149
1150 return ret;
1151}
1152
1153
1154
1155
1156
1157
1158
1159
1160static int onenand_bbt_wait(struct mtd_info *mtd, int state)
1161{
1162 struct onenand_chip *this = mtd->priv;
1163 unsigned int interrupt;
1164 unsigned int ctrl;
1165
1166
1167 u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
1168 u32 time_start = get_timer(0);
1169 do {
1170 WATCHDOG_RESET();
1171 if (get_timer(time_start) > timeo)
1172 return ONENAND_BBT_READ_FATAL_ERROR;
1173 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
1174 } while ((interrupt & ONENAND_INT_MASTER) == 0);
1175
1176
1177 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
1178 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
1179
1180 if (interrupt & ONENAND_INT_READ) {
1181 int ecc = onenand_read_ecc(this);
1182 if (ecc & ONENAND_ECC_2BIT_ALL) {
1183 printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
1184 ", controller = 0x%04x\n", ecc, ctrl);
1185 return ONENAND_BBT_READ_ERROR;
1186 }
1187 } else {
1188 printk(KERN_ERR "onenand_bbt_wait: read timeout!"
1189 "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
1190 return ONENAND_BBT_READ_FATAL_ERROR;
1191 }
1192
1193
1194 if (ctrl & ONENAND_CTRL_ERROR) {
1195 printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
1196 return ONENAND_BBT_READ_ERROR;
1197 }
1198
1199 return 0;
1200}
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
1211 struct mtd_oob_ops *ops)
1212{
1213 struct onenand_chip *this = mtd->priv;
1214 int read = 0, thislen, column;
1215 int ret = 0, readcmd;
1216 size_t len = ops->ooblen;
1217 u_char *buf = ops->oobbuf;
1218
1219 pr_debug("onenand_bbt_read_oob: from = 0x%08x, len = %zi\n",
1220 (unsigned int) from, len);
1221
1222 readcmd = ONENAND_IS_4KB_PAGE(this) ?
1223 ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1224
1225
1226 ops->oobretlen = 0;
1227
1228
1229 if (unlikely((from + len) > mtd->size)) {
1230 printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
1231 return ONENAND_BBT_READ_FATAL_ERROR;
1232 }
1233
1234
1235 onenand_get_device(mtd, FL_READING);
1236
1237 column = from & (mtd->oobsize - 1);
1238
1239 while (read < len) {
1240
1241 thislen = mtd->oobsize - column;
1242 thislen = min_t(int, thislen, len);
1243
1244 this->spare_buf = buf;
1245 this->command(mtd, readcmd, from, mtd->oobsize);
1246
1247 onenand_update_bufferram(mtd, from, 0);
1248
1249 ret = this->bbt_wait(mtd, FL_READING);
1250 if (unlikely(ret))
1251 ret = onenand_recover_lsb(mtd, from, ret);
1252
1253 if (ret)
1254 break;
1255
1256 this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen);
1257 read += thislen;
1258 if (read == len)
1259 break;
1260
1261 buf += thislen;
1262
1263
1264 if (read < len) {
1265
1266 from += this->writesize;
1267 column = 0;
1268 }
1269 }
1270
1271
1272 onenand_release_device(mtd);
1273
1274 ops->oobretlen = read;
1275 return ret;
1276}
1277
1278
1279#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
1280
1281
1282
1283
1284
1285
1286static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
1287{
1288 struct onenand_chip *this = mtd->priv;
1289 u_char *oob_buf = this->oob_buf;
1290 int status, i, readcmd;
1291
1292 readcmd = ONENAND_IS_4KB_PAGE(this) ?
1293 ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1294
1295 this->command(mtd, readcmd, to, mtd->oobsize);
1296 onenand_update_bufferram(mtd, to, 0);
1297 status = this->wait(mtd, FL_READING);
1298 if (status)
1299 return status;
1300
1301 this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
1302 for (i = 0; i < mtd->oobsize; i++)
1303 if (buf[i] != 0xFF && buf[i] != oob_buf[i])
1304 return -EBADMSG;
1305
1306 return 0;
1307}
1308
1309
1310
1311
1312
1313
1314
1315
1316static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len)
1317{
1318 struct onenand_chip *this = mtd->priv;
1319 void __iomem *dataram;
1320 int ret = 0;
1321 int thislen, column;
1322
1323 while (len != 0) {
1324 thislen = min_t(int, this->writesize, len);
1325 column = addr & (this->writesize - 1);
1326 if (column + thislen > this->writesize)
1327 thislen = this->writesize - column;
1328
1329 this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
1330
1331 onenand_update_bufferram(mtd, addr, 0);
1332
1333 ret = this->wait(mtd, FL_READING);
1334 if (ret)
1335 return ret;
1336
1337 onenand_update_bufferram(mtd, addr, 1);
1338
1339 dataram = this->base + ONENAND_DATARAM;
1340 dataram += onenand_bufferram_offset(mtd, ONENAND_DATARAM);
1341
1342 if (memcmp(buf, dataram + column, thislen))
1343 return -EBADMSG;
1344
1345 len -= thislen;
1346 buf += thislen;
1347 addr += thislen;
1348 }
1349
1350 return 0;
1351}
1352#else
1353#define onenand_verify(...) (0)
1354#define onenand_verify_oob(...) (0)
1355#endif
1356
1357#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0)
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
1368 const u_char *buf, int column, int thislen)
1369{
1370 struct onenand_chip *this = mtd->priv;
1371 struct nand_oobfree *free;
1372 int writecol = column;
1373 int writeend = column + thislen;
1374 int lastgap = 0;
1375 unsigned int i;
1376
1377 free = this->ecclayout->oobfree;
1378 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
1379 i++, free++) {
1380 if (writecol >= lastgap)
1381 writecol += free->offset - lastgap;
1382 if (writeend >= lastgap)
1383 writeend += free->offset - lastgap;
1384 lastgap = free->offset + free->length;
1385 }
1386 free = this->ecclayout->oobfree;
1387 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
1388 i++, free++) {
1389 int free_end = free->offset + free->length;
1390 if (free->offset < writeend && free_end > writecol) {
1391 int st = max_t(int,free->offset,writecol);
1392 int ed = min_t(int,free_end,writeend);
1393 int n = ed - st;
1394 memcpy(oob_buf + st, buf, n);
1395 buf += n;
1396 } else if (column == 0)
1397 break;
1398 }
1399 return 0;
1400}
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
1411 struct mtd_oob_ops *ops)
1412{
1413 struct onenand_chip *this = mtd->priv;
1414 int written = 0, column, thislen, subpage;
1415 int oobwritten = 0, oobcolumn, thisooblen, oobsize;
1416 size_t len = ops->len;
1417 size_t ooblen = ops->ooblen;
1418 const u_char *buf = ops->datbuf;
1419 const u_char *oob = ops->oobbuf;
1420 u_char *oobbuf;
1421 int ret = 0;
1422
1423 pr_debug("onenand_write_ops_nolock: to = 0x%08x, len = %i\n",
1424 (unsigned int) to, (int) len);
1425
1426
1427 ops->retlen = 0;
1428 ops->oobretlen = 0;
1429
1430
1431 if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
1432 printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
1433 return -EINVAL;
1434 }
1435
1436 if (ops->mode == MTD_OPS_AUTO_OOB)
1437 oobsize = this->ecclayout->oobavail;
1438 else
1439 oobsize = mtd->oobsize;
1440
1441 oobcolumn = to & (mtd->oobsize - 1);
1442
1443 column = to & (mtd->writesize - 1);
1444
1445
1446 while (written < len) {
1447 u_char *wbuf = (u_char *) buf;
1448
1449 thislen = min_t(int, mtd->writesize - column, len - written);
1450 thisooblen = min_t(int, oobsize - oobcolumn, ooblen - oobwritten);
1451
1452 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
1453
1454
1455 subpage = thislen < mtd->writesize;
1456 if (subpage) {
1457 memset(this->page_buf, 0xff, mtd->writesize);
1458 memcpy(this->page_buf + column, buf, thislen);
1459 wbuf = this->page_buf;
1460 }
1461
1462 this->write_bufferram(mtd, to, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
1463
1464 if (oob) {
1465 oobbuf = this->oob_buf;
1466
1467
1468
1469 memset(oobbuf, 0xff, mtd->oobsize);
1470 if (ops->mode == MTD_OPS_AUTO_OOB)
1471 onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
1472 else
1473 memcpy(oobbuf + oobcolumn, oob, thisooblen);
1474
1475 oobwritten += thisooblen;
1476 oob += thisooblen;
1477 oobcolumn = 0;
1478 } else
1479 oobbuf = (u_char *) ffchars;
1480
1481 this->write_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
1482
1483 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
1484
1485 ret = this->wait(mtd, FL_WRITING);
1486
1487
1488 onenand_update_bufferram(mtd, to, !ret && !subpage);
1489 if (ONENAND_IS_2PLANE(this)) {
1490 ONENAND_SET_BUFFERRAM1(this);
1491 onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
1492 }
1493
1494 if (ret) {
1495 printk(KERN_ERR "onenand_write_ops_nolock: write filaed %d\n", ret);
1496 break;
1497 }
1498
1499
1500 ret = onenand_verify(mtd, buf, to, thislen);
1501 if (ret) {
1502 printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
1503 break;
1504 }
1505
1506 written += thislen;
1507
1508 if (written == len)
1509 break;
1510
1511 column = 0;
1512 to += thislen;
1513 buf += thislen;
1514 }
1515
1516 ops->retlen = written;
1517
1518 return ret;
1519}
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
1533 struct mtd_oob_ops *ops)
1534{
1535 struct onenand_chip *this = mtd->priv;
1536 int column, ret = 0, oobsize;
1537 int written = 0, oobcmd;
1538 u_char *oobbuf;
1539 size_t len = ops->ooblen;
1540 const u_char *buf = ops->oobbuf;
1541 unsigned int mode = ops->mode;
1542
1543 to += ops->ooboffs;
1544
1545 pr_debug("onenand_write_oob_nolock: to = 0x%08x, len = %i\n",
1546 (unsigned int) to, (int) len);
1547
1548
1549 ops->oobretlen = 0;
1550
1551 if (mode == MTD_OPS_AUTO_OOB)
1552 oobsize = this->ecclayout->oobavail;
1553 else
1554 oobsize = mtd->oobsize;
1555
1556 column = to & (mtd->oobsize - 1);
1557
1558 if (unlikely(column >= oobsize)) {
1559 printk(KERN_ERR "onenand_write_oob_nolock: Attempted to start write outside oob\n");
1560 return -EINVAL;
1561 }
1562
1563
1564 if (unlikely(column + len > oobsize)) {
1565 printk(KERN_ERR "onenand_write_oob_nolock: "
1566 "Attempt to write past end of page\n");
1567 return -EINVAL;
1568 }
1569
1570
1571 if (unlikely(to >= mtd->size ||
1572 column + len > ((mtd->size >> this->page_shift) -
1573 (to >> this->page_shift)) * oobsize)) {
1574 printk(KERN_ERR "onenand_write_oob_nolock: Attempted to write past end of device\n");
1575 return -EINVAL;
1576 }
1577
1578 oobbuf = this->oob_buf;
1579
1580 oobcmd = ONENAND_IS_4KB_PAGE(this) ?
1581 ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
1582
1583
1584 while (written < len) {
1585 int thislen = min_t(int, oobsize, len - written);
1586
1587 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
1588
1589
1590
1591 memset(oobbuf, 0xff, mtd->oobsize);
1592 if (mode == MTD_OPS_AUTO_OOB)
1593 onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
1594 else
1595 memcpy(oobbuf + column, buf, thislen);
1596 this->write_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
1597
1598 if (ONENAND_IS_4KB_PAGE(this)) {
1599
1600 memset(this->page_buf, 0xff, mtd->writesize);
1601 this->write_bufferram(mtd, 0, ONENAND_DATARAM,
1602 this->page_buf, 0, mtd->writesize);
1603 }
1604
1605 this->command(mtd, oobcmd, to, mtd->oobsize);
1606
1607 onenand_update_bufferram(mtd, to, 0);
1608 if (ONENAND_IS_2PLANE(this)) {
1609 ONENAND_SET_BUFFERRAM1(this);
1610 onenand_update_bufferram(mtd, to + this->writesize, 0);
1611 }
1612
1613 ret = this->wait(mtd, FL_WRITING);
1614 if (ret) {
1615 printk(KERN_ERR "onenand_write_oob_nolock: write failed %d\n", ret);
1616 break;
1617 }
1618
1619 ret = onenand_verify_oob(mtd, oobbuf, to);
1620 if (ret) {
1621 printk(KERN_ERR "onenand_write_oob_nolock: verify failed %d\n", ret);
1622 break;
1623 }
1624
1625 written += thislen;
1626 if (written == len)
1627 break;
1628
1629 to += mtd->writesize;
1630 buf += thislen;
1631 column = 0;
1632 }
1633
1634 ops->oobretlen = written;
1635
1636 return ret;
1637}
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
1650 size_t * retlen, const u_char * buf)
1651{
1652 struct mtd_oob_ops ops = {
1653 .len = len,
1654 .ooblen = 0,
1655 .datbuf = (u_char *) buf,
1656 .oobbuf = NULL,
1657 };
1658 int ret;
1659
1660 onenand_get_device(mtd, FL_WRITING);
1661 ret = onenand_write_ops_nolock(mtd, to, &ops);
1662 onenand_release_device(mtd);
1663
1664 *retlen = ops.retlen;
1665 return ret;
1666}
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676int onenand_write_oob(struct mtd_info *mtd, loff_t to,
1677 struct mtd_oob_ops *ops)
1678{
1679 int ret;
1680
1681 switch (ops->mode) {
1682 case MTD_OPS_PLACE_OOB:
1683 case MTD_OPS_AUTO_OOB:
1684 break;
1685 case MTD_OPS_RAW:
1686
1687 default:
1688 return -EINVAL;
1689 }
1690
1691 onenand_get_device(mtd, FL_WRITING);
1692 if (ops->datbuf)
1693 ret = onenand_write_ops_nolock(mtd, to, ops);
1694 else
1695 ret = onenand_write_oob_nolock(mtd, to, ops);
1696 onenand_release_device(mtd);
1697
1698 return ret;
1699
1700}
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allowbbt)
1712{
1713 struct onenand_chip *this = mtd->priv;
1714 struct bbm_info *bbm = this->bbm;
1715
1716
1717 return bbm->isbad_bbt(mtd, ofs, allowbbt);
1718}
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1729{
1730 struct onenand_chip *this = mtd->priv;
1731 unsigned int block_size;
1732 loff_t addr = instr->addr;
1733 unsigned int len = instr->len;
1734 int ret = 0, i;
1735 struct mtd_erase_region_info *region = NULL;
1736 unsigned int region_end = 0;
1737
1738 pr_debug("onenand_erase: start = 0x%08x, len = %i\n",
1739 (unsigned int) addr, len);
1740
1741 if (FLEXONENAND(this)) {
1742
1743 i = flexonenand_region(mtd, addr);
1744 region = &mtd->eraseregions[i];
1745
1746 block_size = region->erasesize;
1747 region_end = region->offset
1748 + region->erasesize * region->numblocks;
1749
1750
1751
1752
1753 if (unlikely((addr - region->offset) & (block_size - 1))) {
1754 pr_debug("onenand_erase:" " Unaligned address\n");
1755 return -EINVAL;
1756 }
1757 } else {
1758 block_size = 1 << this->erase_shift;
1759
1760
1761 if (unlikely(addr & (block_size - 1))) {
1762 pr_debug("onenand_erase:" "Unaligned address\n");
1763 return -EINVAL;
1764 }
1765 }
1766
1767
1768 if (unlikely(len & (block_size - 1))) {
1769 pr_debug("onenand_erase: Length not block aligned\n");
1770 return -EINVAL;
1771 }
1772
1773
1774 onenand_get_device(mtd, FL_ERASING);
1775
1776
1777 instr->state = MTD_ERASING;
1778
1779 while (len) {
1780
1781
1782 if (instr->priv == 0 && onenand_block_isbad_nolock(mtd, addr, 0)) {
1783 printk(KERN_WARNING "onenand_erase: attempt to erase"
1784 " a bad block at addr 0x%08x\n",
1785 (unsigned int) addr);
1786 instr->state = MTD_ERASE_FAILED;
1787 goto erase_exit;
1788 }
1789
1790 this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
1791
1792 onenand_invalidate_bufferram(mtd, addr, block_size);
1793
1794 ret = this->wait(mtd, FL_ERASING);
1795
1796 if (ret) {
1797 if (ret == -EPERM)
1798 pr_debug("onenand_erase: "
1799 "Device is write protected!!!\n");
1800 else
1801 pr_debug("onenand_erase: "
1802 "Failed erase, block %d\n",
1803 onenand_block(this, addr));
1804 instr->state = MTD_ERASE_FAILED;
1805 instr->fail_addr = addr;
1806
1807 goto erase_exit;
1808 }
1809
1810 len -= block_size;
1811 addr += block_size;
1812
1813 if (addr == region_end) {
1814 if (!len)
1815 break;
1816 region++;
1817
1818 block_size = region->erasesize;
1819 region_end = region->offset
1820 + region->erasesize * region->numblocks;
1821
1822 if (len & (block_size - 1)) {
1823
1824
1825 printk("onenand_erase: Unaligned address\n");
1826 goto erase_exit;
1827 }
1828 }
1829 }
1830
1831 instr->state = MTD_ERASE_DONE;
1832
1833erase_exit:
1834
1835 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
1836
1837 if (!ret)
1838 mtd_erase_callback(instr);
1839
1840
1841 onenand_release_device(mtd);
1842
1843 return ret;
1844}
1845
1846
1847
1848
1849
1850
1851
1852void onenand_sync(struct mtd_info *mtd)
1853{
1854 pr_debug("onenand_sync: called\n");
1855
1856
1857 onenand_get_device(mtd, FL_SYNCING);
1858
1859
1860 onenand_release_device(mtd);
1861}
1862
1863
1864
1865
1866
1867
1868
1869
1870int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
1871{
1872 int ret;
1873
1874
1875 if (ofs > mtd->size)
1876 return -EINVAL;
1877
1878 onenand_get_device(mtd, FL_READING);
1879 ret = onenand_block_isbad_nolock(mtd,ofs, 0);
1880 onenand_release_device(mtd);
1881 return ret;
1882}
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
1893{
1894 struct onenand_chip *this = mtd->priv;
1895 struct bbm_info *bbm = this->bbm;
1896 u_char buf[2] = {0, 0};
1897 struct mtd_oob_ops ops = {
1898 .mode = MTD_OPS_PLACE_OOB,
1899 .ooblen = 2,
1900 .oobbuf = buf,
1901 .ooboffs = 0,
1902 };
1903 int block;
1904
1905
1906 block = onenand_block(this, ofs);
1907 if (bbm->bbt)
1908 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
1909
1910
1911 ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
1912 return onenand_write_oob_nolock(mtd, ofs, &ops);
1913}
1914
1915
1916
1917
1918
1919
1920
1921
1922int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
1923{
1924 struct onenand_chip *this = mtd->priv;
1925 int ret;
1926
1927 ret = onenand_block_isbad(mtd, ofs);
1928 if (ret) {
1929
1930 if (ret > 0)
1931 return 0;
1932 return ret;
1933 }
1934
1935 onenand_get_device(mtd, FL_WRITING);
1936 ret = this->block_markbad(mtd, ofs);
1937 onenand_release_device(mtd);
1938
1939 return ret;
1940}
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd)
1952{
1953 struct onenand_chip *this = mtd->priv;
1954 int start, end, block, value, status;
1955
1956 start = onenand_block(this, ofs);
1957 end = onenand_block(this, ofs + len);
1958
1959
1960 if (this->options & ONENAND_HAS_CONT_LOCK) {
1961
1962 this->write_word(start,
1963 this->base + ONENAND_REG_START_BLOCK_ADDRESS);
1964
1965 this->write_word(end - 1,
1966 this->base + ONENAND_REG_END_BLOCK_ADDRESS);
1967
1968 this->command(mtd, cmd, 0, 0);
1969
1970
1971 this->wait(mtd, FL_UNLOCKING);
1972
1973
1974 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
1975 & ONENAND_CTRL_ONGO)
1976 continue;
1977
1978
1979 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
1980 if (!(status & ONENAND_WP_US))
1981 printk(KERN_ERR "wp status = 0x%x\n", status);
1982
1983 return 0;
1984 }
1985
1986
1987 for (block = start; block < end; block++) {
1988
1989 value = onenand_block_address(this, block);
1990 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
1991
1992 value = onenand_bufferram_address(this, block);
1993 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
1994
1995
1996 this->write_word(block,
1997 this->base + ONENAND_REG_START_BLOCK_ADDRESS);
1998
1999 this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
2000
2001
2002 this->wait(mtd, FL_UNLOCKING);
2003
2004
2005 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
2006 & ONENAND_CTRL_ONGO)
2007 continue;
2008
2009
2010 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
2011 if (!(status & ONENAND_WP_US))
2012 printk(KERN_ERR "block = %d, wp status = 0x%x\n",
2013 block, status);
2014 }
2015
2016 return 0;
2017}
2018
2019#ifdef ONENAND_LINUX
2020
2021
2022
2023
2024
2025
2026
2027
2028static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
2029{
2030 int ret;
2031
2032 onenand_get_device(mtd, FL_LOCKING);
2033 ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
2034 onenand_release_device(mtd);
2035 return ret;
2036}
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
2047{
2048 int ret;
2049
2050 onenand_get_device(mtd, FL_LOCKING);
2051 ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
2052 onenand_release_device(mtd);
2053 return ret;
2054}
2055#endif
2056
2057
2058
2059
2060
2061
2062
2063static int onenand_check_lock_status(struct onenand_chip *this)
2064{
2065 unsigned int value, block, status;
2066 unsigned int end;
2067
2068 end = this->chipsize >> this->erase_shift;
2069 for (block = 0; block < end; block++) {
2070
2071 value = onenand_block_address(this, block);
2072 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
2073
2074 value = onenand_bufferram_address(this, block);
2075 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
2076
2077 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2078
2079
2080 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
2081 if (!(status & ONENAND_WP_US)) {
2082 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
2083 return 0;
2084 }
2085 }
2086
2087 return 1;
2088}
2089
2090
2091
2092
2093
2094
2095
2096static void onenand_unlock_all(struct mtd_info *mtd)
2097{
2098 struct onenand_chip *this = mtd->priv;
2099 loff_t ofs = 0;
2100 size_t len = mtd->size;
2101
2102 if (this->options & ONENAND_HAS_UNLOCK_ALL) {
2103
2104 this->write_word(0, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2105
2106 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
2107
2108
2109 this->wait(mtd, FL_LOCKING);
2110
2111
2112 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
2113 & ONENAND_CTRL_ONGO)
2114 continue;
2115
2116
2117 if (onenand_check_lock_status(this))
2118 return;
2119
2120
2121 if (ONENAND_IS_DDP(this) && !FLEXONENAND(this)) {
2122
2123 ofs = this->chipsize >> 1;
2124 len = this->chipsize >> 1;
2125 }
2126 }
2127
2128 onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
2129}
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140static void onenand_check_features(struct mtd_info *mtd)
2141{
2142 struct onenand_chip *this = mtd->priv;
2143 unsigned int density, process;
2144
2145
2146 density = onenand_get_density(this->device_id);
2147 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
2148
2149
2150 switch (density) {
2151 case ONENAND_DEVICE_DENSITY_4Gb:
2152 if (ONENAND_IS_DDP(this))
2153 this->options |= ONENAND_HAS_2PLANE;
2154 else
2155 this->options |= ONENAND_HAS_4KB_PAGE;
2156
2157 case ONENAND_DEVICE_DENSITY_2Gb:
2158
2159 if (!ONENAND_IS_DDP(this))
2160 this->options |= ONENAND_HAS_2PLANE;
2161 this->options |= ONENAND_HAS_UNLOCK_ALL;
2162
2163 case ONENAND_DEVICE_DENSITY_1Gb:
2164
2165 if (process)
2166 this->options |= ONENAND_HAS_UNLOCK_ALL;
2167 break;
2168
2169 default:
2170
2171 if (!process)
2172 this->options |= ONENAND_HAS_CONT_LOCK;
2173 break;
2174 }
2175
2176 if (ONENAND_IS_MLC(this))
2177 this->options |= ONENAND_HAS_4KB_PAGE;
2178
2179 if (ONENAND_IS_4KB_PAGE(this))
2180 this->options &= ~ONENAND_HAS_2PLANE;
2181
2182 if (FLEXONENAND(this)) {
2183 this->options &= ~ONENAND_HAS_CONT_LOCK;
2184 this->options |= ONENAND_HAS_UNLOCK_ALL;
2185 }
2186
2187 if (this->options & ONENAND_HAS_CONT_LOCK)
2188 printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
2189 if (this->options & ONENAND_HAS_UNLOCK_ALL)
2190 printk(KERN_DEBUG "Chip support all block unlock\n");
2191 if (this->options & ONENAND_HAS_2PLANE)
2192 printk(KERN_DEBUG "Chip has 2 plane\n");
2193 if (this->options & ONENAND_HAS_4KB_PAGE)
2194 printk(KERN_DEBUG "Chip has 4KiB pagesize\n");
2195
2196}
2197
2198
2199
2200
2201
2202
2203
2204char *onenand_print_device_info(int device, int version)
2205{
2206 int vcc, demuxed, ddp, density, flexonenand;
2207 char *dev_info = malloc(80);
2208 char *p = dev_info;
2209
2210 vcc = device & ONENAND_DEVICE_VCC_MASK;
2211 demuxed = device & ONENAND_DEVICE_IS_DEMUX;
2212 ddp = device & ONENAND_DEVICE_IS_DDP;
2213 density = onenand_get_density(device);
2214 flexonenand = device & DEVICE_IS_FLEXONENAND;
2215 p += sprintf(dev_info, "%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)",
2216 demuxed ? "" : "Muxed ",
2217 flexonenand ? "Flex-" : "",
2218 ddp ? "(DDP)" : "",
2219 (16 << density), vcc ? "2.65/3.3" : "1.8", device);
2220
2221 sprintf(p, "\nOneNAND version = 0x%04x", version);
2222 printk("%s\n", dev_info);
2223
2224 return dev_info;
2225}
2226
2227static const struct onenand_manufacturers onenand_manuf_ids[] = {
2228 {ONENAND_MFR_NUMONYX, "Numonyx"},
2229 {ONENAND_MFR_SAMSUNG, "Samsung"},
2230};
2231
2232
2233
2234
2235
2236
2237
2238static int onenand_check_maf(int manuf)
2239{
2240 int size = ARRAY_SIZE(onenand_manuf_ids);
2241 int i;
2242#ifdef ONENAND_DEBUG
2243 char *name;
2244#endif
2245
2246 for (i = 0; i < size; i++)
2247 if (manuf == onenand_manuf_ids[i].id)
2248 break;
2249
2250#ifdef ONENAND_DEBUG
2251 if (i < size)
2252 name = onenand_manuf_ids[i].name;
2253 else
2254 name = "Unknown";
2255
2256 printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);
2257#endif
2258
2259 return i == size;
2260}
2261
2262
2263
2264
2265
2266
2267
2268static int flexonenand_get_boundary(struct mtd_info *mtd)
2269{
2270 struct onenand_chip *this = mtd->priv;
2271 unsigned int die, bdry;
2272 int syscfg, locked;
2273
2274
2275 syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
2276 this->write_word((syscfg | 0x0100), this->base + ONENAND_REG_SYS_CFG1);
2277
2278 for (die = 0; die < this->dies; die++) {
2279 this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
2280 this->wait(mtd, FL_SYNCING);
2281
2282 this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
2283 this->wait(mtd, FL_READING);
2284
2285 bdry = this->read_word(this->base + ONENAND_DATARAM);
2286 if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
2287 locked = 0;
2288 else
2289 locked = 1;
2290 this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
2291
2292 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
2293 this->wait(mtd, FL_RESETING);
2294
2295 printk(KERN_INFO "Die %d boundary: %d%s\n", die,
2296 this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
2297 }
2298
2299
2300 this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
2301 return 0;
2302}
2303
2304
2305
2306
2307
2308
2309
2310static void flexonenand_get_size(struct mtd_info *mtd)
2311{
2312 struct onenand_chip *this = mtd->priv;
2313 int die, i, eraseshift, density;
2314 int blksperdie, maxbdry;
2315 loff_t ofs;
2316
2317 density = onenand_get_density(this->device_id);
2318 blksperdie = ((loff_t)(16 << density) << 20) >> (this->erase_shift);
2319 blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
2320 maxbdry = blksperdie - 1;
2321 eraseshift = this->erase_shift - 1;
2322
2323 mtd->numeraseregions = this->dies << 1;
2324
2325
2326 flexonenand_get_boundary(mtd);
2327 die = 0;
2328 ofs = 0;
2329 i = -1;
2330 for (; die < this->dies; die++) {
2331 if (!die || this->boundary[die-1] != maxbdry) {
2332 i++;
2333 mtd->eraseregions[i].offset = ofs;
2334 mtd->eraseregions[i].erasesize = 1 << eraseshift;
2335 mtd->eraseregions[i].numblocks =
2336 this->boundary[die] + 1;
2337 ofs += mtd->eraseregions[i].numblocks << eraseshift;
2338 eraseshift++;
2339 } else {
2340 mtd->numeraseregions -= 1;
2341 mtd->eraseregions[i].numblocks +=
2342 this->boundary[die] + 1;
2343 ofs += (this->boundary[die] + 1) << (eraseshift - 1);
2344 }
2345 if (this->boundary[die] != maxbdry) {
2346 i++;
2347 mtd->eraseregions[i].offset = ofs;
2348 mtd->eraseregions[i].erasesize = 1 << eraseshift;
2349 mtd->eraseregions[i].numblocks = maxbdry ^
2350 this->boundary[die];
2351 ofs += mtd->eraseregions[i].numblocks << eraseshift;
2352 eraseshift--;
2353 } else
2354 mtd->numeraseregions -= 1;
2355 }
2356
2357
2358 mtd->erasesize = 1 << this->erase_shift;
2359 if (mtd->numeraseregions == 1)
2360 mtd->erasesize >>= 1;
2361
2362 printk(KERN_INFO "Device has %d eraseregions\n", mtd->numeraseregions);
2363 for (i = 0; i < mtd->numeraseregions; i++)
2364 printk(KERN_INFO "[offset: 0x%08llx, erasesize: 0x%05x,"
2365 " numblocks: %04u]\n", mtd->eraseregions[i].offset,
2366 mtd->eraseregions[i].erasesize,
2367 mtd->eraseregions[i].numblocks);
2368
2369 for (die = 0, mtd->size = 0; die < this->dies; die++) {
2370 this->diesize[die] = (loff_t) (blksperdie << this->erase_shift);
2371 this->diesize[die] -= (loff_t) (this->boundary[die] + 1)
2372 << (this->erase_shift - 1);
2373 mtd->size += this->diesize[die];
2374 }
2375}
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391static int flexonenand_check_blocks_erased(struct mtd_info *mtd,
2392 int start, int end)
2393{
2394 struct onenand_chip *this = mtd->priv;
2395 int i, ret;
2396 int block;
2397 struct mtd_oob_ops ops = {
2398 .mode = MTD_OPS_PLACE_OOB,
2399 .ooboffs = 0,
2400 .ooblen = mtd->oobsize,
2401 .datbuf = NULL,
2402 .oobbuf = this->oob_buf,
2403 };
2404 loff_t addr;
2405
2406 printk(KERN_DEBUG "Check blocks from %d to %d\n", start, end);
2407
2408 for (block = start; block <= end; block++) {
2409 addr = flexonenand_addr(this, block);
2410 if (onenand_block_isbad_nolock(mtd, addr, 0))
2411 continue;
2412
2413
2414
2415
2416
2417 ret = onenand_read_oob_nolock(mtd, addr, &ops);
2418 if (ret)
2419 return ret;
2420
2421 for (i = 0; i < mtd->oobsize; i++)
2422 if (this->oob_buf[i] != 0xff)
2423 break;
2424
2425 if (i != mtd->oobsize) {
2426 printk(KERN_WARNING "Block %d not erased.\n", block);
2427 return 1;
2428 }
2429 }
2430
2431 return 0;
2432}
2433
2434
2435
2436
2437
2438int flexonenand_set_boundary(struct mtd_info *mtd, int die,
2439 int boundary, int lock)
2440{
2441 struct onenand_chip *this = mtd->priv;
2442 int ret, density, blksperdie, old, new, thisboundary;
2443 loff_t addr;
2444
2445 if (die >= this->dies)
2446 return -EINVAL;
2447
2448 if (boundary == this->boundary[die])
2449 return 0;
2450
2451 density = onenand_get_density(this->device_id);
2452 blksperdie = ((16 << density) << 20) >> this->erase_shift;
2453 blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
2454
2455 if (boundary >= blksperdie) {
2456 printk("flexonenand_set_boundary:"
2457 "Invalid boundary value. "
2458 "Boundary not changed.\n");
2459 return -EINVAL;
2460 }
2461
2462
2463 old = this->boundary[die] + (die * this->density_mask);
2464 new = boundary + (die * this->density_mask);
2465 ret = flexonenand_check_blocks_erased(mtd, min(old, new)
2466 + 1, max(old, new));
2467 if (ret) {
2468 printk(KERN_ERR "flexonenand_set_boundary: Please erase blocks before boundary change\n");
2469 return ret;
2470 }
2471
2472 this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
2473 this->wait(mtd, FL_SYNCING);
2474
2475
2476 this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
2477 ret = this->wait(mtd, FL_READING);
2478
2479 thisboundary = this->read_word(this->base + ONENAND_DATARAM);
2480 if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
2481 printk(KERN_ERR "flexonenand_set_boundary: boundary locked\n");
2482 goto out;
2483 }
2484
2485 printk(KERN_INFO "flexonenand_set_boundary: Changing die %d boundary: %d%s\n",
2486 die, boundary, lock ? "(Locked)" : "(Unlocked)");
2487
2488 boundary &= FLEXONENAND_PI_MASK;
2489 boundary |= lock ? 0 : (3 << FLEXONENAND_PI_UNLOCK_SHIFT);
2490
2491 addr = die ? this->diesize[0] : 0;
2492 this->command(mtd, ONENAND_CMD_ERASE, addr, 0);
2493 ret = this->wait(mtd, FL_ERASING);
2494 if (ret) {
2495 printk("flexonenand_set_boundary:"
2496 "Failed PI erase for Die %d\n", die);
2497 goto out;
2498 }
2499
2500 this->write_word(boundary, this->base + ONENAND_DATARAM);
2501 this->command(mtd, ONENAND_CMD_PROG, addr, 0);
2502 ret = this->wait(mtd, FL_WRITING);
2503 if (ret) {
2504 printk("flexonenand_set_boundary:"
2505 "Failed PI write for Die %d\n", die);
2506 goto out;
2507 }
2508
2509 this->command(mtd, FLEXONENAND_CMD_PI_UPDATE, die, 0);
2510 ret = this->wait(mtd, FL_WRITING);
2511out:
2512 this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND);
2513 this->wait(mtd, FL_RESETING);
2514 if (!ret)
2515
2516 flexonenand_get_size(mtd);
2517
2518 return ret;
2519}
2520
2521
2522
2523
2524
2525
2526
2527
2528static int onenand_chip_probe(struct mtd_info *mtd)
2529{
2530 struct onenand_chip *this = mtd->priv;
2531 int bram_maf_id, bram_dev_id, maf_id, dev_id;
2532 int syscfg;
2533
2534
2535 syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
2536
2537
2538 this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ),
2539 this->base + ONENAND_REG_SYS_CFG1);
2540
2541
2542 this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);
2543
2544
2545 bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0);
2546 bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2);
2547
2548
2549 this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
2550
2551
2552 if (this->wait(mtd, FL_RESETING))
2553 return -ENXIO;
2554
2555
2556 this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
2557
2558
2559 if (onenand_check_maf(bram_maf_id))
2560 return -ENXIO;
2561
2562
2563 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
2564 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
2565
2566
2567 if (maf_id != bram_maf_id || dev_id != bram_dev_id)
2568 return -ENXIO;
2569
2570 return 0;
2571}
2572
2573
2574
2575
2576
2577
2578
2579
2580int onenand_probe(struct mtd_info *mtd)
2581{
2582 struct onenand_chip *this = mtd->priv;
2583 int dev_id, ver_id;
2584 int density;
2585 int ret;
2586
2587 ret = this->chip_probe(mtd);
2588 if (ret)
2589 return ret;
2590
2591
2592 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
2593 ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
2594 this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
2595
2596
2597 mtd->name = onenand_print_device_info(dev_id, ver_id);
2598 this->device_id = dev_id;
2599 this->version_id = ver_id;
2600
2601
2602 onenand_check_features(mtd);
2603
2604 density = onenand_get_density(dev_id);
2605 if (FLEXONENAND(this)) {
2606 this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
2607
2608 mtd->numeraseregions = this->dies << 1;
2609 mtd->eraseregions = malloc(sizeof(struct mtd_erase_region_info)
2610 * (this->dies << 1));
2611 if (!mtd->eraseregions)
2612 return -ENOMEM;
2613 }
2614
2615
2616
2617
2618
2619 this->chipsize = (16 << density) << 20;
2620
2621
2622
2623 mtd->writesize =
2624 this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
2625
2626 if (ONENAND_IS_4KB_PAGE(this))
2627 mtd->writesize <<= 1;
2628
2629 mtd->oobsize = mtd->writesize >> 5;
2630
2631 mtd->erasesize = mtd->writesize << 6;
2632
2633
2634
2635
2636
2637 if (FLEXONENAND(this))
2638 mtd->erasesize <<= 1;
2639
2640 this->erase_shift = ffs(mtd->erasesize) - 1;
2641 this->page_shift = ffs(mtd->writesize) - 1;
2642 this->ppb_shift = (this->erase_shift - this->page_shift);
2643 this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
2644
2645 if (ONENAND_IS_DDP(this))
2646 this->density_mask = this->chipsize >> (this->erase_shift + 1);
2647
2648 this->writesize = mtd->writesize;
2649
2650
2651
2652 if (FLEXONENAND(this))
2653 flexonenand_get_size(mtd);
2654 else
2655 mtd->size = this->chipsize;
2656
2657 mtd->flags = MTD_CAP_NANDFLASH;
2658 mtd->_erase = onenand_erase;
2659 mtd->_read_oob = onenand_read_oob;
2660 mtd->_write_oob = onenand_write_oob;
2661 mtd->_sync = onenand_sync;
2662 mtd->_block_isbad = onenand_block_isbad;
2663 mtd->_block_markbad = onenand_block_markbad;
2664 mtd->writebufsize = mtd->writesize;
2665
2666 return 0;
2667}
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679int onenand_scan(struct mtd_info *mtd, int maxchips)
2680{
2681 int i;
2682 struct onenand_chip *this = mtd->priv;
2683
2684 if (!this->read_word)
2685 this->read_word = onenand_readw;
2686 if (!this->write_word)
2687 this->write_word = onenand_writew;
2688
2689 if (!this->command)
2690 this->command = onenand_command;
2691 if (!this->wait)
2692 this->wait = onenand_wait;
2693 if (!this->bbt_wait)
2694 this->bbt_wait = onenand_bbt_wait;
2695
2696 if (!this->read_bufferram)
2697 this->read_bufferram = onenand_read_bufferram;
2698 if (!this->write_bufferram)
2699 this->write_bufferram = onenand_write_bufferram;
2700
2701 if (!this->chip_probe)
2702 this->chip_probe = onenand_chip_probe;
2703
2704 if (!this->block_markbad)
2705 this->block_markbad = onenand_default_block_markbad;
2706 if (!this->scan_bbt)
2707 this->scan_bbt = onenand_default_bbt;
2708
2709 if (onenand_probe(mtd))
2710 return -ENXIO;
2711
2712
2713 if (this->mmcontrol) {
2714 printk(KERN_INFO "OneNAND Sync. Burst Read support\n");
2715 this->read_bufferram = onenand_sync_read_bufferram;
2716 }
2717
2718
2719 if (!this->page_buf) {
2720 this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
2721 if (!this->page_buf) {
2722 printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
2723 return -ENOMEM;
2724 }
2725 this->options |= ONENAND_PAGEBUF_ALLOC;
2726 }
2727 if (!this->oob_buf) {
2728 this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
2729 if (!this->oob_buf) {
2730 printk(KERN_ERR "onenand_scan: Can't allocate oob_buf\n");
2731 if (this->options & ONENAND_PAGEBUF_ALLOC) {
2732 this->options &= ~ONENAND_PAGEBUF_ALLOC;
2733 kfree(this->page_buf);
2734 }
2735 return -ENOMEM;
2736 }
2737 this->options |= ONENAND_OOBBUF_ALLOC;
2738 }
2739
2740 this->state = FL_READY;
2741
2742
2743
2744
2745 switch (mtd->oobsize) {
2746 case 128:
2747 this->ecclayout = &onenand_oob_128;
2748 mtd->subpage_sft = 0;
2749 break;
2750
2751 case 64:
2752 this->ecclayout = &onenand_oob_64;
2753 mtd->subpage_sft = 2;
2754 break;
2755
2756 case 32:
2757 this->ecclayout = &onenand_oob_32;
2758 mtd->subpage_sft = 1;
2759 break;
2760
2761 default:
2762 printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
2763 mtd->oobsize);
2764 mtd->subpage_sft = 0;
2765
2766 this->ecclayout = &onenand_oob_32;
2767 break;
2768 }
2769
2770 this->subpagesize = mtd->writesize >> mtd->subpage_sft;
2771
2772
2773
2774
2775
2776 this->ecclayout->oobavail = 0;
2777
2778 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE &&
2779 this->ecclayout->oobfree[i].length; i++)
2780 this->ecclayout->oobavail +=
2781 this->ecclayout->oobfree[i].length;
2782 mtd->oobavail = this->ecclayout->oobavail;
2783
2784 mtd->ecclayout = this->ecclayout;
2785
2786
2787 onenand_unlock_all(mtd);
2788
2789 return this->scan_bbt(mtd);
2790}
2791
2792
2793
2794
2795
2796void onenand_release(struct mtd_info *mtd)
2797{
2798}
2799