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