VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / mtd / chips / jedec_probe.c
1 /* 
2    Common Flash Interface probe code.
3    (C) 2000 Red Hat. GPL'd.
4    $Id: jedec_probe.c,v 1.51 2004/07/14 14:44:30 thayne Exp $
5    See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
6    for the standard this probe goes back to.
7
8    Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
9 */
10
11 #include <linux/config.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <asm/io.h>
17 #include <asm/byteorder.h>
18 #include <linux/errno.h>
19 #include <linux/slab.h>
20 #include <linux/interrupt.h>
21 #include <linux/init.h>
22
23 #include <linux/mtd/mtd.h>
24 #include <linux/mtd/map.h>
25 #include <linux/mtd/cfi.h>
26 #include <linux/mtd/gen_probe.h>
27
28 /* Manufacturers */
29 #define MANUFACTURER_AMD        0x0001
30 #define MANUFACTURER_ATMEL      0x001f
31 #define MANUFACTURER_FUJITSU    0x0004
32 #define MANUFACTURER_INTEL      0x0089
33 #define MANUFACTURER_MACRONIX   0x00C2
34 #define MANUFACTURER_PMC        0x009D
35 #define MANUFACTURER_SST        0x00BF
36 #define MANUFACTURER_ST         0x0020
37 #define MANUFACTURER_TOSHIBA    0x0098
38 #define MANUFACTURER_WINBOND    0x00da
39
40
41 /* AMD */
42 #define AM29DL800BB     0x22C8
43 #define AM29DL800BT     0x224A
44
45 #define AM29F800BB      0x2258
46 #define AM29F800BT      0x22D6
47 #define AM29LV400BB     0x22BA
48 #define AM29LV400BT     0x22B9
49 #define AM29LV800BB     0x225B
50 #define AM29LV800BT     0x22DA
51 #define AM29LV160DT     0x22C4
52 #define AM29LV160DB     0x2249
53 #define AM29F017D       0x003D
54 #define AM29F016D       0x00AD
55 #define AM29F080        0x00D5
56 #define AM29F040        0x00A4
57 #define AM29LV040B      0x004F
58 #define AM29F032B       0x0041
59
60 /* Atmel */
61 #define AT49BV512       0x0003
62 #define AT29LV512       0x003d
63 #define AT49BV16X       0x00C0
64 #define AT49BV16XT      0x00C2
65 #define AT49BV32X       0x00C8
66 #define AT49BV32XT      0x00C9
67
68 /* Fujitsu */
69 #define MBM29F040C      0x00A4
70 #define MBM29LV650UE    0x22D7
71 #define MBM29LV320TE    0x22F6
72 #define MBM29LV320BE    0x22F9
73 #define MBM29LV160TE    0x22C4
74 #define MBM29LV160BE    0x2249
75 #define MBM29LV800BA    0x225B
76 #define MBM29LV800TA    0x22DA
77 #define MBM29LV400TC    0x22B9
78 #define MBM29LV400BC    0x22BA
79
80
81 /* Intel */
82 #define I28F004B3T      0x00d4
83 #define I28F004B3B      0x00d5
84 #define I28F400B3T      0x8894
85 #define I28F400B3B      0x8895
86 #define I28F008S5       0x00a6
87 #define I28F016S5       0x00a0
88 #define I28F008SA       0x00a2
89 #define I28F008B3T      0x00d2
90 #define I28F008B3B      0x00d3
91 #define I28F800B3T      0x8892
92 #define I28F800B3B      0x8893
93 #define I28F016S3       0x00aa
94 #define I28F016B3T      0x00d0
95 #define I28F016B3B      0x00d1
96 #define I28F160B3T      0x8890
97 #define I28F160B3B      0x8891
98 #define I28F320B3T      0x8896
99 #define I28F320B3B      0x8897
100 #define I28F640B3T      0x8898
101 #define I28F640B3B      0x8899
102 #define I82802AB        0x00ad
103 #define I82802AC        0x00ac
104
105 /* Macronix */
106 #define MX29LV160T      0x22C4
107 #define MX29LV160B      0x2249
108 #define MX29F016        0x00AD
109 #define MX29F004T       0x0045
110 #define MX29F004B       0x0046
111
112 /* PMC */
113 #define PM49FL002       0x006D
114 #define PM49FL004       0x006E
115 #define PM49FL008       0x006A
116
117 /* ST - www.st.com */
118 #define M29W800DT       0x00D7
119 #define M29W800DB       0x005B
120 #define M29W160DT       0x22C4
121 #define M29W160DB       0x2249
122 #define M29W040B        0x00E3
123 #define M50FW040        0x002C
124 #define M50FW080        0x002D
125 #define M50FW016        0x002E
126
127 /* SST */
128 #define SST29EE020      0x0010
129 #define SST29LE020      0x0012
130 #define SST29EE512      0x005d
131 #define SST29LE512      0x003d
132 #define SST39LF800      0x2781
133 #define SST39LF160      0x2782
134 #define SST39LF512      0x00D4
135 #define SST39LF010      0x00D5
136 #define SST39LF020      0x00D6
137 #define SST39LF040      0x00D7
138 #define SST39SF010A     0x00B5
139 #define SST39SF020A     0x00B6
140 #define SST49LF004B     0x0060
141 #define SST49LF008A     0x005a
142 #define SST49LF030A     0x001C
143 #define SST49LF040A     0x0051
144 #define SST49LF080A     0x005B
145
146 /* Toshiba */
147 #define TC58FVT160      0x00C2
148 #define TC58FVB160      0x0043
149 #define TC58FVT321      0x009A
150 #define TC58FVB321      0x009C
151 #define TC58FVT641      0x0093
152 #define TC58FVB641      0x0095
153
154 /* Winbond */
155 #define W49V002A        0x00b0
156
157
158 /*
159  * Unlock address sets for AMD command sets.
160  * Intel command sets use the MTD_UADDR_UNNECESSARY.
161  * Each identifier, except MTD_UADDR_UNNECESSARY, and
162  * MTD_UADDR_NO_SUPPORT must be defined below in unlock_addrs[].
163  * MTD_UADDR_NOT_SUPPORTED must be 0 so that structure
164  * initialization need not require initializing all of the
165  * unlock addresses for all bit widths.
166  */
167 enum uaddr {
168         MTD_UADDR_NOT_SUPPORTED = 0,    /* data width not supported */
169         MTD_UADDR_0x0555_0x02AA,
170         MTD_UADDR_0x0555_0x0AAA,
171         MTD_UADDR_0x5555_0x2AAA,
172         MTD_UADDR_0x0AAA_0x0555,
173         MTD_UADDR_DONT_CARE,            /* Requires an arbitrary address */
174         MTD_UADDR_UNNECESSARY,          /* Does not require any address */
175 };
176
177
178 struct unlock_addr {
179         int addr1;
180         int addr2;
181 };
182
183
184 /*
185  * I don't like the fact that the first entry in unlock_addrs[]
186  * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore,
187  * should not be used.  The  problem is that structures with
188  * initializers have extra fields initialized to 0.  It is _very_
189  * desireable to have the unlock address entries for unsupported
190  * data widths automatically initialized - that means that
191  * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here
192  * must go unused.
193  */
194 static const struct unlock_addr  unlock_addrs[] = {
195         [MTD_UADDR_NOT_SUPPORTED] = {
196                 .addr1 = 0xffff,
197                 .addr2 = 0xffff
198         },
199
200         [MTD_UADDR_0x0555_0x02AA] = {
201                 .addr1 = 0x0555,
202                 .addr2 = 0x02aa
203         },
204
205         [MTD_UADDR_0x0555_0x0AAA] = {
206                 .addr1 = 0x0555,
207                 .addr2 = 0x0aaa
208         },
209
210         [MTD_UADDR_0x5555_0x2AAA] = {
211                 .addr1 = 0x5555,
212                 .addr2 = 0x2aaa
213         },
214
215         [MTD_UADDR_0x0AAA_0x0555] = {
216                 .addr1 = 0x0AAA,
217                 .addr2 = 0x0555
218         },
219
220         [MTD_UADDR_DONT_CARE] = {
221                 .addr1 = 0x0000,      /* Doesn't matter which address */
222                 .addr2 = 0x0000       /* is used - must be last entry */
223         }
224 };
225
226
227 struct amd_flash_info {
228         const __u16 mfr_id;
229         const __u16 dev_id;
230         const char *name;
231         const int DevSize;
232         const int NumEraseRegions;
233         const int CmdSet;
234         const __u8 uaddr[4];            /* unlock addrs for 8, 16, 32, 64 */
235         const ulong regions[6];
236 };
237
238 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
239
240 #define SIZE_64KiB  16
241 #define SIZE_128KiB 17
242 #define SIZE_256KiB 18
243 #define SIZE_512KiB 19
244 #define SIZE_1MiB   20
245 #define SIZE_2MiB   21
246 #define SIZE_4MiB   22
247 #define SIZE_8MiB   23
248
249
250 /*
251  * Please keep this list ordered by manufacturer!
252  * Fortunately, the list isn't searched often and so a
253  * slow, linear search isn't so bad.
254  */
255 static const struct amd_flash_info jedec_table[] = {
256         {
257                 .mfr_id         = MANUFACTURER_AMD,
258                 .dev_id         = AM29F032B,
259                 .name           = "AMD AM29F032B",
260                 .uaddr          = {
261                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
262                 },
263                 .DevSize        = SIZE_4MiB,
264                 .CmdSet         = P_ID_AMD_STD,
265                 .NumEraseRegions= 1,
266                 .regions        = {
267                         ERASEINFO(0x10000,64)
268                 }
269         }, {
270                 .mfr_id         = MANUFACTURER_AMD,
271                 .dev_id         = AM29LV160DT,
272                 .name           = "AMD AM29LV160DT",
273                 .uaddr          = {
274                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
275                         [1] = MTD_UADDR_0x0555_0x02AA   /* x16 */
276                 },
277                 .DevSize        = SIZE_2MiB,
278                 .CmdSet         = P_ID_AMD_STD,
279                 .NumEraseRegions= 4,
280                 .regions        = {
281                         ERASEINFO(0x10000,31),
282                         ERASEINFO(0x08000,1),
283                         ERASEINFO(0x02000,2),
284                         ERASEINFO(0x04000,1)
285                 }
286         }, {
287                 .mfr_id         = MANUFACTURER_AMD,
288                 .dev_id         = AM29LV160DB,
289                 .name           = "AMD AM29LV160DB",
290                 .uaddr          = {
291                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
292                         [1] = MTD_UADDR_0x0555_0x02AA   /* x16 */
293                 },
294                 .DevSize        = SIZE_2MiB,
295                 .CmdSet         = P_ID_AMD_STD,
296                 .NumEraseRegions= 4,
297                 .regions        = {
298                         ERASEINFO(0x04000,1),
299                         ERASEINFO(0x02000,2),
300                         ERASEINFO(0x08000,1),
301                         ERASEINFO(0x10000,31)
302                 }
303         }, {
304                 .mfr_id         = MANUFACTURER_AMD,
305                 .dev_id         = AM29LV400BB,
306                 .name           = "AMD AM29LV400BB",
307                 .uaddr          = {
308                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
309                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
310                 },
311                 .DevSize        = SIZE_512KiB,
312                 .CmdSet         = P_ID_AMD_STD,
313                 .NumEraseRegions= 4,
314                 .regions        = {
315                         ERASEINFO(0x04000,1),
316                         ERASEINFO(0x02000,2),
317                         ERASEINFO(0x08000,1),
318                         ERASEINFO(0x10000,7)
319                 }
320         }, {
321                 .mfr_id         = MANUFACTURER_AMD,
322                 .dev_id         = AM29LV400BT,
323                 .name           = "AMD AM29LV400BT",
324                 .uaddr          = {
325                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
326                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
327                 },
328                 .DevSize        = SIZE_512KiB,
329                 .CmdSet         = P_ID_AMD_STD,
330                 .NumEraseRegions= 4,
331                 .regions        = {
332                         ERASEINFO(0x10000,7),
333                         ERASEINFO(0x08000,1),
334                         ERASEINFO(0x02000,2),
335                         ERASEINFO(0x04000,1)
336                 }
337         }, {
338                 .mfr_id         = MANUFACTURER_AMD,
339                 .dev_id         = AM29LV800BB,
340                 .name           = "AMD AM29LV800BB",
341                 .uaddr          = {
342                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
343                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
344                 },
345                 .DevSize        = SIZE_1MiB,
346                 .CmdSet         = P_ID_AMD_STD,
347                 .NumEraseRegions= 4,
348                 .regions        = {
349                         ERASEINFO(0x04000,1),
350                         ERASEINFO(0x02000,2),
351                         ERASEINFO(0x08000,1),
352                         ERASEINFO(0x10000,15),
353                 }
354         }, {
355 /* add DL */
356                 .mfr_id         = MANUFACTURER_AMD,
357                 .dev_id         = AM29DL800BB,
358                 .name           = "AMD AM29DL800BB",
359                 .uaddr          = {
360                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
361                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
362                 },
363                 .DevSize        = SIZE_1MiB,
364                 .CmdSet         = P_ID_AMD_STD,
365                 .NumEraseRegions= 6,
366                 .regions        = {
367                         ERASEINFO(0x04000,1),
368                         ERASEINFO(0x08000,1),
369                         ERASEINFO(0x02000,4),
370                         ERASEINFO(0x08000,1),
371                         ERASEINFO(0x04000,1),
372                         ERASEINFO(0x10000,14)
373                 }
374         }, {
375                 .mfr_id         = MANUFACTURER_AMD,
376                 .dev_id         = AM29DL800BT,
377                 .name           = "AMD AM29DL800BT",
378                 .uaddr          = {
379                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
380                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
381                 },
382                 .DevSize        = SIZE_1MiB,
383                 .CmdSet         = P_ID_AMD_STD,
384                 .NumEraseRegions= 6,
385                 .regions        = {
386                         ERASEINFO(0x10000,14),
387                         ERASEINFO(0x04000,1),
388                         ERASEINFO(0x08000,1),
389                         ERASEINFO(0x02000,4),
390                         ERASEINFO(0x08000,1),
391                         ERASEINFO(0x04000,1)
392                 }
393         }, {
394                 .mfr_id         = MANUFACTURER_AMD,
395                 .dev_id         = AM29F800BB,
396                 .name           = "AMD AM29F800BB",
397                 .uaddr          = {
398                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
399                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
400                 },
401                 .DevSize        = SIZE_1MiB,
402                 .CmdSet         = P_ID_AMD_STD,
403                 .NumEraseRegions= 4,
404                 .regions        = {
405                         ERASEINFO(0x04000,1),
406                         ERASEINFO(0x02000,2),
407                         ERASEINFO(0x08000,1),
408                         ERASEINFO(0x10000,15),
409                 }
410         }, {
411                 .mfr_id         = MANUFACTURER_AMD,
412                 .dev_id         = AM29LV800BT,
413                 .name           = "AMD AM29LV800BT",
414                 .uaddr          = {
415                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
416                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
417                 },
418                 .DevSize        = SIZE_1MiB,
419                 .CmdSet         = P_ID_AMD_STD,
420                 .NumEraseRegions= 4,
421                 .regions        = {
422                         ERASEINFO(0x10000,15),
423                         ERASEINFO(0x08000,1),
424                         ERASEINFO(0x02000,2),
425                         ERASEINFO(0x04000,1)
426                 }
427         }, {
428                 .mfr_id         = MANUFACTURER_AMD,
429                 .dev_id         = AM29F800BT,
430                 .name           = "AMD AM29F800BT",
431                 .uaddr          = {
432                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
433                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
434                 },
435                 .DevSize        = SIZE_1MiB,
436                 .CmdSet         = P_ID_AMD_STD,
437                 .NumEraseRegions= 4,
438                 .regions        = {
439                         ERASEINFO(0x10000,15),
440                         ERASEINFO(0x08000,1),
441                         ERASEINFO(0x02000,2),
442                         ERASEINFO(0x04000,1)
443                 }
444         }, {
445                 .mfr_id         = MANUFACTURER_AMD,
446                 .dev_id         = AM29F017D,
447                 .name           = "AMD AM29F017D",
448                 .uaddr          = {
449                         [0] = MTD_UADDR_DONT_CARE     /* x8 */
450                 },
451                 .DevSize        = SIZE_2MiB,
452                 .CmdSet         = P_ID_AMD_STD,
453                 .NumEraseRegions= 1,
454                 .regions        = {
455                         ERASEINFO(0x10000,32),
456                 }
457         }, {
458                 .mfr_id         = MANUFACTURER_AMD,
459                 .dev_id         = AM29F016D,
460                 .name           = "AMD AM29F016D",
461                 .uaddr          = {
462                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
463                 },
464                 .DevSize        = SIZE_2MiB,
465                 .CmdSet         = P_ID_AMD_STD,
466                 .NumEraseRegions= 1,
467                 .regions        = {
468                         ERASEINFO(0x10000,32),
469                 }
470         }, {
471                 .mfr_id         = MANUFACTURER_AMD,
472                 .dev_id         = AM29F080,
473                 .name           = "AMD AM29F080",
474                 .uaddr          = {
475                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
476                 },
477                 .DevSize        = SIZE_1MiB,
478                 .CmdSet         = P_ID_AMD_STD,
479                 .NumEraseRegions= 1,
480                 .regions        = {
481                         ERASEINFO(0x10000,16),
482                 }
483         }, {
484                 .mfr_id         = MANUFACTURER_AMD,
485                 .dev_id         = AM29F040,
486                 .name           = "AMD AM29F040",
487                 .uaddr          = {
488                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
489                 },
490                 .DevSize        = SIZE_512KiB,
491                 .CmdSet         = P_ID_AMD_STD,
492                 .NumEraseRegions= 1,
493                 .regions        = {
494                         ERASEINFO(0x10000,8),
495                 }
496         }, {
497                 .mfr_id         = MANUFACTURER_AMD,
498                 .dev_id         = AM29LV040B,
499                 .name           = "AMD AM29LV040B",
500                 .uaddr          = {
501                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
502                 },
503                 .DevSize        = SIZE_512KiB,
504                 .CmdSet         = P_ID_AMD_STD,
505                 .NumEraseRegions= 1,
506                 .regions        = {
507                         ERASEINFO(0x10000,8),
508                 }
509         }, {
510                 .mfr_id         = MANUFACTURER_ATMEL,
511                 .dev_id         = AT49BV512,
512                 .name           = "Atmel AT49BV512",
513                 .uaddr          = {
514                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
515                 },
516                 .DevSize        = SIZE_64KiB,
517                 .CmdSet         = P_ID_AMD_STD,
518                 .NumEraseRegions= 1,
519                 .regions        = {
520                         ERASEINFO(0x10000,1)
521                 }
522         }, {
523                 .mfr_id         = MANUFACTURER_ATMEL,
524                 .dev_id         = AT29LV512,
525                 .name           = "Atmel AT29LV512",
526                 .uaddr          = {
527                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
528                 },
529                 .DevSize        = SIZE_64KiB,
530                 .CmdSet         = P_ID_AMD_STD,
531                 .NumEraseRegions= 1,
532                 .regions        = {
533                         ERASEINFO(0x80,256),
534                         ERASEINFO(0x80,256)
535                 }
536         }, {
537                 .mfr_id         = MANUFACTURER_ATMEL,
538                 .dev_id         = AT49BV16X,
539                 .name           = "Atmel AT49BV16X",
540                 .uaddr          = {
541                         [0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
542                         [1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
543                 },
544                 .DevSize        = SIZE_2MiB,
545                 .CmdSet         = P_ID_AMD_STD,
546                 .NumEraseRegions= 2,
547                 .regions        = {
548                         ERASEINFO(0x02000,8),
549                         ERASEINFO(0x10000,31)
550                 }
551         }, {
552                 .mfr_id         = MANUFACTURER_ATMEL,
553                 .dev_id         = AT49BV16XT,
554                 .name           = "Atmel AT49BV16XT",
555                 .uaddr          = {
556                         [0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
557                         [1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
558                 },
559                 .DevSize        = SIZE_2MiB,
560                 .CmdSet         = P_ID_AMD_STD,
561                 .NumEraseRegions= 2,
562                 .regions        = {
563                         ERASEINFO(0x10000,31),
564                         ERASEINFO(0x02000,8)
565                 }
566         }, {
567                 .mfr_id         = MANUFACTURER_ATMEL,
568                 .dev_id         = AT49BV32X,
569                 .name           = "Atmel AT49BV32X",
570                 .uaddr          = {
571                         [0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
572                         [1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
573                 },
574                 .DevSize        = SIZE_4MiB,
575                 .CmdSet         = P_ID_AMD_STD,
576                 .NumEraseRegions= 2,
577                 .regions        = {
578                         ERASEINFO(0x02000,8),
579                         ERASEINFO(0x10000,63)
580                 }
581         }, {
582                 .mfr_id         = MANUFACTURER_ATMEL,
583                 .dev_id         = AT49BV32XT,
584                 .name           = "Atmel AT49BV32XT",
585                 .uaddr          = {
586                         [0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
587                         [1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
588                 },
589                 .DevSize        = SIZE_4MiB,
590                 .CmdSet         = P_ID_AMD_STD,
591                 .NumEraseRegions= 2,
592                 .regions        = {
593                         ERASEINFO(0x10000,63),
594                         ERASEINFO(0x02000,8)
595                 }
596         }, {
597                 .mfr_id         = MANUFACTURER_FUJITSU,
598                 .dev_id         = MBM29F040C,
599                 .name           = "Fujitsu MBM29F040C",
600                 .uaddr          = {
601                         [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
602                 },
603                 .DevSize        = SIZE_512KiB,
604                 .CmdSet         = P_ID_AMD_STD,
605                 .NumEraseRegions= 1,
606                 .regions        = {
607                         ERASEINFO(0x10000,8)
608                 }
609         }, {
610                 .mfr_id         = MANUFACTURER_FUJITSU,
611                 .dev_id         = MBM29LV650UE,
612                 .name           = "Fujitsu MBM29LV650UE",
613                 .uaddr          = {
614                         [0] = MTD_UADDR_DONT_CARE     /* x16 */
615                 },
616                 .DevSize        = SIZE_8MiB,
617                 .CmdSet         = P_ID_AMD_STD,
618                 .NumEraseRegions= 1,
619                 .regions        = {
620                         ERASEINFO(0x10000,128)
621                 }
622         }, {
623                 .mfr_id         = MANUFACTURER_FUJITSU,
624                 .dev_id         = MBM29LV320TE,
625                 .name           = "Fujitsu MBM29LV320TE",
626                 .uaddr          = {
627                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
628                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
629                 },
630                 .DevSize        = SIZE_4MiB,
631                 .CmdSet         = P_ID_AMD_STD,
632                 .NumEraseRegions= 2,
633                 .regions        = {
634                         ERASEINFO(0x10000,63),
635                         ERASEINFO(0x02000,8)
636                 }
637         }, {
638                 .mfr_id         = MANUFACTURER_FUJITSU,
639                 .dev_id         = MBM29LV320BE,
640                 .name           = "Fujitsu MBM29LV320BE",
641                 .uaddr          = {
642                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
643                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
644                 },
645                 .DevSize        = SIZE_4MiB,
646                 .CmdSet         = P_ID_AMD_STD,
647                 .NumEraseRegions= 2,
648                 .regions        = {
649                         ERASEINFO(0x02000,8),
650                         ERASEINFO(0x10000,63)
651                 }
652         }, {
653                 .mfr_id         = MANUFACTURER_FUJITSU,
654                 .dev_id         = MBM29LV160TE,
655                 .name           = "Fujitsu MBM29LV160TE",
656                 .uaddr          = {
657                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
658                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
659                 },
660                 .DevSize        = SIZE_2MiB,
661                 .CmdSet         = P_ID_AMD_STD,
662                 .NumEraseRegions= 4,
663                 .regions        = {
664                         ERASEINFO(0x10000,31),
665                         ERASEINFO(0x08000,1),
666                         ERASEINFO(0x02000,2),
667                         ERASEINFO(0x04000,1)
668                 }
669         }, {
670                 .mfr_id         = MANUFACTURER_FUJITSU,
671                 .dev_id         = MBM29LV160BE,
672                 .name           = "Fujitsu MBM29LV160BE",
673                 .uaddr          = {
674                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
675                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
676                 },
677                 .DevSize        = SIZE_2MiB,
678                 .CmdSet         = P_ID_AMD_STD,
679                 .NumEraseRegions= 4,
680                 .regions        = {
681                         ERASEINFO(0x04000,1),
682                         ERASEINFO(0x02000,2),
683                         ERASEINFO(0x08000,1),
684                         ERASEINFO(0x10000,31)
685                 }
686         }, {
687                 .mfr_id         = MANUFACTURER_FUJITSU,
688                 .dev_id         = MBM29LV800BA,
689                 .name           = "Fujitsu MBM29LV800BA",
690                 .uaddr          = {
691                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
692                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
693                 },
694                 .DevSize        = SIZE_1MiB,
695                 .CmdSet         = P_ID_AMD_STD,
696                 .NumEraseRegions= 4,
697                 .regions        = {
698                         ERASEINFO(0x04000,1),
699                         ERASEINFO(0x02000,2),
700                         ERASEINFO(0x08000,1),
701                         ERASEINFO(0x10000,15)
702                 }
703         }, {
704                 .mfr_id         = MANUFACTURER_FUJITSU,
705                 .dev_id         = MBM29LV800TA,
706                 .name           = "Fujitsu MBM29LV800TA",
707                 .uaddr          = {
708                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
709                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
710                 },
711                 .DevSize        = SIZE_1MiB,
712                 .CmdSet         = P_ID_AMD_STD,
713                 .NumEraseRegions= 4,
714                 .regions        = {
715                         ERASEINFO(0x10000,15),
716                         ERASEINFO(0x08000,1),
717                         ERASEINFO(0x02000,2),
718                         ERASEINFO(0x04000,1)
719                 }
720         }, {
721                 .mfr_id         = MANUFACTURER_FUJITSU,
722                 .dev_id         = MBM29LV400BC,
723                 .name           = "Fujitsu MBM29LV400BC",
724                 .uaddr          = {
725                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
726                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
727                 },
728                 .DevSize        = SIZE_512KiB,
729                 .CmdSet         = P_ID_AMD_STD,
730                 .NumEraseRegions= 4,
731                 .regions        = {
732                         ERASEINFO(0x04000,1),
733                         ERASEINFO(0x02000,2),
734                         ERASEINFO(0x08000,1),
735                         ERASEINFO(0x10000,7)
736                 }
737         }, {
738                 .mfr_id         = MANUFACTURER_FUJITSU,
739                 .dev_id         = MBM29LV400TC,
740                 .name           = "Fujitsu MBM29LV400TC",
741                 .uaddr          = {
742                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
743                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
744                 },
745                 .DevSize        = SIZE_512KiB,
746                 .CmdSet         = P_ID_AMD_STD,
747                 .NumEraseRegions= 4,
748                 .regions        = {
749                         ERASEINFO(0x10000,7),
750                         ERASEINFO(0x08000,1),
751                         ERASEINFO(0x02000,2),
752                         ERASEINFO(0x04000,1)
753                 }
754         }, {
755                 .mfr_id         = MANUFACTURER_INTEL,
756                 .dev_id         = I28F004B3B,
757                 .name           = "Intel 28F004B3B",
758                 .uaddr          = {
759                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
760                 },
761                 .DevSize        = SIZE_512KiB,
762                 .CmdSet         = P_ID_INTEL_STD,
763                 .NumEraseRegions= 2,
764                 .regions        = {
765                         ERASEINFO(0x02000, 8),
766                         ERASEINFO(0x10000, 7),
767                 }
768         }, {
769                 .mfr_id         = MANUFACTURER_INTEL,
770                 .dev_id         = I28F004B3T,
771                 .name           = "Intel 28F004B3T",
772                 .uaddr          = {
773                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
774                 },
775                 .DevSize        = SIZE_512KiB,
776                 .CmdSet         = P_ID_INTEL_STD,
777                 .NumEraseRegions= 2,
778                 .regions        = {
779                         ERASEINFO(0x10000, 7),
780                         ERASEINFO(0x02000, 8),
781                 }
782         }, {
783                 .mfr_id         = MANUFACTURER_INTEL,
784                 .dev_id         = I28F400B3B,
785                 .name           = "Intel 28F400B3B",
786                 .uaddr          = {
787                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
788                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
789                 },
790                 .DevSize        = SIZE_512KiB,
791                 .CmdSet         = P_ID_INTEL_STD,
792                 .NumEraseRegions= 2,
793                 .regions        = {
794                         ERASEINFO(0x02000, 8),
795                         ERASEINFO(0x10000, 7),
796                 }
797         }, {
798                 .mfr_id         = MANUFACTURER_INTEL,
799                 .dev_id         = I28F400B3T,
800                 .name           = "Intel 28F400B3T",
801                 .uaddr          = {
802                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
803                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
804                 },
805                 .DevSize        = SIZE_512KiB,
806                 .CmdSet         = P_ID_INTEL_STD,
807                 .NumEraseRegions= 2,
808                 .regions        = {
809                         ERASEINFO(0x10000, 7),
810                         ERASEINFO(0x02000, 8),
811                 }
812         }, {
813                 .mfr_id         = MANUFACTURER_INTEL,
814                 .dev_id         = I28F008B3B,
815                 .name           = "Intel 28F008B3B",
816                 .uaddr          = {
817                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
818                 },
819                 .DevSize        = SIZE_1MiB,
820                 .CmdSet         = P_ID_INTEL_STD,
821                 .NumEraseRegions= 2,
822                 .regions        = {
823                         ERASEINFO(0x02000, 8),
824                         ERASEINFO(0x10000, 15),
825                 }
826         }, {
827                 .mfr_id         = MANUFACTURER_INTEL,
828                 .dev_id         = I28F008B3T,
829                 .name           = "Intel 28F008B3T",
830                 .uaddr          = {
831                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
832                 },
833                 .DevSize        = SIZE_1MiB,
834                 .CmdSet         = P_ID_INTEL_STD,
835                 .NumEraseRegions= 2,
836                 .regions        = {
837                         ERASEINFO(0x10000, 15),
838                         ERASEINFO(0x02000, 8),
839                 }
840         }, {
841                 .mfr_id         = MANUFACTURER_INTEL,
842                 .dev_id         = I28F008S5,
843                 .name           = "Intel 28F008S5",
844                 .uaddr          = {
845                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
846                 },
847                 .DevSize        = SIZE_1MiB,
848                 .CmdSet         = P_ID_INTEL_EXT,
849                 .NumEraseRegions= 1,
850                 .regions        = {
851                         ERASEINFO(0x10000,16),
852                 }
853         }, {
854                 .mfr_id         = MANUFACTURER_INTEL,
855                 .dev_id         = I28F016S5,
856                 .name           = "Intel 28F016S5",
857                 .uaddr          = {
858                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
859                 },
860                 .DevSize        = SIZE_2MiB,
861                 .CmdSet         = P_ID_INTEL_EXT,
862                 .NumEraseRegions= 1,
863                 .regions        = {
864                         ERASEINFO(0x10000,32),
865                 }
866         }, {
867                 .mfr_id         = MANUFACTURER_INTEL,
868                 .dev_id         = I28F008SA,
869                 .name           = "Intel 28F008SA",
870                 .uaddr          = {
871                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
872                 },
873                 .DevSize        = SIZE_1MiB,
874                 .CmdSet         = P_ID_INTEL_STD,
875                 .NumEraseRegions= 1,
876                 .regions        = {
877                         ERASEINFO(0x10000, 16),
878                 }
879         }, {
880                 .mfr_id         = MANUFACTURER_INTEL,
881                 .dev_id         = I28F800B3B,
882                 .name           = "Intel 28F800B3B",
883                 .uaddr          = {
884                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
885                 },
886                 .DevSize        = SIZE_1MiB,
887                 .CmdSet         = P_ID_INTEL_STD,
888                 .NumEraseRegions= 2,
889                 .regions        = {
890                         ERASEINFO(0x02000, 8),
891                         ERASEINFO(0x10000, 15),
892                 }
893         }, {
894                 .mfr_id         = MANUFACTURER_INTEL,
895                 .dev_id         = I28F800B3T,
896                 .name           = "Intel 28F800B3T",
897                 .uaddr          = {
898                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
899                 },
900                 .DevSize        = SIZE_1MiB,
901                 .CmdSet         = P_ID_INTEL_STD,
902                 .NumEraseRegions= 2,
903                 .regions        = {
904                         ERASEINFO(0x10000, 15),
905                         ERASEINFO(0x02000, 8),
906                 }
907         }, {
908                 .mfr_id         = MANUFACTURER_INTEL,
909                 .dev_id         = I28F016B3B,
910                 .name           = "Intel 28F016B3B",
911                 .uaddr          = {
912                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
913                 },
914                 .DevSize        = SIZE_2MiB,
915                 .CmdSet         = P_ID_INTEL_STD,
916                 .NumEraseRegions= 2,
917                 .regions        = {
918                         ERASEINFO(0x02000, 8),
919                         ERASEINFO(0x10000, 31),
920                 }
921         }, {
922                 .mfr_id         = MANUFACTURER_INTEL,
923                 .dev_id         = I28F016S3,
924                 .name           = "Intel I28F016S3",
925                 .uaddr          = {
926                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
927                 },
928                 .DevSize        = SIZE_2MiB,
929                 .CmdSet         = P_ID_INTEL_STD,
930                 .NumEraseRegions= 1,
931                 .regions        = {
932                         ERASEINFO(0x10000, 32),
933                 }
934         }, {
935                 .mfr_id         = MANUFACTURER_INTEL,
936                 .dev_id         = I28F016B3T,
937                 .name           = "Intel 28F016B3T",
938                 .uaddr          = {
939                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
940                 },
941                 .DevSize        = SIZE_2MiB,
942                 .CmdSet         = P_ID_INTEL_STD,
943                 .NumEraseRegions= 2,
944                 .regions        = {
945                         ERASEINFO(0x10000, 31),
946                         ERASEINFO(0x02000, 8),
947                 }
948         }, {
949                 .mfr_id         = MANUFACTURER_INTEL,
950                 .dev_id         = I28F160B3B,
951                 .name           = "Intel 28F160B3B",
952                 .uaddr          = {
953                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
954                 },
955                 .DevSize        = SIZE_2MiB,
956                 .CmdSet         = P_ID_INTEL_STD,
957                 .NumEraseRegions= 2,
958                 .regions        = {
959                         ERASEINFO(0x02000, 8),
960                         ERASEINFO(0x10000, 31),
961                 }
962         }, {
963                 .mfr_id         = MANUFACTURER_INTEL,
964                 .dev_id         = I28F160B3T,
965                 .name           = "Intel 28F160B3T",
966                 .uaddr          = {
967                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
968                 },
969                 .DevSize        = SIZE_2MiB,
970                 .CmdSet         = P_ID_INTEL_STD,
971                 .NumEraseRegions= 2,
972                 .regions        = {
973                         ERASEINFO(0x10000, 31),
974                         ERASEINFO(0x02000, 8),
975                 }
976         }, {
977                 .mfr_id         = MANUFACTURER_INTEL,
978                 .dev_id         = I28F320B3B,
979                 .name           = "Intel 28F320B3B",
980                 .uaddr          = {
981                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
982                 },
983                 .DevSize        = SIZE_4MiB,
984                 .CmdSet         = P_ID_INTEL_STD,
985                 .NumEraseRegions= 2,
986                 .regions        = {
987                         ERASEINFO(0x02000, 8),
988                         ERASEINFO(0x10000, 63),
989                 }
990         }, {
991                 .mfr_id         = MANUFACTURER_INTEL,
992                 .dev_id         = I28F320B3T,
993                 .name           = "Intel 28F320B3T",
994                 .uaddr          = {
995                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
996                 },
997                 .DevSize        = SIZE_4MiB,
998                 .CmdSet         = P_ID_INTEL_STD,
999                 .NumEraseRegions= 2,
1000                 .regions        = {
1001                         ERASEINFO(0x10000, 63),
1002                         ERASEINFO(0x02000, 8),
1003                 }
1004         }, {
1005                 .mfr_id         = MANUFACTURER_INTEL,
1006                 .dev_id         = I28F640B3B,
1007                 .name           = "Intel 28F640B3B",
1008                 .uaddr          = {
1009                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
1010                 },
1011                 .DevSize        = SIZE_8MiB,
1012                 .CmdSet         = P_ID_INTEL_STD,
1013                 .NumEraseRegions= 2,
1014                 .regions        = {
1015                         ERASEINFO(0x02000, 8),
1016                         ERASEINFO(0x10000, 127),
1017                 }
1018         }, {
1019                 .mfr_id         = MANUFACTURER_INTEL,
1020                 .dev_id         = I28F640B3T,
1021                 .name           = "Intel 28F640B3T",
1022                 .uaddr          = {
1023                         [1] = MTD_UADDR_UNNECESSARY,    /* x16 */
1024                 },
1025                 .DevSize        = SIZE_8MiB,
1026                 .CmdSet         = P_ID_INTEL_STD,
1027                 .NumEraseRegions= 2,
1028                 .regions        = {
1029                         ERASEINFO(0x10000, 127),
1030                         ERASEINFO(0x02000, 8),
1031                 }
1032         }, {
1033                 .mfr_id         = MANUFACTURER_INTEL,
1034                 .dev_id         = I82802AB,
1035                 .name           = "Intel 82802AB",
1036                 .uaddr          = {
1037                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
1038                 },
1039                 .DevSize        = SIZE_512KiB,
1040                 .CmdSet         = P_ID_INTEL_EXT,
1041                 .NumEraseRegions= 1,
1042                 .regions        = {
1043                         ERASEINFO(0x10000,8),
1044                 }
1045         }, {
1046                 .mfr_id         = MANUFACTURER_INTEL,
1047                 .dev_id         = I82802AC,
1048                 .name           = "Intel 82802AC",
1049                 .uaddr          = {
1050                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
1051                 },
1052                 .DevSize        = SIZE_1MiB,
1053                 .CmdSet         = P_ID_INTEL_EXT,
1054                 .NumEraseRegions= 1,
1055                 .regions        = {
1056                         ERASEINFO(0x10000,16),
1057                 }
1058         }, {
1059                 .mfr_id         = MANUFACTURER_MACRONIX,
1060                 .dev_id         = MX29LV160T,
1061                 .name           = "MXIC MX29LV160T",
1062                 .uaddr          = {
1063                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
1064                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
1065                 },
1066                 .DevSize        = SIZE_2MiB,
1067                 .CmdSet         = P_ID_AMD_STD,
1068                 .NumEraseRegions= 4,
1069                 .regions        = {
1070                         ERASEINFO(0x10000,31),
1071                         ERASEINFO(0x08000,1),
1072                         ERASEINFO(0x02000,2),
1073                         ERASEINFO(0x04000,1)
1074                 }
1075         }, {
1076                 .mfr_id         = MANUFACTURER_MACRONIX,
1077                 .dev_id         = MX29LV160B,
1078                 .name           = "MXIC MX29LV160B",
1079                 .uaddr          = {
1080                         [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
1081                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
1082                 },
1083                 .DevSize        = SIZE_2MiB,
1084                 .CmdSet         = P_ID_AMD_STD,
1085                 .NumEraseRegions= 4,
1086                 .regions        = {
1087                         ERASEINFO(0x04000,1),
1088                         ERASEINFO(0x02000,2),
1089                         ERASEINFO(0x08000,1),
1090                         ERASEINFO(0x10000,31)
1091                 }
1092         }, {
1093                 .mfr_id         = MANUFACTURER_MACRONIX,
1094                 .dev_id         = MX29F016,
1095                 .name           = "Macronix MX29F016",
1096                 .uaddr          = {
1097                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
1098                 },
1099                 .DevSize        = SIZE_2MiB,
1100                 .CmdSet         = P_ID_AMD_STD,
1101                 .NumEraseRegions= 1,
1102                 .regions        = {
1103                         ERASEINFO(0x10000,32),
1104                 }
1105         }, {
1106                 .mfr_id         = MANUFACTURER_MACRONIX,
1107                 .dev_id         = MX29F004T,
1108                 .name           = "Macronix MX29F004T",
1109                 .uaddr          = {
1110                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
1111                 },
1112                 .DevSize        = SIZE_512KiB,
1113                 .CmdSet         = P_ID_AMD_STD,
1114                 .NumEraseRegions= 4,
1115                 .regions        = {
1116                         ERASEINFO(0x10000,7),
1117                         ERASEINFO(0x08000,1),
1118                         ERASEINFO(0x02000,2),
1119                         ERASEINFO(0x04000,1),
1120                 }
1121         }, {
1122                 .mfr_id         = MANUFACTURER_MACRONIX,
1123                 .dev_id         = MX29F004B,
1124                 .name           = "Macronix MX29F004B",
1125                 .uaddr          = {
1126                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
1127                 },
1128                 .DevSize        = SIZE_512KiB,
1129                 .CmdSet         = P_ID_AMD_STD,
1130                 .NumEraseRegions= 4,
1131                 .regions        = {
1132                         ERASEINFO(0x04000,1),
1133                         ERASEINFO(0x02000,2),
1134                         ERASEINFO(0x08000,1),
1135                         ERASEINFO(0x10000,7),
1136                 }
1137         }, {
1138                 .mfr_id         = MANUFACTURER_PMC,
1139                 .dev_id         = PM49FL002,
1140                 .name           = "PMC Pm49FL002",
1141                 .uaddr          = {
1142                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1143                 },
1144                 .DevSize        = SIZE_256KiB,
1145                 .CmdSet         = P_ID_AMD_STD,
1146                 .NumEraseRegions= 1,
1147                 .regions        = {
1148                         ERASEINFO( 0x01000, 64 )
1149                 }
1150         }, {
1151                 .mfr_id         = MANUFACTURER_PMC,
1152                 .dev_id         = PM49FL004,
1153                 .name           = "PMC Pm49FL004",
1154                 .uaddr          = {
1155                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1156                 },
1157                 .DevSize        = SIZE_512KiB,
1158                 .CmdSet         = P_ID_AMD_STD,
1159                 .NumEraseRegions= 1,
1160                 .regions        = {
1161                         ERASEINFO( 0x01000, 128 )
1162                 }
1163         }, {
1164                 .mfr_id         = MANUFACTURER_PMC,
1165                 .dev_id         = PM49FL008,
1166                 .name           = "PMC Pm49FL008",
1167                 .uaddr          = {
1168                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1169                 },
1170                 .DevSize        = SIZE_1MiB,
1171                 .CmdSet         = P_ID_AMD_STD,
1172                 .NumEraseRegions= 1,
1173                 .regions        = {
1174                         ERASEINFO( 0x01000, 256 )
1175                 }
1176         }, {
1177                 .mfr_id         = MANUFACTURER_SST,
1178                 .dev_id         = SST39LF512,
1179                 .name           = "SST 39LF512",
1180                 .uaddr          = {
1181                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1182                 },
1183                 .DevSize        = SIZE_64KiB,
1184                 .CmdSet         = P_ID_AMD_STD,
1185                 .NumEraseRegions= 1,
1186                 .regions        = {
1187                         ERASEINFO(0x01000,16),
1188                 }
1189         }, {
1190                 .mfr_id         = MANUFACTURER_SST,
1191                 .dev_id         = SST39LF010,
1192                 .name           = "SST 39LF010",
1193                 .uaddr          = {
1194                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1195                 },
1196                 .DevSize        = SIZE_128KiB,
1197                 .CmdSet         = P_ID_AMD_STD,
1198                 .NumEraseRegions= 1,
1199                 .regions        = {
1200                         ERASEINFO(0x01000,32),
1201                 }
1202         }, {
1203                 .mfr_id         = MANUFACTURER_SST,
1204                 .dev_id         = SST29EE020,
1205                 .name           = "SST 29EE020",
1206                 .uaddr          = {
1207                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1208                 },
1209                 .DevSize        = SIZE_256KiB,
1210                 .CmdSet         = P_ID_SST_PAGE,
1211                 .NumEraseRegions= 1,
1212                 regions: {ERASEINFO(0x01000,64),
1213                 }
1214          }, {
1215                 .mfr_id         = MANUFACTURER_SST,
1216                 .dev_id         = SST29LE020,
1217                 .name           = "SST 29LE020",
1218                 .uaddr          = {
1219                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1220                 },
1221                 .DevSize        = SIZE_256KiB,
1222                 .CmdSet         = P_ID_SST_PAGE,
1223                 .NumEraseRegions= 1,
1224                 regions: {ERASEINFO(0x01000,64),
1225                 }
1226         }, {
1227                 .mfr_id         = MANUFACTURER_SST,
1228                 .dev_id         = SST39LF020,
1229                 .name           = "SST 39LF020",
1230                 .uaddr          = {
1231                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1232                 },
1233                 .DevSize        = SIZE_256KiB,
1234                 .CmdSet         = P_ID_AMD_STD,
1235                 .NumEraseRegions= 1,
1236                 .regions        = {
1237                         ERASEINFO(0x01000,64),
1238                 }
1239         }, {
1240                 .mfr_id         = MANUFACTURER_SST,
1241                 .dev_id         = SST39LF040,
1242                 .name           = "SST 39LF040",
1243                 .uaddr          = {
1244                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1245                 },
1246                 .DevSize        = SIZE_512KiB,
1247                 .CmdSet         = P_ID_AMD_STD,
1248                 .NumEraseRegions= 1,
1249                 .regions        = {
1250                         ERASEINFO(0x01000,128),
1251                 }
1252         }, {
1253                 .mfr_id         = MANUFACTURER_SST,
1254                 .dev_id         = SST39SF010A,
1255                 .name           = "SST 39SF010A",
1256                 .uaddr          = {
1257                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1258                 },
1259                 .DevSize        = SIZE_128KiB,
1260                 .CmdSet         = P_ID_AMD_STD,
1261                 .NumEraseRegions= 1,
1262                 .regions        = {
1263                         ERASEINFO(0x01000,32),
1264                 }
1265         }, {
1266                 .mfr_id         = MANUFACTURER_SST,
1267                 .dev_id         = SST39SF020A,
1268                 .name           = "SST 39SF020A",
1269                 .uaddr          = {
1270                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1271                 },
1272                 .DevSize        = SIZE_256KiB,
1273                 .CmdSet         = P_ID_AMD_STD,
1274                 .NumEraseRegions= 1,
1275                 .regions        = {
1276                         ERASEINFO(0x01000,64),
1277                 }
1278         }, {
1279                 .mfr_id         = MANUFACTURER_SST,
1280                 .dev_id         = SST49LF004B,
1281                 .name           = "SST 49LF004B",
1282                 .uaddr          = {
1283                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1284                 },
1285                 .DevSize        = SIZE_512KiB,
1286                 .CmdSet         = P_ID_AMD_STD,
1287                 .NumEraseRegions= 1,
1288                 .regions        = {
1289                         ERASEINFO(0x01000,128),
1290                 }
1291         }, {
1292                 .mfr_id         = MANUFACTURER_SST,
1293                 .dev_id         = SST49LF008A,
1294                 .name           = "SST 49LF008A",
1295                 .uaddr          = {
1296                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1297                 },
1298                 .DevSize        = SIZE_1MiB,
1299                 .CmdSet         = P_ID_AMD_STD,
1300                 .NumEraseRegions= 1,
1301                 .regions        = {
1302                         ERASEINFO(0x01000,256),
1303                 }
1304         }, {
1305                 .mfr_id         = MANUFACTURER_SST,
1306                 .dev_id         = SST49LF030A,
1307                 .name           = "SST 49LF030A",
1308                 .uaddr          = {
1309                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1310                 },
1311                 .DevSize        = SIZE_512KiB,
1312                 .CmdSet         = P_ID_AMD_STD,
1313                 .NumEraseRegions= 1,
1314                 .regions        = {
1315                         ERASEINFO(0x01000,96),
1316                 }
1317         }, {
1318                 .mfr_id         = MANUFACTURER_SST,
1319                 .dev_id         = SST49LF040A,
1320                 .name           = "SST 49LF040A",
1321                 .uaddr          = {
1322                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1323                 },
1324                 .DevSize        = SIZE_512KiB,
1325                 .CmdSet         = P_ID_AMD_STD,
1326                 .NumEraseRegions= 1,
1327                 .regions        = {
1328                         ERASEINFO(0x01000,128),
1329                 }
1330         }, {
1331                 .mfr_id         = MANUFACTURER_SST,
1332                 .dev_id         = SST49LF080A,
1333                 .name           = "SST 49LF080A",
1334                 .uaddr          = {
1335                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1336                 },
1337                 .DevSize        = SIZE_1MiB,
1338                 .CmdSet         = P_ID_AMD_STD,
1339                 .NumEraseRegions= 1,
1340                 .regions        = {
1341                         ERASEINFO(0x01000,256),
1342                 }
1343         }, {
1344                 .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
1345                 .dev_id         = M29W800DT,
1346                 .name           = "ST M29W800DT",
1347                 .uaddr          = {
1348                         [0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
1349                         [1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
1350                 },
1351                 .DevSize        = SIZE_1MiB,
1352                 .CmdSet         = P_ID_AMD_STD,
1353                 .NumEraseRegions= 4,
1354                 .regions        = {
1355                         ERASEINFO(0x10000,15),
1356                         ERASEINFO(0x08000,1),
1357                         ERASEINFO(0x02000,2),
1358                         ERASEINFO(0x04000,1)
1359                 }
1360         }, {
1361                 .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
1362                 .dev_id         = M29W800DB,
1363                 .name           = "ST M29W800DB",
1364                 .uaddr          = {
1365                         [0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
1366                         [1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
1367                 },
1368                 .DevSize        = SIZE_1MiB,
1369                 .CmdSet         = P_ID_AMD_STD,
1370                 .NumEraseRegions= 4,
1371                 .regions        = {
1372                         ERASEINFO(0x04000,1),
1373                         ERASEINFO(0x02000,2),
1374                         ERASEINFO(0x08000,1),
1375                         ERASEINFO(0x10000,15)
1376                 }
1377         }, {
1378                 .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
1379                 .dev_id         = M29W160DT,
1380                 .name           = "ST M29W160DT",
1381                 .uaddr          = {
1382                         [0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
1383                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
1384                 },
1385                 .DevSize        = SIZE_2MiB,
1386                 .CmdSet         = P_ID_AMD_STD,
1387                 .NumEraseRegions= 4,
1388                 .regions        = {
1389                         ERASEINFO(0x10000,31),
1390                         ERASEINFO(0x08000,1),
1391                         ERASEINFO(0x02000,2),
1392                         ERASEINFO(0x04000,1)
1393                 }
1394         }, {
1395                 .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
1396                 .dev_id         = M29W160DB,
1397                 .name           = "ST M29W160DB",
1398                 .uaddr          = {
1399                         [0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
1400                         [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
1401                 },
1402                 .DevSize        = SIZE_2MiB,
1403                 .CmdSet         = P_ID_AMD_STD,
1404                 .NumEraseRegions= 4,
1405                 .regions        = {
1406                         ERASEINFO(0x04000,1),
1407                         ERASEINFO(0x02000,2),
1408                         ERASEINFO(0x08000,1),
1409                         ERASEINFO(0x10000,31)
1410                 }
1411         }, {
1412                 .mfr_id         = MANUFACTURER_ST,
1413                 .dev_id         = M29W040B,
1414                 .name           = "ST M29W040B",
1415                 .uaddr          = {
1416                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
1417                 },
1418                 .DevSize        = SIZE_512KiB,
1419                 .CmdSet         = P_ID_AMD_STD,
1420                 .NumEraseRegions= 1,
1421                 .regions        = {
1422                         ERASEINFO(0x10000,8),
1423                 }
1424         }, {
1425                 .mfr_id         = MANUFACTURER_ST,
1426                 .dev_id         = M50FW040,
1427                 .name           = "ST M50FW040",
1428                 .uaddr          = {
1429                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
1430                 },
1431                 .DevSize        = SIZE_512KiB,
1432                 .CmdSet         = P_ID_INTEL_EXT,
1433                 .NumEraseRegions= 1,
1434                 .regions        = {
1435                         ERASEINFO(0x10000,8),
1436                 }
1437         }, {
1438                 .mfr_id         = MANUFACTURER_ST,
1439                 .dev_id         = M50FW080,
1440                 .name           = "ST M50FW080",
1441                 .uaddr          = {
1442                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
1443                 },
1444                 .DevSize        = SIZE_1MiB,
1445                 .CmdSet         = P_ID_INTEL_EXT,
1446                 .NumEraseRegions= 1,
1447                 .regions        = {
1448                         ERASEINFO(0x10000,16),
1449                 }
1450         }, {
1451                 .mfr_id         = MANUFACTURER_ST,
1452                 .dev_id         = M50FW016,
1453                 .name           = "ST M50FW016",
1454                 .uaddr          = {
1455                         [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
1456                 },
1457                 .DevSize        = SIZE_2MiB,
1458                 .CmdSet         = P_ID_INTEL_EXT,
1459                 .NumEraseRegions= 1,
1460                 .regions        = {
1461                         ERASEINFO(0x10000,32),
1462                 }
1463         }, {
1464                 .mfr_id         = MANUFACTURER_TOSHIBA,
1465                 .dev_id         = TC58FVT160,
1466                 .name           = "Toshiba TC58FVT160",
1467                 .uaddr          = {
1468                         [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
1469                         [1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
1470                 },
1471                 .DevSize        = SIZE_2MiB,
1472                 .CmdSet         = P_ID_AMD_STD,
1473                 .NumEraseRegions= 4,
1474                 .regions        = {
1475                         ERASEINFO(0x10000,31),
1476                         ERASEINFO(0x08000,1),
1477                         ERASEINFO(0x02000,2),
1478                         ERASEINFO(0x04000,1)
1479                 }
1480         }, {
1481                 .mfr_id         = MANUFACTURER_TOSHIBA,
1482                 .dev_id         = TC58FVB160,
1483                 .name           = "Toshiba TC58FVB160",
1484                 .uaddr          = {
1485                         [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
1486                         [1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
1487                 },
1488                 .DevSize        = SIZE_2MiB,
1489                 .CmdSet         = P_ID_AMD_STD,
1490                 .NumEraseRegions= 4,
1491                 .regions        = {
1492                         ERASEINFO(0x04000,1),
1493                         ERASEINFO(0x02000,2),
1494                         ERASEINFO(0x08000,1),
1495                         ERASEINFO(0x10000,31)
1496                 }
1497         }, {
1498                 .mfr_id         = MANUFACTURER_TOSHIBA,
1499                 .dev_id         = TC58FVB321,
1500                 .name           = "Toshiba TC58FVB321",
1501                 .uaddr          = {
1502                         [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
1503                         [1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
1504                 },
1505                 .DevSize        = SIZE_4MiB,
1506                 .CmdSet         = P_ID_AMD_STD,
1507                 .NumEraseRegions= 2,
1508                 .regions        = {
1509                         ERASEINFO(0x02000,8),
1510                         ERASEINFO(0x10000,63)
1511                 }
1512         }, {
1513                 .mfr_id         = MANUFACTURER_TOSHIBA,
1514                 .dev_id         = TC58FVT321,
1515                 .name           = "Toshiba TC58FVT321",
1516                 .uaddr          = {
1517                         [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
1518                         [1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
1519                 },
1520                 .DevSize        = SIZE_4MiB,
1521                 .CmdSet         = P_ID_AMD_STD,
1522                 .NumEraseRegions= 2,
1523                 .regions        = {
1524                         ERASEINFO(0x10000,63),
1525                         ERASEINFO(0x02000,8)
1526                 }
1527         }, {
1528                 .mfr_id         = MANUFACTURER_TOSHIBA,
1529                 .dev_id         = TC58FVB641,
1530                 .name           = "Toshiba TC58FVB641",
1531                 .uaddr          = {
1532                         [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
1533                         [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
1534                 },
1535                 .DevSize        = SIZE_8MiB,
1536                 .CmdSet         = P_ID_AMD_STD,
1537                 .NumEraseRegions= 2,
1538                 .regions        = {
1539                         ERASEINFO(0x02000,8),
1540                         ERASEINFO(0x10000,127)
1541                 }
1542         }, {
1543                 .mfr_id         = MANUFACTURER_TOSHIBA,
1544                 .dev_id         = TC58FVT641,
1545                 .name           = "Toshiba TC58FVT641",
1546                 .uaddr          = {
1547                         [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
1548                         [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
1549                 },
1550                 .DevSize        = SIZE_8MiB,
1551                 .CmdSet         = P_ID_AMD_STD,
1552                 .NumEraseRegions= 2,
1553                 .regions        = {
1554                         ERASEINFO(0x10000,127),
1555                         ERASEINFO(0x02000,8)
1556                 }
1557         }, {
1558                 .mfr_id         = MANUFACTURER_WINBOND,
1559                 .dev_id         = W49V002A,
1560                 .name           = "Winbond W49V002A",
1561                 .uaddr          = {
1562                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1563                 },
1564                 .DevSize        = SIZE_256KiB,
1565                 .CmdSet         = P_ID_AMD_STD,
1566                 .NumEraseRegions= 4,
1567                 .regions        = {
1568                         ERASEINFO(0x10000, 3),
1569                         ERASEINFO(0x08000, 1),
1570                         ERASEINFO(0x02000, 2),
1571                         ERASEINFO(0x04000, 1),
1572                 }
1573         } 
1574 };
1575
1576
1577 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
1578
1579 static int jedec_probe_chip(struct map_info *map, __u32 base,
1580                             unsigned long *chip_map, struct cfi_private *cfi);
1581
1582 struct mtd_info *jedec_probe(struct map_info *map);
1583
1584 static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, 
1585         struct cfi_private *cfi)
1586 {
1587         map_word result;
1588         unsigned long mask;
1589         mask = (1 << (cfi->device_type * 8)) -1;
1590         result = map_read(map, base);
1591         return result.x[0] & mask;
1592 }
1593
1594 static inline u32 jedec_read_id(struct map_info *map, __u32 base, 
1595         struct cfi_private *cfi)
1596 {
1597         int osf;
1598         map_word result;
1599         unsigned long mask;
1600         osf = cfi->interleave *cfi->device_type;
1601         mask = (1 << (cfi->device_type * 8)) -1;
1602         result = map_read(map, base + osf);
1603         return result.x[0] & mask;
1604 }
1605
1606 static inline void jedec_reset(u32 base, struct map_info *map, 
1607         struct cfi_private *cfi)
1608 {
1609         /* Reset */
1610
1611         /* after checking the datasheets for SST, MACRONIX and ATMEL
1612          * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
1613          * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
1614          * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
1615          * as they will ignore the writes and dont care what address
1616          * the F0 is written to */
1617         if(cfi->addr_unlock1) {
1618                 /*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/
1619                 cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1620                 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1621         }
1622
1623         cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
1624         /* Some misdesigned intel chips do not respond for 0xF0 for a reset,
1625          * so ensure we're in read mode.  Send both the Intel and the AMD command
1626          * for this.  Intel uses 0xff for this, AMD uses 0xff for NOP, so
1627          * this should be safe.
1628          */ 
1629         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
1630         /* FIXME - should have reset delay before continuing */
1631 }
1632
1633
1634 static inline __u8 finfo_uaddr(const struct amd_flash_info *finfo, int device_type)
1635 {
1636         int uaddr_idx;
1637         __u8 uaddr = MTD_UADDR_NOT_SUPPORTED;
1638
1639         switch ( device_type ) {
1640         case CFI_DEVICETYPE_X8:  uaddr_idx = 0; break;
1641         case CFI_DEVICETYPE_X16: uaddr_idx = 1; break;
1642         case CFI_DEVICETYPE_X32: uaddr_idx = 2; break;
1643         default:
1644                 printk(KERN_NOTICE "MTD: %s(): unknown device_type %d\n",
1645                        __func__, device_type);
1646                 goto uaddr_done;
1647         }
1648
1649         uaddr = finfo->uaddr[uaddr_idx];
1650
1651         if (uaddr != MTD_UADDR_NOT_SUPPORTED ) {
1652                 /* ASSERT("The unlock addresses for non-8-bit mode
1653                    are bollocks. We don't really need an array."); */
1654                 uaddr = finfo->uaddr[0];
1655         }
1656
1657  uaddr_done:
1658         return uaddr;
1659 }
1660
1661
1662 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
1663 {
1664         int i,num_erase_regions;
1665         unsigned long mask;
1666         __u8 uaddr;
1667
1668         printk("Found: %s\n",jedec_table[index].name);
1669
1670         num_erase_regions = jedec_table[index].NumEraseRegions;
1671         
1672         p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
1673         if (!p_cfi->cfiq) {
1674                 //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
1675                 return 0;
1676         }
1677
1678         memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); 
1679
1680         p_cfi->cfiq->P_ID = jedec_table[index].CmdSet;
1681         p_cfi->cfiq->NumEraseRegions = jedec_table[index].NumEraseRegions;
1682         p_cfi->cfiq->DevSize = jedec_table[index].DevSize;
1683         p_cfi->cfi_mode = CFI_MODE_JEDEC;
1684
1685         for (i=0; i<num_erase_regions; i++){
1686                 p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
1687         }
1688         p_cfi->cmdset_priv = NULL;
1689
1690         /* This may be redundant for some cases, but it doesn't hurt */
1691         p_cfi->mfr = jedec_table[index].mfr_id;
1692         p_cfi->id = jedec_table[index].dev_id;
1693
1694         uaddr = finfo_uaddr(&jedec_table[index], p_cfi->device_type);
1695         if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) {
1696                 kfree( p_cfi->cfiq );
1697                 return 0;
1698         }
1699
1700         /* Mask out address bits which are smaller than the device type */
1701         mask = ~(p_cfi->device_type-1);
1702         p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask;
1703         p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask;
1704
1705         return 1;       /* ok */
1706 }
1707
1708
1709 /*
1710  * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing
1711  * the mapped address, unlock addresses, and proper chip ID.  This function
1712  * attempts to minimize errors.  It is doubtfull that this probe will ever
1713  * be perfect - consequently there should be some module parameters that
1714  * could be manually specified to force the chip info.
1715  */
1716 static inline int jedec_match( __u32 base,
1717                                struct map_info *map,
1718                                struct cfi_private *cfi,
1719                                const struct amd_flash_info *finfo )
1720 {
1721         int rc = 0;           /* failure until all tests pass */
1722         u32 mfr, id;
1723         __u8 uaddr;
1724         unsigned long mask;
1725
1726         /*
1727          * The IDs must match.  For X16 and X32 devices operating in
1728          * a lower width ( X8 or X16 ), the device ID's are usually just
1729          * the lower byte(s) of the larger device ID for wider mode.  If
1730          * a part is found that doesn't fit this assumption (device id for
1731          * smaller width mode is completely unrealated to full-width mode)
1732          * then the jedec_table[] will have to be augmented with the IDs
1733          * for different widths.
1734          */
1735         switch (cfi->device_type) {
1736         case CFI_DEVICETYPE_X8:
1737                 mfr = (__u8)finfo->mfr_id;
1738                 id = (__u8)finfo->dev_id;
1739                 break;
1740         case CFI_DEVICETYPE_X16:
1741                 mfr = (__u16)finfo->mfr_id;
1742                 id = (__u16)finfo->dev_id;
1743                 break;
1744         case CFI_DEVICETYPE_X32:
1745                 mfr = (__u16)finfo->mfr_id;
1746                 id = (__u32)finfo->dev_id;
1747                 break;
1748         default:
1749                 printk(KERN_WARNING
1750                        "MTD %s(): Unsupported device type %d\n",
1751                        __func__, cfi->device_type);
1752                 goto match_done;
1753         }
1754         if ( cfi->mfr != mfr || cfi->id != id ) {
1755                 goto match_done;
1756         }
1757
1758         /* the part size must fit in the memory window */
1759         DEBUG( MTD_DEBUG_LEVEL3,
1760                "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
1761                __func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) );
1762         if ( base + cfi->interleave * ( 1 << finfo->DevSize ) > map->size ) {
1763                 DEBUG( MTD_DEBUG_LEVEL3,
1764                        "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
1765                        __func__, finfo->mfr_id, finfo->dev_id,
1766                        1 << finfo->DevSize );
1767                 goto match_done;
1768         }
1769
1770         uaddr = finfo_uaddr(finfo, cfi->device_type);
1771         if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) {
1772                 goto match_done;
1773         }
1774
1775         mask = ~(cfi->device_type-1);
1776
1777         DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
1778                __func__, cfi->addr_unlock1, cfi->addr_unlock2 );
1779         if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
1780              && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 ||
1781                   (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) {
1782                 DEBUG( MTD_DEBUG_LEVEL3,
1783                        "MTD %s(): 0x%.4lx 0x%.4lx did not match\n",
1784                        __func__,
1785                        unlock_addrs[uaddr].addr1 & mask,
1786                        unlock_addrs[uaddr].addr2 & mask);
1787                 goto match_done;
1788         }
1789
1790         /*
1791          * Make sure the ID's dissappear when the device is taken out of
1792          * ID mode.  The only time this should fail when it should succeed
1793          * is when the ID's are written as data to the same
1794          * addresses.  For this rare and unfortunate case the chip
1795          * cannot be probed correctly.
1796          * FIXME - write a driver that takes all of the chip info as
1797          * module parameters, doesn't probe but forces a load.
1798          */
1799         DEBUG( MTD_DEBUG_LEVEL3,
1800                "MTD %s(): check ID's disappear when not in ID mode\n",
1801                __func__ );
1802         jedec_reset( base, map, cfi );
1803         mfr = jedec_read_mfr( map, base, cfi );
1804         id = jedec_read_id( map, base, cfi );
1805         if ( mfr == cfi->mfr && id == cfi->id ) {
1806                 DEBUG( MTD_DEBUG_LEVEL3,
1807                        "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
1808                        "You might need to manually specify JEDEC parameters.\n",
1809                         __func__, cfi->mfr, cfi->id );
1810                 goto match_done;
1811         }
1812
1813         /* all tests passed - mark  as success */
1814         rc = 1;
1815
1816         /*
1817          * Put the device back in ID mode - only need to do this if we
1818          * were truly frobbing a real device.
1819          */
1820         DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
1821         if(cfi->addr_unlock1) {
1822                 cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1823                 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1824         }
1825         cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1826         /* FIXME - should have a delay before continuing */
1827
1828  match_done:    
1829         return rc;
1830 }
1831
1832
1833 static int jedec_probe_chip(struct map_info *map, __u32 base,
1834                             unsigned long *chip_map, struct cfi_private *cfi)
1835 {
1836         int i;
1837         enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
1838
1839  retry:
1840         if (!cfi->numchips) {
1841                 unsigned long mask = ~(cfi->device_type-1);
1842
1843                 uaddr_idx++;
1844
1845                 if (MTD_UADDR_UNNECESSARY == uaddr_idx)
1846                         return 0;
1847
1848                 /* Mask out address bits which are smaller than the device type */
1849                 cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask;
1850                 cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask;
1851         }
1852
1853         /* Make certain we aren't probing past the end of map */
1854         if (base >= map->size) {
1855                 printk(KERN_NOTICE
1856                         "Probe at base(0x%08x) past the end of the map(0x%08lx)\n",
1857                         base, map->size -1);
1858                 return 0;
1859                 
1860         }
1861         if ((base + cfi->addr_unlock1) >= map->size) {
1862                 printk(KERN_NOTICE
1863                         "Probe at addr_unlock1(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
1864                         base, cfi->addr_unlock1, map->size -1);
1865
1866                 return 0;
1867         }
1868         if ((base + cfi->addr_unlock2) >= map->size) {
1869                 printk(KERN_NOTICE
1870                         "Probe at addr_unlock2(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
1871                         base, cfi->addr_unlock2, map->size -1);
1872                 return 0;
1873                 
1874         }
1875
1876         /* Reset */
1877         jedec_reset(base, map, cfi);
1878
1879         /* Autoselect Mode */
1880         if(cfi->addr_unlock1) {
1881                 cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1882                 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1883         }
1884         cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
1885         /* FIXME - should have a delay before continuing */
1886
1887         if (!cfi->numchips) {
1888                 /* This is the first time we're called. Set up the CFI 
1889                    stuff accordingly and return */
1890                 
1891                 cfi->mfr = jedec_read_mfr(map, base, cfi);
1892                 cfi->id = jedec_read_id(map, base, cfi);
1893                 DEBUG(MTD_DEBUG_LEVEL3,
1894                       "Search for id:(%02x %02x) interleave(%d) type(%d)\n", 
1895                         cfi->mfr, cfi->id, cfi->interleave, cfi->device_type);
1896                 for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
1897                         if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
1898                                 DEBUG( MTD_DEBUG_LEVEL3,
1899                                        "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
1900                                        __func__, cfi->mfr, cfi->id,
1901                                        cfi->addr_unlock1, cfi->addr_unlock2 );
1902                                 if (!cfi_jedec_setup(cfi, i))
1903                                         return 0;
1904                                 goto ok_out;
1905                         }
1906                 }
1907                 goto retry;
1908         } else {
1909                 __u16 mfr;
1910                 __u16 id;
1911
1912                 /* Make sure it is a chip of the same manufacturer and id */
1913                 mfr = jedec_read_mfr(map, base, cfi);
1914                 id = jedec_read_id(map, base, cfi);
1915
1916                 if ((mfr != cfi->mfr) || (id != cfi->id)) {
1917                         printk(KERN_DEBUG "%s: Found different chip or no chip at all (mfr 0x%x, id 0x%x) at 0x%x\n",
1918                                map->name, mfr, id, base);
1919                         jedec_reset(base, map, cfi);
1920                         return 0;
1921                 }
1922         }
1923         
1924         /* Check each previous chip locations to see if it's an alias */
1925         for (i=0; i < (base >> cfi->chipshift); i++) {
1926                 unsigned long start;
1927                 if(!test_bit(i, chip_map)) {
1928                         continue; /* Skip location; no valid chip at this address */
1929                 }
1930                 start = i << cfi->chipshift;
1931                 if (jedec_read_mfr(map, start, cfi) == cfi->mfr &&
1932                     jedec_read_id(map, start, cfi) == cfi->id) {
1933                         /* Eep. This chip also looks like it's in autoselect mode.
1934                            Is it an alias for the new one? */
1935                         jedec_reset(start, map, cfi);
1936
1937                         /* If the device IDs go away, it's an alias */
1938                         if (jedec_read_mfr(map, base, cfi) != cfi->mfr ||
1939                             jedec_read_id(map, base, cfi) != cfi->id) {
1940                                 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
1941                                        map->name, base, start);
1942                                 return 0;
1943                         }
1944                         
1945                         /* Yes, it's actually got the device IDs as data. Most
1946                          * unfortunate. Stick the new chip in read mode
1947                          * too and if it's the same, assume it's an alias. */
1948                         /* FIXME: Use other modes to do a proper check */
1949                         jedec_reset(base, map, cfi);
1950                         if (jedec_read_mfr(map, base, cfi) == cfi->mfr &&
1951                             jedec_read_id(map, base, cfi) == cfi->id) {
1952                                 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
1953                                        map->name, base, start);
1954                                 return 0;
1955                         }
1956                 }
1957         }
1958                 
1959         /* OK, if we got to here, then none of the previous chips appear to
1960            be aliases for the current one. */
1961         set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
1962         cfi->numchips++;
1963                 
1964 ok_out:
1965         /* Put it back into Read Mode */
1966         jedec_reset(base, map, cfi);
1967
1968         printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
1969                map->name, cfi->interleave, cfi->device_type*8, base, 
1970                map->bankwidth*8);
1971         
1972         return 1;
1973 }
1974
1975 static struct chip_probe jedec_chip_probe = {
1976         .name = "JEDEC",
1977         .probe_chip = jedec_probe_chip
1978 };
1979
1980 struct mtd_info *jedec_probe(struct map_info *map)
1981 {
1982         /*
1983          * Just use the generic probe stuff to call our CFI-specific
1984          * chip_probe routine in all the possible permutations, etc.
1985          */
1986         return mtd_do_chip_probe(map, &jedec_chip_probe);
1987 }
1988
1989 static struct mtd_chip_driver jedec_chipdrv = {
1990         .probe  = jedec_probe,
1991         .name   = "jedec_probe",
1992         .module = THIS_MODULE
1993 };
1994
1995 int __init jedec_probe_init(void)
1996 {
1997         register_mtd_chip_driver(&jedec_chipdrv);
1998         return 0;
1999 }
2000
2001 static void __exit jedec_probe_exit(void)
2002 {
2003         unregister_mtd_chip_driver(&jedec_chipdrv);
2004 }
2005
2006 module_init(jedec_probe_init);
2007 module_exit(jedec_probe_exit);
2008
2009 MODULE_LICENSE("GPL");
2010 MODULE_AUTHOR("Erwin Authried <eauth@softsys.co.at> et al.");
2011 MODULE_DESCRIPTION("Probe code for JEDEC-compliant flash chips");