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