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