2 Common Flash Interface probe code.
3 (C) 2000 Red Hat. GPL'd.
4 $Id: jedec_probe.c,v 1.19 2002/11/12 13:12:10 dwmw2 Exp $
5 See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
6 for the standard this probe goes back to.
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/types.h>
12 #include <linux/kernel.h>
14 #include <asm/byteorder.h>
15 #include <linux/errno.h>
16 #include <linux/slab.h>
17 #include <linux/interrupt.h>
19 #include <linux/mtd/map.h>
20 #include <linux/mtd/cfi.h>
21 #include <linux/mtd/gen_probe.h>
24 #define MANUFACTURER_AMD 0x0001
25 #define MANUFACTURER_ATMEL 0x001f
26 #define MANUFACTURER_FUJITSU 0x0004
27 #define MANUFACTURER_INTEL 0x0089
28 #define MANUFACTURER_MACRONIX 0x00C2
29 #define MANUFACTURER_ST 0x0020
30 #define MANUFACTURER_SST 0x00BF
31 #define MANUFACTURER_TOSHIBA 0x0098
35 #define AM29F800BB 0x2258
36 #define AM29F800BT 0x22D6
37 #define AM29LV800BB 0x225B
38 #define AM29LV800BT 0x22DA
39 #define AM29LV160DT 0x22C4
40 #define AM29LV160DB 0x2249
41 #define AM29F017D 0x003D
42 #define AM29F016 0x00AD
43 #define AM29F080 0x00D5
44 #define AM29F040 0x00A4
45 #define AM29LV040B 0x004F
46 #define AM29F032B 0x0041
49 #define AT49BV512 0x0003
50 #define AT29LV512 0x003d
51 #define AT49BV16X 0x00C0
52 #define AT49BV16XT 0x00C2
53 #define AT49BV32X 0x00C8
54 #define AT49BV32XT 0x00C9
57 #define MBM29LV650UE 0x22D7
58 #define MBM29LV320TE 0x22F6
59 #define MBM29LV320BE 0x22F9
60 #define MBM29LV160TE 0x22C4
61 #define MBM29LV160BE 0x2249
62 #define MBM29LV800BA 0x225B
63 #define MBM29LV800TA 0x22DA
66 #define I28F004B3T 0x00d4
67 #define I28F004B3B 0x00d5
68 #define I28F400B3T 0x8894
69 #define I28F400B3B 0x8895
70 #define I28F008S5 0x00a6
71 #define I28F016S5 0x00a0
72 #define I28F008SA 0x00a2
73 #define I28F008B3T 0x00d2
74 #define I28F008B3B 0x00d3
75 #define I28F800B3T 0x8892
76 #define I28F800B3B 0x8893
77 #define I28F016S3 0x00aa
78 #define I28F016B3T 0x00d0
79 #define I28F016B3B 0x00d1
80 #define I28F160B3T 0x8890
81 #define I28F160B3B 0x8891
82 #define I28F320B3T 0x8896
83 #define I28F320B3B 0x8897
84 #define I28F640B3T 0x8898
85 #define I28F640B3B 0x8899
86 #define I82802AB 0x00ad
87 #define I82802AC 0x00ac
90 #define MX29LV160T 0x22C4
91 #define MX29LV160B 0x2249
92 #define MX29F016 0x00AD
93 #define MX29F004T 0x0045
94 #define MX29F004B 0x0046
97 #define M29W800T 0x00D7
98 #define M29W160DT 0x22C4
99 #define M29W160DB 0x2249
100 #define M29W040B 0x00E3
103 #define SST29EE512 0x005d
104 #define SST29LE512 0x003d
105 #define SST39LF800 0x2781
106 #define SST39LF160 0x2782
107 #define SST39LF512 0x00D4
108 #define SST39LF010 0x00D5
109 #define SST39LF020 0x00D6
110 #define SST39LF040 0x00D7
111 #define SST39SF010A 0x00B5
112 #define SST39SF020A 0x00B6
113 #define SST49LF030A 0x001C
114 #define SST49LF040A 0x0051
115 #define SST49LF080A 0x005B
118 #define TC58FVT160 0x00C2
119 #define TC58FVB160 0x0043
120 #define TC58FVT321 0x009A
121 #define TC58FVB321 0x009C
122 #define TC58FVT641 0x0093
123 #define TC58FVB641 0x0095
126 struct amd_flash_info {
131 const int InterfaceDesc;
132 const int NumEraseRegions;
134 const ulong regions[4];
137 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
139 #define SIZE_64KiB 16
140 #define SIZE_128KiB 17
141 #define SIZE_256KiB 18
142 #define SIZE_512KiB 19
148 static const struct amd_flash_info jedec_table[] = {
150 mfr_id: MANUFACTURER_AMD,
152 name: "AMD AM29F032B",
154 CmdSet: P_ID_AMD_STD,
156 regions: {ERASEINFO(0x10000,64)
159 mfr_id: MANUFACTURER_AMD,
161 name: "AMD AM29LV160DT",
163 CmdSet: P_ID_AMD_STD,
165 regions: {ERASEINFO(0x10000,31),
166 ERASEINFO(0x08000,1),
167 ERASEINFO(0x02000,2),
171 mfr_id: MANUFACTURER_AMD,
173 name: "AMD AM29LV160DB",
175 CmdSet: P_ID_AMD_STD,
177 regions: {ERASEINFO(0x04000,1),
178 ERASEINFO(0x02000,2),
179 ERASEINFO(0x08000,1),
180 ERASEINFO(0x10000,31)
183 mfr_id: MANUFACTURER_TOSHIBA,
185 name: "Toshiba TC58FVT160",
187 CmdSet: P_ID_AMD_STD,
189 regions: {ERASEINFO(0x10000,31),
190 ERASEINFO(0x08000,1),
191 ERASEINFO(0x02000,2),
195 mfr_id: MANUFACTURER_TOSHIBA,
197 name: "Toshiba TC58FVB160",
199 CmdSet: P_ID_AMD_STD,
201 regions: {ERASEINFO(0x04000,1),
202 ERASEINFO(0x02000,2),
203 ERASEINFO(0x08000,1),
204 ERASEINFO(0x10000,31)
207 mfr_id: MANUFACTURER_TOSHIBA,
209 name: "Toshiba TC58FVB321",
211 CmdSet: P_ID_AMD_STD,
213 regions: {ERASEINFO(0x02000,8),
214 ERASEINFO(0x10000,63)
217 mfr_id: MANUFACTURER_TOSHIBA,
219 name: "Toshiba TC58FVT321",
221 CmdSet: P_ID_AMD_STD,
223 regions: {ERASEINFO(0x10000,63),
227 mfr_id: MANUFACTURER_TOSHIBA,
229 name: "Toshiba TC58FVB641",
231 CmdSet: P_ID_AMD_STD,
233 regions: {ERASEINFO(0x02000,8),
234 ERASEINFO(0x10000,127)
237 mfr_id: MANUFACTURER_TOSHIBA,
239 name: "Toshiba TC58FVT641",
241 CmdSet: P_ID_AMD_STD,
243 regions: {ERASEINFO(0x10000,127),
247 mfr_id: MANUFACTURER_FUJITSU,
248 dev_id: MBM29LV650UE,
249 name: "Fujitsu MBM29LV650UE",
251 CmdSet: P_ID_AMD_STD,
253 regions: {ERASEINFO(0x10000,128)
256 mfr_id: MANUFACTURER_FUJITSU,
257 dev_id: MBM29LV320TE,
258 name: "Fujitsu MBM29LV320TE",
260 CmdSet: P_ID_AMD_STD,
262 regions: {ERASEINFO(0x10000,63),
266 mfr_id: MANUFACTURER_FUJITSU,
267 dev_id: MBM29LV320BE,
268 name: "Fujitsu MBM29LV320BE",
270 CmdSet: P_ID_AMD_STD,
272 regions: {ERASEINFO(0x02000,8),
273 ERASEINFO(0x10000,63)
276 mfr_id: MANUFACTURER_FUJITSU,
277 dev_id: MBM29LV160TE,
278 name: "Fujitsu MBM29LV160TE",
280 CmdSet: P_ID_AMD_STD,
282 regions: {ERASEINFO(0x10000,31),
283 ERASEINFO(0x08000,1),
284 ERASEINFO(0x02000,2),
288 mfr_id: MANUFACTURER_FUJITSU,
289 dev_id: MBM29LV160BE,
290 name: "Fujitsu MBM29LV160BE",
292 CmdSet: P_ID_AMD_STD,
294 regions: {ERASEINFO(0x04000,1),
295 ERASEINFO(0x02000,2),
296 ERASEINFO(0x08000,1),
297 ERASEINFO(0x10000,31)
300 mfr_id: MANUFACTURER_FUJITSU,
301 dev_id: MBM29LV800BA,
302 name: "Fujitsu MBM29LV800BA",
304 CmdSet: P_ID_AMD_STD,
306 regions: {ERASEINFO(0x04000,1),
307 ERASEINFO(0x02000,2),
308 ERASEINFO(0x08000,1),
309 ERASEINFO(0x10000,15)
312 mfr_id: MANUFACTURER_FUJITSU,
313 dev_id: MBM29LV800TA,
314 name: "Fujitsu MBM29LV800TA",
316 CmdSet: P_ID_AMD_STD,
318 regions: {ERASEINFO(0x10000,15),
319 ERASEINFO(0x08000,1),
320 ERASEINFO(0x02000,2),
324 mfr_id: MANUFACTURER_AMD,
326 name: "AMD AM29LV800BB",
328 CmdSet: P_ID_AMD_STD,
330 regions: {ERASEINFO(0x04000,1),
331 ERASEINFO(0x02000,2),
332 ERASEINFO(0x08000,1),
333 ERASEINFO(0x10000,15),
336 mfr_id: MANUFACTURER_AMD,
338 name: "AMD AM29F800BB",
340 CmdSet: P_ID_AMD_STD,
342 regions: {ERASEINFO(0x04000,1),
343 ERASEINFO(0x02000,2),
344 ERASEINFO(0x08000,1),
345 ERASEINFO(0x10000,15),
348 mfr_id: MANUFACTURER_AMD,
350 name: "AMD AM29LV800BT",
352 CmdSet: P_ID_AMD_STD,
354 regions: {ERASEINFO(0x10000,15),
355 ERASEINFO(0x08000,1),
356 ERASEINFO(0x02000,2),
360 mfr_id: MANUFACTURER_AMD,
362 name: "AMD AM29F800BT",
364 CmdSet: P_ID_AMD_STD,
366 regions: {ERASEINFO(0x10000,15),
367 ERASEINFO(0x08000,1),
368 ERASEINFO(0x02000,2),
372 mfr_id: MANUFACTURER_AMD,
374 name: "AMD AM29LV800BB",
376 CmdSet: P_ID_AMD_STD,
378 regions: {ERASEINFO(0x10000,15),
379 ERASEINFO(0x08000,1),
380 ERASEINFO(0x02000,2),
384 mfr_id: MANUFACTURER_INTEL,
386 name: "Intel 28F004B3B",
387 DevSize: SIZE_512KiB,
388 CmdSet: P_ID_INTEL_STD,
391 ERASEINFO(0x02000, 8),
392 ERASEINFO(0x10000, 7),
395 mfr_id: MANUFACTURER_INTEL,
397 name: "Intel 28F004B3T",
398 DevSize: SIZE_512KiB,
399 CmdSet: P_ID_INTEL_STD,
402 ERASEINFO(0x10000, 7),
403 ERASEINFO(0x02000, 8),
406 mfr_id: MANUFACTURER_INTEL,
408 name: "Intel 28F400B3B",
409 DevSize: SIZE_512KiB,
410 CmdSet: P_ID_INTEL_STD,
413 ERASEINFO(0x02000, 8),
414 ERASEINFO(0x10000, 7),
417 mfr_id: MANUFACTURER_INTEL,
419 name: "Intel 28F400B3T",
420 DevSize: SIZE_512KiB,
421 CmdSet: P_ID_INTEL_STD,
424 ERASEINFO(0x10000, 7),
425 ERASEINFO(0x02000, 8),
428 mfr_id: MANUFACTURER_INTEL,
430 name: "Intel 28F008B3B",
432 CmdSet: P_ID_INTEL_STD,
435 ERASEINFO(0x02000, 8),
436 ERASEINFO(0x10000, 15),
439 mfr_id: MANUFACTURER_INTEL,
441 name: "Intel 28F008B3T",
443 CmdSet: P_ID_INTEL_STD,
446 ERASEINFO(0x10000, 15),
447 ERASEINFO(0x02000, 8),
450 mfr_id: MANUFACTURER_INTEL,
452 name: "Intel 28F008S5",
454 CmdSet: P_ID_INTEL_EXT,
456 regions: {ERASEINFO(0x10000,16),
459 mfr_id: MANUFACTURER_INTEL,
461 name: "Intel 28F016S5",
463 CmdSet: P_ID_INTEL_EXT,
465 regions: {ERASEINFO(0x10000,32),
468 mfr_id: MANUFACTURER_INTEL,
470 name: "Intel 28F008SA",
472 CmdSet: P_ID_INTEL_STD,
475 ERASEINFO(0x10000, 16),
478 mfr_id: MANUFACTURER_INTEL,
480 name: "Intel 28F800B3B",
482 CmdSet: P_ID_INTEL_STD,
485 ERASEINFO(0x02000, 8),
486 ERASEINFO(0x10000, 15),
489 mfr_id: MANUFACTURER_INTEL,
491 name: "Intel 28F800B3T",
493 CmdSet: P_ID_INTEL_STD,
496 ERASEINFO(0x10000, 15),
497 ERASEINFO(0x02000, 8),
500 mfr_id: MANUFACTURER_INTEL,
502 name: "Intel 28F016B3B",
504 CmdSet: P_ID_INTEL_STD,
507 ERASEINFO(0x02000, 8),
508 ERASEINFO(0x10000, 31),
511 mfr_id: MANUFACTURER_INTEL,
513 name: "Intel I28F016S3",
515 CmdSet: P_ID_INTEL_STD,
518 ERASEINFO(0x10000, 32),
521 mfr_id: MANUFACTURER_INTEL,
523 name: "Intel 28F016B3T",
525 CmdSet: P_ID_INTEL_STD,
528 ERASEINFO(0x10000, 31),
529 ERASEINFO(0x02000, 8),
532 mfr_id: MANUFACTURER_INTEL,
534 name: "Intel 28F160B3B",
536 CmdSet: P_ID_INTEL_STD,
539 ERASEINFO(0x02000, 8),
540 ERASEINFO(0x10000, 31),
543 mfr_id: MANUFACTURER_INTEL,
545 name: "Intel 28F160B3T",
547 CmdSet: P_ID_INTEL_STD,
550 ERASEINFO(0x10000, 31),
551 ERASEINFO(0x02000, 8),
554 mfr_id: MANUFACTURER_INTEL,
556 name: "Intel 28F320B3B",
558 CmdSet: P_ID_INTEL_STD,
561 ERASEINFO(0x02000, 8),
562 ERASEINFO(0x10000, 63),
565 mfr_id: MANUFACTURER_INTEL,
567 name: "Intel 28F320B3T",
569 CmdSet: P_ID_INTEL_STD,
572 ERASEINFO(0x10000, 63),
573 ERASEINFO(0x02000, 8),
576 mfr_id: MANUFACTURER_INTEL,
578 name: "Intel 28F640B3B",
580 CmdSet: P_ID_INTEL_STD,
583 ERASEINFO(0x02000, 8),
584 ERASEINFO(0x10000, 127),
587 mfr_id: MANUFACTURER_INTEL,
589 name: "Intel 28F640B3T",
591 CmdSet: P_ID_INTEL_STD,
594 ERASEINFO(0x10000, 127),
595 ERASEINFO(0x02000, 8),
598 mfr_id: MANUFACTURER_INTEL,
600 name: "Intel 82802AB",
601 DevSize: SIZE_512KiB,
602 CmdSet: P_ID_INTEL_EXT,
604 regions: {ERASEINFO(0x10000,8),
607 mfr_id: MANUFACTURER_INTEL,
609 name: "Intel 82802AC",
611 CmdSet: P_ID_INTEL_EXT,
613 regions: {ERASEINFO(0x10000,16),
616 mfr_id: MANUFACTURER_ST,
620 CmdSet: P_ID_AMD_STD,
622 regions: {ERASEINFO(0x10000,15),
623 ERASEINFO(0x08000,1),
624 ERASEINFO(0x02000,2),
628 mfr_id: MANUFACTURER_ST,
630 name: "ST M29W160DT",
632 CmdSet: P_ID_AMD_STD,
634 regions: {ERASEINFO(0x10000,31),
635 ERASEINFO(0x08000,1),
636 ERASEINFO(0x02000,2),
640 mfr_id: MANUFACTURER_ST,
642 name: "ST M29W160DB",
644 CmdSet: P_ID_AMD_STD,
646 regions: {ERASEINFO(0x04000,1),
647 ERASEINFO(0x02000,2),
648 ERASEINFO(0x08000,1),
649 ERASEINFO(0x10000,31)
652 mfr_id: MANUFACTURER_ATMEL,
654 name: "Atmel AT49BV512",
656 CmdSet: P_ID_AMD_STD,
658 regions: {ERASEINFO(0x10000,1)
661 mfr_id: MANUFACTURER_ATMEL,
663 name: "Atmel AT29LV512",
665 CmdSet: P_ID_AMD_STD,
672 mfr_id: MANUFACTURER_ATMEL,
674 name: "Atmel AT49BV16X",
676 CmdSet: P_ID_AMD_STD,
678 regions: {ERASEINFO(0x02000,8),
679 ERASEINFO(0x10000,31)
682 mfr_id: MANUFACTURER_ATMEL,
684 name: "Atmel AT49BV16XT",
686 CmdSet: P_ID_AMD_STD,
688 regions: {ERASEINFO(0x10000,31),
692 mfr_id: MANUFACTURER_ATMEL,
694 name: "Atmel AT49BV32X",
696 CmdSet: P_ID_AMD_STD,
698 regions: {ERASEINFO(0x02000,8),
699 ERASEINFO(0x10000,63)
702 mfr_id: MANUFACTURER_ATMEL,
704 name: "Atmel AT49BV32XT",
706 CmdSet: P_ID_AMD_STD,
708 regions: {ERASEINFO(0x10000,63),
712 mfr_id: MANUFACTURER_AMD,
714 name: "AMD AM29F017D",
716 CmdSet: P_ID_AMD_STD,
718 regions: {ERASEINFO(0x10000,32),
721 mfr_id: MANUFACTURER_AMD,
723 name: "AMD AM29F016",
725 CmdSet: P_ID_AMD_STD,
727 regions: {ERASEINFO(0x10000,32),
730 mfr_id: MANUFACTURER_AMD,
732 name: "AMD AM29F080",
734 CmdSet: P_ID_AMD_STD,
736 regions: {ERASEINFO(0x10000,16),
739 mfr_id: MANUFACTURER_AMD,
741 name: "AMD AM29F040",
742 DevSize: SIZE_512KiB,
743 CmdSet: P_ID_AMD_STD,
745 regions: {ERASEINFO(0x10000,8),
748 mfr_id: MANUFACTURER_AMD,
750 name: "AMD AM29LV040B",
751 DevSize: SIZE_512KiB,
752 CmdSet: P_ID_AMD_STD,
754 regions: {ERASEINFO(0x10000,8),
757 mfr_id: MANUFACTURER_ST,
760 DevSize: SIZE_512KiB,
761 CmdSet: P_ID_AMD_STD,
763 regions: {ERASEINFO(0x10000,8),
766 mfr_id: MANUFACTURER_MACRONIX,
768 name: "MXIC MX29LV160T",
770 CmdSet: P_ID_AMD_STD,
772 regions: {ERASEINFO(0x10000,31),
773 ERASEINFO(0x08000,1),
774 ERASEINFO(0x02000,2),
778 mfr_id: MANUFACTURER_MACRONIX,
780 name: "MXIC MX29LV160B",
782 CmdSet: P_ID_AMD_STD,
784 regions: {ERASEINFO(0x04000,1),
785 ERASEINFO(0x02000,2),
786 ERASEINFO(0x08000,1),
787 ERASEINFO(0x10000,31)
790 mfr_id: MANUFACTURER_MACRONIX,
792 name: "Macronix MX29F016",
794 CmdSet: P_ID_AMD_STD,
796 regions: {ERASEINFO(0x10000,32),
799 mfr_id: MANUFACTURER_MACRONIX,
801 name: "Macronix MX29F004T",
802 DevSize: SIZE_512KiB,
803 CmdSet: P_ID_AMD_STD,
805 regions: {ERASEINFO(0x10000,7),
806 ERASEINFO(0x08000,1),
807 ERASEINFO(0x02000,2),
808 ERASEINFO(0x04000,1),
811 mfr_id: MANUFACTURER_MACRONIX,
813 name: "Macronix MX29F004B",
814 DevSize: SIZE_512KiB,
815 CmdSet: P_ID_AMD_STD,
817 regions: {ERASEINFO(0x04000,1),
818 ERASEINFO(0x02000,2),
819 ERASEINFO(0x08000,1),
820 ERASEINFO(0x10000,7),
823 mfr_id: MANUFACTURER_SST,
827 CmdSet: P_ID_AMD_STD,
829 regions: {ERASEINFO(0x01000,16),
832 mfr_id: MANUFACTURER_SST,
835 DevSize: SIZE_128KiB,
836 CmdSet: P_ID_AMD_STD,
838 regions: {ERASEINFO(0x01000,32),
841 mfr_id: MANUFACTURER_SST,
844 DevSize: SIZE_256KiB,
845 CmdSet: P_ID_AMD_STD,
847 regions: {ERASEINFO(0x01000,64),
850 mfr_id: MANUFACTURER_SST,
853 DevSize: SIZE_512KiB,
854 CmdSet: P_ID_AMD_STD,
856 regions: {ERASEINFO(0x01000,128),
859 mfr_id: MANUFACTURER_SST,
861 name: "SST 39SF010A",
862 DevSize: SIZE_128KiB,
863 CmdSet: P_ID_AMD_STD,
865 regions: {ERASEINFO(0x01000,32),
868 mfr_id: MANUFACTURER_SST,
870 name: "SST 39SF020A",
871 DevSize: SIZE_256KiB,
872 CmdSet: P_ID_AMD_STD,
874 regions: {ERASEINFO(0x01000,64),
877 mfr_id: MANUFACTURER_SST,
879 name: "SST 49LF030A",
880 DevSize: SIZE_512KiB,
881 CmdSet: P_ID_AMD_STD,
883 regions: {ERASEINFO(0x01000,96),
886 mfr_id: MANUFACTURER_SST,
888 name: "SST 49LF040A",
889 DevSize: SIZE_512KiB,
890 CmdSet: P_ID_AMD_STD,
892 regions: {ERASEINFO(0x01000,128),
895 mfr_id: MANUFACTURER_SST,
897 name: "SST 49LF080A",
899 CmdSet: P_ID_AMD_STD,
901 regions: {ERASEINFO(0x01000,256),
907 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
909 static int jedec_probe_chip(struct map_info *map, __u32 base,
910 struct flchip *chips, struct cfi_private *cfi);
912 struct mtd_info *jedec_probe(struct map_info *map);
914 static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
915 struct cfi_private *cfi)
918 mask = (1 << (cfi->device_type * 8)) -1;
919 result = cfi_read(map, base);
924 static inline u32 jedec_read_id(struct map_info *map, __u32 base,
925 struct cfi_private *cfi)
929 osf = cfi->interleave *cfi->device_type;
930 mask = (1 << (cfi->device_type * 8)) -1;
931 result = cfi_read(map, base + osf);
936 static inline void jedec_reset(u32 base, struct map_info *map,
937 struct cfi_private *cfi)
940 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
941 /* Some misdesigned intel chips do not respond for 0xF0 for a reset,
942 * so ensure we're in read mode. Send both the Intel and the AMD command
943 * for this. Intel uses 0xff for this, AMD uses 0xff for NOP, so
944 * this should be safe.
946 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
949 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
951 int i,num_erase_regions;
953 printk("Found: %s\n",jedec_table[index].name);
955 num_erase_regions = jedec_table[index].NumEraseRegions;
957 p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
959 //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
963 memset(p_cfi->cfiq,0,sizeof(struct cfi_ident));
965 p_cfi->cfiq->P_ID = jedec_table[index].CmdSet;
966 p_cfi->cfiq->NumEraseRegions = jedec_table[index].NumEraseRegions;
967 p_cfi->cfiq->DevSize = jedec_table[index].DevSize;
968 p_cfi->cfi_mode = CFI_MODE_JEDEC;
970 for (i=0; i<num_erase_regions; i++){
971 p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
973 p_cfi->cmdset_priv = 0;
977 static int jedec_probe_chip(struct map_info *map, __u32 base,
978 struct flchip *chips, struct cfi_private *cfi)
983 if (!cfi->numchips) {
984 switch (cfi->device_type) {
985 case CFI_DEVICETYPE_X8:
986 cfi->addr_unlock1 = 0x555;
987 cfi->addr_unlock2 = 0x2aa;
989 case CFI_DEVICETYPE_X16:
990 cfi->addr_unlock1 = 0xaaa;
991 if (map->buswidth == cfi->interleave) {
992 /* X16 chip(s) in X8 mode */
993 cfi->addr_unlock2 = 0x555;
995 cfi->addr_unlock2 = 0x554;
998 case CFI_DEVICETYPE_X32:
999 cfi->addr_unlock1 = 0x1555;
1000 cfi->addr_unlock2 = 0xaaa;
1003 printk(KERN_NOTICE "Eep. Unknown jedec_probe device type %d\n", cfi->device_type);
1009 /* Make certain we aren't probing past the end of map */
1010 if (base >= map->size) {
1012 "Probe at base(0x%08x) past the end of the map(0x%08lx)\n",
1013 base, map->size -1);
1017 if ((base + cfi->addr_unlock1) >= map->size) {
1019 "Probe at addr_unlock1(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
1020 base, cfi->addr_unlock1, map->size -1);
1024 if ((base + cfi->addr_unlock2) >= map->size) {
1026 "Probe at addr_unlock2(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
1027 base, cfi->addr_unlock2, map->size -1);
1033 jedec_reset(base, map, cfi);
1035 /* Autoselect Mode */
1036 if(cfi->addr_unlock1) {
1037 cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1038 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1040 cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1042 if (!cfi->numchips) {
1043 /* This is the first time we're called. Set up the CFI
1044 stuff accordingly and return */
1046 cfi->mfr = jedec_read_mfr(map, base, cfi);
1047 cfi->id = jedec_read_id(map, base, cfi);
1048 printk(KERN_INFO "Search for id:(%02x %02x) interleave(%d) type(%d)\n",
1049 cfi->mfr, cfi->id, cfi->interleave, cfi->device_type);
1050 for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
1051 if (cfi->mfr == jedec_table[i].mfr_id &&
1052 cfi->id == jedec_table[i].dev_id) {
1053 if (!cfi_jedec_setup(cfi, i))
1058 switch(unlockpass++) {
1060 cfi->addr_unlock1 |= cfi->addr_unlock1 << 4;
1061 cfi->addr_unlock2 |= cfi->addr_unlock2 << 4;
1064 cfi->addr_unlock1 = cfi->addr_unlock2 = 0;
1072 /* Make sure it is a chip of the same manufacturer and id */
1073 mfr = jedec_read_mfr(map, base, cfi);
1074 id = jedec_read_id(map, base, cfi);
1076 if ((mfr != cfi->mfr) || (id != cfi->id)) {
1077 printk(KERN_DEBUG "%s: Found different chip or no chip at all (mfr 0x%x, id 0x%x) at 0x%x\n",
1078 map->name, mfr, id, base);
1079 jedec_reset(base, map, cfi);
1084 /* Check each previous chip to see if it's an alias */
1085 for (i=0; i<cfi->numchips; i++) {
1086 /* This chip should be in read mode if it's one
1087 we've already touched. */
1088 if (jedec_read_mfr(map, chips[i].start, cfi) == cfi->mfr &&
1089 jedec_read_id(map, chips[i].start, cfi) == cfi->id) {
1090 /* Eep. This chip also looks like it's in autoselect mode.
1091 Is it an alias for the new one? */
1092 jedec_reset(chips[i].start, map, cfi);
1094 /* If the device IDs go away, it's an alias */
1095 if (jedec_read_mfr(map, base, cfi) != cfi->mfr ||
1096 jedec_read_id(map, base, cfi) != cfi->id) {
1097 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
1098 map->name, base, chips[i].start);
1102 /* Yes, it's actually got the device IDs as data. Most
1103 * unfortunate. Stick the new chip in read mode
1104 * too and if it's the same, assume it's an alias. */
1105 /* FIXME: Use other modes to do a proper check */
1106 jedec_reset(base, map, cfi);
1107 if (jedec_read_mfr(map, base, cfi) == cfi->mfr &&
1108 jedec_read_id(map, base, cfi) == cfi->id) {
1109 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
1110 map->name, base, chips[i].start);
1116 /* OK, if we got to here, then none of the previous chips appear to
1117 be aliases for the current one. */
1118 if (cfi->numchips == MAX_CFI_CHIPS) {
1119 printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS);
1120 /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */
1123 chips[cfi->numchips].start = base;
1124 chips[cfi->numchips].state = FL_READY;
1128 /* Put it back into Read Mode */
1129 jedec_reset(base, map, cfi);
1131 printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
1132 map->name, cfi->interleave, cfi->device_type*8, base,
1138 static struct chip_probe jedec_chip_probe = {
1140 probe_chip: jedec_probe_chip
1143 struct mtd_info *jedec_probe(struct map_info *map)
1146 * Just use the generic probe stuff to call our CFI-specific
1147 * chip_probe routine in all the possible permutations, etc.
1149 return mtd_do_chip_probe(map, &jedec_chip_probe);
1152 static struct mtd_chip_driver jedec_chipdrv = {
1154 name: "jedec_probe",
1158 int __init jedec_probe_init(void)
1160 register_mtd_chip_driver(&jedec_chipdrv);
1164 static void __exit jedec_probe_exit(void)
1166 unregister_mtd_chip_driver(&jedec_chipdrv);
1169 module_init(jedec_probe_init);
1170 module_exit(jedec_probe_exit);
1172 MODULE_LICENSE("GPL");
1173 MODULE_AUTHOR("Erwin Authried <eauth@softsys.co.at> et al.");
1174 MODULE_DESCRIPTION("Probe code for JEDEC-compliant flash chips");