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