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