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