1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <common.h>
28#include <ppc4xx.h>
29#include <asm/u-boot.h>
30#include <asm/processor.h>
31
32flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
33
34
35#define FLASH_WORD_SIZE unsigned long
36#define FLASH_ID_MASK 0xFFFFFFFF
37
38
39
40
41
42ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info);
43
44static int write_word (flash_info_t *info, ulong dest, ulong data);
45static void flash_get_offsets (ulong base, flash_info_t *info);
46
47
48
49
50
51unsigned long flash_init (void)
52{
53 unsigned long size_b0, size_b1;
54 int i;
55 uint pbcr;
56 unsigned long base_b0, base_b1;
57 volatile FLASH_WORD_SIZE* flash_base;
58
59
60 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
61 flash_info[i].flash_id = FLASH_UNKNOWN;
62 }
63
64
65
66 debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_8M_PRELIM);
67 flash_base = (volatile FLASH_WORD_SIZE*)(FLASH_BASE0_8M_PRELIM);
68 size_b0 = flash_get_size(flash_base, &flash_info[0]);
69
70 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
71 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
72 size_b0, size_b0<<20);
73 return 0;
74 }
75
76 if (size_b0 < 8*1024*1024) {
77
78 debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_4M_PRELIM);
79 flash_base = (volatile FLASH_WORD_SIZE*)(FLASH_BASE0_4M_PRELIM);
80 size_b0 = flash_get_size(flash_base, &flash_info[0]);
81 }
82
83 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
84 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
85 size_b0, size_b0<<20);
86 return 0;
87 }
88
89
90 if (CONFIG_SYS_MAX_FLASH_BANKS == 1) {
91
92 flash_get_offsets ((ulong)flash_base, &flash_info[0]);
93
94
95 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
96 CONFIG_SYS_MONITOR_BASE+CONFIG_SYS_MONITOR_LEN-1, &flash_info[0]);
97 size_b1 = 0 ;
98 flash_info[0].size = size_b0;
99 return(size_b0);
100 }
101
102
103 size_b1 = flash_get_size(flash_base, &flash_info[1]);
104
105
106 if (size_b1) {
107 mtdcr(EBC0_CFGADDR, PB0CR);
108 pbcr = mfdcr(EBC0_CFGDATA);
109 mtdcr(EBC0_CFGADDR, PB0CR);
110 base_b1 = -size_b1;
111 pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
112 mtdcr(EBC0_CFGDATA, pbcr);
113 }
114
115 if (size_b0) {
116 mtdcr(EBC0_CFGADDR, PB1CR);
117 pbcr = mfdcr(EBC0_CFGDATA);
118 mtdcr(EBC0_CFGADDR, PB1CR);
119 base_b0 = base_b1 - size_b0;
120 pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
121 mtdcr(EBC0_CFGDATA, pbcr);
122 }
123
124 size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b0, &flash_info[0]);
125 flash_get_offsets (base_b0, &flash_info[0]);
126
127
128 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
129 CONFIG_SYS_MONITOR_BASE+CONFIG_SYS_MONITOR_LEN-1, &flash_info[0]);
130
131 if (size_b1) {
132
133 size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b1, &flash_info[1]);
134 flash_get_offsets (base_b1, &flash_info[1]);
135
136
137 (void)flash_protect(FLAG_PROTECT_SET, base_b1+size_b1-CONFIG_SYS_MONITOR_LEN,
138 base_b1+size_b1-1, &flash_info[1]);
139
140
141 (void)flash_protect(FLAG_PROTECT_CLEAR, base_b0+size_b0-CONFIG_SYS_MONITOR_LEN,
142 base_b0+size_b0-1, &flash_info[0]);
143 } else {
144 flash_info[1].flash_id = FLASH_UNKNOWN;
145 flash_info[1].sector_count = -1;
146 }
147
148 flash_info[0].size = size_b0;
149 flash_info[1].size = size_b1;
150 return (size_b0 + size_b1);
151}
152
153
154
155
156
157
158static void flash_get_offsets (ulong base, flash_info_t *info)
159{
160 int i;
161 long large_sect_size;
162 long small_sect_size;
163
164
165 large_sect_size = info->size / (info->sector_count - 8 + 1);
166 small_sect_size = large_sect_size / 8;
167
168 if (info->flash_id & FLASH_BTYPE) {
169
170
171 for (i = 0; i < 7; i++) {
172 info->start[i] = base;
173 base += small_sect_size;
174 }
175
176 for (; i < info->sector_count; i++) {
177 info->start[i] = base;
178 base += large_sect_size;
179 }
180 }
181 else
182 {
183
184 for (i = 0; i < (info->sector_count - 8); i++) {
185 info->start[i] = base;
186 base += large_sect_size;
187 }
188
189 for (; i < info->sector_count; i++) {
190 info->start[i] = base;
191 base += small_sect_size;
192 }
193 }
194}
195
196
197
198
199void flash_print_info (flash_info_t *info)
200{
201 int i;
202 uchar *boottype;
203 uchar botboot[]=", bottom boot sect)\n";
204 uchar topboot[]=", top boot sector)\n";
205
206 if (info->flash_id == FLASH_UNKNOWN) {
207 printf ("missing or unknown FLASH type\n");
208 return;
209 }
210
211 switch (info->flash_id & FLASH_VENDMASK) {
212 case FLASH_MAN_AMD:
213 printf ("AMD ");
214 break;
215 case FLASH_MAN_FUJ:
216 printf ("FUJITSU ");
217 break;
218 case FLASH_MAN_SST:
219 printf ("SST ");
220 break;
221 case FLASH_MAN_STM:
222 printf ("STM ");
223 break;
224 case FLASH_MAN_INTEL:
225 printf ("INTEL ");
226 break;
227 default:
228 printf ("Unknown Vendor ");
229 break;
230 }
231
232 if (info->flash_id & 0x0001 ) {
233 boottype = botboot;
234 } else {
235 boottype = topboot;
236 }
237
238 switch (info->flash_id & FLASH_TYPEMASK) {
239 case FLASH_AM160B:
240 printf ("AM29LV160B (16 Mbit%s",boottype);
241 break;
242 case FLASH_AM160T:
243 printf ("AM29LV160T (16 Mbit%s",boottype);
244 break;
245 case FLASH_AMDL163T:
246 printf ("AM29DL163T (16 Mbit%s",boottype);
247 break;
248 case FLASH_AMDL163B:
249 printf ("AM29DL163B (16 Mbit%s",boottype);
250 break;
251 case FLASH_AM320B:
252 printf ("AM29LV320B (32 Mbit%s",boottype);
253 break;
254 case FLASH_AM320T:
255 printf ("AM29LV320T (32 Mbit%s",boottype);
256 break;
257 case FLASH_AMDL323T:
258 printf ("AM29DL323T (32 Mbit%s",boottype);
259 break;
260 case FLASH_AMDL323B:
261 printf ("AM29DL323B (32 Mbit%s",boottype);
262 break;
263 case FLASH_AMDL322T:
264 printf ("AM29DL322T (32 Mbit%s",boottype);
265 break;
266 default:
267 printf ("Unknown Chip Type\n");
268 break;
269 }
270
271 printf (" Size: %ld MB in %d Sectors\n",
272 info->size >> 20, info->sector_count);
273
274 printf (" Sector Start Addresses:");
275 for (i=0; i<info->sector_count; ++i) {
276 if ((i % 5) == 0)
277 printf ("\n ");
278 printf (" %08lX%s", info->start[i],
279 info->protect[i] ? " (RO)" : " ");
280 }
281 printf ("\n");
282 return;
283}
284
285
286
287
288
289ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
290{
291 short i;
292 ulong base = (ulong)addr;
293 FLASH_WORD_SIZE value;
294
295
296
297
298
299
300
301
302
303 addr[0x0000] = 0x00900090;
304 if(addr[0x0000] != 0x00890089){
305 addr[0x0555] = 0x00AA00AA;
306 addr[0x02AA] = 0x00550055;
307 addr[0x0555] = 0x00900090;
308 }
309 value = addr[0];
310
311 switch (value) {
312 case (AMD_MANUFACT & FLASH_ID_MASK):
313 info->flash_id = FLASH_MAN_AMD;
314 break;
315 case (FUJ_MANUFACT & FLASH_ID_MASK):
316 info->flash_id = FLASH_MAN_FUJ;
317 break;
318 case (STM_MANUFACT & FLASH_ID_MASK):
319 info->flash_id = FLASH_MAN_STM;
320 break;
321 case (SST_MANUFACT & FLASH_ID_MASK):
322 info->flash_id = FLASH_MAN_SST;
323 break;
324 case (INTEL_MANUFACT & FLASH_ID_MASK):
325 info->flash_id = FLASH_MAN_INTEL;
326 break;
327 default:
328 info->flash_id = FLASH_UNKNOWN;
329 info->sector_count = 0;
330 info->size = 0;
331 return (0);
332 }
333
334 value = addr[1];
335
336 switch (value) {
337 case (AMD_ID_LV160T & FLASH_ID_MASK):
338 info->flash_id += FLASH_AM160T;
339 info->sector_count = 35;
340 info->size = 0x00400000;
341 break;
342
343 case (AMD_ID_LV160B & FLASH_ID_MASK):
344 info->flash_id += FLASH_AM160B;
345 info->sector_count = 35;
346 info->size = 0x00400000;
347 break;
348
349 case (AMD_ID_DL163T & FLASH_ID_MASK):
350 info->flash_id += FLASH_AMDL163T;
351 info->sector_count = 39;
352 info->size = 0x00400000;
353 break;
354
355 case (AMD_ID_DL163B & FLASH_ID_MASK):
356 info->flash_id += FLASH_AMDL163B;
357 info->sector_count = 39;
358 info->size = 0x00400000;
359 break;
360
361 case (AMD_ID_DL323T & FLASH_ID_MASK):
362 info->flash_id += FLASH_AMDL323T;
363 info->sector_count = 71;
364 info->size = 0x00800000;
365 break;
366
367 case (AMD_ID_DL323B & FLASH_ID_MASK):
368 info->flash_id += FLASH_AMDL323B;
369 info->sector_count = 71;
370 info->size = 0x00800000;
371 break;
372
373 case (AMD_ID_DL322T & FLASH_ID_MASK):
374 info->flash_id += FLASH_AMDL322T;
375 info->sector_count = 71;
376 info->size = 0x00800000;
377 break;
378
379 default:
380
381 info->flash_id = FLASH_UNKNOWN;
382 return (0);
383 }
384
385 flash_get_offsets(base, info);
386
387
388 for (i = 0; i < info->sector_count; i++) {
389
390
391 addr = (volatile FLASH_WORD_SIZE *)(info->start[i]);
392 info->protect[i] = addr[2] & 1;
393 }
394
395
396
397
398 if (info->flash_id != FLASH_UNKNOWN) {
399 addr = (volatile FLASH_WORD_SIZE *)info->start[0];
400 *addr = (0x00FF00FF & FLASH_ID_MASK);
401 }
402
403 return (info->size);
404}
405
406
407
408
409
410int flash_erase (flash_info_t *info, int s_first, int s_last)
411{
412 volatile FLASH_WORD_SIZE *addr=(volatile FLASH_WORD_SIZE*)(info->start[0]);
413 int flag, prot, sect, l_sect;
414 ulong start, now, last;
415 int rcode = 0;
416
417 if ((s_first < 0) || (s_first > s_last)) {
418 if (info->flash_id == FLASH_UNKNOWN) {
419 printf ("- missing\n");
420 } else {
421 printf ("- no sectors to erase\n");
422 }
423 return 1;
424 }
425
426 if ((info->flash_id == FLASH_UNKNOWN) ||
427 (info->flash_id > FLASH_AMD_COMP) ) {
428 printf ("Can't erase unknown flash type - aborted\n");
429 return 1;
430 }
431
432 prot = 0;
433 for (sect=s_first; sect<=s_last; ++sect) {
434 if (info->protect[sect]) {
435 prot++;
436 }
437 }
438
439 if (prot) {
440 printf ("- Warning: %d protected sectors will not be erased!\n",
441 prot);
442 } else {
443 printf ("\n");
444 }
445
446 l_sect = -1;
447
448
449 flag = disable_interrupts();
450 addr[0x0555] = 0x00AA00AA;
451 addr[0x02AA] = 0x00550055;
452 addr[0x0555] = 0x00800080;
453 addr[0x0555] = 0x00AA00AA;
454 addr[0x02AA] = 0x00550055;
455
456 for (sect = s_first; sect<=s_last; sect++) {
457 if (info->protect[sect] == 0) {
458 addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]);
459 addr[0] = (0x00300030 & FLASH_ID_MASK);
460 l_sect = sect;
461 }
462 }
463
464
465 if (flag)
466 enable_interrupts();
467
468
469 udelay (1000);
470
471
472
473
474 if (l_sect < 0)
475 goto DONE;
476
477 start = get_timer (0);
478 last = start;
479 addr = (volatile FLASH_WORD_SIZE*)(info->start[l_sect]);
480 while ((addr[0] & (0x00800080&FLASH_ID_MASK)) !=
481 (0x00800080&FLASH_ID_MASK) )
482 {
483 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
484 printf ("Timeout\n");
485 return 1;
486 }
487
488 if ((now - last) > 1000) {
489 serial_putc ('.');
490 last = now;
491 }
492 }
493
494DONE:
495
496 addr = (volatile FLASH_WORD_SIZE *)info->start[0];
497 addr[0] = (0x00F000F0 & FLASH_ID_MASK);
498
499 printf (" done\n");
500 return rcode;
501}
502
503
504
505
506
507
508
509
510int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
511{
512 ulong cp, wp, data;
513 int l;
514 int i, rc;
515
516 wp = (addr & ~3);
517
518
519
520
521 if ((l = addr - wp) != 0) {
522 data = 0;
523 for (i=0, cp=wp; i<l; ++i, ++cp) {
524 data = (data << 8) | (*(uchar *)cp);
525 }
526 for (; i<4 && cnt>0; ++i) {
527 data = (data << 8) | *src++;
528 --cnt;
529 ++cp;
530 }
531 for (; cnt==0 && i<4; ++i, ++cp) {
532 data = (data << 8) | (*(uchar *)cp);
533 }
534
535 if ((rc = write_word(info, wp, data)) != 0) {
536 return (rc);
537 }
538 wp += 4;
539 }
540
541
542
543
544 while (cnt >= 4) {
545 data = 0;
546 for (i=0; i<4; ++i) {
547 data = (data << 8) | *src++;
548 }
549 if ((rc = write_word(info, wp, data)) != 0) {
550 return (rc);
551 }
552 wp += 4;
553 cnt -= 4;
554 }
555
556 if (cnt == 0) {
557 return (0);
558 }
559
560
561
562
563 data = 0;
564 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
565 data = (data << 8) | *src++;
566 --cnt;
567 }
568 for (; i<4; ++i, ++cp) {
569 data = (data << 8) | (*(uchar *)cp);
570 }
571
572 return (write_word(info, wp, data));
573}
574
575
576
577
578
579
580
581static int write_word (flash_info_t *info, ulong dest, ulong data)
582{
583 vu_long *addr = (vu_long*)(info->start[0]);
584 ulong start;
585 int flag;
586
587
588 if ((*((vu_long *)dest) & data) != data) {
589 return (2);
590 }
591
592
593 flag = disable_interrupts();
594
595
596 addr[0x0555] = 0x00AA00AA;
597 addr[0x02AA] = 0x00550055;
598 addr[0x0555] = 0x00A000A0;
599
600 *((vu_long *)dest) = data;
601
602
603 if (flag)
604 enable_interrupts();
605
606
607 start = get_timer(0);
608
609 while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
610 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
611 return (1);
612 }
613 }
614
615 return (0);
616}
617