1
2
3
4
5
6
7
8#include <common.h>
9
10#ifndef CONFIG_FLASH_CFI_DRIVER
11flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
12
13
14
15
16#ifdef CONFIG_FLASH_16BIT
17typedef unsigned short FLASH_PORT_WIDTH;
18typedef volatile unsigned short FLASH_PORT_WIDTHV;
19#define FLASH_ID_MASK 0xFFFF
20#else
21typedef unsigned char FLASH_PORT_WIDTH;
22typedef volatile unsigned char FLASH_PORT_WIDTHV;
23#define FLASH_ID_MASK 0xFF
24#endif
25
26#define FPW FLASH_PORT_WIDTH
27#define FPWV FLASH_PORT_WIDTHV
28
29#define ORMASK(size) ((-size) & OR_AM_MSK)
30
31#define FLASH_CYCLE1 0x0555
32#define FLASH_CYCLE2 0x02aa
33
34
35
36
37static ulong flash_get_size(FPWV *addr, flash_info_t *info);
38static void flash_reset(flash_info_t *info);
39static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
40static flash_info_t *flash_get_info(ulong base);
41
42
43
44
45
46
47unsigned long flash_init (void)
48{
49 unsigned long size = 0;
50 int i;
51 extern void flash_preinit(void);
52 extern void flash_afterinit(ulong);
53 ulong flashbase = CONFIG_SYS_FLASH_BASE;
54
55 flash_preinit();
56
57
58 for (i=0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
59 memset(&flash_info[i], 0, sizeof(flash_info_t));
60
61 flash_info[i].size =
62 flash_get_size((FPW *)flashbase, &flash_info[i]);
63
64 size += flash_info[i].size;
65 flashbase += 0x800000;
66 }
67#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
68
69 flash_protect(FLAG_PROTECT_SET,
70 CONFIG_SYS_MONITOR_BASE,
71 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
72 flash_get_info(CONFIG_SYS_MONITOR_BASE));
73#endif
74
75#ifdef CONFIG_ENV_IS_IN_FLASH
76
77 flash_protect(FLAG_PROTECT_SET,
78 CONFIG_ENV_ADDR,
79 CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
80 flash_get_info(CONFIG_ENV_ADDR));
81#endif
82
83
84 flash_afterinit(size);
85 return size ? size : 1;
86}
87
88
89
90static void flash_reset(flash_info_t *info)
91{
92 FPWV *base = (FPWV *)(info->start[0]);
93
94
95 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
96 *base = (FPW)0x00FF00FF;
97 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
98 *base = (FPW)0x00F000F0;
99}
100
101
102
103
104static flash_info_t *flash_get_info(ulong base)
105{
106 int i;
107 flash_info_t * info;
108
109 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
110 info = & flash_info[i];
111 if (info->size &&
112 info->start[0] <= base && base <= info->start[0] + info->size - 1)
113 break;
114 }
115
116 return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
117}
118
119
120
121
122void flash_print_info (flash_info_t *info)
123{
124 int i;
125 uchar *boottype;
126 uchar *bootletter;
127 char *fmt;
128 uchar botbootletter[] = "B";
129 uchar topbootletter[] = "T";
130 uchar botboottype[] = "bottom boot sector";
131 uchar topboottype[] = "top boot sector";
132
133 if (info->flash_id == FLASH_UNKNOWN) {
134 printf ("missing or unknown FLASH type\n");
135 return;
136 }
137
138 switch (info->flash_id & FLASH_VENDMASK) {
139 case FLASH_MAN_AMD: printf ("AMD "); break;
140 case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break;
141 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
142 case FLASH_MAN_SST: printf ("SST "); break;
143 case FLASH_MAN_STM: printf ("STM "); break;
144 case FLASH_MAN_INTEL: printf ("INTEL "); break;
145 default: printf ("Unknown Vendor "); break;
146 }
147
148
149 if (info->flash_id & FLASH_BTYPE) {
150 boottype = botboottype;
151 bootletter = botbootletter;
152 }
153 else {
154 boottype = topboottype;
155 bootletter = topbootletter;
156 }
157
158 switch (info->flash_id & FLASH_TYPEMASK) {
159 case FLASH_AMDLV065D:
160 fmt = "29LV065 (64 Mbit, uniform sectors)\n";
161 break;
162 default:
163 fmt = "Unknown Chip Type\n";
164 break;
165 }
166
167 printf (fmt, bootletter, boottype);
168
169 printf (" Size: %ld MB in %d Sectors\n",
170 info->size >> 20,
171 info->sector_count);
172
173 printf (" Sector Start Addresses:");
174
175 for (i=0; i<info->sector_count; ++i) {
176 if ((i % 5) == 0) {
177 printf ("\n ");
178 }
179
180 printf (" %08lX%s", info->start[i],
181 info->protect[i] ? " (RO)" : " ");
182 }
183
184 printf ("\n");
185}
186
187
188
189
190
191
192
193
194ulong flash_get_size (FPWV *addr, flash_info_t *info)
195{
196 int i;
197 FPWV* addr2;
198
199
200
201 addr[FLASH_CYCLE1] = (FPW)0x00AA00AA;
202 addr[FLASH_CYCLE2] = (FPW)0x00550055;
203 addr[FLASH_CYCLE1] = (FPW)0x00900090;
204
205
206
207
208 udelay(100);
209 switch (addr[0] & 0xff) {
210
211 case (uchar)AMD_MANUFACT:
212 info->flash_id = FLASH_MAN_AMD;
213 break;
214
215 case (uchar)INTEL_MANUFACT:
216 info->flash_id = FLASH_MAN_INTEL;
217 break;
218
219 default:
220 info->flash_id = FLASH_UNKNOWN;
221 info->sector_count = 0;
222 info->size = 0;
223 break;
224 }
225
226
227 if (info->flash_id != FLASH_UNKNOWN) switch ((FPW)addr[1]) {
228
229 case (FPW)AMD_ID_LV065D:
230 info->flash_id += FLASH_AMDLV065D;
231 info->sector_count = 128;
232 info->size = 0x00800000;
233 for( i = 0; i < info->sector_count; i++ )
234 info->start[i] = (ulong)addr + (i * 0x10000);
235 break;
236
237 default:
238 info->flash_id = FLASH_UNKNOWN;
239 info->sector_count = 0;
240 info->size = 0;
241 return (0);
242 }
243
244
245 addr2 = (FPW *)((ulong)addr | 0x800000);
246 if (addr2 != addr &&
247 ((addr2[0] & 0xff) == (addr[0] & 0xff)) && ((FPW)addr2[1] == (FPW)addr[1])) {
248
249
250
251 info->flash_id = FLASH_UNKNOWN;
252 info->sector_count = 0;
253 info->size = 0;
254 }
255
256 flash_reset(info);
257
258 return (info->size);
259}
260
261
262
263
264int flash_erase (flash_info_t *info, int s_first, int s_last)
265{
266 FPWV *addr;
267 int flag, prot, sect;
268 int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
269 ulong start, now, last;
270 int rcode = 0;
271
272 if ((s_first < 0) || (s_first > s_last)) {
273 if (info->flash_id == FLASH_UNKNOWN) {
274 printf ("- missing\n");
275 } else {
276 printf ("- no sectors to erase\n");
277 }
278 return 1;
279 }
280
281 switch (info->flash_id & FLASH_TYPEMASK) {
282 case FLASH_AMDLV065D:
283 break;
284 case FLASH_UNKNOWN:
285 default:
286 printf ("Can't erase unknown flash type %08lx - aborted\n",
287 info->flash_id);
288 return 1;
289 }
290
291 prot = 0;
292 for (sect=s_first; sect<=s_last; ++sect) {
293 if (info->protect[sect]) {
294 prot++;
295 }
296 }
297
298 if (prot) {
299 printf ("- Warning: %d protected sectors will not be erased!\n",
300 prot);
301 } else {
302 printf ("\n");
303 }
304
305 last = get_timer(0);
306
307
308 for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
309
310 if (info->protect[sect] != 0)
311 continue;
312
313
314 flag = disable_interrupts();
315
316 addr = (FPWV *)(info->start[sect]);
317 if (intel) {
318 *addr = (FPW)0x00500050;
319 *addr = (FPW)0x00200020;
320 *addr = (FPW)0x00D000D0;
321 }
322 else {
323
324 FPWV *base;
325
326 base = (FPWV *)(info->start[0]);
327 base[FLASH_CYCLE1] = (FPW)0x00AA00AA;
328 base[FLASH_CYCLE2] = (FPW)0x00550055;
329 base[FLASH_CYCLE1] = (FPW)0x00800080;
330 base[FLASH_CYCLE1] = (FPW)0x00AA00AA;
331 base[FLASH_CYCLE2] = (FPW)0x00550055;
332 *addr = (FPW)0x00300030;
333 }
334
335
336 if (flag)
337 enable_interrupts();
338
339 start = get_timer(0);
340
341
342
343
344 udelay (1000);
345
346 while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
347 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
348 printf ("Timeout\n");
349
350 if (intel) {
351
352 *addr = (FPW)0x00B000B0;
353 }
354
355 flash_reset(info);
356 rcode = 1;
357 break;
358 }
359
360
361 if ((get_timer(last)) > CONFIG_SYS_HZ) {
362 putc ('.');
363 last = get_timer(0);
364 }
365 }
366
367
368 if ((get_timer(last)) > CONFIG_SYS_HZ) {
369 putc ('.');
370 last = get_timer(0);
371 }
372
373 flash_reset(info);
374 }
375
376 printf (" done\n");
377 return rcode;
378}
379
380
381
382
383
384
385
386int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
387{
388 FPW data = 0;
389 int bytes;
390 int left;
391 int i, res;
392
393 for (left = cnt, res = 0;
394 left > 0 && res == 0;
395 addr += sizeof(data), left -= sizeof(data) - bytes) {
396
397 bytes = addr & (sizeof(data) - 1);
398 addr &= ~(sizeof(data) - 1);
399
400
401
402
403 for (i = 0; i < sizeof(data); i++) {
404 data <<= 8;
405 if (i < bytes || i - bytes >= left )
406 data += *((uchar *)addr + i);
407 else
408 data += *src++;
409 }
410
411
412 switch (info->flash_id & FLASH_VENDMASK) {
413 case FLASH_MAN_AMD:
414 res = write_word_amd(info, (FPWV *)addr, data);
415 break;
416 default:
417
418 printf ("missing or unknown FLASH type\n");
419 res = 1;
420 break;
421 }
422 }
423
424 return (res);
425}
426
427
428
429
430
431
432
433
434
435
436
437static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
438{
439 ulong start;
440 int flag;
441 int res = 0;
442 FPWV *base;
443
444
445 if ((*dest & data) != data) {
446 return (2);
447 }
448
449
450 base = (FPWV *)(info->start[0]);
451
452
453 flag = disable_interrupts();
454
455 base[FLASH_CYCLE1] = (FPW)0x00AA00AA;
456 base[FLASH_CYCLE2] = (FPW)0x00550055;
457 base[FLASH_CYCLE1] = (FPW)0x00A000A0;
458
459 *dest = data;
460
461
462 if (flag)
463 enable_interrupts();
464
465 start = get_timer (0);
466
467
468 while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
469 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
470 *dest = (FPW)0x00F000F0;
471 res = 1;
472 }
473 }
474
475 return (res);
476}
477#endif
478