1
2
3
4
5
6
7
8#include <common.h>
9#include <mpc8xx.h>
10
11
12
13#include <environment.h>
14
15flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
16
17
18
19
20#ifdef CONFIG_FLASH_16BIT
21typedef unsigned short FLASH_PORT_WIDTH;
22typedef volatile unsigned short FLASH_PORT_WIDTHV;
23#define FLASH_ID_MASK 0xFFFF
24#else
25typedef unsigned long FLASH_PORT_WIDTH;
26typedef volatile unsigned long FLASH_PORT_WIDTHV;
27#define FLASH_ID_MASK 0xFFFFFFFF
28#endif
29
30#define FPW FLASH_PORT_WIDTH
31#define FPWV FLASH_PORT_WIDTHV
32
33#define ORMASK(size) ((-size) & OR_AM_MSK)
34
35
36
37
38static ulong flash_get_size(FPWV *addr, flash_info_t *info);
39static void flash_reset(flash_info_t *info);
40static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
41static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
42static void flash_get_offsets(ulong base, flash_info_t *info);
43#ifdef CONFIG_SYS_FLASH_PROTECTION
44static void flash_sync_real_protect(flash_info_t *info);
45#endif
46
47
48
49
50
51
52unsigned long flash_init (void)
53{
54 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
55 volatile memctl8xx_t *memctl = &immap->im_memctl;
56 unsigned long size_b;
57 int i;
58
59
60 for (i=0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
61 flash_info[i].flash_id = FLASH_UNKNOWN;
62 }
63
64 size_b = flash_get_size((FPW *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
65
66 flash_info[0].size = size_b;
67
68 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
69 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx\n",size_b);
70 }
71
72
73 memctl->memc_or0 = (memctl->memc_or0 & ~OR_AM_MSK) | ORMASK(size_b);
74
75
76
77
78 flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
79
80#ifdef CONFIG_SYS_FLASH_PROTECTION
81
82
83
84 flash_sync_real_protect(&flash_info[0]);
85#endif
86
87#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
88
89 flash_protect(FLAG_PROTECT_SET,
90 CONFIG_SYS_MONITOR_BASE,
91 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
92 &flash_info[0]);
93#endif
94
95#ifdef CONFIG_ENV_ADDR
96 flash_protect ( FLAG_PROTECT_SET,
97 CONFIG_ENV_ADDR,
98 CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, &flash_info[0]);
99#endif
100
101#ifdef CONFIG_ENV_ADDR_REDUND
102 flash_protect ( FLAG_PROTECT_SET,
103 CONFIG_ENV_ADDR_REDUND,
104 CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
105 &flash_info[0]);
106#endif
107
108 return (size_b);
109}
110
111
112
113static void flash_reset(flash_info_t *info)
114{
115 FPWV *base = (FPWV *)(info->start[0]);
116
117
118 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
119 *base = (FPW)0x00FF00FF;
120 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
121 *base = (FPW)0x00F000F0;
122}
123
124
125
126static void flash_get_offsets (ulong base, flash_info_t *info)
127{
128 int i;
129
130
131 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
132 && (info->flash_id & FLASH_BTYPE)) {
133 int bootsect_size;
134 int sect_size;
135
136 bootsect_size = 0x00002000 * (sizeof(FPW)/2);
137 sect_size = 0x00010000 * (sizeof(FPW)/2);
138
139
140 for (i = 0; i < 8; ++i) {
141 info->start[i] = base + (i * bootsect_size);
142 }
143 for (i = 8; i < info->sector_count; i++) {
144 info->start[i] = base + ((i - 7) * sect_size);
145 }
146 }
147 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
148 && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
149
150 int sect_size;
151
152 sect_size = 0x00010000 * (sizeof(FPW)/2);
153
154
155 for( i = 0; i < info->sector_count; i++ )
156 info->start[i] = base + (i * sect_size);
157 }
158 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
159 && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM800T) {
160
161 int sect_size;
162
163 sect_size = 0x00010000 * (sizeof(FPW)/2);
164
165
166 for (i = 0; i < info->sector_count - 3; i++)
167 info->start[i] = base + (i * sect_size);
168 i = info->sector_count - 1;
169 info->start[i--] = base + (info->size - 0x00004000) * (sizeof(FPW)/2);
170 info->start[i--] = base + (info->size - 0x00006000) * (sizeof(FPW)/2);
171 info->start[i--] = base + (info->size - 0x00008000) * (sizeof(FPW)/2);
172 }
173}
174
175
176
177
178void flash_print_info (flash_info_t *info)
179{
180 int i;
181 uchar *boottype;
182 uchar *bootletter;
183 char *fmt;
184 uchar botbootletter[] = "B";
185 uchar topbootletter[] = "T";
186 uchar botboottype[] = "bottom boot sector";
187 uchar topboottype[] = "top boot sector";
188
189 if (info->flash_id == FLASH_UNKNOWN) {
190 printf ("missing or unknown FLASH type\n");
191 return;
192 }
193
194 switch (info->flash_id & FLASH_VENDMASK) {
195 case FLASH_MAN_AMD: printf ("AMD "); break;
196 case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break;
197 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
198 case FLASH_MAN_SST: printf ("SST "); break;
199 case FLASH_MAN_STM: printf ("STM "); break;
200 case FLASH_MAN_INTEL: printf ("INTEL "); break;
201 default: printf ("Unknown Vendor "); break;
202 }
203
204
205 if (info->flash_id & FLASH_BTYPE) {
206 boottype = botboottype;
207 bootletter = botbootletter;
208 }
209 else {
210 boottype = topboottype;
211 bootletter = topbootletter;
212 }
213
214 switch (info->flash_id & FLASH_TYPEMASK) {
215 case FLASH_AM800T:
216 fmt = "29LV800B%s (8 Mbit, %s)\n";
217 break;
218 case FLASH_AM640U:
219 fmt = "29LV641D (64 Mbit, uniform sectors)\n";
220 break;
221 case FLASH_28F800C3B:
222 case FLASH_28F800C3T:
223 fmt = "28F800C3%s (8 Mbit, %s)\n";
224 break;
225 case FLASH_INTEL800B:
226 case FLASH_INTEL800T:
227 fmt = "28F800B3%s (8 Mbit, %s)\n";
228 break;
229 case FLASH_28F160C3B:
230 case FLASH_28F160C3T:
231 fmt = "28F160C3%s (16 Mbit, %s)\n";
232 break;
233 case FLASH_INTEL160B:
234 case FLASH_INTEL160T:
235 fmt = "28F160B3%s (16 Mbit, %s)\n";
236 break;
237 case FLASH_28F320C3B:
238 case FLASH_28F320C3T:
239 fmt = "28F320C3%s (32 Mbit, %s)\n";
240 break;
241 case FLASH_INTEL320B:
242 case FLASH_INTEL320T:
243 fmt = "28F320B3%s (32 Mbit, %s)\n";
244 break;
245 case FLASH_28F640C3B:
246 case FLASH_28F640C3T:
247 fmt = "28F640C3%s (64 Mbit, %s)\n";
248 break;
249 case FLASH_INTEL640B:
250 case FLASH_INTEL640T:
251 fmt = "28F640B3%s (64 Mbit, %s)\n";
252 break;
253 default:
254 fmt = "Unknown Chip Type\n";
255 break;
256 }
257
258 printf (fmt, bootletter, boottype);
259
260 printf (" Size: %ld MB in %d Sectors\n",
261 info->size >> 20,
262 info->sector_count);
263
264 printf (" Sector Start Addresses:");
265
266 for (i=0; i<info->sector_count; ++i) {
267 if ((i % 5) == 0) {
268 printf ("\n ");
269 }
270
271 printf (" %08lX%s", info->start[i],
272 info->protect[i] ? " (RO)" : " ");
273 }
274
275 printf ("\n");
276}
277
278
279
280
281
282
283
284
285ulong flash_get_size (FPWV *addr, flash_info_t *info)
286{
287
288
289
290 addr[0x0555] = (FPW)0x00AA00AA;
291 addr[0x02AA] = (FPW)0x00550055;
292 addr[0x0555] = (FPW)0x00900090;
293
294
295
296
297 switch (addr[0] & 0xff) {
298
299 case (uchar)AMD_MANUFACT:
300 info->flash_id = FLASH_MAN_AMD;
301 break;
302
303 case (uchar)INTEL_MANUFACT:
304 info->flash_id = FLASH_MAN_INTEL;
305 break;
306
307 default:
308 info->flash_id = FLASH_UNKNOWN;
309 info->sector_count = 0;
310 info->size = 0;
311 break;
312 }
313
314
315 if (info->flash_id != FLASH_UNKNOWN) switch (addr[1]) {
316
317 case (FPW)AMD_ID_LV800T:
318 info->flash_id += FLASH_AM800T;
319 info->sector_count = 19;
320 info->size = 0x00100000 * (sizeof(FPW)/2);
321 break;
322
323 case (FPW)AMD_ID_LV640U:
324 info->flash_id += FLASH_AM640U;
325 info->sector_count = 128;
326 info->size = 0x00800000 * (sizeof(FPW)/2);
327 break;
328
329 case (FPW)INTEL_ID_28F800C3B:
330 info->flash_id += FLASH_28F800C3B;
331 info->sector_count = 23;
332 info->size = 0x00100000 * (sizeof(FPW)/2);
333 break;
334
335 case (FPW)INTEL_ID_28F800B3B:
336 info->flash_id += FLASH_INTEL800B;
337 info->sector_count = 23;
338 info->size = 0x00100000 * (sizeof(FPW)/2);
339 break;
340
341 case (FPW)INTEL_ID_28F160C3B:
342 info->flash_id += FLASH_28F160C3B;
343 info->sector_count = 39;
344 info->size = 0x00200000 * (sizeof(FPW)/2);
345 break;
346
347 case (FPW)INTEL_ID_28F160B3B:
348 info->flash_id += FLASH_INTEL160B;
349 info->sector_count = 39;
350 info->size = 0x00200000 * (sizeof(FPW)/2);
351 break;
352
353 case (FPW)INTEL_ID_28F320C3B:
354 info->flash_id += FLASH_28F320C3B;
355 info->sector_count = 71;
356 info->size = 0x00400000 * (sizeof(FPW)/2);
357 break;
358
359 case (FPW)INTEL_ID_28F320B3B:
360 info->flash_id += FLASH_INTEL320B;
361 info->sector_count = 71;
362 info->size = 0x00400000 * (sizeof(FPW)/2);
363 break;
364
365 case (FPW)INTEL_ID_28F640C3B:
366 info->flash_id += FLASH_28F640C3B;
367 info->sector_count = 135;
368 info->size = 0x00800000 * (sizeof(FPW)/2);
369 break;
370
371 case (FPW)INTEL_ID_28F640B3B:
372 info->flash_id += FLASH_INTEL640B;
373 info->sector_count = 135;
374 info->size = 0x00800000 * (sizeof(FPW)/2);
375 break;
376
377 default:
378 info->flash_id = FLASH_UNKNOWN;
379 info->sector_count = 0;
380 info->size = 0;
381 return (0);
382 }
383
384 flash_get_offsets((ulong)addr, info);
385
386
387 flash_reset(info);
388
389 return (info->size);
390}
391
392#ifdef CONFIG_SYS_FLASH_PROTECTION
393
394
395
396static void flash_sync_real_protect(flash_info_t *info)
397{
398 FPWV *addr = (FPWV *)(info->start[0]);
399 FPWV *sect;
400 int i;
401
402 switch (info->flash_id & FLASH_TYPEMASK) {
403 case FLASH_28F800C3B:
404 case FLASH_28F800C3T:
405 case FLASH_28F160C3B:
406 case FLASH_28F160C3T:
407 case FLASH_28F320C3B:
408 case FLASH_28F320C3T:
409 case FLASH_28F640C3B:
410 case FLASH_28F640C3T:
411
412 *addr = (FPW)0x00900090;
413 for (i = 0; i < info->sector_count; i++) {
414
415
416
417
418
419
420 sect = (FPWV *)(info->start[i]);
421 info->protect[i] = (sect[2] & (FPW)(0x00010001)) ? 1 : 0;
422 }
423
424
425 flash_reset(info);
426 break;
427
428 case FLASH_AM640U:
429 case FLASH_AM800T:
430 default:
431
432 break;
433 }
434}
435#endif
436
437
438
439
440int flash_erase (flash_info_t *info, int s_first, int s_last)
441{
442 FPWV *addr;
443 int flag, prot, sect;
444 int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
445 ulong start, now, last;
446 int rcode = 0;
447
448 if ((s_first < 0) || (s_first > s_last)) {
449 if (info->flash_id == FLASH_UNKNOWN) {
450 printf ("- missing\n");
451 } else {
452 printf ("- no sectors to erase\n");
453 }
454 return 1;
455 }
456
457 switch (info->flash_id & FLASH_TYPEMASK) {
458 case FLASH_INTEL800B:
459 case FLASH_INTEL160B:
460 case FLASH_INTEL320B:
461 case FLASH_INTEL640B:
462 case FLASH_28F800C3B:
463 case FLASH_28F160C3B:
464 case FLASH_28F320C3B:
465 case FLASH_28F640C3B:
466 case FLASH_AM640U:
467 case FLASH_AM800T:
468 break;
469 case FLASH_UNKNOWN:
470 default:
471 printf ("Can't erase unknown flash type %08lx - aborted\n",
472 info->flash_id);
473 return 1;
474 }
475
476 prot = 0;
477 for (sect=s_first; sect<=s_last; ++sect) {
478 if (info->protect[sect]) {
479 prot++;
480 }
481 }
482
483 if (prot) {
484 printf ("- Warning: %d protected sectors will not be erased!\n",
485 prot);
486 } else {
487 printf ("\n");
488 }
489
490 start = get_timer(0);
491 last = start;
492
493
494 for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
495
496 if (info->protect[sect] != 0)
497 continue;
498
499
500 flag = disable_interrupts();
501
502 addr = (FPWV *)(info->start[sect]);
503 if (intel) {
504 *addr = (FPW)0x00500050;
505 *addr = (FPW)0x00200020;
506 *addr = (FPW)0x00D000D0;
507 }
508 else {
509
510 FPWV *base;
511
512 base = (FPWV *)(info->start[0]);
513 base[0x0555] = (FPW)0x00AA00AA;
514 base[0x02AA] = (FPW)0x00550055;
515 base[0x0555] = (FPW)0x00800080;
516 base[0x0555] = (FPW)0x00AA00AA;
517 base[0x02AA] = (FPW)0x00550055;
518 *addr = (FPW)0x00300030;
519 }
520
521
522 if (flag)
523 enable_interrupts();
524
525
526
527
528 udelay (1000);
529
530 while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
531 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
532 printf ("Timeout\n");
533
534 if (intel) {
535
536 *addr = (FPW)0x00B000B0;
537 }
538
539 flash_reset(info);
540 rcode = 1;
541 break;
542 }
543
544
545 if ((now - last) > 1000) {
546 putc ('.');
547 last = now;
548 }
549 }
550
551 flash_reset(info);
552 }
553
554 printf (" done\n");
555 return rcode;
556}
557
558
559
560
561
562
563
564int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
565{
566 FPW data = 0;
567 int bytes;
568 int left;
569 int i, res;
570
571 for (left = cnt, res = 0;
572 left > 0 && res == 0;
573 addr += sizeof(data), left -= sizeof(data) - bytes) {
574
575 bytes = addr & (sizeof(data) - 1);
576 addr &= ~(sizeof(data) - 1);
577
578
579
580
581 for (i = 0; i < sizeof(data); i++) {
582 data <<= 8;
583 if (i < bytes || i - bytes >= left )
584 data += *((uchar *)addr + i);
585 else
586 data += *src++;
587 }
588
589
590 switch (info->flash_id & FLASH_VENDMASK) {
591 case FLASH_MAN_AMD:
592 res = write_word_amd(info, (FPWV *)addr, data);
593 break;
594 case FLASH_MAN_INTEL:
595 res = write_word_intel(info, (FPWV *)addr, data);
596 break;
597 default:
598
599 printf ("missing or unknown FLASH type\n");
600 res = 1;
601 break;
602 }
603 }
604
605 return (res);
606}
607
608
609
610
611
612
613
614
615
616
617
618static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
619{
620 ulong start;
621 int flag;
622 int res = 0;
623 FPWV *base;
624
625
626 if ((*dest & data) != data) {
627 return (2);
628 }
629
630
631 base = (FPWV *)(info->start[0]);
632
633
634 flag = disable_interrupts();
635
636 base[0x0555] = (FPW)0x00AA00AA;
637 base[0x02AA] = (FPW)0x00550055;
638 base[0x0555] = (FPW)0x00A000A0;
639
640 *dest = data;
641
642
643 if (flag)
644 enable_interrupts();
645
646 start = get_timer (0);
647
648
649 while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
650 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
651 *dest = (FPW)0x00F000F0;
652 res = 1;
653 }
654 }
655
656 return (res);
657}
658
659
660
661
662
663
664
665
666
667
668
669static int write_word_intel (flash_info_t *info, FPWV *dest, FPW data)
670{
671 ulong start;
672 int flag;
673 int res = 0;
674
675
676 if ((*dest & data) != data) {
677 return (2);
678 }
679
680
681 flag = disable_interrupts();
682
683 *dest = (FPW)0x00500050;
684 *dest = (FPW)0x00FF00FF;
685 *dest = (FPW)0x00400040;
686
687 *dest = data;
688
689
690 if (flag)
691 enable_interrupts();
692
693 start = get_timer (0);
694
695 while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
696 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
697 *dest = (FPW)0x00B000B0;
698 res = 1;
699 }
700 }
701
702 if (res == 0 && (*dest & (FPW)0x00100010))
703 res = 1;
704
705 *dest = (FPW)0x00500050;
706 *dest = (FPW)0x00FF00FF;
707
708 return (res);
709}
710
711#ifdef CONFIG_SYS_FLASH_PROTECTION
712
713
714int flash_real_protect (flash_info_t * info, long sector, int prot)
715{
716 int rcode = 0;
717 FPWV *addr;
718 FPW value;
719
720 addr = (FPWV *) (info->start[sector]);
721
722 switch (info->flash_id & FLASH_TYPEMASK) {
723 case FLASH_28F800C3B:
724 case FLASH_28F800C3T:
725 case FLASH_28F160C3B:
726 case FLASH_28F160C3T:
727 case FLASH_28F320C3B:
728 case FLASH_28F320C3T:
729 case FLASH_28F640C3B:
730 case FLASH_28F640C3T:
731 flash_reset (info);
732 *addr = (FPW) 0x00600060L;
733 if (prot)
734 *addr = (FPW) 0x00010001L;
735 else
736 *addr = (FPW) 0x00D000D0L;
737 flash_reset (info);
738
739
740 *addr = (FPW) 0x00900090;
741
742
743
744
745
746
747 value = addr[2] & (FPW) 0x00010001;
748 if (value == 0)
749 info->protect[sector] = 0;
750 else if (value == (FPW) 0x00010001)
751 info->protect[sector] = 1;
752 else {
753
754 rcode = 1;
755 info->protect[sector] = 1;
756 }
757 if (info->protect[sector] != prot)
758 rcode = 1;
759
760
761 flash_sync_real_protect (info);
762 break;
763
764 case FLASH_AM640U:
765 case FLASH_AM800T:
766 default:
767
768 info->protect[sector] = prot;
769 break;
770 }
771
772 return rcode;
773}
774#endif
775