1 /*
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.
7 */
8
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <asm/io.h>
14 #include <asm/byteorder.h>
15 #include <linux/errno.h>
16 #include <linux/slab.h>
17 #include <linux/interrupt.h>
18
19 #include <linux/mtd/map.h>
20 #include <linux/mtd/cfi.h>
21 #include <linux/mtd/gen_probe.h>
22
23 /* Manufacturers */
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
32
33
34 /* AMD */
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
47
48 /* Atmel */
49 #define AT49BV512 0x0003
50 #define AT29LV512 0x003d
51 #define AT49BV16X 0x00C0
52 #define AT49BV16XT 0x00C2
53 #define AT49BV32X 0x00C8
54 #define AT49BV32XT 0x00C9
55
56 /* Fujitsu */
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
64
65 /* Intel */
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
88
89 /* Macronix */
90 #define MX29LV160T 0x22C4
91 #define MX29LV160B 0x2249
92 #define MX29F016 0x00AD
93 #define MX29F004T 0x0045
94 #define MX29F004B 0x0046
95
96 /* ST - www.st.com */
97 #define M29W800T 0x00D7
98 #define M29W160DT 0x22C4
99 #define M29W160DB 0x2249
100 #define M29W040B 0x00E3
101
102 /* SST */
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
116
117 /* Toshiba */
118 #define TC58FVT160 0x00C2
119 #define TC58FVB160 0x0043
120 #define TC58FVT321 0x009A
121 #define TC58FVB321 0x009C
122 #define TC58FVT641 0x0093
123 #define TC58FVB641 0x0095
124
125
126 struct amd_flash_info {
127 const __u16 mfr_id;
128 const __u16 dev_id;
129 const char *name;
130 const int DevSize;
131 const int InterfaceDesc;
132 const int NumEraseRegions;
133 const int CmdSet;
134 const ulong regions[4];
135 };
136
137 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
138
139 #define SIZE_64KiB 16
140 #define SIZE_128KiB 17
141 #define SIZE_256KiB 18
142 #define SIZE_512KiB 19
143 #define SIZE_1MiB 20
144 #define SIZE_2MiB 21
145 #define SIZE_4MiB 22
146 #define SIZE_8MiB 23
147
148 static const struct amd_flash_info jedec_table[] = {
149 {
150 mfr_id: MANUFACTURER_AMD,
151 dev_id: AM29F032B,
152 name: "AMD AM29F032B",
153 DevSize: SIZE_4MiB,
154 CmdSet: P_ID_AMD_STD,
155 NumEraseRegions: 1,
156 regions: {ERASEINFO(0x10000,64)
157 }
158 }, {
159 mfr_id: MANUFACTURER_AMD,
160 dev_id: AM29LV160DT,
161 name: "AMD AM29LV160DT",
162 DevSize: SIZE_2MiB,
163 CmdSet: P_ID_AMD_STD,
164 NumEraseRegions: 4,
165 regions: {ERASEINFO(0x10000,31),
166 ERASEINFO(0x08000,1),
167 ERASEINFO(0x02000,2),
168 ERASEINFO(0x04000,1)
169 }
170 }, {
171 mfr_id: MANUFACTURER_AMD,
172 dev_id: AM29LV160DB,
173 name: "AMD AM29LV160DB",
174 DevSize: SIZE_2MiB,
175 CmdSet: P_ID_AMD_STD,
176 NumEraseRegions: 4,
177 regions: {ERASEINFO(0x04000,1),
178 ERASEINFO(0x02000,2),
179 ERASEINFO(0x08000,1),
180 ERASEINFO(0x10000,31)
181 }
182 }, {
183 mfr_id: MANUFACTURER_TOSHIBA,
184 dev_id: TC58FVT160,
185 name: "Toshiba TC58FVT160",
186 DevSize: SIZE_2MiB,
187 CmdSet: P_ID_AMD_STD,
188 NumEraseRegions: 4,
189 regions: {ERASEINFO(0x10000,31),
190 ERASEINFO(0x08000,1),
191 ERASEINFO(0x02000,2),
192 ERASEINFO(0x04000,1)
193 }
194 }, {
195 mfr_id: MANUFACTURER_TOSHIBA,
196 dev_id: TC58FVB160,
197 name: "Toshiba TC58FVB160",
198 DevSize: SIZE_2MiB,
199 CmdSet: P_ID_AMD_STD,
200 NumEraseRegions: 4,
201 regions: {ERASEINFO(0x04000,1),
202 ERASEINFO(0x02000,2),
203 ERASEINFO(0x08000,1),
204 ERASEINFO(0x10000,31)
205 }
206 }, {
207 mfr_id: MANUFACTURER_TOSHIBA,
208 dev_id: TC58FVB321,
209 name: "Toshiba TC58FVB321",
210 DevSize: SIZE_4MiB,
211 CmdSet: P_ID_AMD_STD,
212 NumEraseRegions: 2,
213 regions: {ERASEINFO(0x02000,8),
214 ERASEINFO(0x10000,63)
215 }
216 }, {
217 mfr_id: MANUFACTURER_TOSHIBA,
218 dev_id: TC58FVT321,
219 name: "Toshiba TC58FVT321",
220 DevSize: SIZE_4MiB,
221 CmdSet: P_ID_AMD_STD,
222 NumEraseRegions: 2,
223 regions: {ERASEINFO(0x10000,63),
224 ERASEINFO(0x02000,8)
225 }
226 }, {
227 mfr_id: MANUFACTURER_TOSHIBA,
228 dev_id: TC58FVB641,
229 name: "Toshiba TC58FVB641",
230 DevSize: SIZE_8MiB,
231 CmdSet: P_ID_AMD_STD,
232 NumEraseRegions: 2,
233 regions: {ERASEINFO(0x02000,8),
234 ERASEINFO(0x10000,127)
235 }
236 }, {
237 mfr_id: MANUFACTURER_TOSHIBA,
238 dev_id: TC58FVT641,
239 name: "Toshiba TC58FVT641",
240 DevSize: SIZE_8MiB,
241 CmdSet: P_ID_AMD_STD,
242 NumEraseRegions: 2,
243 regions: {ERASEINFO(0x10000,127),
244 ERASEINFO(0x02000,8)
245 }
246 }, {
247 mfr_id: MANUFACTURER_FUJITSU,
248 dev_id: MBM29LV650UE,
249 name: "Fujitsu MBM29LV650UE",
250 DevSize: SIZE_8MiB,
251 CmdSet: P_ID_AMD_STD,
252 NumEraseRegions: 1,
253 regions: {ERASEINFO(0x10000,128)
254 }
255 }, {
256 mfr_id: MANUFACTURER_FUJITSU,
257 dev_id: MBM29LV320TE,
258 name: "Fujitsu MBM29LV320TE",
259 DevSize: SIZE_4MiB,
260 CmdSet: P_ID_AMD_STD,
261 NumEraseRegions: 2,
262 regions: {ERASEINFO(0x10000,63),
263 ERASEINFO(0x02000,8)
264 }
265 }, {
266 mfr_id: MANUFACTURER_FUJITSU,
267 dev_id: MBM29LV320BE,
268 name: "Fujitsu MBM29LV320BE",
269 DevSize: SIZE_4MiB,
270 CmdSet: P_ID_AMD_STD,
271 NumEraseRegions: 2,
272 regions: {ERASEINFO(0x02000,8),
273 ERASEINFO(0x10000,63)
274 }
275 }, {
276 mfr_id: MANUFACTURER_FUJITSU,
277 dev_id: MBM29LV160TE,
278 name: "Fujitsu MBM29LV160TE",
279 DevSize: SIZE_2MiB,
280 CmdSet: P_ID_AMD_STD,
281 NumEraseRegions: 4,
282 regions: {ERASEINFO(0x10000,31),
283 ERASEINFO(0x08000,1),
284 ERASEINFO(0x02000,2),
285 ERASEINFO(0x04000,1)
286 }
287 }, {
288 mfr_id: MANUFACTURER_FUJITSU,
289 dev_id: MBM29LV160BE,
290 name: "Fujitsu MBM29LV160BE",
291 DevSize: SIZE_2MiB,
292 CmdSet: P_ID_AMD_STD,
293 NumEraseRegions: 4,
294 regions: {ERASEINFO(0x04000,1),
295 ERASEINFO(0x02000,2),
296 ERASEINFO(0x08000,1),
297 ERASEINFO(0x10000,31)
298 }
299 }, {
300 mfr_id: MANUFACTURER_FUJITSU,
301 dev_id: MBM29LV800BA,
302 name: "Fujitsu MBM29LV800BA",
303 DevSize: SIZE_1MiB,
304 CmdSet: P_ID_AMD_STD,
305 NumEraseRegions: 4,
306 regions: {ERASEINFO(0x04000,1),
307 ERASEINFO(0x02000,2),
308 ERASEINFO(0x08000,1),
309 ERASEINFO(0x10000,15)
310 }
311 }, {
312 mfr_id: MANUFACTURER_FUJITSU,
313 dev_id: MBM29LV800TA,
314 name: "Fujitsu MBM29LV800TA",
315 DevSize: SIZE_1MiB,
316 CmdSet: P_ID_AMD_STD,
317 NumEraseRegions: 4,
318 regions: {ERASEINFO(0x10000,15),
319 ERASEINFO(0x08000,1),
320 ERASEINFO(0x02000,2),
321 ERASEINFO(0x04000,1)
322 }
323 }, {
324 mfr_id: MANUFACTURER_AMD,
325 dev_id: AM29LV800BB,
326 name: "AMD AM29LV800BB",
327 DevSize: SIZE_1MiB,
328 CmdSet: P_ID_AMD_STD,
329 NumEraseRegions: 4,
330 regions: {ERASEINFO(0x04000,1),
331 ERASEINFO(0x02000,2),
332 ERASEINFO(0x08000,1),
333 ERASEINFO(0x10000,15),
334 }
335 }, {
336 mfr_id: MANUFACTURER_AMD,
337 dev_id: AM29F800BB,
338 name: "AMD AM29F800BB",
339 DevSize: SIZE_1MiB,
340 CmdSet: P_ID_AMD_STD,
341 NumEraseRegions: 4,
342 regions: {ERASEINFO(0x04000,1),
343 ERASEINFO(0x02000,2),
344 ERASEINFO(0x08000,1),
345 ERASEINFO(0x10000,15),
346 }
347 }, {
348 mfr_id: MANUFACTURER_AMD,
349 dev_id: AM29LV800BT,
350 name: "AMD AM29LV800BT",
351 DevSize: SIZE_1MiB,
352 CmdSet: P_ID_AMD_STD,
353 NumEraseRegions: 4,
354 regions: {ERASEINFO(0x10000,15),
355 ERASEINFO(0x08000,1),
356 ERASEINFO(0x02000,2),
357 ERASEINFO(0x04000,1)
358 }
359 }, {
360 mfr_id: MANUFACTURER_AMD,
361 dev_id: AM29F800BT,
362 name: "AMD AM29F800BT",
363 DevSize: SIZE_1MiB,
364 CmdSet: P_ID_AMD_STD,
365 NumEraseRegions: 4,
366 regions: {ERASEINFO(0x10000,15),
367 ERASEINFO(0x08000,1),
368 ERASEINFO(0x02000,2),
369 ERASEINFO(0x04000,1)
370 }
371 }, {
372 mfr_id: MANUFACTURER_AMD,
373 dev_id: AM29LV800BB,
374 name: "AMD AM29LV800BB",
375 DevSize: SIZE_1MiB,
376 CmdSet: P_ID_AMD_STD,
377 NumEraseRegions: 4,
378 regions: {ERASEINFO(0x10000,15),
379 ERASEINFO(0x08000,1),
380 ERASEINFO(0x02000,2),
381 ERASEINFO(0x04000,1)
382 }
383 }, {
384 mfr_id: MANUFACTURER_INTEL,
385 dev_id: I28F004B3B,
386 name: "Intel 28F004B3B",
387 DevSize: SIZE_512KiB,
388 CmdSet: P_ID_INTEL_STD,
389 NumEraseRegions: 2,
390 regions: {
391 ERASEINFO(0x02000, 8),
392 ERASEINFO(0x10000, 7),
393 }
394 }, {
395 mfr_id: MANUFACTURER_INTEL,
396 dev_id: I28F004B3T,
397 name: "Intel 28F004B3T",
398 DevSize: SIZE_512KiB,
399 CmdSet: P_ID_INTEL_STD,
400 NumEraseRegions: 2,
401 regions: {
402 ERASEINFO(0x10000, 7),
403 ERASEINFO(0x02000, 8),
404 }
405 }, {
406 mfr_id: MANUFACTURER_INTEL,
407 dev_id: I28F400B3B,
408 name: "Intel 28F400B3B",
409 DevSize: SIZE_512KiB,
410 CmdSet: P_ID_INTEL_STD,
411 NumEraseRegions: 2,
412 regions: {
413 ERASEINFO(0x02000, 8),
414 ERASEINFO(0x10000, 7),
415 }
416 }, {
417 mfr_id: MANUFACTURER_INTEL,
418 dev_id: I28F400B3T,
419 name: "Intel 28F400B3T",
420 DevSize: SIZE_512KiB,
421 CmdSet: P_ID_INTEL_STD,
422 NumEraseRegions: 2,
423 regions: {
424 ERASEINFO(0x10000, 7),
425 ERASEINFO(0x02000, 8),
426 }
427 }, {
428 mfr_id: MANUFACTURER_INTEL,
429 dev_id: I28F008B3B,
430 name: "Intel 28F008B3B",
431 DevSize: SIZE_1MiB,
432 CmdSet: P_ID_INTEL_STD,
433 NumEraseRegions: 2,
434 regions: {
435 ERASEINFO(0x02000, 8),
436 ERASEINFO(0x10000, 15),
437 }
438 }, {
439 mfr_id: MANUFACTURER_INTEL,
440 dev_id: I28F008B3T,
441 name: "Intel 28F008B3T",
442 DevSize: SIZE_1MiB,
443 CmdSet: P_ID_INTEL_STD,
444 NumEraseRegions: 2,
445 regions: {
446 ERASEINFO(0x10000, 15),
447 ERASEINFO(0x02000, 8),
448 }
449 }, {
450 mfr_id: MANUFACTURER_INTEL,
451 dev_id: I28F008S5,
452 name: "Intel 28F008S5",
453 DevSize: SIZE_1MiB,
454 CmdSet: P_ID_INTEL_EXT,
455 NumEraseRegions: 1,
456 regions: {ERASEINFO(0x10000,16),
457 }
458 }, {
459 mfr_id: MANUFACTURER_INTEL,
460 dev_id: I28F016S5,
461 name: "Intel 28F016S5",
462 DevSize: SIZE_2MiB,
463 CmdSet: P_ID_INTEL_EXT,
464 NumEraseRegions: 1,
465 regions: {ERASEINFO(0x10000,32),
466 }
467 }, {
468 mfr_id: MANUFACTURER_INTEL,
469 dev_id: I28F008SA,
470 name: "Intel 28F008SA",
471 DevSize: SIZE_1MiB,
472 CmdSet: P_ID_INTEL_STD,
473 NumEraseRegions: 1,
474 regions: {
475 ERASEINFO(0x10000, 16),
476 }
477 }, {
478 mfr_id: MANUFACTURER_INTEL,
479 dev_id: I28F800B3B,
480 name: "Intel 28F800B3B",
481 DevSize: SIZE_1MiB,
482 CmdSet: P_ID_INTEL_STD,
483 NumEraseRegions: 2,
484 regions: {
485 ERASEINFO(0x02000, 8),
486 ERASEINFO(0x10000, 15),
487 }
488 }, {
489 mfr_id: MANUFACTURER_INTEL,
490 dev_id: I28F800B3T,
491 name: "Intel 28F800B3T",
492 DevSize: SIZE_1MiB,
493 CmdSet: P_ID_INTEL_STD,
494 NumEraseRegions: 2,
495 regions: {
496 ERASEINFO(0x10000, 15),
497 ERASEINFO(0x02000, 8),
498 }
499 }, {
500 mfr_id: MANUFACTURER_INTEL,
501 dev_id: I28F016B3B,
502 name: "Intel 28F016B3B",
503 DevSize: SIZE_2MiB,
504 CmdSet: P_ID_INTEL_STD,
505 NumEraseRegions: 2,
506 regions: {
507 ERASEINFO(0x02000, 8),
508 ERASEINFO(0x10000, 31),
509 }
510 }, {
511 mfr_id: MANUFACTURER_INTEL,
512 dev_id: I28F016S3,
513 name: "Intel I28F016S3",
514 DevSize: SIZE_2MiB,
515 CmdSet: P_ID_INTEL_STD,
516 NumEraseRegions: 1,
517 regions: {
518 ERASEINFO(0x10000, 32),
519 }
520 }, {
521 mfr_id: MANUFACTURER_INTEL,
522 dev_id: I28F016B3T,
523 name: "Intel 28F016B3T",
524 DevSize: SIZE_2MiB,
525 CmdSet: P_ID_INTEL_STD,
526 NumEraseRegions: 2,
527 regions: {
528 ERASEINFO(0x10000, 31),
529 ERASEINFO(0x02000, 8),
530 }
531 }, {
532 mfr_id: MANUFACTURER_INTEL,
533 dev_id: I28F160B3B,
534 name: "Intel 28F160B3B",
535 DevSize: SIZE_2MiB,
536 CmdSet: P_ID_INTEL_STD,
537 NumEraseRegions: 2,
538 regions: {
539 ERASEINFO(0x02000, 8),
540 ERASEINFO(0x10000, 31),
541 }
542 }, {
543 mfr_id: MANUFACTURER_INTEL,
544 dev_id: I28F160B3T,
545 name: "Intel 28F160B3T",
546 DevSize: SIZE_2MiB,
547 CmdSet: P_ID_INTEL_STD,
548 NumEraseRegions: 2,
549 regions: {
550 ERASEINFO(0x10000, 31),
551 ERASEINFO(0x02000, 8),
552 }
553 }, {
554 mfr_id: MANUFACTURER_INTEL,
555 dev_id: I28F320B3B,
556 name: "Intel 28F320B3B",
557 DevSize: SIZE_4MiB,
558 CmdSet: P_ID_INTEL_STD,
559 NumEraseRegions: 2,
560 regions: {
561 ERASEINFO(0x02000, 8),
562 ERASEINFO(0x10000, 63),
563 }
564 }, {
565 mfr_id: MANUFACTURER_INTEL,
566 dev_id: I28F320B3T,
567 name: "Intel 28F320B3T",
568 DevSize: SIZE_4MiB,
569 CmdSet: P_ID_INTEL_STD,
570 NumEraseRegions: 2,
571 regions: {
572 ERASEINFO(0x10000, 63),
573 ERASEINFO(0x02000, 8),
574 }
575 }, {
576 mfr_id: MANUFACTURER_INTEL,
577 dev_id: I28F640B3B,
578 name: "Intel 28F640B3B",
579 DevSize: SIZE_8MiB,
580 CmdSet: P_ID_INTEL_STD,
581 NumEraseRegions: 2,
582 regions: {
583 ERASEINFO(0x02000, 8),
584 ERASEINFO(0x10000, 127),
585 }
586 }, {
587 mfr_id: MANUFACTURER_INTEL,
588 dev_id: I28F640B3T,
589 name: "Intel 28F640B3T",
590 DevSize: SIZE_8MiB,
591 CmdSet: P_ID_INTEL_STD,
592 NumEraseRegions: 2,
593 regions: {
594 ERASEINFO(0x10000, 127),
595 ERASEINFO(0x02000, 8),
596 }
597 }, {
598 mfr_id: MANUFACTURER_INTEL,
599 dev_id: I82802AB,
600 name: "Intel 82802AB",
601 DevSize: SIZE_512KiB,
602 CmdSet: P_ID_INTEL_EXT,
603 NumEraseRegions: 1,
604 regions: {ERASEINFO(0x10000,8),
605 }
606 }, {
607 mfr_id: MANUFACTURER_INTEL,
608 dev_id: I82802AC,
609 name: "Intel 82802AC",
610 DevSize: SIZE_1MiB,
611 CmdSet: P_ID_INTEL_EXT,
612 NumEraseRegions: 1,
613 regions: {ERASEINFO(0x10000,16),
614 }
615 }, {
616 mfr_id: MANUFACTURER_ST,
617 dev_id: M29W800T,
618 name: "ST M29W800T",
619 DevSize: SIZE_1MiB,
620 CmdSet: P_ID_AMD_STD,
621 NumEraseRegions: 4,
622 regions: {ERASEINFO(0x10000,15),
623 ERASEINFO(0x08000,1),
624 ERASEINFO(0x02000,2),
625 ERASEINFO(0x04000,1)
626 }
627 }, {
628 mfr_id: MANUFACTURER_ST,
629 dev_id: M29W160DT,
630 name: "ST M29W160DT",
631 DevSize: SIZE_2MiB,
632 CmdSet: P_ID_AMD_STD,
633 NumEraseRegions: 4,
634 regions: {ERASEINFO(0x10000,31),
635 ERASEINFO(0x08000,1),
636 ERASEINFO(0x02000,2),
637 ERASEINFO(0x04000,1)
638 }
639 }, {
640 mfr_id: MANUFACTURER_ST,
641 dev_id: M29W160DB,
642 name: "ST M29W160DB",
643 DevSize: SIZE_2MiB,
644 CmdSet: P_ID_AMD_STD,
645 NumEraseRegions: 4,
646 regions: {ERASEINFO(0x04000,1),
647 ERASEINFO(0x02000,2),
648 ERASEINFO(0x08000,1),
649 ERASEINFO(0x10000,31)
650 }
651 }, {
652 mfr_id: MANUFACTURER_ATMEL,
653 dev_id: AT49BV512,
654 name: "Atmel AT49BV512",
655 DevSize: SIZE_64KiB,
656 CmdSet: P_ID_AMD_STD,
657 NumEraseRegions: 1,
658 regions: {ERASEINFO(0x10000,1)
659 }
660 }, {
661 mfr_id: MANUFACTURER_ATMEL,
662 dev_id: AT29LV512,
663 name: "Atmel AT29LV512",
664 DevSize: SIZE_64KiB,
665 CmdSet: P_ID_AMD_STD,
666 NumEraseRegions: 1,
667 regions: {
668 ERASEINFO(0x80,256),
669 ERASEINFO(0x80,256)
670 }
671 }, {
672 mfr_id: MANUFACTURER_ATMEL,
673 dev_id: AT49BV16X,
674 name: "Atmel AT49BV16X",
675 DevSize: SIZE_2MiB,
676 CmdSet: P_ID_AMD_STD,
677 NumEraseRegions: 2,
678 regions: {ERASEINFO(0x02000,8),
679 ERASEINFO(0x10000,31)
680 }
681 }, {
682 mfr_id: MANUFACTURER_ATMEL,
683 dev_id: AT49BV16XT,
684 name: "Atmel AT49BV16XT",
685 DevSize: SIZE_2MiB,
686 CmdSet: P_ID_AMD_STD,
687 NumEraseRegions: 2,
688 regions: {ERASEINFO(0x10000,31),
689 ERASEINFO(0x02000,8)
690 }
691 }, {
692 mfr_id: MANUFACTURER_ATMEL,
693 dev_id: AT49BV32X,
694 name: "Atmel AT49BV32X",
695 DevSize: SIZE_4MiB,
696 CmdSet: P_ID_AMD_STD,
697 NumEraseRegions: 2,
698 regions: {ERASEINFO(0x02000,8),
699 ERASEINFO(0x10000,63)
700 }
701 }, {
702 mfr_id: MANUFACTURER_ATMEL,
703 dev_id: AT49BV32XT,
704 name: "Atmel AT49BV32XT",
705 DevSize: SIZE_4MiB,
706 CmdSet: P_ID_AMD_STD,
707 NumEraseRegions: 2,
708 regions: {ERASEINFO(0x10000,63),
709 ERASEINFO(0x02000,8)
710 }
711 }, {
712 mfr_id: MANUFACTURER_AMD,
713 dev_id: AM29F017D,
714 name: "AMD AM29F017D",
715 DevSize: SIZE_2MiB,
716 CmdSet: P_ID_AMD_STD,
717 NumEraseRegions: 1,
718 regions: {ERASEINFO(0x10000,32),
719 }
720 }, {
721 mfr_id: MANUFACTURER_AMD,
722 dev_id: AM29F016,
723 name: "AMD AM29F016",
724 DevSize: SIZE_2MiB,
725 CmdSet: P_ID_AMD_STD,
726 NumEraseRegions: 1,
727 regions: {ERASEINFO(0x10000,32),
728 }
729 }, {
730 mfr_id: MANUFACTURER_AMD,
731 dev_id: AM29F080,
732 name: "AMD AM29F080",
733 DevSize: SIZE_1MiB,
734 CmdSet: P_ID_AMD_STD,
735 NumEraseRegions: 1,
736 regions: {ERASEINFO(0x10000,16),
737 }
738 }, {
739 mfr_id: MANUFACTURER_AMD,
740 dev_id: AM29F040,
741 name: "AMD AM29F040",
742 DevSize: SIZE_512KiB,
743 CmdSet: P_ID_AMD_STD,
744 NumEraseRegions: 1,
745 regions: {ERASEINFO(0x10000,8),
746 }
747 }, {
748 mfr_id: MANUFACTURER_AMD,
749 dev_id: AM29LV040B,
750 name: "AMD AM29LV040B",
751 DevSize: SIZE_512KiB,
752 CmdSet: P_ID_AMD_STD,
753 NumEraseRegions: 1,
754 regions: {ERASEINFO(0x10000,8),
755 }
756 }, {
757 mfr_id: MANUFACTURER_ST,
758 dev_id: M29W040B,
759 name: "ST M29W040B",
760 DevSize: SIZE_512KiB,
761 CmdSet: P_ID_AMD_STD,
762 NumEraseRegions: 1,
763 regions: {ERASEINFO(0x10000,8),
764 }
765 }, {
766 mfr_id: MANUFACTURER_MACRONIX,
767 dev_id: MX29LV160T,
768 name: "MXIC MX29LV160T",
769 DevSize: SIZE_2MiB,
770 CmdSet: P_ID_AMD_STD,
771 NumEraseRegions: 4,
772 regions: {ERASEINFO(0x10000,31),
773 ERASEINFO(0x08000,1),
774 ERASEINFO(0x02000,2),
775 ERASEINFO(0x04000,1)
776 }
777 }, {
778 mfr_id: MANUFACTURER_MACRONIX,
779 dev_id: MX29LV160B,
780 name: "MXIC MX29LV160B",
781 DevSize: SIZE_2MiB,
782 CmdSet: P_ID_AMD_STD,
783 NumEraseRegions: 4,
784 regions: {ERASEINFO(0x04000,1),
785 ERASEINFO(0x02000,2),
786 ERASEINFO(0x08000,1),
787 ERASEINFO(0x10000,31)
788 }
789 }, {
790 mfr_id: MANUFACTURER_MACRONIX,
791 dev_id: MX29F016,
792 name: "Macronix MX29F016",
793 DevSize: SIZE_2MiB,
794 CmdSet: P_ID_AMD_STD,
795 NumEraseRegions: 1,
796 regions: {ERASEINFO(0x10000,32),
797 }
798 }, {
799 mfr_id: MANUFACTURER_MACRONIX,
800 dev_id: MX29F004T,
801 name: "Macronix MX29F004T",
802 DevSize: SIZE_512KiB,
803 CmdSet: P_ID_AMD_STD,
804 NumEraseRegions: 4,
805 regions: {ERASEINFO(0x10000,7),
806 ERASEINFO(0x08000,1),
807 ERASEINFO(0x02000,2),
808 ERASEINFO(0x04000,1),
809 }
810 }, {
811 mfr_id: MANUFACTURER_MACRONIX,
812 dev_id: MX29F004B,
813 name: "Macronix MX29F004B",
814 DevSize: SIZE_512KiB,
815 CmdSet: P_ID_AMD_STD,
816 NumEraseRegions: 4,
817 regions: {ERASEINFO(0x04000,1),
818 ERASEINFO(0x02000,2),
819 ERASEINFO(0x08000,1),
820 ERASEINFO(0x10000,7),
821 }
822 }, {
823 mfr_id: MANUFACTURER_SST,
824 dev_id: SST39LF512,
825 name: "SST 39LF512",
826 DevSize: SIZE_64KiB,
827 CmdSet: P_ID_AMD_STD,
828 NumEraseRegions: 1,
829 regions: {ERASEINFO(0x01000,16),
830 }
831 }, {
832 mfr_id: MANUFACTURER_SST,
833 dev_id: SST39LF010,
834 name: "SST 39LF010",
835 DevSize: SIZE_128KiB,
836 CmdSet: P_ID_AMD_STD,
837 NumEraseRegions: 1,
838 regions: {ERASEINFO(0x01000,32),
839 }
840 }, {
841 mfr_id: MANUFACTURER_SST,
842 dev_id: SST39LF020,
843 name: "SST 39LF020",
844 DevSize: SIZE_256KiB,
845 CmdSet: P_ID_AMD_STD,
846 NumEraseRegions: 1,
847 regions: {ERASEINFO(0x01000,64),
848 }
849 }, {
850 mfr_id: MANUFACTURER_SST,
851 dev_id: SST39LF040,
852 name: "SST 39LF040",
853 DevSize: SIZE_512KiB,
854 CmdSet: P_ID_AMD_STD,
855 NumEraseRegions: 1,
856 regions: {ERASEINFO(0x01000,128),
857 }
858 }, {
859 mfr_id: MANUFACTURER_SST,
860 dev_id: SST39SF010A,
861 name: "SST 39SF010A",
862 DevSize: SIZE_128KiB,
863 CmdSet: P_ID_AMD_STD,
864 NumEraseRegions: 1,
865 regions: {ERASEINFO(0x01000,32),
866 }
867 }, {
868 mfr_id: MANUFACTURER_SST,
869 dev_id: SST39SF020A,
870 name: "SST 39SF020A",
871 DevSize: SIZE_256KiB,
872 CmdSet: P_ID_AMD_STD,
873 NumEraseRegions: 1,
874 regions: {ERASEINFO(0x01000,64),
875 }
876 }, {
877 mfr_id: MANUFACTURER_SST,
878 dev_id: SST49LF030A,
879 name: "SST 49LF030A",
880 DevSize: SIZE_512KiB,
881 CmdSet: P_ID_AMD_STD,
882 NumEraseRegions: 1,
883 regions: {ERASEINFO(0x01000,96),
884 }
885 }, {
886 mfr_id: MANUFACTURER_SST,
887 dev_id: SST49LF040A,
888 name: "SST 49LF040A",
889 DevSize: SIZE_512KiB,
890 CmdSet: P_ID_AMD_STD,
891 NumEraseRegions: 1,
892 regions: {ERASEINFO(0x01000,128),
893 }
894 }, {
895 mfr_id: MANUFACTURER_SST,
896 dev_id: SST49LF080A,
897 name: "SST 49LF080A",
898 DevSize: SIZE_1MiB,
899 CmdSet: P_ID_AMD_STD,
900 NumEraseRegions: 1,
901 regions: {ERASEINFO(0x01000,256),
902 }
903 }
904 };
905
906
907 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
908
909 static int jedec_probe_chip(struct map_info *map, __u32 base,
910 struct flchip *chips, struct cfi_private *cfi);
911
912 struct mtd_info *jedec_probe(struct map_info *map);
913
jedec_read_mfr(struct map_info * map,__u32 base,struct cfi_private * cfi)914 static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
915 struct cfi_private *cfi)
916 {
917 u32 result, mask;
918 mask = (1 << (cfi->device_type * 8)) -1;
919 result = cfi_read(map, base);
920 result &= mask;
921 return result;
922 }
923
jedec_read_id(struct map_info * map,__u32 base,struct cfi_private * cfi)924 static inline u32 jedec_read_id(struct map_info *map, __u32 base,
925 struct cfi_private *cfi)
926 {
927 int osf;
928 u32 result, mask;
929 osf = cfi->interleave *cfi->device_type;
930 mask = (1 << (cfi->device_type * 8)) -1;
931 result = cfi_read(map, base + osf);
932 result &= mask;
933 return result;
934 }
935
jedec_reset(u32 base,struct map_info * map,struct cfi_private * cfi)936 static inline void jedec_reset(u32 base, struct map_info *map,
937 struct cfi_private *cfi)
938 {
939 /* Reset */
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.
945 */
946 cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
947
948 }
cfi_jedec_setup(struct cfi_private * p_cfi,int index)949 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
950 {
951 int i,num_erase_regions;
952
953 printk("Found: %s\n",jedec_table[index].name);
954
955 num_erase_regions = jedec_table[index].NumEraseRegions;
956
957 p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
958 if (!p_cfi->cfiq) {
959 //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
960 return 0;
961 }
962
963 memset(p_cfi->cfiq,0,sizeof(struct cfi_ident));
964
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;
969
970 for (i=0; i<num_erase_regions; i++){
971 p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
972 }
973 p_cfi->cmdset_priv = 0;
974 return 1; /* ok */
975 }
976
jedec_probe_chip(struct map_info * map,__u32 base,struct flchip * chips,struct cfi_private * cfi)977 static int jedec_probe_chip(struct map_info *map, __u32 base,
978 struct flchip *chips, struct cfi_private *cfi)
979 {
980 int i;
981 int unlockpass = 0;
982
983 if (!cfi->numchips) {
984 switch (cfi->device_type) {
985 case CFI_DEVICETYPE_X8:
986 cfi->addr_unlock1 = 0x555;
987 cfi->addr_unlock2 = 0x2aa;
988 break;
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;
994 } else {
995 cfi->addr_unlock2 = 0x554;
996 }
997 break;
998 case CFI_DEVICETYPE_X32:
999 cfi->addr_unlock1 = 0x1555;
1000 cfi->addr_unlock2 = 0xaaa;
1001 break;
1002 default:
1003 printk(KERN_NOTICE "Eep. Unknown jedec_probe device type %d\n", cfi->device_type);
1004 return 0;
1005 }
1006 }
1007
1008 retry:
1009 /* Make certain we aren't probing past the end of map */
1010 if (base >= map->size) {
1011 printk(KERN_NOTICE
1012 "Probe at base(0x%08x) past the end of the map(0x%08lx)\n",
1013 base, map->size -1);
1014 return 0;
1015
1016 }
1017 if ((base + cfi->addr_unlock1) >= map->size) {
1018 printk(KERN_NOTICE
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);
1021
1022 return 0;
1023 }
1024 if ((base + cfi->addr_unlock2) >= map->size) {
1025 printk(KERN_NOTICE
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);
1028 return 0;
1029
1030 }
1031
1032 /* Reset */
1033 jedec_reset(base, map, cfi);
1034
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);
1039 }
1040 cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1041
1042 if (!cfi->numchips) {
1043 /* This is the first time we're called. Set up the CFI
1044 stuff accordingly and return */
1045
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))
1054 return 0;
1055 goto ok_out;
1056 }
1057 }
1058 switch(unlockpass++) {
1059 case 0:
1060 cfi->addr_unlock1 |= cfi->addr_unlock1 << 4;
1061 cfi->addr_unlock2 |= cfi->addr_unlock2 << 4;
1062 goto retry;
1063 case 1:
1064 cfi->addr_unlock1 = cfi->addr_unlock2 = 0;
1065 goto retry;
1066 }
1067 return 0;
1068 } else {
1069 __u16 mfr;
1070 __u16 id;
1071
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);
1075
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);
1080 return 0;
1081 }
1082 }
1083
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);
1093
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);
1099 return 0;
1100 }
1101
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);
1111 return 0;
1112 }
1113 }
1114 }
1115
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 */
1121 return -1;
1122 }
1123 chips[cfi->numchips].start = base;
1124 chips[cfi->numchips].state = FL_READY;
1125 cfi->numchips++;
1126
1127 ok_out:
1128 /* Put it back into Read Mode */
1129 jedec_reset(base, map, cfi);
1130
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,
1133 map->buswidth*8);
1134
1135 return 1;
1136 }
1137
1138 static struct chip_probe jedec_chip_probe = {
1139 name: "JEDEC",
1140 probe_chip: jedec_probe_chip
1141 };
1142
jedec_probe(struct map_info * map)1143 struct mtd_info *jedec_probe(struct map_info *map)
1144 {
1145 /*
1146 * Just use the generic probe stuff to call our CFI-specific
1147 * chip_probe routine in all the possible permutations, etc.
1148 */
1149 return mtd_do_chip_probe(map, &jedec_chip_probe);
1150 }
1151
1152 static struct mtd_chip_driver jedec_chipdrv = {
1153 probe: jedec_probe,
1154 name: "jedec_probe",
1155 module: THIS_MODULE
1156 };
1157
jedec_probe_init(void)1158 int __init jedec_probe_init(void)
1159 {
1160 register_mtd_chip_driver(&jedec_chipdrv);
1161 return 0;
1162 }
1163
jedec_probe_exit(void)1164 static void __exit jedec_probe_exit(void)
1165 {
1166 unregister_mtd_chip_driver(&jedec_chipdrv);
1167 }
1168
1169 module_init(jedec_probe_init);
1170 module_exit(jedec_probe_exit);
1171
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");
1175