xref: /OK3568_Linux_fs/u-boot/drivers/mtd/jedec_flash.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2007
3*4882a593Smuzhiyun  * Michael Schwingen, <michael@schwingen.org>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * based in great part on jedec_probe.c from linux kernel:
6*4882a593Smuzhiyun  * (C) 2000 Red Hat. GPL'd.
7*4882a593Smuzhiyun  * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun /* The DEBUG define must be before common to enable debugging */
13*4882a593Smuzhiyun /*#define DEBUG*/
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <common.h>
16*4882a593Smuzhiyun #include <asm/processor.h>
17*4882a593Smuzhiyun #include <asm/io.h>
18*4882a593Smuzhiyun #include <asm/byteorder.h>
19*4882a593Smuzhiyun #include <environment.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define P_ID_AMD_STD CFI_CMDSET_AMD_LEGACY
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun /* AMD */
24*4882a593Smuzhiyun #define AM29DL800BB	0x22CB
25*4882a593Smuzhiyun #define AM29DL800BT	0x224A
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define AM29F400BB	0x22AB
28*4882a593Smuzhiyun #define AM29F800BB	0x2258
29*4882a593Smuzhiyun #define AM29F800BT	0x22D6
30*4882a593Smuzhiyun #define AM29LV400BB	0x22BA
31*4882a593Smuzhiyun #define AM29LV400BT	0x22B9
32*4882a593Smuzhiyun #define AM29LV800BB	0x225B
33*4882a593Smuzhiyun #define AM29LV800BT	0x22DA
34*4882a593Smuzhiyun #define AM29LV160DT	0x22C4
35*4882a593Smuzhiyun #define AM29LV160DB	0x2249
36*4882a593Smuzhiyun #define AM29F017D	0x003D
37*4882a593Smuzhiyun #define AM29F016D	0x00AD
38*4882a593Smuzhiyun #define AM29F080	0x00D5
39*4882a593Smuzhiyun #define AM29F040	0x00A4
40*4882a593Smuzhiyun #define AM29LV040B	0x004F
41*4882a593Smuzhiyun #define AM29F032B	0x0041
42*4882a593Smuzhiyun #define AM29F002T	0x00B0
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /* SST */
45*4882a593Smuzhiyun #define SST39LF800	0x2781
46*4882a593Smuzhiyun #define SST39LF160	0x2782
47*4882a593Smuzhiyun #define SST39VF1601	0x234b
48*4882a593Smuzhiyun #define SST39LF512	0x00D4
49*4882a593Smuzhiyun #define SST39LF010	0x00D5
50*4882a593Smuzhiyun #define SST39LF020	0x00D6
51*4882a593Smuzhiyun #define SST39LF040	0x00D7
52*4882a593Smuzhiyun #define SST39SF010A	0x00B5
53*4882a593Smuzhiyun #define SST39SF020A	0x00B6
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /* STM */
56*4882a593Smuzhiyun #define STM29F400BB	0x00D6
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /* MXIC */
59*4882a593Smuzhiyun #define MX29LV040	0x004F
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /* WINBOND */
62*4882a593Smuzhiyun #define W39L040A	0x00D6
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* AMIC */
65*4882a593Smuzhiyun #define A29L040		0x0092
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /* EON */
68*4882a593Smuzhiyun #define EN29LV040A	0x004F
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun /*
71*4882a593Smuzhiyun  * Unlock address sets for AMD command sets.
72*4882a593Smuzhiyun  * Intel command sets use the MTD_UADDR_UNNECESSARY.
73*4882a593Smuzhiyun  * Each identifier, except MTD_UADDR_UNNECESSARY, and
74*4882a593Smuzhiyun  * MTD_UADDR_NO_SUPPORT must be defined below in unlock_addrs[].
75*4882a593Smuzhiyun  * MTD_UADDR_NOT_SUPPORTED must be 0 so that structure
76*4882a593Smuzhiyun  * initialization need not require initializing all of the
77*4882a593Smuzhiyun  * unlock addresses for all bit widths.
78*4882a593Smuzhiyun  */
79*4882a593Smuzhiyun enum uaddr {
80*4882a593Smuzhiyun 	MTD_UADDR_NOT_SUPPORTED = 0,	/* data width not supported */
81*4882a593Smuzhiyun 	MTD_UADDR_0x0555_0x02AA,
82*4882a593Smuzhiyun 	MTD_UADDR_0x0555_0x0AAA,
83*4882a593Smuzhiyun 	MTD_UADDR_0x5555_0x2AAA,
84*4882a593Smuzhiyun 	MTD_UADDR_0x0AAA_0x0555,
85*4882a593Smuzhiyun 	MTD_UADDR_DONT_CARE,		/* Requires an arbitrary address */
86*4882a593Smuzhiyun 	MTD_UADDR_UNNECESSARY,		/* Does not require any address */
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun struct unlock_addr {
91*4882a593Smuzhiyun 	u32 addr1;
92*4882a593Smuzhiyun 	u32 addr2;
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun /*
97*4882a593Smuzhiyun  * I don't like the fact that the first entry in unlock_addrs[]
98*4882a593Smuzhiyun  * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore,
99*4882a593Smuzhiyun  * should not be used.  The  problem is that structures with
100*4882a593Smuzhiyun  * initializers have extra fields initialized to 0.  It is _very_
101*4882a593Smuzhiyun  * desireable to have the unlock address entries for unsupported
102*4882a593Smuzhiyun  * data widths automatically initialized - that means that
103*4882a593Smuzhiyun  * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here
104*4882a593Smuzhiyun  * must go unused.
105*4882a593Smuzhiyun  */
106*4882a593Smuzhiyun static const struct unlock_addr  unlock_addrs[] = {
107*4882a593Smuzhiyun 	[MTD_UADDR_NOT_SUPPORTED] = {
108*4882a593Smuzhiyun 		.addr1 = 0xffff,
109*4882a593Smuzhiyun 		.addr2 = 0xffff
110*4882a593Smuzhiyun 	},
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	[MTD_UADDR_0x0555_0x02AA] = {
113*4882a593Smuzhiyun 		.addr1 = 0x0555,
114*4882a593Smuzhiyun 		.addr2 = 0x02aa
115*4882a593Smuzhiyun 	},
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	[MTD_UADDR_0x0555_0x0AAA] = {
118*4882a593Smuzhiyun 		.addr1 = 0x0555,
119*4882a593Smuzhiyun 		.addr2 = 0x0aaa
120*4882a593Smuzhiyun 	},
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	[MTD_UADDR_0x5555_0x2AAA] = {
123*4882a593Smuzhiyun 		.addr1 = 0x5555,
124*4882a593Smuzhiyun 		.addr2 = 0x2aaa
125*4882a593Smuzhiyun 	},
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	[MTD_UADDR_0x0AAA_0x0555] = {
128*4882a593Smuzhiyun 		.addr1 = 0x0AAA,
129*4882a593Smuzhiyun 		.addr2 = 0x0555
130*4882a593Smuzhiyun 	},
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	[MTD_UADDR_DONT_CARE] = {
133*4882a593Smuzhiyun 		.addr1 = 0x0000,      /* Doesn't matter which address */
134*4882a593Smuzhiyun 		.addr2 = 0x0000       /* is used - must be last entry */
135*4882a593Smuzhiyun 	},
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	[MTD_UADDR_UNNECESSARY] = {
138*4882a593Smuzhiyun 		.addr1 = 0x0000,
139*4882a593Smuzhiyun 		.addr2 = 0x0000
140*4882a593Smuzhiyun 	}
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun struct amd_flash_info {
145*4882a593Smuzhiyun 	const __u16 mfr_id;
146*4882a593Smuzhiyun 	const __u16 dev_id;
147*4882a593Smuzhiyun 	const char *name;
148*4882a593Smuzhiyun 	const int DevSize;
149*4882a593Smuzhiyun 	const int NumEraseRegions;
150*4882a593Smuzhiyun 	const int CmdSet;
151*4882a593Smuzhiyun 	const __u8 uaddr[4];		/* unlock addrs for 8, 16, 32, 64 */
152*4882a593Smuzhiyun 	const ulong regions[6];
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun #define SIZE_64KiB  16
158*4882a593Smuzhiyun #define SIZE_128KiB 17
159*4882a593Smuzhiyun #define SIZE_256KiB 18
160*4882a593Smuzhiyun #define SIZE_512KiB 19
161*4882a593Smuzhiyun #define SIZE_1MiB   20
162*4882a593Smuzhiyun #define SIZE_2MiB   21
163*4882a593Smuzhiyun #define SIZE_4MiB   22
164*4882a593Smuzhiyun #define SIZE_8MiB   23
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun static const struct amd_flash_info jedec_table[] = {
167*4882a593Smuzhiyun #ifdef CONFIG_SYS_FLASH_LEGACY_256Kx8
168*4882a593Smuzhiyun 	{
169*4882a593Smuzhiyun 		.mfr_id		= (u16)SST_MANUFACT,
170*4882a593Smuzhiyun 		.dev_id		= SST39LF020,
171*4882a593Smuzhiyun 		.name		= "SST 39LF020",
172*4882a593Smuzhiyun 		.uaddr		= {
173*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
174*4882a593Smuzhiyun 		},
175*4882a593Smuzhiyun 		.DevSize	= SIZE_256KiB,
176*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
177*4882a593Smuzhiyun 		.NumEraseRegions= 1,
178*4882a593Smuzhiyun 		.regions	= {
179*4882a593Smuzhiyun 			ERASEINFO(0x01000,64),
180*4882a593Smuzhiyun 		}
181*4882a593Smuzhiyun 	},
182*4882a593Smuzhiyun #endif
183*4882a593Smuzhiyun #ifdef CONFIG_SYS_FLASH_LEGACY_512Kx8
184*4882a593Smuzhiyun 	{
185*4882a593Smuzhiyun 		.mfr_id		= (u16)AMD_MANUFACT,
186*4882a593Smuzhiyun 		.dev_id		= AM29LV040B,
187*4882a593Smuzhiyun 		.name		= "AMD AM29LV040B",
188*4882a593Smuzhiyun 		.uaddr		= {
189*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
190*4882a593Smuzhiyun 		},
191*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
192*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
193*4882a593Smuzhiyun 		.NumEraseRegions= 1,
194*4882a593Smuzhiyun 		.regions	= {
195*4882a593Smuzhiyun 			ERASEINFO(0x10000,8),
196*4882a593Smuzhiyun 		}
197*4882a593Smuzhiyun 	},
198*4882a593Smuzhiyun 	{
199*4882a593Smuzhiyun 		.mfr_id		= (u16)SST_MANUFACT,
200*4882a593Smuzhiyun 		.dev_id		= SST39LF040,
201*4882a593Smuzhiyun 		.name		= "SST 39LF040",
202*4882a593Smuzhiyun 		.uaddr		= {
203*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
204*4882a593Smuzhiyun 		},
205*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
206*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
207*4882a593Smuzhiyun 		.NumEraseRegions= 1,
208*4882a593Smuzhiyun 		.regions	= {
209*4882a593Smuzhiyun 			ERASEINFO(0x01000,128),
210*4882a593Smuzhiyun 		}
211*4882a593Smuzhiyun 	},
212*4882a593Smuzhiyun 	{
213*4882a593Smuzhiyun 		.mfr_id		= (u16)STM_MANUFACT,
214*4882a593Smuzhiyun 		.dev_id		= STM_ID_M29W040B,
215*4882a593Smuzhiyun 		.name		= "ST Micro M29W040B",
216*4882a593Smuzhiyun 		.uaddr		= {
217*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
218*4882a593Smuzhiyun 		},
219*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
220*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
221*4882a593Smuzhiyun 		.NumEraseRegions= 1,
222*4882a593Smuzhiyun 		.regions	= {
223*4882a593Smuzhiyun 			ERASEINFO(0x10000,8),
224*4882a593Smuzhiyun 		}
225*4882a593Smuzhiyun 	},
226*4882a593Smuzhiyun 	{
227*4882a593Smuzhiyun 		.mfr_id		= (u16)MX_MANUFACT,
228*4882a593Smuzhiyun 		.dev_id		= MX29LV040,
229*4882a593Smuzhiyun 		.name		= "MXIC MX29LV040",
230*4882a593Smuzhiyun 		.uaddr		= {
231*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
232*4882a593Smuzhiyun 		},
233*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
234*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
235*4882a593Smuzhiyun 		.NumEraseRegions= 1,
236*4882a593Smuzhiyun 		.regions	= {
237*4882a593Smuzhiyun 			ERASEINFO(0x10000, 8),
238*4882a593Smuzhiyun 		}
239*4882a593Smuzhiyun 	},
240*4882a593Smuzhiyun 	{
241*4882a593Smuzhiyun 		.mfr_id		= (u16)WINB_MANUFACT,
242*4882a593Smuzhiyun 		.dev_id		= W39L040A,
243*4882a593Smuzhiyun 		.name		= "WINBOND W39L040A",
244*4882a593Smuzhiyun 		.uaddr		= {
245*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
246*4882a593Smuzhiyun 		},
247*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
248*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
249*4882a593Smuzhiyun 		.NumEraseRegions= 1,
250*4882a593Smuzhiyun 		.regions	= {
251*4882a593Smuzhiyun 			ERASEINFO(0x10000, 8),
252*4882a593Smuzhiyun 		}
253*4882a593Smuzhiyun 	},
254*4882a593Smuzhiyun 	{
255*4882a593Smuzhiyun 		.mfr_id		= (u16)AMIC_MANUFACT,
256*4882a593Smuzhiyun 		.dev_id		= A29L040,
257*4882a593Smuzhiyun 		.name		= "AMIC A29L040",
258*4882a593Smuzhiyun 		.uaddr		= {
259*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
260*4882a593Smuzhiyun 		},
261*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
262*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
263*4882a593Smuzhiyun 		.NumEraseRegions= 1,
264*4882a593Smuzhiyun 		.regions	= {
265*4882a593Smuzhiyun 			ERASEINFO(0x10000, 8),
266*4882a593Smuzhiyun 		}
267*4882a593Smuzhiyun 	},
268*4882a593Smuzhiyun 	{
269*4882a593Smuzhiyun 		.mfr_id		= (u16)EON_MANUFACT,
270*4882a593Smuzhiyun 		.dev_id		= EN29LV040A,
271*4882a593Smuzhiyun 		.name		= "EON EN29LV040A",
272*4882a593Smuzhiyun 		.uaddr		= {
273*4882a593Smuzhiyun 			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
274*4882a593Smuzhiyun 		},
275*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
276*4882a593Smuzhiyun 		.CmdSet		= P_ID_AMD_STD,
277*4882a593Smuzhiyun 		.NumEraseRegions= 1,
278*4882a593Smuzhiyun 		.regions	= {
279*4882a593Smuzhiyun 			ERASEINFO(0x10000, 8),
280*4882a593Smuzhiyun 		}
281*4882a593Smuzhiyun 	},
282*4882a593Smuzhiyun #endif
283*4882a593Smuzhiyun #ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
284*4882a593Smuzhiyun 	{
285*4882a593Smuzhiyun 		.mfr_id		= (u16)AMD_MANUFACT,
286*4882a593Smuzhiyun 		.dev_id		= AM29F400BB,
287*4882a593Smuzhiyun 		.name		= "AMD AM29F400BB",
288*4882a593Smuzhiyun 		.uaddr		= {
289*4882a593Smuzhiyun 			[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
290*4882a593Smuzhiyun 		},
291*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
292*4882a593Smuzhiyun 		.CmdSet		= CFI_CMDSET_AMD_LEGACY,
293*4882a593Smuzhiyun 		.NumEraseRegions= 4,
294*4882a593Smuzhiyun 		.regions	= {
295*4882a593Smuzhiyun 			ERASEINFO(0x04000, 1),
296*4882a593Smuzhiyun 			ERASEINFO(0x02000, 2),
297*4882a593Smuzhiyun 			ERASEINFO(0x08000, 1),
298*4882a593Smuzhiyun 			ERASEINFO(0x10000, 7),
299*4882a593Smuzhiyun 		}
300*4882a593Smuzhiyun 	},
301*4882a593Smuzhiyun 	{
302*4882a593Smuzhiyun 		.mfr_id		= (u16)AMD_MANUFACT,
303*4882a593Smuzhiyun 		.dev_id		= AM29LV400BB,
304*4882a593Smuzhiyun 		.name		= "AMD AM29LV400BB",
305*4882a593Smuzhiyun 		.uaddr		= {
306*4882a593Smuzhiyun 			[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
307*4882a593Smuzhiyun 		},
308*4882a593Smuzhiyun 		.DevSize	= SIZE_512KiB,
309*4882a593Smuzhiyun 		.CmdSet		= CFI_CMDSET_AMD_LEGACY,
310*4882a593Smuzhiyun 		.NumEraseRegions= 4,
311*4882a593Smuzhiyun 		.regions	= {
312*4882a593Smuzhiyun 			ERASEINFO(0x04000,1),
313*4882a593Smuzhiyun 			ERASEINFO(0x02000,2),
314*4882a593Smuzhiyun 			ERASEINFO(0x08000,1),
315*4882a593Smuzhiyun 			ERASEINFO(0x10000,7),
316*4882a593Smuzhiyun 		}
317*4882a593Smuzhiyun 	},
318*4882a593Smuzhiyun 	{
319*4882a593Smuzhiyun 		.mfr_id		= (u16)AMD_MANUFACT,
320*4882a593Smuzhiyun 		.dev_id		= AM29LV800BB,
321*4882a593Smuzhiyun 		.name		= "AMD AM29LV800BB",
322*4882a593Smuzhiyun 		.uaddr		= {
323*4882a593Smuzhiyun 			[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
324*4882a593Smuzhiyun 		},
325*4882a593Smuzhiyun 		.DevSize	= SIZE_1MiB,
326*4882a593Smuzhiyun 		.CmdSet		= CFI_CMDSET_AMD_LEGACY,
327*4882a593Smuzhiyun 		.NumEraseRegions= 4,
328*4882a593Smuzhiyun 		.regions	= {
329*4882a593Smuzhiyun 			ERASEINFO(0x04000, 1),
330*4882a593Smuzhiyun 			ERASEINFO(0x02000, 2),
331*4882a593Smuzhiyun 			ERASEINFO(0x08000, 1),
332*4882a593Smuzhiyun 			ERASEINFO(0x10000, 15),
333*4882a593Smuzhiyun 		}
334*4882a593Smuzhiyun 	},
335*4882a593Smuzhiyun 	{
336*4882a593Smuzhiyun 		.mfr_id		= (u16)AMD_MANUFACT,
337*4882a593Smuzhiyun 		.dev_id		= AM29LV800BT,
338*4882a593Smuzhiyun 		.name		= "AMD AM29LV800BT",
339*4882a593Smuzhiyun 		.uaddr		= {
340*4882a593Smuzhiyun 			[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
341*4882a593Smuzhiyun 		},
342*4882a593Smuzhiyun 		.DevSize	= SIZE_1MiB,
343*4882a593Smuzhiyun 		.CmdSet		= CFI_CMDSET_AMD_LEGACY,
344*4882a593Smuzhiyun 		.NumEraseRegions= 4,
345*4882a593Smuzhiyun 		.regions	= {
346*4882a593Smuzhiyun 			ERASEINFO(0x10000, 15),
347*4882a593Smuzhiyun 			ERASEINFO(0x08000, 1),
348*4882a593Smuzhiyun 			ERASEINFO(0x02000, 2),
349*4882a593Smuzhiyun 			ERASEINFO(0x04000, 1),
350*4882a593Smuzhiyun 		}
351*4882a593Smuzhiyun 	},
352*4882a593Smuzhiyun 	{
353*4882a593Smuzhiyun 		.mfr_id		= (u16)MX_MANUFACT,
354*4882a593Smuzhiyun 		.dev_id		= AM29LV800BT,
355*4882a593Smuzhiyun 		.name		= "MXIC MX29LV800BT",
356*4882a593Smuzhiyun 		.uaddr		= {
357*4882a593Smuzhiyun 			[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
358*4882a593Smuzhiyun 		},
359*4882a593Smuzhiyun 		.DevSize	= SIZE_1MiB,
360*4882a593Smuzhiyun 		.CmdSet		= CFI_CMDSET_AMD_LEGACY,
361*4882a593Smuzhiyun 		.NumEraseRegions= 4,
362*4882a593Smuzhiyun 		.regions	= {
363*4882a593Smuzhiyun 			ERASEINFO(0x10000, 15),
364*4882a593Smuzhiyun 			ERASEINFO(0x08000, 1),
365*4882a593Smuzhiyun 			ERASEINFO(0x02000, 2),
366*4882a593Smuzhiyun 			ERASEINFO(0x04000, 1),
367*4882a593Smuzhiyun 		}
368*4882a593Smuzhiyun 	},
369*4882a593Smuzhiyun 	{
370*4882a593Smuzhiyun 		.mfr_id		= (u16)EON_ALT_MANU,
371*4882a593Smuzhiyun 		.dev_id		= AM29LV800BT,
372*4882a593Smuzhiyun 		.name		= "EON EN29LV800BT",
373*4882a593Smuzhiyun 		.uaddr		= {
374*4882a593Smuzhiyun 			[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
375*4882a593Smuzhiyun 		},
376*4882a593Smuzhiyun 		.DevSize	= SIZE_1MiB,
377*4882a593Smuzhiyun 		.CmdSet		= CFI_CMDSET_AMD_LEGACY,
378*4882a593Smuzhiyun 		.NumEraseRegions= 4,
379*4882a593Smuzhiyun 		.regions	= {
380*4882a593Smuzhiyun 			ERASEINFO(0x10000, 15),
381*4882a593Smuzhiyun 			ERASEINFO(0x08000, 1),
382*4882a593Smuzhiyun 			ERASEINFO(0x02000, 2),
383*4882a593Smuzhiyun 			ERASEINFO(0x04000, 1),
384*4882a593Smuzhiyun 		}
385*4882a593Smuzhiyun 	},
386*4882a593Smuzhiyun 	{
387*4882a593Smuzhiyun 		.mfr_id		= (u16)STM_MANUFACT,
388*4882a593Smuzhiyun 		.dev_id		= STM29F400BB,
389*4882a593Smuzhiyun 		.name		= "ST Micro M29F400BB",
390*4882a593Smuzhiyun 		.uaddr		= {
391*4882a593Smuzhiyun 			[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
392*4882a593Smuzhiyun 		},
393*4882a593Smuzhiyun 		.DevSize		= SIZE_512KiB,
394*4882a593Smuzhiyun 		.CmdSet			= CFI_CMDSET_AMD_LEGACY,
395*4882a593Smuzhiyun 		.NumEraseRegions	= 4,
396*4882a593Smuzhiyun 		.regions		= {
397*4882a593Smuzhiyun 			ERASEINFO(0x04000, 1),
398*4882a593Smuzhiyun 			ERASEINFO(0x02000, 2),
399*4882a593Smuzhiyun 			ERASEINFO(0x08000, 1),
400*4882a593Smuzhiyun 			ERASEINFO(0x10000, 7),
401*4882a593Smuzhiyun 		}
402*4882a593Smuzhiyun 	},
403*4882a593Smuzhiyun #endif
404*4882a593Smuzhiyun };
405*4882a593Smuzhiyun 
fill_info(flash_info_t * info,const struct amd_flash_info * jedec_entry,ulong base)406*4882a593Smuzhiyun static inline void fill_info(flash_info_t *info, const struct amd_flash_info *jedec_entry, ulong base)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	int i,j;
409*4882a593Smuzhiyun 	int sect_cnt;
410*4882a593Smuzhiyun 	int size_ratio;
411*4882a593Smuzhiyun 	int total_size;
412*4882a593Smuzhiyun 	enum uaddr uaddr_idx;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	size_ratio = info->portwidth / info->chipwidth;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	debug("Found JEDEC Flash: %s\n", jedec_entry->name);
417*4882a593Smuzhiyun 	info->vendor = jedec_entry->CmdSet;
418*4882a593Smuzhiyun 	/* Todo: do we need device-specific timeouts? */
419*4882a593Smuzhiyun 	info->erase_blk_tout = 30000;
420*4882a593Smuzhiyun 	info->buffer_write_tout = 1000;
421*4882a593Smuzhiyun 	info->write_tout = 100;
422*4882a593Smuzhiyun 	info->name = jedec_entry->name;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	/* copy unlock addresses from device table to CFI info struct. This
425*4882a593Smuzhiyun 	   is just here because the addresses are in the table anyway - if
426*4882a593Smuzhiyun 	   the flash is not detected due to wrong unlock addresses,
427*4882a593Smuzhiyun 	   flash_detect_legacy would have to try all of them before we even
428*4882a593Smuzhiyun 	   get here. */
429*4882a593Smuzhiyun 	switch(info->chipwidth) {
430*4882a593Smuzhiyun 	case FLASH_CFI_8BIT:
431*4882a593Smuzhiyun 		uaddr_idx = jedec_entry->uaddr[0];
432*4882a593Smuzhiyun 		break;
433*4882a593Smuzhiyun 	case FLASH_CFI_16BIT:
434*4882a593Smuzhiyun 		uaddr_idx = jedec_entry->uaddr[1];
435*4882a593Smuzhiyun 		break;
436*4882a593Smuzhiyun 	case FLASH_CFI_32BIT:
437*4882a593Smuzhiyun 		uaddr_idx = jedec_entry->uaddr[2];
438*4882a593Smuzhiyun 		break;
439*4882a593Smuzhiyun 	default:
440*4882a593Smuzhiyun 		uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
441*4882a593Smuzhiyun 		break;
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	debug("unlock address index %d\n", uaddr_idx);
445*4882a593Smuzhiyun 	info->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
446*4882a593Smuzhiyun 	info->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
447*4882a593Smuzhiyun 	debug("unlock addresses are 0x%lx/0x%lx\n",
448*4882a593Smuzhiyun 		info->addr_unlock1, info->addr_unlock2);
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	sect_cnt = 0;
451*4882a593Smuzhiyun 	total_size = 0;
452*4882a593Smuzhiyun 	for (i = 0; i < jedec_entry->NumEraseRegions; i++) {
453*4882a593Smuzhiyun 		ulong erase_region_size = jedec_entry->regions[i] >> 8;
454*4882a593Smuzhiyun 		ulong erase_region_count = (jedec_entry->regions[i] & 0xff) + 1;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 		total_size += erase_region_size * erase_region_count;
457*4882a593Smuzhiyun 		debug("erase_region_count = %ld erase_region_size = %ld\n",
458*4882a593Smuzhiyun 		       erase_region_count, erase_region_size);
459*4882a593Smuzhiyun 		for (j = 0; j < erase_region_count; j++) {
460*4882a593Smuzhiyun 			if (sect_cnt >= CONFIG_SYS_MAX_FLASH_SECT) {
461*4882a593Smuzhiyun 				printf("ERROR: too many flash sectors\n");
462*4882a593Smuzhiyun 				break;
463*4882a593Smuzhiyun 			}
464*4882a593Smuzhiyun 			info->start[sect_cnt] = base;
465*4882a593Smuzhiyun 			base += (erase_region_size * size_ratio);
466*4882a593Smuzhiyun 			sect_cnt++;
467*4882a593Smuzhiyun 		}
468*4882a593Smuzhiyun 	}
469*4882a593Smuzhiyun 	info->sector_count = sect_cnt;
470*4882a593Smuzhiyun 	info->size = total_size * size_ratio;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun /*-----------------------------------------------------------------------
474*4882a593Smuzhiyun  * match jedec ids against table. If a match is found, fill flash_info entry
475*4882a593Smuzhiyun  */
jedec_flash_match(flash_info_t * info,ulong base)476*4882a593Smuzhiyun int jedec_flash_match(flash_info_t *info, ulong base)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun 	int ret = 0;
479*4882a593Smuzhiyun 	int i;
480*4882a593Smuzhiyun 	ulong mask = 0xFFFF;
481*4882a593Smuzhiyun 	if (info->chipwidth == 1)
482*4882a593Smuzhiyun 		mask = 0xFF;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
485*4882a593Smuzhiyun 		if ((jedec_table[i].mfr_id & mask) == (info->manufacturer_id & mask) &&
486*4882a593Smuzhiyun 		    (jedec_table[i].dev_id & mask) == (info->device_id & mask)) {
487*4882a593Smuzhiyun 			fill_info(info, &jedec_table[i], base);
488*4882a593Smuzhiyun 			ret = 1;
489*4882a593Smuzhiyun 			break;
490*4882a593Smuzhiyun 		}
491*4882a593Smuzhiyun 	}
492*4882a593Smuzhiyun 	return ret;
493*4882a593Smuzhiyun }
494