1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <common.h>
25#include <configs/sacsng.h>
26
27
28#undef DEBUG
29
30#ifndef CONFIG_ENV_ADDR
31#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
32#endif
33#ifndef CONFIG_ENV_SIZE
34#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
35#endif
36
37
38flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
39
40
41
42
43static ulong flash_get_size (vu_short *addr, flash_info_t *info);
44static int write_word (flash_info_t *info, ulong dest, ulong data);
45
46
47
48
49unsigned long flash_init (void)
50{
51 unsigned long size_b0, size_b1;
52 int i;
53
54
55 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
56 flash_info[i].flash_id = FLASH_UNKNOWN;
57 }
58
59 size_b0 = flash_get_size((vu_short *)CONFIG_SYS_FLASH0_BASE, &flash_info[0]);
60
61 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
62 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
63 size_b0, size_b0<<20);
64 }
65
66 size_b1 = flash_get_size((vu_short *)CONFIG_SYS_FLASH1_BASE, &flash_info[1]);
67
68#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
69
70 flash_protect(FLAG_PROTECT_SET,
71 CONFIG_SYS_MONITOR_BASE,
72 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
73 &flash_info[0]);
74#endif
75
76#ifdef CONFIG_ENV_IS_IN_FLASH
77
78 flash_protect(FLAG_PROTECT_SET,
79 CONFIG_ENV_ADDR,
80 CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
81 &flash_info[0]);
82#endif
83
84 if (size_b1) {
85#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
86
87 flash_protect(FLAG_PROTECT_SET,
88 CONFIG_SYS_MONITOR_BASE,
89 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
90 &flash_info[1]);
91#endif
92
93#ifdef CONFIG_ENV_IS_IN_FLASH
94
95 flash_protect(FLAG_PROTECT_SET,
96 CONFIG_ENV_ADDR,
97 CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
98 &flash_info[1]);
99#endif
100 } else {
101 flash_info[1].flash_id = FLASH_UNKNOWN;
102 flash_info[1].sector_count = -1;
103 }
104
105 flash_info[0].size = size_b0;
106 flash_info[1].size = size_b1;
107
108
109
110
111 return (size_b0);
112}
113
114
115
116void flash_print_info (flash_info_t *info)
117{
118 int i;
119
120 if (info->flash_id == FLASH_UNKNOWN) {
121 printf ("missing or unknown FLASH type\n");
122 return;
123 }
124
125 switch (info->flash_id & FLASH_VENDMASK) {
126 case FLASH_MAN_AMD: printf ("AMD "); break;
127 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
128 default: printf ("Unknown Vendor "); break;
129 }
130
131 switch (info->flash_id & FLASH_TYPEMASK) {
132 case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
133 break;
134 case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
135 break;
136 case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
137 break;
138 case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
139 break;
140 case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
141 break;
142 case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
143 break;
144 case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
145 break;
146 case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
147 break;
148 default: printf ("Unknown Chip Type\n");
149 break;
150 }
151
152 printf (" Size: %ld MB in %d Sectors\n",
153 info->size >> 20, info->sector_count);
154
155 printf (" Sector Start Addresses:");
156 for (i=0; i<info->sector_count; ++i) {
157 if ((i % 5) == 0)
158 printf ("\n ");
159 printf (" %08lX%s",
160 info->start[i],
161 info->protect[i] ? " (RO)" : " "
162 );
163 }
164 printf ("\n");
165 return;
166}
167
168
169
170
171
172
173
174
175
176
177
178
179static ulong flash_get_size (vu_short *addr, flash_info_t *info)
180{
181 short i;
182 ushort value;
183 ulong base = (ulong)addr;
184
185
186 addr[0x0555] = 0xAAAA;
187 addr[0x02AA] = 0x5555;
188 addr[0x0555] = 0x9090;
189 __asm__ __volatile__(" sync\n ");
190
191 value = addr[0];
192#ifdef DEBUG
193 printf("Flash manufacturer 0x%04X\n", value);
194#endif
195
196 if(value == (ushort)AMD_MANUFACT) {
197 info->flash_id = FLASH_MAN_AMD;
198 } else if (value == (ushort)FUJ_MANUFACT) {
199 info->flash_id = FLASH_MAN_FUJ;
200 } else {
201#ifdef DEBUG
202 printf("Unknown flash manufacturer 0x%04X\n", value);
203#endif
204 info->flash_id = FLASH_UNKNOWN;
205 info->sector_count = 0;
206 info->size = 0;
207 return (0);
208 }
209
210 value = addr[1];
211#ifdef DEBUG
212 printf("Flash type 0x%04X\n", value);
213#endif
214
215 if(value == (ushort)AMD_ID_LV400T) {
216 info->flash_id += FLASH_AM400T;
217 info->sector_count = 11;
218 info->size = 0x00080000;
219 } else if(value == (ushort)AMD_ID_LV400B) {
220 info->flash_id += FLASH_AM400B;
221 info->sector_count = 11;
222 info->size = 0x00080000;
223 } else if(value == (ushort)AMD_ID_LV800T) {
224 info->flash_id += FLASH_AM800T;
225 info->sector_count = 19;
226 info->size = 0x00100000;
227 } else if(value == (ushort)AMD_ID_LV800B) {
228 info->flash_id += FLASH_AM800B;
229 info->sector_count = 19;
230 info->size = 0x00100000;
231 } else if(value == (ushort)AMD_ID_LV160T) {
232 info->flash_id += FLASH_AM160T;
233 info->sector_count = 35;
234 info->size = 0x00200000;
235 } else if(value == (ushort)AMD_ID_LV160B) {
236 info->flash_id += FLASH_AM160B;
237 info->sector_count = 35;
238 info->size = 0x00200000;
239 } else if(value == (ushort)AMD_ID_LV320T) {
240 info->flash_id += FLASH_AM320T;
241 info->sector_count = 67;
242 info->size = 0x00400000;
243 } else if(value == (ushort)AMD_ID_LV320B) {
244 info->flash_id += FLASH_AM320B;
245 info->sector_count = 67;
246 info->size = 0x00400000;
247 } else {
248#ifdef DEBUG
249 printf("Unknown flash type 0x%04X\n", value);
250 info->size = CONFIG_SYS_FLASH_SIZE;
251#else
252 info->flash_id = FLASH_UNKNOWN;
253 return (0);
254#endif
255 }
256
257
258 if (info->flash_id & FLASH_BTYPE) {
259
260 info->start[0] = base + 0x00000000;
261 info->start[1] = base + 0x00004000;
262 info->start[2] = base + 0x00006000;
263 info->start[3] = base + 0x00008000;
264 for (i = 4; i < info->sector_count; i++) {
265 info->start[i] = base + ((i - 3) * 0x00010000);
266 }
267 } else {
268
269 i = info->sector_count - 1;
270 info->start[i--] = base + info->size - 0x00004000;
271 info->start[i--] = base + info->size - 0x00006000;
272 info->start[i--] = base + info->size - 0x00008000;
273 for (; i >= 0; i--) {
274 info->start[i] = base + (i * 0x00010000);
275 }
276 }
277
278
279 for (i = 0; i < info->sector_count; i++) {
280
281
282 addr = (volatile unsigned short *)(info->start[i]);
283 info->protect[i] = addr[2] & 1;
284 }
285
286
287
288
289 if (info->flash_id != FLASH_UNKNOWN) {
290 addr = (volatile unsigned short *)info->start[0];
291
292 }
293
294 addr[0] = 0xF0F0;
295 __asm__ __volatile__(" sync\n ");
296 return (info->size);
297}
298
299
300
301
302
303int flash_erase (flash_info_t *info, int s_first, int s_last)
304{
305 vu_short *addr = (vu_short*)(info->start[0]);
306 int flag, prot, sect, l_sect;
307 ulong start, now, last;
308
309 if ((s_first < 0) || (s_first > s_last)) {
310 if (info->flash_id == FLASH_UNKNOWN) {
311 printf ("- missing\n");
312 } else {
313 printf ("- no sectors to erase\n");
314 }
315 return 1;
316 }
317
318 if ((info->flash_id == FLASH_UNKNOWN) ||
319 (info->flash_id > FLASH_AMD_COMP)) {
320 printf ("Can't erase unknown flash type %08lx - aborted\n",
321 info->flash_id);
322 return 1;
323 }
324
325 prot = 0;
326 for (sect=s_first; sect<=s_last; ++sect) {
327 if (info->protect[sect]) {
328 prot++;
329 }
330 }
331
332 if (prot) {
333 printf ("- Warning: %d protected sectors will not be erased!\n",
334 prot);
335 } else {
336 printf ("\n");
337 }
338
339 l_sect = -1;
340
341
342 flag = disable_interrupts();
343
344 addr[0x0555] = 0xAAAA;
345 addr[0x02AA] = 0x5555;
346 addr[0x0555] = 0x8080;
347 addr[0x0555] = 0xAAAA;
348 addr[0x02AA] = 0x5555;
349 __asm__ __volatile__(" sync\n ");
350
351
352 for (sect = s_first; sect<=s_last; sect++) {
353 if (info->protect[sect] == 0) {
354 addr = (vu_short*)(info->start[sect]);
355 addr[0] = 0x3030;
356 l_sect = sect;
357 }
358 }
359
360
361 if (flag)
362 enable_interrupts();
363
364
365 udelay (1000);
366
367
368
369
370 if (l_sect < 0)
371 goto DONE;
372
373 start = get_timer (0);
374 last = start;
375 addr = (vu_short*)(info->start[l_sect]);
376 while ((addr[0] & 0x0080) != 0x0080) {
377 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
378 printf ("Timeout\n");
379 addr[0] = 0xF0F0;
380 __asm__ __volatile__(" sync\n ");
381 return 1;
382 }
383
384 if ((now - last) > 1000) {
385 putc ('.');
386 last = now;
387 }
388 }
389
390DONE:
391
392 addr = (vu_short*)info->start[0];
393 addr[0] = 0xF0F0;
394 __asm__ __volatile__(" sync\n ");
395
396 printf (" done\n");
397 return 0;
398}
399
400
401
402
403
404
405
406
407int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
408{
409 ulong cp, wp, data;
410 int i, l, rc;
411
412 wp = (addr & ~3);
413
414
415
416
417 if ((l = addr - wp) != 0) {
418 data = 0;
419 for (i=0, cp=wp; i<l; ++i, ++cp) {
420 data = (data << 8) | (*(uchar *)cp);
421 }
422 for (; i<4 && cnt>0; ++i) {
423 data = (data << 8) | *src++;
424 --cnt;
425 ++cp;
426 }
427 for (; cnt==0 && i<4; ++i, ++cp) {
428 data = (data << 8) | (*(uchar *)cp);
429 }
430
431 if ((rc = write_word(info, wp, data)) != 0) {
432 return (rc);
433 }
434 wp += 4;
435 }
436
437
438
439
440 while (cnt >= 4) {
441 data = 0;
442 for (i=0; i<4; ++i) {
443 data = (data << 8) | *src++;
444 }
445 if ((rc = write_word(info, wp, data)) != 0) {
446 return (rc);
447 }
448 wp += 4;
449 cnt -= 4;
450 }
451
452 if (cnt == 0) {
453 return (0);
454 }
455
456
457
458
459 data = 0;
460 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
461 data = (data << 8) | *src++;
462 --cnt;
463 }
464 for (; i<4; ++i, ++cp) {
465 data = (data << 8) | (*(uchar *)cp);
466 }
467
468 return (write_word(info, wp, data));
469}
470
471
472
473
474
475
476
477static int write_word (flash_info_t *info, ulong dest, ulong data)
478{
479 vu_short *addr = (vu_short*)(info->start[0]);
480 ulong start;
481 int flag;
482 int j;
483
484
485 if (((*(vu_long *)dest) & data) != data) {
486 return (2);
487 }
488
489 flag = disable_interrupts();
490
491
492
493
494
495
496 dest += 2;
497 for(j = 0; j < 2; j++) {
498 addr[0x0555] = 0xAAAA;
499 addr[0x02AA] = 0x5555;
500 addr[0x0555] = 0xA0A0;
501 __asm__ __volatile__(" sync\n ");
502
503 *((vu_short *)dest) = (ushort)data;
504
505
506 if (flag)
507 enable_interrupts();
508
509
510 start = get_timer (0);
511 while (*(vu_short *)dest != (ushort)data) {
512 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
513 return (1);
514 }
515 }
516 dest -= 2;
517 data >>= 16;
518 }
519 return (0);
520}
521
522
523
524