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