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