1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/init.h>
25#include <linux/sched.h>
26#include <linux/delay.h>
27#include <linux/interrupt.h>
28#include <linux/jiffies.h>
29#include <linux/mtd/mtd.h>
30#include <linux/mtd/onenand.h>
31#include <linux/mtd/partitions.h>
32
33#include <asm/io.h>
34
35
36static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };
37
38module_param_array(flex_bdry, int, NULL, 0400);
39MODULE_PARM_DESC(flex_bdry, "SLC Boundary information for Flex-OneNAND"
40 "Syntax:flex_bdry=DIE_BDRY,LOCK,..."
41 "DIE_BDRY: SLC boundary of the die"
42 "LOCK: Locking information for SLC boundary"
43 " : 0->Set boundary in unlocked status"
44 " : 1->Set boundary in locked status");
45
46
47
48
49
50static struct nand_ecclayout onenand_oob_128 = {
51 .eccbytes = 64,
52 .eccpos = {
53 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
54 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
55 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
56 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
57 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
58 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
59 102, 103, 104, 105
60 },
61 .oobfree = {
62 {2, 4}, {18, 4}, {34, 4}, {50, 4},
63 {66, 4}, {82, 4}, {98, 4}, {114, 4}
64 }
65};
66
67
68
69
70static struct nand_ecclayout onenand_oob_64 = {
71 .eccbytes = 20,
72 .eccpos = {
73 8, 9, 10, 11, 12,
74 24, 25, 26, 27, 28,
75 40, 41, 42, 43, 44,
76 56, 57, 58, 59, 60,
77 },
78 .oobfree = {
79 {2, 3}, {14, 2}, {18, 3}, {30, 2},
80 {34, 3}, {46, 2}, {50, 3}, {62, 2}
81 }
82};
83
84
85
86
87static struct nand_ecclayout onenand_oob_32 = {
88 .eccbytes = 10,
89 .eccpos = {
90 8, 9, 10, 11, 12,
91 24, 25, 26, 27, 28,
92 },
93 .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} }
94};
95
96static const unsigned char ffchars[] = {
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 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
112 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
113};
114
115
116
117
118
119
120
121static unsigned short onenand_readw(void __iomem *addr)
122{
123 return readw(addr);
124}
125
126
127
128
129
130
131
132
133static void onenand_writew(unsigned short value, void __iomem *addr)
134{
135 writew(value, addr);
136}
137
138
139
140
141
142
143
144
145
146static int onenand_block_address(struct onenand_chip *this, int block)
147{
148
149 if (block & this->density_mask)
150 return ONENAND_DDP_CHIP1 | (block ^ this->density_mask);
151
152 return block;
153}
154
155
156
157
158
159
160
161
162
163static int onenand_bufferram_address(struct onenand_chip *this, int block)
164{
165
166 if (block & this->density_mask)
167 return ONENAND_DDP_CHIP1;
168
169 return ONENAND_DDP_CHIP0;
170}
171
172
173
174
175
176
177
178
179
180static int onenand_page_address(int page, int sector)
181{
182
183 int fpa, fsa;
184
185 fpa = page & ONENAND_FPA_MASK;
186 fsa = sector & ONENAND_FSA_MASK;
187
188 return ((fpa << ONENAND_FPA_SHIFT) | fsa);
189}
190
191
192
193
194
195
196
197
198
199
200static int onenand_buffer_address(int dataram1, int sectors, int count)
201{
202 int bsa, bsc;
203
204
205 bsa = sectors & ONENAND_BSA_MASK;
206
207 if (dataram1)
208 bsa |= ONENAND_BSA_DATARAM1;
209 else
210 bsa |= ONENAND_BSA_DATARAM0;
211
212
213 bsc = count & ONENAND_BSC_MASK;
214
215 return ((bsa << ONENAND_BSA_SHIFT) | bsc);
216}
217
218
219
220
221
222
223static unsigned flexonenand_block(struct onenand_chip *this, loff_t addr)
224{
225 unsigned boundary, blk, die = 0;
226
227 if (ONENAND_IS_DDP(this) && addr >= this->diesize[0]) {
228 die = 1;
229 addr -= this->diesize[0];
230 }
231
232 boundary = this->boundary[die];
233
234 blk = addr >> (this->erase_shift - 1);
235 if (blk > boundary)
236 blk = (blk + boundary + 1) >> 1;
237
238 blk += die ? this->density_mask : 0;
239 return blk;
240}
241
242inline unsigned onenand_block(struct onenand_chip *this, loff_t addr)
243{
244 if (!FLEXONENAND(this))
245 return addr >> this->erase_shift;
246 return flexonenand_block(this, addr);
247}
248
249
250
251
252
253
254
255
256static loff_t flexonenand_addr(struct onenand_chip *this, int block)
257{
258 loff_t ofs = 0;
259 int die = 0, boundary;
260
261 if (ONENAND_IS_DDP(this) && block >= this->density_mask) {
262 block -= this->density_mask;
263 die = 1;
264 ofs = this->diesize[0];
265 }
266
267 boundary = this->boundary[die];
268 ofs += (loff_t)block << (this->erase_shift - 1);
269 if (block > (boundary + 1))
270 ofs += (loff_t)(block - boundary - 1) << (this->erase_shift - 1);
271 return ofs;
272}
273
274loff_t onenand_addr(struct onenand_chip *this, int block)
275{
276 if (!FLEXONENAND(this))
277 return (loff_t)block << this->erase_shift;
278 return flexonenand_addr(this, block);
279}
280EXPORT_SYMBOL(onenand_addr);
281
282
283
284
285
286
287
288static inline int onenand_get_density(int dev_id)
289{
290 int density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
291 return (density & ONENAND_DEVICE_DENSITY_MASK);
292}
293
294
295
296
297
298
299int flexonenand_region(struct mtd_info *mtd, loff_t addr)
300{
301 int i;
302
303 for (i = 0; i < mtd->numeraseregions; i++)
304 if (addr < mtd->eraseregions[i].offset)
305 break;
306 return i - 1;
307}
308EXPORT_SYMBOL(flexonenand_region);
309
310
311
312
313
314
315
316
317
318
319
320static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len)
321{
322 struct onenand_chip *this = mtd->priv;
323 int value, block, page;
324
325
326 switch (cmd) {
327 case ONENAND_CMD_UNLOCK:
328 case ONENAND_CMD_LOCK:
329 case ONENAND_CMD_LOCK_TIGHT:
330 case ONENAND_CMD_UNLOCK_ALL:
331 block = -1;
332 page = -1;
333 break;
334
335 case FLEXONENAND_CMD_PI_ACCESS:
336
337 block = addr * this->density_mask;
338 page = -1;
339 break;
340
341 case ONENAND_CMD_ERASE:
342 case ONENAND_CMD_BUFFERRAM:
343 case ONENAND_CMD_OTP_ACCESS:
344 block = onenand_block(this, addr);
345 page = -1;
346 break;
347
348 case FLEXONENAND_CMD_READ_PI:
349 cmd = ONENAND_CMD_READ;
350 block = addr * this->density_mask;
351 page = 0;
352 break;
353
354 default:
355 block = onenand_block(this, addr);
356 page = (int) (addr - onenand_addr(this, block)) >> this->page_shift;
357
358 if (ONENAND_IS_2PLANE(this)) {
359
360 block &= ~1;
361
362 if (addr & this->writesize)
363 block++;
364 page >>= 1;
365 }
366 page &= this->page_mask;
367 break;
368 }
369
370
371 if (cmd == ONENAND_CMD_BUFFERRAM) {
372
373 value = onenand_bufferram_address(this, block);
374 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
375
376 if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this))
377
378 ONENAND_SET_BUFFERRAM0(this);
379 else
380
381 ONENAND_SET_NEXT_BUFFERRAM(this);
382
383 return 0;
384 }
385
386 if (block != -1) {
387
388 value = onenand_block_address(this, block);
389 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
390
391
392 value = onenand_bufferram_address(this, block);
393 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
394 }
395
396 if (page != -1) {
397
398 int sectors = 0, count = 0;
399 int dataram;
400
401 switch (cmd) {
402 case FLEXONENAND_CMD_RECOVER_LSB:
403 case ONENAND_CMD_READ:
404 case ONENAND_CMD_READOOB:
405 if (ONENAND_IS_MLC(this))
406
407 dataram = ONENAND_SET_BUFFERRAM0(this);
408 else
409 dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
410 break;
411
412 default:
413 if (ONENAND_IS_2PLANE(this) && cmd == ONENAND_CMD_PROG)
414 cmd = ONENAND_CMD_2X_PROG;
415 dataram = ONENAND_CURRENT_BUFFERRAM(this);
416 break;
417 }
418
419
420 value = onenand_page_address(page, sectors);
421 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS8);
422
423
424 value = onenand_buffer_address(dataram, sectors, count);
425 this->write_word(value, this->base + ONENAND_REG_START_BUFFER);
426 }
427
428
429 this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT);
430
431
432 this->write_word(cmd, this->base + ONENAND_REG_COMMAND);
433
434 return 0;
435}
436
437
438
439
440
441static inline int onenand_read_ecc(struct onenand_chip *this)
442{
443 int ecc, i, result = 0;
444
445 if (!FLEXONENAND(this))
446 return this->read_word(this->base + ONENAND_REG_ECC_STATUS);
447
448 for (i = 0; i < 4; i++) {
449 ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i);
450 if (likely(!ecc))
451 continue;
452 if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR)
453 return ONENAND_ECC_2BIT_ALL;
454 else
455 result = ONENAND_ECC_1BIT_ALL;
456 }
457
458 return result;
459}
460
461
462
463
464
465
466
467
468
469
470static int onenand_wait(struct mtd_info *mtd, int state)
471{
472 struct onenand_chip * this = mtd->priv;
473 unsigned long timeout;
474 unsigned int flags = ONENAND_INT_MASTER;
475 unsigned int interrupt = 0;
476 unsigned int ctrl;
477
478
479 timeout = jiffies + msecs_to_jiffies(20);
480 while (time_before(jiffies, timeout)) {
481 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
482
483 if (interrupt & flags)
484 break;
485
486 if (state != FL_READING)
487 cond_resched();
488 }
489
490 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
491
492 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
493
494
495
496
497
498
499 if (interrupt & ONENAND_INT_READ) {
500 int ecc = onenand_read_ecc(this);
501 if (ecc) {
502 if (ecc & ONENAND_ECC_2BIT_ALL) {
503 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
504 mtd->ecc_stats.failed++;
505 return -EBADMSG;
506 } else if (ecc & ONENAND_ECC_1BIT_ALL) {
507 printk(KERN_DEBUG "onenand_wait: correctable ECC error = 0x%04x\n", ecc);
508 mtd->ecc_stats.corrected++;
509 }
510 }
511 } else if (state == FL_READING) {
512 printk(KERN_ERR "onenand_wait: read timeout! ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
513 return -EIO;
514 }
515
516
517 if (ctrl & ONENAND_CTRL_ERROR) {
518 printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n",
519 ctrl);
520 if (ctrl & ONENAND_CTRL_LOCK)
521 printk(KERN_ERR "onenand_wait: it's locked error.\n");
522 return -EIO;
523 }
524
525 return 0;
526}
527
528
529
530
531
532
533
534
535static irqreturn_t onenand_interrupt(int irq, void *data)
536{
537 struct onenand_chip *this = data;
538
539
540 if (!this->complete.done)
541 complete(&this->complete);
542
543 return IRQ_HANDLED;
544}
545
546
547
548
549
550
551
552
553static int onenand_interrupt_wait(struct mtd_info *mtd, int state)
554{
555 struct onenand_chip *this = mtd->priv;
556
557 wait_for_completion(&this->complete);
558
559 return onenand_wait(mtd, state);
560}
561
562
563
564
565
566
567
568
569static int onenand_try_interrupt_wait(struct mtd_info *mtd, int state)
570{
571 struct onenand_chip *this = mtd->priv;
572 unsigned long remain, timeout;
573
574
575 this->wait = onenand_interrupt_wait;
576
577 timeout = msecs_to_jiffies(100);
578 remain = wait_for_completion_timeout(&this->complete, timeout);
579 if (!remain) {
580 printk(KERN_INFO "OneNAND: There's no interrupt. "
581 "We use the normal wait\n");
582
583
584 free_irq(this->irq, this);
585
586 this->wait = onenand_wait;
587 }
588
589 return onenand_wait(mtd, state);
590}
591
592
593
594
595
596
597
598
599
600static void onenand_setup_wait(struct mtd_info *mtd)
601{
602 struct onenand_chip *this = mtd->priv;
603 int syscfg;
604
605 init_completion(&this->complete);
606
607 if (this->irq <= 0) {
608 this->wait = onenand_wait;
609 return;
610 }
611
612 if (request_irq(this->irq, &onenand_interrupt,
613 IRQF_SHARED, "onenand", this)) {
614
615 this->wait = onenand_wait;
616 return;
617 }
618
619
620 syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
621 syscfg |= ONENAND_SYS_CFG1_IOBE;
622 this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
623
624 this->wait = onenand_try_interrupt_wait;
625}
626
627
628
629
630
631
632
633
634
635static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
636{
637 struct onenand_chip *this = mtd->priv;
638
639 if (ONENAND_CURRENT_BUFFERRAM(this)) {
640
641 if (area == ONENAND_DATARAM)
642 return this->writesize;
643 if (area == ONENAND_SPARERAM)
644 return mtd->oobsize;
645 }
646
647 return 0;
648}
649
650
651
652
653
654
655
656
657
658
659
660static int onenand_read_bufferram(struct mtd_info *mtd, int area,
661 unsigned char *buffer, int offset, size_t count)
662{
663 struct onenand_chip *this = mtd->priv;
664 void __iomem *bufferram;
665
666 bufferram = this->base + area;
667
668 bufferram += onenand_bufferram_offset(mtd, area);
669
670 if (ONENAND_CHECK_BYTE_ACCESS(count)) {
671 unsigned short word;
672
673
674 count--;
675
676
677 word = this->read_word(bufferram + offset + count);
678 buffer[count] = (word & 0xff);
679 }
680
681 memcpy(buffer, bufferram + offset, count);
682
683 return 0;
684}
685
686
687
688
689
690
691
692
693
694
695
696static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area,
697 unsigned char *buffer, int offset, size_t count)
698{
699 struct onenand_chip *this = mtd->priv;
700 void __iomem *bufferram;
701
702 bufferram = this->base + area;
703
704 bufferram += onenand_bufferram_offset(mtd, area);
705
706 this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);
707
708 if (ONENAND_CHECK_BYTE_ACCESS(count)) {
709 unsigned short word;
710
711
712 count--;
713
714
715 word = this->read_word(bufferram + offset + count);
716 buffer[count] = (word & 0xff);
717 }
718
719 memcpy(buffer, bufferram + offset, count);
720
721 this->mmcontrol(mtd, 0);
722
723 return 0;
724}
725
726
727
728
729
730
731
732
733
734
735
736static int onenand_write_bufferram(struct mtd_info *mtd, int area,
737 const unsigned char *buffer, int offset, size_t count)
738{
739 struct onenand_chip *this = mtd->priv;
740 void __iomem *bufferram;
741
742 bufferram = this->base + area;
743
744 bufferram += onenand_bufferram_offset(mtd, area);
745
746 if (ONENAND_CHECK_BYTE_ACCESS(count)) {
747 unsigned short word;
748 int byte_offset;
749
750
751 count--;
752
753
754 byte_offset = offset + count;
755
756
757 word = this->read_word(bufferram + byte_offset);
758 word = (word & ~0xff) | buffer[count];
759 this->write_word(word, bufferram + byte_offset);
760 }
761
762 memcpy(bufferram + offset, buffer, count);
763
764 return 0;
765}
766
767
768
769
770
771
772
773
774
775static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
776{
777 struct onenand_chip *this = mtd->priv;
778 int blockpage, block, page;
779
780
781 block = (int) (addr >> this->erase_shift) & ~1;
782
783 if (addr & this->writesize)
784 block++;
785 page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
786 blockpage = (block << 7) | page;
787
788 return blockpage;
789}
790
791
792
793
794
795
796
797
798
799static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
800{
801 struct onenand_chip *this = mtd->priv;
802 int blockpage, found = 0;
803 unsigned int i;
804
805 if (ONENAND_IS_2PLANE(this))
806 blockpage = onenand_get_2x_blockpage(mtd, addr);
807 else
808 blockpage = (int) (addr >> this->page_shift);
809
810
811 i = ONENAND_CURRENT_BUFFERRAM(this);
812 if (this->bufferram[i].blockpage == blockpage)
813 found = 1;
814 else {
815
816 i = ONENAND_NEXT_BUFFERRAM(this);
817 if (this->bufferram[i].blockpage == blockpage) {
818 ONENAND_SET_NEXT_BUFFERRAM(this);
819 found = 1;
820 }
821 }
822
823 if (found && ONENAND_IS_DDP(this)) {
824
825 int block = onenand_block(this, addr);
826 int value = onenand_bufferram_address(this, block);
827 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
828 }
829
830 return found;
831}
832
833
834
835
836
837
838
839
840
841static void onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
842 int valid)
843{
844 struct onenand_chip *this = mtd->priv;
845 int blockpage;
846 unsigned int i;
847
848 if (ONENAND_IS_2PLANE(this))
849 blockpage = onenand_get_2x_blockpage(mtd, addr);
850 else
851 blockpage = (int) (addr >> this->page_shift);
852
853
854 i = ONENAND_NEXT_BUFFERRAM(this);
855 if (this->bufferram[i].blockpage == blockpage)
856 this->bufferram[i].blockpage = -1;
857
858
859 i = ONENAND_CURRENT_BUFFERRAM(this);
860 if (valid)
861 this->bufferram[i].blockpage = blockpage;
862 else
863 this->bufferram[i].blockpage = -1;
864}
865
866
867
868
869
870
871
872
873
874static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
875 unsigned int len)
876{
877 struct onenand_chip *this = mtd->priv;
878 int i;
879 loff_t end_addr = addr + len;
880
881
882 for (i = 0; i < MAX_BUFFERRAM; i++) {
883 loff_t buf_addr = this->bufferram[i].blockpage << this->page_shift;
884 if (buf_addr >= addr && buf_addr < end_addr)
885 this->bufferram[i].blockpage = -1;
886 }
887}
888
889
890
891
892
893
894
895
896static int onenand_get_device(struct mtd_info *mtd, int new_state)
897{
898 struct onenand_chip *this = mtd->priv;
899 DECLARE_WAITQUEUE(wait, current);
900
901
902
903
904 while (1) {
905 spin_lock(&this->chip_lock);
906 if (this->state == FL_READY) {
907 this->state = new_state;
908 spin_unlock(&this->chip_lock);
909 break;
910 }
911 if (new_state == FL_PM_SUSPENDED) {
912 spin_unlock(&this->chip_lock);
913 return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
914 }
915 set_current_state(TASK_UNINTERRUPTIBLE);
916 add_wait_queue(&this->wq, &wait);
917 spin_unlock(&this->chip_lock);
918 schedule();
919 remove_wait_queue(&this->wq, &wait);
920 }
921
922 return 0;
923}
924
925
926
927
928
929
930
931static void onenand_release_device(struct mtd_info *mtd)
932{
933 struct onenand_chip *this = mtd->priv;
934
935
936 spin_lock(&this->chip_lock);
937 this->state = FL_READY;
938 wake_up(&this->wq);
939 spin_unlock(&this->chip_lock);
940}
941
942
943
944
945
946
947
948
949static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int column,
950 int thislen)
951{
952 struct onenand_chip *this = mtd->priv;
953 struct nand_oobfree *free;
954 int readcol = column;
955 int readend = column + thislen;
956 int lastgap = 0;
957 unsigned int i;
958 uint8_t *oob_buf = this->oob_buf;
959
960 free = this->ecclayout->oobfree;
961 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
962 if (readcol >= lastgap)
963 readcol += free->offset - lastgap;
964 if (readend >= lastgap)
965 readend += free->offset - lastgap;
966 lastgap = free->offset + free->length;
967 }
968 this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
969 free = this->ecclayout->oobfree;
970 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
971 int free_end = free->offset + free->length;
972 if (free->offset < readend && free_end > readcol) {
973 int st = max_t(int,free->offset,readcol);
974 int ed = min_t(int,free_end,readend);
975 int n = ed - st;
976 memcpy(buf, oob_buf + st, n);
977 buf += n;
978 } else if (column == 0)
979 break;
980 }
981 return 0;
982}
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
998{
999 struct onenand_chip *this = mtd->priv;
1000 int i;
1001
1002
1003 if (!FLEXONENAND(this))
1004 return status;
1005
1006
1007 if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
1008 return status;
1009
1010
1011 i = flexonenand_region(mtd, addr);
1012 if (mtd->eraseregions[i].erasesize < (1 << this->erase_shift))
1013 return status;
1014
1015
1016
1017
1018 printk(KERN_INFO "onenand_recover_lsb: Attempting to recover from uncorrectable read\n");
1019 mtd->ecc_stats.failed--;
1020
1021
1022 this->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr, this->writesize);
1023 return this->wait(mtd, FL_READING);
1024}
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
1036 struct mtd_oob_ops *ops)
1037{
1038 struct onenand_chip *this = mtd->priv;
1039 struct mtd_ecc_stats stats;
1040 size_t len = ops->len;
1041 size_t ooblen = ops->ooblen;
1042 u_char *buf = ops->datbuf;
1043 u_char *oobbuf = ops->oobbuf;
1044 int read = 0, column, thislen;
1045 int oobread = 0, oobcolumn, thisooblen, oobsize;
1046 int ret = 0;
1047 int writesize = this->writesize;
1048
1049 DEBUG(MTD_DEBUG_LEVEL3, "onenand_mlc_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
1050
1051 if (ops->mode == MTD_OOB_AUTO)
1052 oobsize = this->ecclayout->oobavail;
1053 else
1054 oobsize = mtd->oobsize;
1055
1056 oobcolumn = from & (mtd->oobsize - 1);
1057
1058
1059 if (from + len > mtd->size) {
1060 printk(KERN_ERR "onenand_mlc_read_ops_nolock: Attempt read beyond end of device\n");
1061 ops->retlen = 0;
1062 ops->oobretlen = 0;
1063 return -EINVAL;
1064 }
1065
1066 stats = mtd->ecc_stats;
1067
1068 while (read < len) {
1069 cond_resched();
1070
1071 thislen = min_t(int, writesize, len - read);
1072
1073 column = from & (writesize - 1);
1074 if (column + thislen > writesize)
1075 thislen = writesize - column;
1076
1077 if (!onenand_check_bufferram(mtd, from)) {
1078 this->command(mtd, ONENAND_CMD_READ, from, writesize);
1079
1080 ret = this->wait(mtd, FL_READING);
1081 if (unlikely(ret))
1082 ret = onenand_recover_lsb(mtd, from, ret);
1083 onenand_update_bufferram(mtd, from, !ret);
1084 if (ret == -EBADMSG)
1085 ret = 0;
1086 }
1087
1088 this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
1089 if (oobbuf) {
1090 thisooblen = oobsize - oobcolumn;
1091 thisooblen = min_t(int, thisooblen, ooblen - oobread);
1092
1093 if (ops->mode == MTD_OOB_AUTO)
1094 onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
1095 else
1096 this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
1097 oobread += thisooblen;
1098 oobbuf += thisooblen;
1099 oobcolumn = 0;
1100 }
1101
1102 read += thislen;
1103 if (read == len)
1104 break;
1105
1106 from += thislen;
1107 buf += thislen;
1108 }
1109
1110
1111
1112
1113
1114
1115 ops->retlen = read;
1116 ops->oobretlen = oobread;
1117
1118 if (ret)
1119 return ret;
1120
1121 if (mtd->ecc_stats.failed - stats.failed)
1122 return -EBADMSG;
1123
1124 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
1125}
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
1136 struct mtd_oob_ops *ops)
1137{
1138 struct onenand_chip *this = mtd->priv;
1139 struct mtd_ecc_stats stats;
1140 size_t len = ops->len;
1141 size_t ooblen = ops->ooblen;
1142 u_char *buf = ops->datbuf;
1143 u_char *oobbuf = ops->oobbuf;
1144 int read = 0, column, thislen;
1145 int oobread = 0, oobcolumn, thisooblen, oobsize;
1146 int ret = 0, boundary = 0;
1147 int writesize = this->writesize;
1148
1149 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
1150
1151 if (ops->mode == MTD_OOB_AUTO)
1152 oobsize = this->ecclayout->oobavail;
1153 else
1154 oobsize = mtd->oobsize;
1155
1156 oobcolumn = from & (mtd->oobsize - 1);
1157
1158
1159 if ((from + len) > mtd->size) {
1160 printk(KERN_ERR "onenand_read_ops_nolock: Attempt read beyond end of device\n");
1161 ops->retlen = 0;
1162 ops->oobretlen = 0;
1163 return -EINVAL;
1164 }
1165
1166 stats = mtd->ecc_stats;
1167
1168
1169
1170
1171 if (read < len) {
1172 if (!onenand_check_bufferram(mtd, from)) {
1173 this->command(mtd, ONENAND_CMD_READ, from, writesize);
1174 ret = this->wait(mtd, FL_READING);
1175 onenand_update_bufferram(mtd, from, !ret);
1176 if (ret == -EBADMSG)
1177 ret = 0;
1178 }
1179 }
1180
1181 thislen = min_t(int, writesize, len - read);
1182 column = from & (writesize - 1);
1183 if (column + thislen > writesize)
1184 thislen = writesize - column;
1185
1186 while (!ret) {
1187
1188 from += thislen;
1189 if (read + thislen < len) {
1190 this->command(mtd, ONENAND_CMD_READ, from, writesize);
1191
1192
1193
1194
1195
1196 if (ONENAND_IS_DDP(this) &&
1197 unlikely(from == (this->chipsize >> 1))) {
1198 this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
1199 boundary = 1;
1200 } else
1201 boundary = 0;
1202 ONENAND_SET_PREV_BUFFERRAM(this);
1203 }
1204
1205 this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
1206
1207
1208 if (oobbuf) {
1209 thisooblen = oobsize - oobcolumn;
1210 thisooblen = min_t(int, thisooblen, ooblen - oobread);
1211
1212 if (ops->mode == MTD_OOB_AUTO)
1213 onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
1214 else
1215 this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
1216 oobread += thisooblen;
1217 oobbuf += thisooblen;
1218 oobcolumn = 0;
1219 }
1220
1221
1222 read += thislen;
1223 if (read == len)
1224 break;
1225
1226 if (unlikely(boundary))
1227 this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
1228 ONENAND_SET_NEXT_BUFFERRAM(this);
1229 buf += thislen;
1230 thislen = min_t(int, writesize, len - read);
1231 column = 0;
1232 cond_resched();
1233
1234 ret = this->wait(mtd, FL_READING);
1235 onenand_update_bufferram(mtd, from, !ret);
1236 if (ret == -EBADMSG)
1237 ret = 0;
1238 }
1239
1240
1241
1242
1243
1244
1245 ops->retlen = read;
1246 ops->oobretlen = oobread;
1247
1248 if (ret)
1249 return ret;
1250
1251 if (mtd->ecc_stats.failed - stats.failed)
1252 return -EBADMSG;
1253
1254 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
1255}
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
1266 struct mtd_oob_ops *ops)
1267{
1268 struct onenand_chip *this = mtd->priv;
1269 struct mtd_ecc_stats stats;
1270 int read = 0, thislen, column, oobsize;
1271 size_t len = ops->ooblen;
1272 mtd_oob_mode_t mode = ops->mode;
1273 u_char *buf = ops->oobbuf;
1274 int ret = 0, readcmd;
1275
1276 from += ops->ooboffs;
1277
1278 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
1279
1280
1281 ops->oobretlen = 0;
1282
1283 if (mode == MTD_OOB_AUTO)
1284 oobsize = this->ecclayout->oobavail;
1285 else
1286 oobsize = mtd->oobsize;
1287
1288 column = from & (mtd->oobsize - 1);
1289
1290 if (unlikely(column >= oobsize)) {
1291 printk(KERN_ERR "onenand_read_oob_nolock: Attempted to start read outside oob\n");
1292 return -EINVAL;
1293 }
1294
1295
1296 if (unlikely(from >= mtd->size ||
1297 column + len > ((mtd->size >> this->page_shift) -
1298 (from >> this->page_shift)) * oobsize)) {
1299 printk(KERN_ERR "onenand_read_oob_nolock: Attempted to read beyond end of device\n");
1300 return -EINVAL;
1301 }
1302
1303 stats = mtd->ecc_stats;
1304
1305 readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1306
1307 while (read < len) {
1308 cond_resched();
1309
1310 thislen = oobsize - column;
1311 thislen = min_t(int, thislen, len);
1312
1313 this->command(mtd, readcmd, from, mtd->oobsize);
1314
1315 onenand_update_bufferram(mtd, from, 0);
1316
1317 ret = this->wait(mtd, FL_READING);
1318 if (unlikely(ret))
1319 ret = onenand_recover_lsb(mtd, from, ret);
1320
1321 if (ret && ret != -EBADMSG) {
1322 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
1323 break;
1324 }
1325
1326 if (mode == MTD_OOB_AUTO)
1327 onenand_transfer_auto_oob(mtd, buf, column, thislen);
1328 else
1329 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
1330
1331 read += thislen;
1332
1333 if (read == len)
1334 break;
1335
1336 buf += thislen;
1337
1338
1339 if (read < len) {
1340
1341 from += mtd->writesize;
1342 column = 0;
1343 }
1344 }
1345
1346 ops->oobretlen = read;
1347
1348 if (ret)
1349 return ret;
1350
1351 if (mtd->ecc_stats.failed - stats.failed)
1352 return -EBADMSG;
1353
1354 return 0;
1355}
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1368 size_t *retlen, u_char *buf)
1369{
1370 struct onenand_chip *this = mtd->priv;
1371 struct mtd_oob_ops ops = {
1372 .len = len,
1373 .ooblen = 0,
1374 .datbuf = buf,
1375 .oobbuf = NULL,
1376 };
1377 int ret;
1378
1379 onenand_get_device(mtd, FL_READING);
1380 ret = ONENAND_IS_MLC(this) ?
1381 onenand_mlc_read_ops_nolock(mtd, from, &ops) :
1382 onenand_read_ops_nolock(mtd, from, &ops);
1383 onenand_release_device(mtd);
1384
1385 *retlen = ops.retlen;
1386 return ret;
1387}
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
1398 struct mtd_oob_ops *ops)
1399{
1400 struct onenand_chip *this = mtd->priv;
1401 int ret;
1402
1403 switch (ops->mode) {
1404 case MTD_OOB_PLACE:
1405 case MTD_OOB_AUTO:
1406 break;
1407 case MTD_OOB_RAW:
1408
1409 default:
1410 return -EINVAL;
1411 }
1412
1413 onenand_get_device(mtd, FL_READING);
1414 if (ops->datbuf)
1415 ret = ONENAND_IS_MLC(this) ?
1416 onenand_mlc_read_ops_nolock(mtd, from, ops) :
1417 onenand_read_ops_nolock(mtd, from, ops);
1418 else
1419 ret = onenand_read_oob_nolock(mtd, from, ops);
1420 onenand_release_device(mtd);
1421
1422 return ret;
1423}
1424
1425
1426
1427
1428
1429
1430
1431
1432static int onenand_bbt_wait(struct mtd_info *mtd, int state)
1433{
1434 struct onenand_chip *this = mtd->priv;
1435 unsigned long timeout;
1436 unsigned int interrupt;
1437 unsigned int ctrl;
1438
1439
1440 timeout = jiffies + msecs_to_jiffies(20);
1441 while (time_before(jiffies, timeout)) {
1442 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
1443 if (interrupt & ONENAND_INT_MASTER)
1444 break;
1445 }
1446
1447 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
1448 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
1449
1450 if (interrupt & ONENAND_INT_READ) {
1451 int ecc = onenand_read_ecc(this);
1452 if (ecc & ONENAND_ECC_2BIT_ALL) {
1453 printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
1454 ", controller error 0x%04x\n", ecc, ctrl);
1455 return ONENAND_BBT_READ_ECC_ERROR;
1456 }
1457 } else {
1458 printk(KERN_ERR "onenand_bbt_wait: read timeout!"
1459 "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
1460 return ONENAND_BBT_READ_FATAL_ERROR;
1461 }
1462
1463
1464 if (ctrl & ONENAND_CTRL_ERROR) {
1465 printk(KERN_DEBUG "onenand_bbt_wait: "
1466 "controller error = 0x%04x\n", ctrl);
1467 return ONENAND_BBT_READ_ERROR;
1468 }
1469
1470 return 0;
1471}
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
1482 struct mtd_oob_ops *ops)
1483{
1484 struct onenand_chip *this = mtd->priv;
1485 int read = 0, thislen, column;
1486 int ret = 0, readcmd;
1487 size_t len = ops->ooblen;
1488 u_char *buf = ops->oobbuf;
1489
1490 DEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len);
1491
1492
1493 ops->oobretlen = 0;
1494
1495
1496 if (unlikely((from + len) > mtd->size)) {
1497 printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
1498 return ONENAND_BBT_READ_FATAL_ERROR;
1499 }
1500
1501
1502 onenand_get_device(mtd, FL_READING);
1503
1504 column = from & (mtd->oobsize - 1);
1505
1506 readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1507
1508 while (read < len) {
1509 cond_resched();
1510
1511 thislen = mtd->oobsize - column;
1512 thislen = min_t(int, thislen, len);
1513
1514 this->command(mtd, readcmd, from, mtd->oobsize);
1515
1516 onenand_update_bufferram(mtd, from, 0);
1517
1518 ret = this->bbt_wait(mtd, FL_READING);
1519 if (unlikely(ret))
1520 ret = onenand_recover_lsb(mtd, from, ret);
1521
1522 if (ret)
1523 break;
1524
1525 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
1526 read += thislen;
1527 if (read == len)
1528 break;
1529
1530 buf += thislen;
1531
1532
1533 if (read < len) {
1534
1535 from += this->writesize;
1536 column = 0;
1537 }
1538 }
1539
1540
1541 onenand_release_device(mtd);
1542
1543 ops->oobretlen = read;
1544 return ret;
1545}
1546
1547#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
1548
1549
1550
1551
1552
1553
1554static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
1555{
1556 struct onenand_chip *this = mtd->priv;
1557 u_char *oob_buf = this->oob_buf;
1558 int status, i, readcmd;
1559
1560 readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1561
1562 this->command(mtd, readcmd, to, mtd->oobsize);
1563 onenand_update_bufferram(mtd, to, 0);
1564 status = this->wait(mtd, FL_READING);
1565 if (status)
1566 return status;
1567
1568 this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
1569 for (i = 0; i < mtd->oobsize; i++)
1570 if (buf[i] != 0xFF && buf[i] != oob_buf[i])
1571 return -EBADMSG;
1572
1573 return 0;
1574}
1575
1576
1577
1578
1579
1580
1581
1582
1583static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len)
1584{
1585 struct onenand_chip *this = mtd->priv;
1586 void __iomem *dataram;
1587 int ret = 0;
1588 int thislen, column;
1589
1590 while (len != 0) {
1591 thislen = min_t(int, this->writesize, len);
1592 column = addr & (this->writesize - 1);
1593 if (column + thislen > this->writesize)
1594 thislen = this->writesize - column;
1595
1596 this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
1597
1598 onenand_update_bufferram(mtd, addr, 0);
1599
1600 ret = this->wait(mtd, FL_READING);
1601 if (ret)
1602 return ret;
1603
1604 onenand_update_bufferram(mtd, addr, 1);
1605
1606 dataram = this->base + ONENAND_DATARAM;
1607 dataram += onenand_bufferram_offset(mtd, ONENAND_DATARAM);
1608
1609 if (memcmp(buf, dataram + column, thislen))
1610 return -EBADMSG;
1611
1612 len -= thislen;
1613 buf += thislen;
1614 addr += thislen;
1615 }
1616
1617 return 0;
1618}
1619#else
1620#define onenand_verify(...) (0)
1621#define onenand_verify_oob(...) (0)
1622#endif
1623
1624#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0)
1625
1626static void onenand_panic_wait(struct mtd_info *mtd)
1627{
1628 struct onenand_chip *this = mtd->priv;
1629 unsigned int interrupt;
1630 int i;
1631
1632 for (i = 0; i < 2000; i++) {
1633 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
1634 if (interrupt & ONENAND_INT_MASTER)
1635 break;
1636 udelay(10);
1637 }
1638}
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
1651 size_t *retlen, const u_char *buf)
1652{
1653 struct onenand_chip *this = mtd->priv;
1654 int column, subpage;
1655 int written = 0;
1656 int ret = 0;
1657
1658 if (this->state == FL_PM_SUSPENDED)
1659 return -EBUSY;
1660
1661
1662 onenand_panic_wait(mtd);
1663
1664 DEBUG(MTD_DEBUG_LEVEL3, "onenand_panic_write: to = 0x%08x, len = %i\n",
1665 (unsigned int) to, (int) len);
1666
1667
1668 *retlen = 0;
1669
1670
1671 if (unlikely((to + len) > mtd->size)) {
1672 printk(KERN_ERR "onenand_panic_write: Attempt write to past end of device\n");
1673 return -EINVAL;
1674 }
1675
1676
1677 if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
1678 printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n");
1679 return -EINVAL;
1680 }
1681
1682 column = to & (mtd->writesize - 1);
1683
1684
1685 while (written < len) {
1686 int thislen = min_t(int, mtd->writesize - column, len - written);
1687 u_char *wbuf = (u_char *) buf;
1688
1689 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
1690
1691
1692 subpage = thislen < mtd->writesize;
1693 if (subpage) {
1694 memset(this->page_buf, 0xff, mtd->writesize);
1695 memcpy(this->page_buf + column, buf, thislen);
1696 wbuf = this->page_buf;
1697 }
1698
1699 this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
1700 this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
1701
1702 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
1703
1704 onenand_panic_wait(mtd);
1705
1706
1707 onenand_update_bufferram(mtd, to, !ret && !subpage);
1708 if (ONENAND_IS_2PLANE(this)) {
1709 ONENAND_SET_BUFFERRAM1(this);
1710 onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
1711 }
1712
1713 if (ret) {
1714 printk(KERN_ERR "onenand_panic_write: write failed %d\n", ret);
1715 break;
1716 }
1717
1718 written += thislen;
1719
1720 if (written == len)
1721 break;
1722
1723 column = 0;
1724 to += thislen;
1725 buf += thislen;
1726 }
1727
1728 *retlen = written;
1729 return ret;
1730}
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
1741 const u_char *buf, int column, int thislen)
1742{
1743 struct onenand_chip *this = mtd->priv;
1744 struct nand_oobfree *free;
1745 int writecol = column;
1746 int writeend = column + thislen;
1747 int lastgap = 0;
1748 unsigned int i;
1749
1750 free = this->ecclayout->oobfree;
1751 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
1752 if (writecol >= lastgap)
1753 writecol += free->offset - lastgap;
1754 if (writeend >= lastgap)
1755 writeend += free->offset - lastgap;
1756 lastgap = free->offset + free->length;
1757 }
1758 free = this->ecclayout->oobfree;
1759 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
1760 int free_end = free->offset + free->length;
1761 if (free->offset < writeend && free_end > writecol) {
1762 int st = max_t(int,free->offset,writecol);
1763 int ed = min_t(int,free_end,writeend);
1764 int n = ed - st;
1765 memcpy(oob_buf + st, buf, n);
1766 buf += n;
1767 } else if (column == 0)
1768 break;
1769 }
1770 return 0;
1771}
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
1782 struct mtd_oob_ops *ops)
1783{
1784 struct onenand_chip *this = mtd->priv;
1785 int written = 0, column, thislen = 0, subpage = 0;
1786 int prev = 0, prevlen = 0, prev_subpage = 0, first = 1;
1787 int oobwritten = 0, oobcolumn, thisooblen, oobsize;
1788 size_t len = ops->len;
1789 size_t ooblen = ops->ooblen;
1790 const u_char *buf = ops->datbuf;
1791 const u_char *oob = ops->oobbuf;
1792 u_char *oobbuf;
1793 int ret = 0;
1794
1795 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
1796
1797
1798 ops->retlen = 0;
1799 ops->oobretlen = 0;
1800
1801
1802 if (unlikely((to + len) > mtd->size)) {
1803 printk(KERN_ERR "onenand_write_ops_nolock: Attempt write to past end of device\n");
1804 return -EINVAL;
1805 }
1806
1807
1808 if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
1809 printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
1810 return -EINVAL;
1811 }
1812
1813
1814 if (!len)
1815 return 0;
1816
1817 if (ops->mode == MTD_OOB_AUTO)
1818 oobsize = this->ecclayout->oobavail;
1819 else
1820 oobsize = mtd->oobsize;
1821
1822 oobcolumn = to & (mtd->oobsize - 1);
1823
1824 column = to & (mtd->writesize - 1);
1825
1826
1827 while (1) {
1828 if (written < len) {
1829 u_char *wbuf = (u_char *) buf;
1830
1831 thislen = min_t(int, mtd->writesize - column, len - written);
1832 thisooblen = min_t(int, oobsize - oobcolumn, ooblen - oobwritten);
1833
1834 cond_resched();
1835
1836 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
1837
1838
1839 subpage = thislen < mtd->writesize;
1840 if (subpage) {
1841 memset(this->page_buf, 0xff, mtd->writesize);
1842 memcpy(this->page_buf + column, buf, thislen);
1843 wbuf = this->page_buf;
1844 }
1845
1846 this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
1847
1848 if (oob) {
1849 oobbuf = this->oob_buf;
1850
1851
1852
1853 memset(oobbuf, 0xff, mtd->oobsize);
1854 if (ops->mode == MTD_OOB_AUTO)
1855 onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
1856 else
1857 memcpy(oobbuf + oobcolumn, oob, thisooblen);
1858
1859 oobwritten += thisooblen;
1860 oob += thisooblen;
1861 oobcolumn = 0;
1862 } else
1863 oobbuf = (u_char *) ffchars;
1864
1865 this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
1866 } else
1867 ONENAND_SET_NEXT_BUFFERRAM(this);
1868
1869
1870
1871
1872
1873 if (!ONENAND_IS_2PLANE(this) && !first) {
1874 ONENAND_SET_PREV_BUFFERRAM(this);
1875
1876 ret = this->wait(mtd, FL_WRITING);
1877
1878
1879 onenand_update_bufferram(mtd, prev, !ret && !prev_subpage);
1880 if (ret) {
1881 written -= prevlen;
1882 printk(KERN_ERR "onenand_write_ops_nolock: write failed %d\n", ret);
1883 break;
1884 }
1885
1886 if (written == len) {
1887
1888 ret = onenand_verify(mtd, buf - len, to - len, len);
1889 if (ret)
1890 printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
1891 break;
1892 }
1893
1894 ONENAND_SET_NEXT_BUFFERRAM(this);
1895 }
1896
1897 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
1898
1899
1900
1901
1902 if (ONENAND_IS_2PLANE(this)) {
1903 ret = this->wait(mtd, FL_WRITING);
1904
1905
1906 onenand_update_bufferram(mtd, to, !ret && !subpage);
1907 if (ret) {
1908 printk(KERN_ERR "onenand_write_ops_nolock: write failed %d\n", ret);
1909 break;
1910 }
1911
1912
1913 ret = onenand_verify(mtd, buf, to, thislen);
1914 if (ret) {
1915 printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
1916 break;
1917 }
1918
1919 written += thislen;
1920
1921 if (written == len)
1922 break;
1923
1924 } else
1925 written += thislen;
1926
1927 column = 0;
1928 prev_subpage = subpage;
1929 prev = to;
1930 prevlen = thislen;
1931 to += thislen;
1932 buf += thislen;
1933 first = 0;
1934 }
1935
1936
1937 if (written != len)
1938 onenand_invalidate_bufferram(mtd, 0, -1);
1939
1940 ops->retlen = written;
1941 ops->oobretlen = oobwritten;
1942
1943 return ret;
1944}
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
1959 struct mtd_oob_ops *ops)
1960{
1961 struct onenand_chip *this = mtd->priv;
1962 int column, ret = 0, oobsize;
1963 int written = 0, oobcmd;
1964 u_char *oobbuf;
1965 size_t len = ops->ooblen;
1966 const u_char *buf = ops->oobbuf;
1967 mtd_oob_mode_t mode = ops->mode;
1968
1969 to += ops->ooboffs;
1970
1971 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
1972
1973
1974 ops->oobretlen = 0;
1975
1976 if (mode == MTD_OOB_AUTO)
1977 oobsize = this->ecclayout->oobavail;
1978 else
1979 oobsize = mtd->oobsize;
1980
1981 column = to & (mtd->oobsize - 1);
1982
1983 if (unlikely(column >= oobsize)) {
1984 printk(KERN_ERR "onenand_write_oob_nolock: Attempted to start write outside oob\n");
1985 return -EINVAL;
1986 }
1987
1988
1989 if (unlikely(column + len > oobsize)) {
1990 printk(KERN_ERR "onenand_write_oob_nolock: "
1991 "Attempt to write past end of page\n");
1992 return -EINVAL;
1993 }
1994
1995
1996 if (unlikely(to >= mtd->size ||
1997 column + len > ((mtd->size >> this->page_shift) -
1998 (to >> this->page_shift)) * oobsize)) {
1999 printk(KERN_ERR "onenand_write_oob_nolock: Attempted to write past end of device\n");
2000 return -EINVAL;
2001 }
2002
2003 oobbuf = this->oob_buf;
2004
2005 oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
2006
2007
2008 while (written < len) {
2009 int thislen = min_t(int, oobsize, len - written);
2010
2011 cond_resched();
2012
2013 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
2014
2015
2016
2017 memset(oobbuf, 0xff, mtd->oobsize);
2018 if (mode == MTD_OOB_AUTO)
2019 onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
2020 else
2021 memcpy(oobbuf + column, buf, thislen);
2022 this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
2023
2024 if (ONENAND_IS_MLC(this)) {
2025
2026 memset(this->page_buf, 0xff, mtd->writesize);
2027 this->write_bufferram(mtd, ONENAND_DATARAM,
2028 this->page_buf, 0, mtd->writesize);
2029 }
2030
2031 this->command(mtd, oobcmd, to, mtd->oobsize);
2032
2033 onenand_update_bufferram(mtd, to, 0);
2034 if (ONENAND_IS_2PLANE(this)) {
2035 ONENAND_SET_BUFFERRAM1(this);
2036 onenand_update_bufferram(mtd, to + this->writesize, 0);
2037 }
2038
2039 ret = this->wait(mtd, FL_WRITING);
2040 if (ret) {
2041 printk(KERN_ERR "onenand_write_oob_nolock: write failed %d\n", ret);
2042 break;
2043 }
2044
2045 ret = onenand_verify_oob(mtd, oobbuf, to);
2046 if (ret) {
2047 printk(KERN_ERR "onenand_write_oob_nolock: verify failed %d\n", ret);
2048 break;
2049 }
2050
2051 written += thislen;
2052 if (written == len)
2053 break;
2054
2055 to += mtd->writesize;
2056 buf += thislen;
2057 column = 0;
2058 }
2059
2060 ops->oobretlen = written;
2061
2062 return ret;
2063}
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
2076 size_t *retlen, const u_char *buf)
2077{
2078 struct mtd_oob_ops ops = {
2079 .len = len,
2080 .ooblen = 0,
2081 .datbuf = (u_char *) buf,
2082 .oobbuf = NULL,
2083 };
2084 int ret;
2085
2086 onenand_get_device(mtd, FL_WRITING);
2087 ret = onenand_write_ops_nolock(mtd, to, &ops);
2088 onenand_release_device(mtd);
2089
2090 *retlen = ops.retlen;
2091 return ret;
2092}
2093
2094
2095
2096
2097
2098
2099
2100static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
2101 struct mtd_oob_ops *ops)
2102{
2103 int ret;
2104
2105 switch (ops->mode) {
2106 case MTD_OOB_PLACE:
2107 case MTD_OOB_AUTO:
2108 break;
2109 case MTD_OOB_RAW:
2110
2111 default:
2112 return -EINVAL;
2113 }
2114
2115 onenand_get_device(mtd, FL_WRITING);
2116 if (ops->datbuf)
2117 ret = onenand_write_ops_nolock(mtd, to, ops);
2118 else
2119 ret = onenand_write_oob_nolock(mtd, to, ops);
2120 onenand_release_device(mtd);
2121
2122 return ret;
2123}
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allowbbt)
2135{
2136 struct onenand_chip *this = mtd->priv;
2137 struct bbm_info *bbm = this->bbm;
2138
2139
2140 return bbm->isbad_bbt(mtd, ofs, allowbbt);
2141}
2142
2143
2144
2145
2146
2147
2148
2149
2150static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
2151{
2152 struct onenand_chip *this = mtd->priv;
2153 unsigned int block_size;
2154 loff_t addr = instr->addr;
2155 loff_t len = instr->len;
2156 int ret = 0, i;
2157 struct mtd_erase_region_info *region = NULL;
2158 loff_t region_end = 0;
2159
2160 DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len);
2161
2162
2163 if (unlikely((len + addr) > mtd->size)) {
2164 printk(KERN_ERR "onenand_erase: Erase past end of device\n");
2165 return -EINVAL;
2166 }
2167
2168 if (FLEXONENAND(this)) {
2169
2170 i = flexonenand_region(mtd, addr);
2171 region = &mtd->eraseregions[i];
2172
2173 block_size = region->erasesize;
2174 region_end = region->offset + region->erasesize * region->numblocks;
2175
2176
2177
2178
2179 if (unlikely((addr - region->offset) & (block_size - 1))) {
2180 printk(KERN_ERR "onenand_erase: Unaligned address\n");
2181 return -EINVAL;
2182 }
2183 } else {
2184 block_size = 1 << this->erase_shift;
2185
2186
2187 if (unlikely(addr & (block_size - 1))) {
2188 printk(KERN_ERR "onenand_erase: Unaligned address\n");
2189 return -EINVAL;
2190 }
2191 }
2192
2193
2194 if (unlikely(len & (block_size - 1))) {
2195 printk(KERN_ERR "onenand_erase: Length not block aligned\n");
2196 return -EINVAL;
2197 }
2198
2199 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
2200
2201
2202 onenand_get_device(mtd, FL_ERASING);
2203
2204
2205 instr->state = MTD_ERASING;
2206
2207 while (len) {
2208 cond_resched();
2209
2210
2211 if (onenand_block_isbad_nolock(mtd, addr, 0)) {
2212 printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%012llx\n", (unsigned long long) addr);
2213 instr->state = MTD_ERASE_FAILED;
2214 goto erase_exit;
2215 }
2216
2217 this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
2218
2219 onenand_invalidate_bufferram(mtd, addr, block_size);
2220
2221 ret = this->wait(mtd, FL_ERASING);
2222
2223 if (ret) {
2224 printk(KERN_ERR "onenand_erase: Failed erase, block %d\n",
2225 onenand_block(this, addr));
2226 instr->state = MTD_ERASE_FAILED;
2227 instr->fail_addr = addr;
2228 goto erase_exit;
2229 }
2230
2231 len -= block_size;
2232 addr += block_size;
2233
2234 if (addr == region_end) {
2235 if (!len)
2236 break;
2237 region++;
2238
2239 block_size = region->erasesize;
2240 region_end = region->offset + region->erasesize * region->numblocks;
2241
2242 if (len & (block_size - 1)) {
2243
2244 printk(KERN_ERR "onenand_erase: Unaligned address\n");
2245 goto erase_exit;
2246 }
2247 }
2248
2249 }
2250
2251 instr->state = MTD_ERASE_DONE;
2252
2253erase_exit:
2254
2255 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
2256
2257
2258 onenand_release_device(mtd);
2259
2260
2261 if (!ret)
2262 mtd_erase_callback(instr);
2263
2264 return ret;
2265}
2266
2267
2268
2269
2270
2271
2272
2273static void onenand_sync(struct mtd_info *mtd)
2274{
2275 DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
2276
2277
2278 onenand_get_device(mtd, FL_SYNCING);
2279
2280
2281 onenand_release_device(mtd);
2282}
2283
2284
2285
2286
2287
2288
2289
2290
2291static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
2292{
2293 int ret;
2294
2295
2296 if (ofs > mtd->size)
2297 return -EINVAL;
2298
2299 onenand_get_device(mtd, FL_READING);
2300 ret = onenand_block_isbad_nolock(mtd, ofs, 0);
2301 onenand_release_device(mtd);
2302 return ret;
2303}
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
2314{
2315 struct onenand_chip *this = mtd->priv;
2316 struct bbm_info *bbm = this->bbm;
2317 u_char buf[2] = {0, 0};
2318 struct mtd_oob_ops ops = {
2319 .mode = MTD_OOB_PLACE,
2320 .ooblen = 2,
2321 .oobbuf = buf,
2322 .ooboffs = 0,
2323 };
2324 int block;
2325
2326
2327 block = onenand_block(this, ofs);
2328 if (bbm->bbt)
2329 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
2330
2331
2332 ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
2333
2334
2335
2336
2337 return onenand_write_oob_nolock(mtd, ofs, &ops);
2338}
2339
2340
2341
2342
2343
2344
2345
2346
2347static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
2348{
2349 struct onenand_chip *this = mtd->priv;
2350 int ret;
2351
2352 ret = onenand_block_isbad(mtd, ofs);
2353 if (ret) {
2354
2355 if (ret > 0)
2356 return 0;
2357 return ret;
2358 }
2359
2360 onenand_get_device(mtd, FL_WRITING);
2361 ret = this->block_markbad(mtd, ofs);
2362 onenand_release_device(mtd);
2363 return ret;
2364}
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd)
2376{
2377 struct onenand_chip *this = mtd->priv;
2378 int start, end, block, value, status;
2379 int wp_status_mask;
2380
2381 start = onenand_block(this, ofs);
2382 end = onenand_block(this, ofs + len) - 1;
2383
2384 if (cmd == ONENAND_CMD_LOCK)
2385 wp_status_mask = ONENAND_WP_LS;
2386 else
2387 wp_status_mask = ONENAND_WP_US;
2388
2389
2390 if (this->options & ONENAND_HAS_CONT_LOCK) {
2391
2392 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2393
2394 this->write_word(end, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
2395
2396 this->command(mtd, cmd, 0, 0);
2397
2398
2399 this->wait(mtd, FL_LOCKING);
2400
2401
2402 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
2403 & ONENAND_CTRL_ONGO)
2404 continue;
2405
2406
2407 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
2408 if (!(status & wp_status_mask))
2409 printk(KERN_ERR "wp status = 0x%x\n", status);
2410
2411 return 0;
2412 }
2413
2414
2415 for (block = start; block < end + 1; block++) {
2416
2417 value = onenand_block_address(this, block);
2418 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
2419
2420 value = onenand_bufferram_address(this, block);
2421 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
2422
2423 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2424
2425 this->command(mtd, cmd, 0, 0);
2426
2427
2428 this->wait(mtd, FL_LOCKING);
2429
2430
2431 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
2432 & ONENAND_CTRL_ONGO)
2433 continue;
2434
2435
2436 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
2437 if (!(status & wp_status_mask))
2438 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
2439 }
2440
2441 return 0;
2442}
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452static int onenand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
2453{
2454 int ret;
2455
2456 onenand_get_device(mtd, FL_LOCKING);
2457 ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
2458 onenand_release_device(mtd);
2459 return ret;
2460}
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
2471{
2472 int ret;
2473
2474 onenand_get_device(mtd, FL_LOCKING);
2475 ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
2476 onenand_release_device(mtd);
2477 return ret;
2478}
2479
2480
2481
2482
2483
2484
2485
2486static int onenand_check_lock_status(struct onenand_chip *this)
2487{
2488 unsigned int value, block, status;
2489 unsigned int end;
2490
2491 end = this->chipsize >> this->erase_shift;
2492 for (block = 0; block < end; block++) {
2493
2494 value = onenand_block_address(this, block);
2495 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
2496
2497 value = onenand_bufferram_address(this, block);
2498 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
2499
2500 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2501
2502
2503 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
2504 if (!(status & ONENAND_WP_US)) {
2505 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
2506 return 0;
2507 }
2508 }
2509
2510 return 1;
2511}
2512
2513
2514
2515
2516
2517
2518
2519static void onenand_unlock_all(struct mtd_info *mtd)
2520{
2521 struct onenand_chip *this = mtd->priv;
2522 loff_t ofs = 0;
2523 loff_t len = mtd->size;
2524
2525 if (this->options & ONENAND_HAS_UNLOCK_ALL) {
2526
2527 this->write_word(0, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2528
2529 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
2530
2531
2532 this->wait(mtd, FL_LOCKING);
2533
2534
2535 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
2536 & ONENAND_CTRL_ONGO)
2537 continue;
2538
2539
2540 if (this->options & ONENAND_SKIP_UNLOCK_CHECK)
2541 return;
2542
2543
2544 if (onenand_check_lock_status(this))
2545 return;
2546
2547
2548 if (ONENAND_IS_DDP(this) && !FLEXONENAND(this)) {
2549
2550 ofs = this->chipsize >> 1;
2551 len = this->chipsize >> 1;
2552 }
2553 }
2554
2555 onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
2556}
2557
2558#ifdef CONFIG_MTD_ONENAND_OTP
2559
2560
2561typedef int (*otp_op_t)(struct mtd_info *mtd, loff_t form, size_t len,
2562 size_t *retlen, u_char *buf);
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
2575 size_t *retlen, u_char *buf)
2576{
2577 struct onenand_chip *this = mtd->priv;
2578 struct mtd_oob_ops ops = {
2579 .len = len,
2580 .ooblen = 0,
2581 .datbuf = buf,
2582 .oobbuf = NULL,
2583 };
2584 int ret;
2585
2586
2587 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2588 this->wait(mtd, FL_OTPING);
2589
2590 ret = ONENAND_IS_MLC(this) ?
2591 onenand_mlc_read_ops_nolock(mtd, from, &ops) :
2592 onenand_read_ops_nolock(mtd, from, &ops);
2593
2594
2595 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
2596 this->wait(mtd, FL_RESETING);
2597
2598 return ret;
2599}
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611static int do_otp_write(struct mtd_info *mtd, loff_t to, size_t len,
2612 size_t *retlen, u_char *buf)
2613{
2614 struct onenand_chip *this = mtd->priv;
2615 unsigned char *pbuf = buf;
2616 int ret;
2617 struct mtd_oob_ops ops;
2618
2619
2620 if (len < mtd->writesize) {
2621 memcpy(this->page_buf, buf, len);
2622 memset(this->page_buf + len, 0xff, mtd->writesize - len);
2623 pbuf = this->page_buf;
2624 len = mtd->writesize;
2625 }
2626
2627
2628 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2629 this->wait(mtd, FL_OTPING);
2630
2631 ops.len = len;
2632 ops.ooblen = 0;
2633 ops.datbuf = pbuf;
2634 ops.oobbuf = NULL;
2635 ret = onenand_write_ops_nolock(mtd, to, &ops);
2636 *retlen = ops.retlen;
2637
2638
2639 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
2640 this->wait(mtd, FL_RESETING);
2641
2642 return ret;
2643}
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
2656 size_t *retlen, u_char *buf)
2657{
2658 struct onenand_chip *this = mtd->priv;
2659 struct mtd_oob_ops ops;
2660 int ret;
2661
2662
2663 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2664 this->wait(mtd, FL_OTPING);
2665
2666 if (FLEXONENAND(this)) {
2667
2668
2669
2670
2671 ops.len = mtd->writesize;
2672 ops.ooblen = 0;
2673 ops.datbuf = buf;
2674 ops.oobbuf = NULL;
2675 ret = onenand_write_ops_nolock(mtd, mtd->writesize * 49, &ops);
2676 *retlen = ops.retlen;
2677 } else {
2678 ops.mode = MTD_OOB_PLACE;
2679 ops.ooblen = len;
2680 ops.oobbuf = buf;
2681 ops.ooboffs = 0;
2682 ret = onenand_write_oob_nolock(mtd, from, &ops);
2683 *retlen = ops.oobretlen;
2684 }
2685
2686
2687 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
2688 this->wait(mtd, FL_RESETING);
2689
2690 return ret;
2691}
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
2706 size_t *retlen, u_char *buf,
2707 otp_op_t action, int mode)
2708{
2709 struct onenand_chip *this = mtd->priv;
2710 int otp_pages;
2711 int density;
2712 int ret = 0;
2713
2714 *retlen = 0;
2715
2716 density = onenand_get_density(this->device_id);
2717 if (density < ONENAND_DEVICE_DENSITY_512Mb)
2718 otp_pages = 20;
2719 else
2720 otp_pages = 10;
2721
2722 if (mode == MTD_OTP_FACTORY) {
2723 from += mtd->writesize * otp_pages;
2724 otp_pages = 64 - otp_pages;
2725 }
2726
2727
2728 if (((mtd->writesize * otp_pages) - (from + len)) < 0)
2729 return 0;
2730
2731 onenand_get_device(mtd, FL_OTPING);
2732 while (len > 0 && otp_pages > 0) {
2733 if (!action) {
2734 struct otp_info *otpinfo;
2735
2736 len -= sizeof(struct otp_info);
2737 if (len <= 0) {
2738 ret = -ENOSPC;
2739 break;
2740 }
2741
2742 otpinfo = (struct otp_info *) buf;
2743 otpinfo->start = from;
2744 otpinfo->length = mtd->writesize;
2745 otpinfo->locked = 0;
2746
2747 from += mtd->writesize;
2748 buf += sizeof(struct otp_info);
2749 *retlen += sizeof(struct otp_info);
2750 } else {
2751 size_t tmp_retlen;
2752 int size = len;
2753
2754 ret = action(mtd, from, len, &tmp_retlen, buf);
2755
2756 buf += size;
2757 len -= size;
2758 *retlen += size;
2759
2760 if (ret)
2761 break;
2762 }
2763 otp_pages--;
2764 }
2765 onenand_release_device(mtd);
2766
2767 return ret;
2768}
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778static int onenand_get_fact_prot_info(struct mtd_info *mtd,
2779 struct otp_info *buf, size_t len)
2780{
2781 size_t retlen;
2782 int ret;
2783
2784 ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_FACTORY);
2785
2786 return ret ? : retlen;
2787}
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799static int onenand_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
2800 size_t len, size_t *retlen, u_char *buf)
2801{
2802 return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_FACTORY);
2803}
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813static int onenand_get_user_prot_info(struct mtd_info *mtd,
2814 struct otp_info *buf, size_t len)
2815{
2816 size_t retlen;
2817 int ret;
2818
2819 ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_USER);
2820
2821 return ret ? : retlen;
2822}
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834static int onenand_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
2835 size_t len, size_t *retlen, u_char *buf)
2836{
2837 return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_USER);
2838}
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
2851 size_t len, size_t *retlen, u_char *buf)
2852{
2853 return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_write, MTD_OTP_USER);
2854}
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
2865 size_t len)
2866{
2867 struct onenand_chip *this = mtd->priv;
2868 u_char *buf = FLEXONENAND(this) ? this->page_buf : this->oob_buf;
2869 size_t retlen;
2870 int ret;
2871
2872 memset(buf, 0xff, FLEXONENAND(this) ? this->writesize
2873 : mtd->oobsize);
2874
2875
2876
2877
2878
2879
2880 if (FLEXONENAND(this))
2881 buf[FLEXONENAND_OTP_LOCK_OFFSET] = 0xFC;
2882 else
2883 buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
2884
2885
2886
2887
2888
2889
2890
2891
2892 from = 0;
2893 len = FLEXONENAND(this) ? mtd->writesize : 16;
2894
2895 ret = onenand_otp_walk(mtd, from, len, &retlen, buf, do_otp_lock, MTD_OTP_USER);
2896
2897 return ret ? : retlen;
2898}
2899#endif
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909static void onenand_check_features(struct mtd_info *mtd)
2910{
2911 struct onenand_chip *this = mtd->priv;
2912 unsigned int density, process;
2913
2914
2915 density = onenand_get_density(this->device_id);
2916 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
2917
2918
2919 switch (density) {
2920 case ONENAND_DEVICE_DENSITY_4Gb:
2921 this->options |= ONENAND_HAS_2PLANE;
2922
2923 case ONENAND_DEVICE_DENSITY_2Gb:
2924
2925 if (!ONENAND_IS_DDP(this))
2926 this->options |= ONENAND_HAS_2PLANE;
2927 this->options |= ONENAND_HAS_UNLOCK_ALL;
2928
2929 case ONENAND_DEVICE_DENSITY_1Gb:
2930
2931 if (process)
2932 this->options |= ONENAND_HAS_UNLOCK_ALL;
2933 break;
2934
2935 default:
2936
2937 if (!process)
2938 this->options |= ONENAND_HAS_CONT_LOCK;
2939 break;
2940 }
2941
2942 if (ONENAND_IS_MLC(this))
2943 this->options &= ~ONENAND_HAS_2PLANE;
2944
2945 if (FLEXONENAND(this)) {
2946 this->options &= ~ONENAND_HAS_CONT_LOCK;
2947 this->options |= ONENAND_HAS_UNLOCK_ALL;
2948 }
2949
2950 if (this->options & ONENAND_HAS_CONT_LOCK)
2951 printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
2952 if (this->options & ONENAND_HAS_UNLOCK_ALL)
2953 printk(KERN_DEBUG "Chip support all block unlock\n");
2954 if (this->options & ONENAND_HAS_2PLANE)
2955 printk(KERN_DEBUG "Chip has 2 plane\n");
2956}
2957
2958
2959
2960
2961
2962
2963
2964
2965static void onenand_print_device_info(int device, int version)
2966{
2967 int vcc, demuxed, ddp, density, flexonenand;
2968
2969 vcc = device & ONENAND_DEVICE_VCC_MASK;
2970 demuxed = device & ONENAND_DEVICE_IS_DEMUX;
2971 ddp = device & ONENAND_DEVICE_IS_DDP;
2972 density = onenand_get_density(device);
2973 flexonenand = device & DEVICE_IS_FLEXONENAND;
2974 printk(KERN_INFO "%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
2975 demuxed ? "" : "Muxed ",
2976 flexonenand ? "Flex-" : "",
2977 ddp ? "(DDP)" : "",
2978 (16 << density),
2979 vcc ? "2.65/3.3" : "1.8",
2980 device);
2981 printk(KERN_INFO "OneNAND version = 0x%04x\n", version);
2982}
2983
2984static const struct onenand_manufacturers onenand_manuf_ids[] = {
2985 {ONENAND_MFR_SAMSUNG, "Samsung"},
2986 {ONENAND_MFR_NUMONYX, "Numonyx"},
2987};
2988
2989
2990
2991
2992
2993
2994
2995static int onenand_check_maf(int manuf)
2996{
2997 int size = ARRAY_SIZE(onenand_manuf_ids);
2998 char *name;
2999 int i;
3000
3001 for (i = 0; i < size; i++)
3002 if (manuf == onenand_manuf_ids[i].id)
3003 break;
3004
3005 if (i < size)
3006 name = onenand_manuf_ids[i].name;
3007 else
3008 name = "Unknown";
3009
3010 printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);
3011
3012 return (i == size);
3013}
3014
3015
3016
3017
3018
3019static int flexonenand_get_boundary(struct mtd_info *mtd)
3020{
3021 struct onenand_chip *this = mtd->priv;
3022 unsigned die, bdry;
3023 int ret, syscfg, locked;
3024
3025
3026 syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
3027 this->write_word((syscfg | 0x0100), this->base + ONENAND_REG_SYS_CFG1);
3028
3029 for (die = 0; die < this->dies; die++) {
3030 this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
3031 this->wait(mtd, FL_SYNCING);
3032
3033 this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
3034 ret = this->wait(mtd, FL_READING);
3035
3036 bdry = this->read_word(this->base + ONENAND_DATARAM);
3037 if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
3038 locked = 0;
3039 else
3040 locked = 1;
3041 this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
3042
3043 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
3044 ret = this->wait(mtd, FL_RESETING);
3045
3046 printk(KERN_INFO "Die %d boundary: %d%s\n", die,
3047 this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
3048 }
3049
3050
3051 this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
3052 return 0;
3053}
3054
3055
3056
3057
3058
3059
3060static void flexonenand_get_size(struct mtd_info *mtd)
3061{
3062 struct onenand_chip *this = mtd->priv;
3063 int die, i, eraseshift, density;
3064 int blksperdie, maxbdry;
3065 loff_t ofs;
3066
3067 density = onenand_get_density(this->device_id);
3068 blksperdie = ((loff_t)(16 << density) << 20) >> (this->erase_shift);
3069 blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
3070 maxbdry = blksperdie - 1;
3071 eraseshift = this->erase_shift - 1;
3072
3073 mtd->numeraseregions = this->dies << 1;
3074
3075
3076 flexonenand_get_boundary(mtd);
3077 die = ofs = 0;
3078 i = -1;
3079 for (; die < this->dies; die++) {
3080 if (!die || this->boundary[die-1] != maxbdry) {
3081 i++;
3082 mtd->eraseregions[i].offset = ofs;
3083 mtd->eraseregions[i].erasesize = 1 << eraseshift;
3084 mtd->eraseregions[i].numblocks =
3085 this->boundary[die] + 1;
3086 ofs += mtd->eraseregions[i].numblocks << eraseshift;
3087 eraseshift++;
3088 } else {
3089 mtd->numeraseregions -= 1;
3090 mtd->eraseregions[i].numblocks +=
3091 this->boundary[die] + 1;
3092 ofs += (this->boundary[die] + 1) << (eraseshift - 1);
3093 }
3094 if (this->boundary[die] != maxbdry) {
3095 i++;
3096 mtd->eraseregions[i].offset = ofs;
3097 mtd->eraseregions[i].erasesize = 1 << eraseshift;
3098 mtd->eraseregions[i].numblocks = maxbdry ^
3099 this->boundary[die];
3100 ofs += mtd->eraseregions[i].numblocks << eraseshift;
3101 eraseshift--;
3102 } else
3103 mtd->numeraseregions -= 1;
3104 }
3105
3106
3107 mtd->erasesize = 1 << this->erase_shift;
3108 if (mtd->numeraseregions == 1)
3109 mtd->erasesize >>= 1;
3110
3111 printk(KERN_INFO "Device has %d eraseregions\n", mtd->numeraseregions);
3112 for (i = 0; i < mtd->numeraseregions; i++)
3113 printk(KERN_INFO "[offset: 0x%08x, erasesize: 0x%05x,"
3114 " numblocks: %04u]\n",
3115 (unsigned int) mtd->eraseregions[i].offset,
3116 mtd->eraseregions[i].erasesize,
3117 mtd->eraseregions[i].numblocks);
3118
3119 for (die = 0, mtd->size = 0; die < this->dies; die++) {
3120 this->diesize[die] = (loff_t)blksperdie << this->erase_shift;
3121 this->diesize[die] -= (loff_t)(this->boundary[die] + 1)
3122 << (this->erase_shift - 1);
3123 mtd->size += this->diesize[die];
3124 }
3125}
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int end)
3142{
3143 struct onenand_chip *this = mtd->priv;
3144 int i, ret;
3145 int block;
3146 struct mtd_oob_ops ops = {
3147 .mode = MTD_OOB_PLACE,
3148 .ooboffs = 0,
3149 .ooblen = mtd->oobsize,
3150 .datbuf = NULL,
3151 .oobbuf = this->oob_buf,
3152 };
3153 loff_t addr;
3154
3155 printk(KERN_DEBUG "Check blocks from %d to %d\n", start, end);
3156
3157 for (block = start; block <= end; block++) {
3158 addr = flexonenand_addr(this, block);
3159 if (onenand_block_isbad_nolock(mtd, addr, 0))
3160 continue;
3161
3162
3163
3164
3165
3166 ret = onenand_read_oob_nolock(mtd, addr, &ops);
3167 if (ret)
3168 return ret;
3169
3170 for (i = 0; i < mtd->oobsize; i++)
3171 if (this->oob_buf[i] != 0xff)
3172 break;
3173
3174 if (i != mtd->oobsize) {
3175 printk(KERN_WARNING "Block %d not erased.\n", block);
3176 return 1;
3177 }
3178 }
3179
3180 return 0;
3181}
3182
3183
3184
3185
3186
3187int flexonenand_set_boundary(struct mtd_info *mtd, int die,
3188 int boundary, int lock)
3189{
3190 struct onenand_chip *this = mtd->priv;
3191 int ret, density, blksperdie, old, new, thisboundary;
3192 loff_t addr;
3193
3194
3195 if (die && (!ONENAND_IS_DDP(this)))
3196 return 0;
3197
3198
3199 if (boundary < 0 || boundary == this->boundary[die])
3200 return 0;
3201
3202 density = onenand_get_density(this->device_id);
3203 blksperdie = ((16 << density) << 20) >> this->erase_shift;
3204 blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
3205
3206 if (boundary >= blksperdie) {
3207 printk(KERN_ERR "flexonenand_set_boundary: Invalid boundary value. "
3208 "Boundary not changed.\n");
3209 return -EINVAL;
3210 }
3211
3212
3213 old = this->boundary[die] + (die * this->density_mask);
3214 new = boundary + (die * this->density_mask);
3215 ret = flexonenand_check_blocks_erased(mtd, min(old, new) + 1, max(old, new));
3216 if (ret) {
3217 printk(KERN_ERR "flexonenand_set_boundary: Please erase blocks before boundary change\n");
3218 return ret;
3219 }
3220
3221 this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
3222 this->wait(mtd, FL_SYNCING);
3223
3224
3225 this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
3226 ret = this->wait(mtd, FL_READING);
3227
3228 thisboundary = this->read_word(this->base + ONENAND_DATARAM);
3229 if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
3230 printk(KERN_ERR "flexonenand_set_boundary: boundary locked\n");
3231 ret = 1;
3232 goto out;
3233 }
3234
3235 printk(KERN_INFO "flexonenand_set_boundary: Changing die %d boundary: %d%s\n",
3236 die, boundary, lock ? "(Locked)" : "(Unlocked)");
3237
3238 addr = die ? this->diesize[0] : 0;
3239
3240 boundary &= FLEXONENAND_PI_MASK;
3241 boundary |= lock ? 0 : (3 << FLEXONENAND_PI_UNLOCK_SHIFT);
3242
3243 this->command(mtd, ONENAND_CMD_ERASE, addr, 0);
3244 ret = this->wait(mtd, FL_ERASING);
3245 if (ret) {
3246 printk(KERN_ERR "flexonenand_set_boundary: Failed PI erase for Die %d\n", die);
3247 goto out;
3248 }
3249
3250 this->write_word(boundary, this->base + ONENAND_DATARAM);
3251 this->command(mtd, ONENAND_CMD_PROG, addr, 0);
3252 ret = this->wait(mtd, FL_WRITING);
3253 if (ret) {
3254 printk(KERN_ERR "flexonenand_set_boundary: Failed PI write for Die %d\n", die);
3255 goto out;
3256 }
3257
3258 this->command(mtd, FLEXONENAND_CMD_PI_UPDATE, die, 0);
3259 ret = this->wait(mtd, FL_WRITING);
3260out:
3261 this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND);
3262 this->wait(mtd, FL_RESETING);
3263 if (!ret)
3264
3265 flexonenand_get_size(mtd);
3266
3267 return ret;
3268}
3269
3270
3271
3272
3273
3274
3275
3276
3277static int onenand_probe(struct mtd_info *mtd)
3278{
3279 struct onenand_chip *this = mtd->priv;
3280 int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;
3281 int density;
3282 int syscfg;
3283
3284
3285 syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
3286
3287 this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE), this->base + ONENAND_REG_SYS_CFG1);
3288
3289
3290 this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);
3291
3292
3293 bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0);
3294 bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2);
3295
3296
3297 this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
3298
3299 this->wait(mtd, FL_RESETING);
3300
3301
3302 this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
3303
3304
3305 if (onenand_check_maf(bram_maf_id))
3306 return -ENXIO;
3307
3308
3309 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
3310 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
3311 ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
3312 this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
3313
3314
3315 if (maf_id != bram_maf_id || dev_id != bram_dev_id)
3316 return -ENXIO;
3317
3318
3319 onenand_print_device_info(dev_id, ver_id);
3320 this->device_id = dev_id;
3321 this->version_id = ver_id;
3322
3323 density = onenand_get_density(dev_id);
3324 if (FLEXONENAND(this)) {
3325 this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
3326
3327 mtd->numeraseregions = this->dies << 1;
3328 mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info)
3329 * (this->dies << 1), GFP_KERNEL);
3330 if (!mtd->eraseregions)
3331 return -ENOMEM;
3332 }
3333
3334
3335
3336
3337
3338 this->chipsize = (16 << density) << 20;
3339
3340
3341
3342 mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
3343
3344 if (ONENAND_IS_MLC(this))
3345 mtd->writesize <<= 1;
3346
3347 mtd->oobsize = mtd->writesize >> 5;
3348
3349 mtd->erasesize = mtd->writesize << 6;
3350
3351
3352
3353
3354
3355 if (FLEXONENAND(this))
3356 mtd->erasesize <<= 1;
3357
3358 this->erase_shift = ffs(mtd->erasesize) - 1;
3359 this->page_shift = ffs(mtd->writesize) - 1;
3360 this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
3361
3362 if (ONENAND_IS_DDP(this))
3363 this->density_mask = this->chipsize >> (this->erase_shift + 1);
3364
3365 this->writesize = mtd->writesize;
3366
3367
3368
3369 if (FLEXONENAND(this))
3370 flexonenand_get_size(mtd);
3371 else
3372 mtd->size = this->chipsize;
3373
3374
3375 onenand_check_features(mtd);
3376
3377
3378
3379
3380
3381
3382
3383 if (ONENAND_IS_2PLANE(this)) {
3384 mtd->writesize <<= 1;
3385 mtd->erasesize <<= 1;
3386 }
3387
3388 return 0;
3389}
3390
3391
3392
3393
3394
3395static int onenand_suspend(struct mtd_info *mtd)
3396{
3397 return onenand_get_device(mtd, FL_PM_SUSPENDED);
3398}
3399
3400
3401
3402
3403
3404static void onenand_resume(struct mtd_info *mtd)
3405{
3406 struct onenand_chip *this = mtd->priv;
3407
3408 if (this->state == FL_PM_SUSPENDED)
3409 onenand_release_device(mtd);
3410 else
3411 printk(KERN_ERR "resume() called for the chip which is not"
3412 "in suspended state\n");
3413}
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425int onenand_scan(struct mtd_info *mtd, int maxchips)
3426{
3427 int i, ret;
3428 struct onenand_chip *this = mtd->priv;
3429
3430 if (!this->read_word)
3431 this->read_word = onenand_readw;
3432 if (!this->write_word)
3433 this->write_word = onenand_writew;
3434
3435 if (!this->command)
3436 this->command = onenand_command;
3437 if (!this->wait)
3438 onenand_setup_wait(mtd);
3439 if (!this->bbt_wait)
3440 this->bbt_wait = onenand_bbt_wait;
3441 if (!this->unlock_all)
3442 this->unlock_all = onenand_unlock_all;
3443
3444 if (!this->read_bufferram)
3445 this->read_bufferram = onenand_read_bufferram;
3446 if (!this->write_bufferram)
3447 this->write_bufferram = onenand_write_bufferram;
3448
3449 if (!this->block_markbad)
3450 this->block_markbad = onenand_default_block_markbad;
3451 if (!this->scan_bbt)
3452 this->scan_bbt = onenand_default_bbt;
3453
3454 if (onenand_probe(mtd))
3455 return -ENXIO;
3456
3457
3458 if (this->mmcontrol) {
3459 printk(KERN_INFO "OneNAND Sync. Burst Read support\n");
3460 this->read_bufferram = onenand_sync_read_bufferram;
3461 }
3462
3463
3464 if (!this->page_buf) {
3465 this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
3466 if (!this->page_buf) {
3467 printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
3468 return -ENOMEM;
3469 }
3470 this->options |= ONENAND_PAGEBUF_ALLOC;
3471 }
3472 if (!this->oob_buf) {
3473 this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
3474 if (!this->oob_buf) {
3475 printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n");
3476 if (this->options & ONENAND_PAGEBUF_ALLOC) {
3477 this->options &= ~ONENAND_PAGEBUF_ALLOC;
3478 kfree(this->page_buf);
3479 }
3480 return -ENOMEM;
3481 }
3482 this->options |= ONENAND_OOBBUF_ALLOC;
3483 }
3484
3485 this->state = FL_READY;
3486 init_waitqueue_head(&this->wq);
3487 spin_lock_init(&this->chip_lock);
3488
3489
3490
3491
3492 switch (mtd->oobsize) {
3493 case 128:
3494 this->ecclayout = &onenand_oob_128;
3495 mtd->subpage_sft = 0;
3496 break;
3497 case 64:
3498 this->ecclayout = &onenand_oob_64;
3499 mtd->subpage_sft = 2;
3500 break;
3501
3502 case 32:
3503 this->ecclayout = &onenand_oob_32;
3504 mtd->subpage_sft = 1;
3505 break;
3506
3507 default:
3508 printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
3509 mtd->oobsize);
3510 mtd->subpage_sft = 0;
3511
3512 this->ecclayout = &onenand_oob_32;
3513 break;
3514 }
3515
3516 this->subpagesize = mtd->writesize >> mtd->subpage_sft;
3517
3518
3519
3520
3521
3522 this->ecclayout->oobavail = 0;
3523 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES &&
3524 this->ecclayout->oobfree[i].length; i++)
3525 this->ecclayout->oobavail +=
3526 this->ecclayout->oobfree[i].length;
3527 mtd->oobavail = this->ecclayout->oobavail;
3528
3529 mtd->ecclayout = this->ecclayout;
3530
3531
3532 mtd->type = MTD_NANDFLASH;
3533 mtd->flags = MTD_CAP_NANDFLASH;
3534 mtd->erase = onenand_erase;
3535 mtd->point = NULL;
3536 mtd->unpoint = NULL;
3537 mtd->read = onenand_read;
3538 mtd->write = onenand_write;
3539 mtd->read_oob = onenand_read_oob;
3540 mtd->write_oob = onenand_write_oob;
3541 mtd->panic_write = onenand_panic_write;
3542#ifdef CONFIG_MTD_ONENAND_OTP
3543 mtd->get_fact_prot_info = onenand_get_fact_prot_info;
3544 mtd->read_fact_prot_reg = onenand_read_fact_prot_reg;
3545 mtd->get_user_prot_info = onenand_get_user_prot_info;
3546 mtd->read_user_prot_reg = onenand_read_user_prot_reg;
3547 mtd->write_user_prot_reg = onenand_write_user_prot_reg;
3548 mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
3549#endif
3550 mtd->sync = onenand_sync;
3551 mtd->lock = onenand_lock;
3552 mtd->unlock = onenand_unlock;
3553 mtd->suspend = onenand_suspend;
3554 mtd->resume = onenand_resume;
3555 mtd->block_isbad = onenand_block_isbad;
3556 mtd->block_markbad = onenand_block_markbad;
3557 mtd->owner = THIS_MODULE;
3558
3559
3560 this->unlock_all(mtd);
3561
3562 ret = this->scan_bbt(mtd);
3563 if ((!FLEXONENAND(this)) || ret)
3564 return ret;
3565
3566
3567 for (i = 0; i < MAX_DIES; i++)
3568 flexonenand_set_boundary(mtd, i, flex_bdry[2 * i],
3569 flex_bdry[(2 * i) + 1]);
3570
3571 return 0;
3572}
3573
3574
3575
3576
3577
3578void onenand_release(struct mtd_info *mtd)
3579{
3580 struct onenand_chip *this = mtd->priv;
3581
3582#ifdef CONFIG_MTD_PARTITIONS
3583
3584 del_mtd_partitions (mtd);
3585#endif
3586
3587 del_mtd_device (mtd);
3588
3589
3590 if (this->bbm) {
3591 struct bbm_info *bbm = this->bbm;
3592 kfree(bbm->bbt);
3593 kfree(this->bbm);
3594 }
3595
3596 if (this->options & ONENAND_PAGEBUF_ALLOC)
3597 kfree(this->page_buf);
3598 if (this->options & ONENAND_OOBBUF_ALLOC)
3599 kfree(this->oob_buf);
3600 kfree(mtd->eraseregions);
3601}
3602
3603EXPORT_SYMBOL_GPL(onenand_scan);
3604EXPORT_SYMBOL_GPL(onenand_release);
3605
3606MODULE_LICENSE("GPL");
3607MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
3608MODULE_DESCRIPTION("Generic OneNAND flash driver code");
3609