]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/mpl/common/flash.c
Initial revision
[people/ms/u-boot.git] / board / mpl / common / flash.c
1 /*
2 * (C) Copyright 2000, 2001
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24 /*
25 * Modified 4/5/2001
26 * Wait for completion of each sector erase command issued
27 * 4/5/2001
28 * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
29 */
30
31 /*
32 * Modified 3/7/2001
33 * - adopted for pip405, Denis Peter, MPL AG Switzerland
34 * TODO:
35 * clean-up
36 */
37
38 #include <common.h>
39 #include <ppc4xx.h>
40 #include <asm/processor.h>
41 #ifdef CONFIG_PIP405
42 #include "../pip405/pip405.h"
43 #endif
44 #ifdef CONFIG_MIP405
45 #include "../mip405/mip405.h"
46 #endif
47 #include "common_util.h"
48
49 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
50 /*-----------------------------------------------------------------------
51 * Functions
52 */
53 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
54 static int write_word (flash_info_t *info, ulong dest, ulong data);
55 static void flash_get_offsets (ulong base, flash_info_t *info);
56
57 void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt);
58
59
60 #ifdef CONFIG_ADCIOP
61 #define ADDR0 0x0aa9
62 #define ADDR1 0x0556
63 #define FLASH_WORD_SIZE unsigned char
64 #endif
65
66 #ifdef CONFIG_CPCI405
67 #define ADDR0 0x5555
68 #define ADDR1 0x2aaa
69 #define FLASH_WORD_SIZE unsigned short
70 #endif
71
72 #ifdef CONFIG_PIP405
73 #define ADDR0 0x5555
74 #define ADDR1 0x2aaa
75 #define FLASH_WORD_SIZE unsigned short
76 #endif
77
78 #ifdef CONFIG_MIP405
79 #define ADDR0 0x5555
80 #define ADDR1 0x2aaa
81 #define FLASH_WORD_SIZE unsigned short
82 #endif
83
84 #define FALSE 0
85 #define TRUE 1
86
87 /*-----------------------------------------------------------------------
88 */
89
90
91 unsigned long flash_init (void)
92 {
93 unsigned long size_b0, size_b1;
94 int i;
95 unsigned long pbcr;
96 unsigned long base_b0, base_b1;
97 unsigned char rc;
98
99 rc=switch_cs(FALSE); /* map Flash High */
100
101 if(rc)
102 printf("(MPS Boot) ");
103 else
104 printf("(Flash Boot) ");
105 /* Init: no FLASHes known */
106 for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
107 flash_info[i].flash_id = FLASH_UNKNOWN;
108 }
109
110 /* Static FLASH Bank configuration here - FIXME XXX */
111
112 size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
113
114 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
115 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
116 size_b0, size_b0<<20);
117 }
118 /* Only one bank */
119 if (CFG_MAX_FLASH_BANKS == 1)
120 {
121 /* Setup offsets */
122 /* flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]); */
123 /* Monitor protection ON by default */
124 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
125 flash_protect(FLAG_PROTECT_SET,
126 CFG_MONITOR_BASE,
127 CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
128 &flash_info[0]);
129 #endif
130 size_b1 = 0 ;
131 flash_info[0].size = size_b0;
132 }
133
134 /* 2 banks */
135 else
136 {
137 size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
138
139 /* Re-do sizing to get full correct info */
140
141 if (size_b1)
142 {
143 mtdcr(ebccfga, pb0cr);
144 pbcr = mfdcr(ebccfgd);
145 mtdcr(ebccfga, pb0cr);
146 base_b1 = -size_b1;
147 pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
148 mtdcr(ebccfgd, pbcr);
149 /* printf("pb1cr = %x\n", pbcr); */
150 }
151
152 if (size_b0)
153 {
154 mtdcr(ebccfga, pb1cr);
155 pbcr = mfdcr(ebccfgd);
156 mtdcr(ebccfga, pb1cr);
157 base_b0 = base_b1 - size_b0;
158 pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
159 mtdcr(ebccfgd, pbcr);
160 /* printf("pb0cr = %x\n", pbcr); */
161 }
162
163 size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]);
164
165 flash_get_offsets (base_b0, &flash_info[0]);
166
167 /* monitor protection ON by default */
168 (void)flash_protect(FLAG_PROTECT_SET,
169 base_b0+size_b0-CFG_MONITOR_LEN,
170 base_b0+size_b0-1,
171 &flash_info[0]);
172
173 if (size_b1) {
174 /* Re-do sizing to get full correct info */
175 size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]);
176
177 flash_get_offsets (base_b1, &flash_info[1]);
178
179 /* monitor protection ON by default */
180 (void)flash_protect(FLAG_PROTECT_SET,
181 base_b1+size_b1-CFG_MONITOR_LEN,
182 base_b1+size_b1-1,
183 &flash_info[1]);
184 /* monitor protection OFF by default (one is enough) */
185 (void)flash_protect(FLAG_PROTECT_CLEAR,
186 base_b0+size_b0-CFG_MONITOR_LEN,
187 base_b0+size_b0-1,
188 &flash_info[0]);
189 } else {
190 flash_info[1].flash_id = FLASH_UNKNOWN;
191 flash_info[1].sector_count = -1;
192 }
193
194 flash_info[0].size = size_b0;
195 flash_info[1].size = size_b1;
196 }/* else 2 banks */
197 switch_cs(rc); /* switch mode back */
198 return (size_b0 + size_b1);
199 }
200
201
202 static void flash_get_offsets (ulong base, flash_info_t *info)
203 {
204 return;
205 }
206 #if 0
207 /*-----------------------------------------------------------------------
208 */
209 static void flash_get_offsets (ulong base, flash_info_t *info)
210 {
211 int i;
212
213 /* set up sector start address table */
214 if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
215 (info->flash_id == FLASH_AM040)){
216 for (i = 0; i < info->sector_count; i++)
217 info->start[i] = base + (i * 0x00010000);
218 }
219 else {
220 if (info->flash_id & FLASH_BTYPE) {
221 /* set sector offsets for bottom boot block type */
222 info->start[0] = base + 0x00000000;
223 info->start[1] = base + 0x00004000;
224 info->start[2] = base + 0x00006000;
225 info->start[3] = base + 0x00008000;
226 for (i = 4; i < info->sector_count; i++) {
227 info->start[i] = base + (i * 0x00010000) - 0x00030000;
228 }
229 } else {
230 /* set sector offsets for top boot block type */
231 i = info->sector_count - 1;
232 info->start[i--] = base + info->size - 0x00004000;
233 info->start[i--] = base + info->size - 0x00006000;
234 info->start[i--] = base + info->size - 0x00008000;
235 for (; i >= 0; i--) {
236 info->start[i] = base + i * 0x00010000;
237 }
238 }
239 }
240 }
241
242 #endif
243 /*-----------------------------------------------------------------------
244 */
245 void flash_print_info (flash_info_t *info)
246 {
247 int i;
248 int k;
249 int size;
250 int erased;
251 volatile unsigned long *flash;
252
253 if (info->flash_id == FLASH_UNKNOWN) {
254 printf ("missing or unknown FLASH type\n");
255 return;
256 }
257
258 switch (info->flash_id & FLASH_VENDMASK) {
259 case FLASH_MAN_AMD: printf ("AMD "); break;
260 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
261 case FLASH_MAN_SST: printf ("SST "); break;
262 case FLASH_MAN_INTEL: printf ("Intel "); break;
263 default: printf ("Unknown Vendor "); break;
264 }
265
266 switch (info->flash_id & FLASH_TYPEMASK) {
267 case FLASH_AM040: printf ("AM29F040 (512 Kbit, uniform sector size)\n");
268 break;
269 case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
270 break;
271 case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
272 break;
273 case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
274 break;
275 case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
276 break;
277 case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
278 break;
279 case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
280 break;
281 case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
282 break;
283 case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
284 break;
285 case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
286 break;
287 case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
288 break;
289 case FLASH_INTEL320T: printf ("TE28F320C3 (32 Mbit, top sector size)\n");
290 break;
291 default: printf ("Unknown Chip Type\n");
292 break;
293 }
294
295 printf (" Size: %ld KB in %d Sectors\n",
296 info->size >> 10, info->sector_count);
297
298 printf (" Sector Start Addresses:");
299 for (i=0; i<info->sector_count; ++i) {
300 /*
301 * Check if whole sector is erased
302 */
303 if (i != (info->sector_count-1))
304 size = info->start[i+1] - info->start[i];
305 else
306 size = info->start[0] + info->size - info->start[i];
307 erased = 1;
308 flash = (volatile unsigned long *)info->start[i];
309 size = size >> 2; /* divide by 4 for longword access */
310 for (k=0; k<size; k++)
311 {
312 if (*flash++ != 0xffffffff)
313 {
314 erased = 0;
315 break;
316 }
317 }
318 if ((i % 5) == 0)
319 printf ("\n ");
320 #if 0 /* test-only */
321 printf (" %08lX%s",
322 info->start[i],
323 info->protect[i] ? " (RO)" : " "
324 #else
325 printf (" %08lX%s%s",
326 info->start[i],
327 erased ? " E" : " ",
328 info->protect[i] ? "RO " : " "
329 #endif
330 );
331 }
332 printf ("\n");
333
334 }
335
336 /*-----------------------------------------------------------------------
337 */
338
339
340 /*-----------------------------------------------------------------------
341 */
342
343 /*
344 * The following code cannot be run from FLASH!
345 */
346 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
347 {
348 short i;
349 FLASH_WORD_SIZE value;
350 ulong base = (ulong)addr;
351 volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
352
353 /* Write auto select command: read Manufacturer ID */
354 addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
355 addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
356 addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;
357
358 value = addr2[0];
359 /* printf("flash_get_size value: %x\n",value); */
360 switch (value) {
361 case (FLASH_WORD_SIZE)AMD_MANUFACT:
362 info->flash_id = FLASH_MAN_AMD;
363 break;
364 case (FLASH_WORD_SIZE)FUJ_MANUFACT:
365 info->flash_id = FLASH_MAN_FUJ;
366 break;
367 case (FLASH_WORD_SIZE)INTEL_MANUFACT:
368 info->flash_id = FLASH_MAN_INTEL;
369 break;
370 case (FLASH_WORD_SIZE)SST_MANUFACT:
371 info->flash_id = FLASH_MAN_SST;
372 break;
373 default:
374 info->flash_id = FLASH_UNKNOWN;
375 info->sector_count = 0;
376 info->size = 0;
377 return (0); /* no or unknown flash */
378 }
379 value = addr2[1]; /* device ID */
380 /* printf("Device value %x\n",value); */
381 switch (value) {
382 case (FLASH_WORD_SIZE)AMD_ID_F040B:
383 info->flash_id += FLASH_AM040;
384 info->sector_count = 8;
385 info->size = 0x0080000; /* => 512 ko */
386 break;
387 case (FLASH_WORD_SIZE)AMD_ID_LV400T:
388 info->flash_id += FLASH_AM400T;
389 info->sector_count = 11;
390 info->size = 0x00080000;
391 break; /* => 0.5 MB */
392
393 case (FLASH_WORD_SIZE)AMD_ID_LV400B:
394 info->flash_id += FLASH_AM400B;
395 info->sector_count = 11;
396 info->size = 0x00080000;
397 break; /* => 0.5 MB */
398
399 case (FLASH_WORD_SIZE)AMD_ID_LV800T:
400 info->flash_id += FLASH_AM800T;
401 info->sector_count = 19;
402 info->size = 0x00100000;
403 break; /* => 1 MB */
404
405 case (FLASH_WORD_SIZE)AMD_ID_LV800B:
406 info->flash_id += FLASH_AM800B;
407 info->sector_count = 19;
408 info->size = 0x00100000;
409 break; /* => 1 MB */
410
411 case (FLASH_WORD_SIZE)AMD_ID_LV160T:
412 info->flash_id += FLASH_AM160T;
413 info->sector_count = 35;
414 info->size = 0x00200000;
415 break; /* => 2 MB */
416
417 case (FLASH_WORD_SIZE)AMD_ID_LV160B:
418 info->flash_id += FLASH_AM160B;
419 info->sector_count = 35;
420 info->size = 0x00200000;
421 break; /* => 2 MB */
422 #if 0 /* enable when device IDs are available */
423 case (FLASH_WORD_SIZE)AMD_ID_LV320T:
424 info->flash_id += FLASH_AM320T;
425 info->sector_count = 67;
426 info->size = 0x00400000;
427 break; /* => 4 MB */
428
429 case (FLASH_WORD_SIZE)AMD_ID_LV320B:
430 info->flash_id += FLASH_AM320B;
431 info->sector_count = 67;
432 info->size = 0x00400000;
433 break; /* => 4 MB */
434 #endif
435 case (FLASH_WORD_SIZE)SST_ID_xF800A:
436 info->flash_id += FLASH_SST800A;
437 info->sector_count = 16;
438 info->size = 0x00100000;
439 break; /* => 1 MB */
440 case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T:
441 info->flash_id += FLASH_INTEL320T;
442 info->sector_count = 71;
443 info->size = 0x00400000;
444 break; /* => 4 MB */
445
446
447 case (FLASH_WORD_SIZE)SST_ID_xF160A:
448 info->flash_id += FLASH_SST160A;
449 info->sector_count = 32;
450 info->size = 0x00200000;
451 break; /* => 2 MB */
452
453 default:
454 info->flash_id = FLASH_UNKNOWN;
455 return (0); /* => no or unknown flash */
456
457 }
458
459 /* set up sector start address table */
460 if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
461 (info->flash_id == FLASH_AM040)){
462 for (i = 0; i < info->sector_count; i++)
463 info->start[i] = base + (i * 0x00010000);
464 } else {
465 if (info->flash_id & FLASH_BTYPE) {
466 /* set sector offsets for bottom boot block type */
467 info->start[0] = base + 0x00000000;
468 info->start[1] = base + 0x00004000;
469 info->start[2] = base + 0x00006000;
470 info->start[3] = base + 0x00008000;
471 for (i = 4; i < info->sector_count; i++)
472 info->start[i] = base + (i * 0x00010000) - 0x00030000;
473 }
474 else {
475 /* set sector offsets for top boot block type */
476 i = info->sector_count - 1;
477 if(info->sector_count==71) {
478
479 info->start[i--] = base + info->size - 0x00002000;
480 info->start[i--] = base + info->size - 0x00004000;
481 info->start[i--] = base + info->size - 0x00006000;
482 info->start[i--] = base + info->size - 0x00008000;
483 info->start[i--] = base + info->size - 0x0000A000;
484 info->start[i--] = base + info->size - 0x0000C000;
485 info->start[i--] = base + info->size - 0x0000E000;
486 for (; i >= 0; i--)
487 info->start[i] = base + i * 0x000010000;
488 }
489 else {
490 info->start[i--] = base + info->size - 0x00004000;
491 info->start[i--] = base + info->size - 0x00006000;
492 info->start[i--] = base + info->size - 0x00008000;
493 for (; i >= 0; i--)
494 info->start[i] = base + i * 0x00010000;
495 }
496 }
497 }
498
499 /* check for protected sectors */
500 for (i = 0; i < info->sector_count; i++) {
501 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
502 /* D0 = 1 if protected */
503 addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
504 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
505 info->protect[i] = 0;
506 else
507 info->protect[i] = addr2[2] & 1;
508 }
509
510 /*
511 * Prevent writes to uninitialized FLASH.
512 */
513 if (info->flash_id != FLASH_UNKNOWN) {
514 #if 0 /* test-only */
515 #ifdef CONFIG_ADCIOP
516 addr2 = (volatile unsigned char *)info->start[0];
517 addr2[ADDR0] = 0xAA;
518 addr2[ADDR1] = 0x55;
519 addr2[ADDR0] = 0xF0; /* reset bank */
520 #else
521 addr2 = (FLASH_WORD_SIZE *)info->start[0];
522 *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
523 #endif
524 #else /* test-only */
525 addr2 = (FLASH_WORD_SIZE *)info->start[0];
526 *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
527 #endif /* test-only */
528 }
529 return (info->size);
530 }
531
532 int wait_for_DQ7(flash_info_t *info, int sect)
533 {
534 ulong start, now, last;
535 volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
536
537 start = get_timer (0);
538 last = start;
539 while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
540 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
541 printf ("Timeout\n");
542 return -1;
543 }
544 /* show that we're waiting */
545 if ((now - last) > 1000) { /* every second */
546 putc ('.');
547 last = now;
548 }
549 }
550 return 0;
551 }
552
553 int intel_wait_for_DQ7(flash_info_t *info, int sect)
554 {
555 ulong start, now, last;
556 volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
557
558 start = get_timer (0);
559 last = start;
560 while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
561 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
562 printf ("Timeout\n");
563 return -1;
564 }
565 /* show that we're waiting */
566 if ((now - last) > 1000) { /* every second */
567 putc ('.');
568 last = now;
569 }
570 }
571 addr[0]=(FLASH_WORD_SIZE)0x00500050;
572 return 0;
573 }
574
575 /*-----------------------------------------------------------------------
576 */
577
578 int flash_erase (flash_info_t *info, int s_first, int s_last)
579 {
580 volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
581 volatile FLASH_WORD_SIZE *addr2;
582 int flag, prot, sect, l_sect;
583 int i;
584
585
586 if ((s_first < 0) || (s_first > s_last)) {
587 if (info->flash_id == FLASH_UNKNOWN) {
588 printf ("- missing\n");
589 } else {
590 printf ("- no sectors to erase\n");
591 }
592 return 1;
593 }
594
595 if (info->flash_id == FLASH_UNKNOWN) {
596 printf ("Can't erase unknown flash type - aborted\n");
597 return 1;
598 }
599
600 prot = 0;
601 for (sect=s_first; sect<=s_last; ++sect) {
602 if (info->protect[sect]) {
603 prot++;
604 }
605 }
606
607 if (prot) {
608 printf ("- Warning: %d protected sectors will not be erased!\n",
609 prot);
610 } else {
611 printf ("\n");
612 }
613
614 l_sect = -1;
615
616 /* Disable interrupts which might cause a timeout here */
617 flag = disable_interrupts();
618
619 /* Start erase on unprotected sectors */
620 for (sect = s_first; sect<=s_last; sect++) {
621 if (info->protect[sect] == 0) { /* not protected */
622 addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
623 /* printf("Erasing sector %p\n", addr2); */ /* CLH */
624 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
625 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
626 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
627 addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
628 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
629 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
630 addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */
631 for (i=0; i<50; i++)
632 udelay(1000); /* wait 1 ms */
633 wait_for_DQ7(info, sect);
634 }
635 else {
636 if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
637 addr2[0] = (FLASH_WORD_SIZE)0x00600060; /* unlock sector */
638 addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* sector erase */
639 intel_wait_for_DQ7(info, sect);
640 addr2[0] = (FLASH_WORD_SIZE)0x00200020; /* sector erase */
641 addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* sector erase */
642 intel_wait_for_DQ7(info, sect);
643 }
644 else {
645 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
646 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
647 addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
648 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
649 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
650 addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */
651 wait_for_DQ7(info, sect);
652 }
653 }
654 l_sect = sect;
655 /*
656 * Wait for each sector to complete, it's more
657 * reliable. According to AMD Spec, you must
658 * issue all erase commands within a specified
659 * timeout. This has been seen to fail, especially
660 * if printf()s are included (for debug)!!
661 */
662 /* wait_for_DQ7(info, sect); */
663 }
664 }
665
666 /* re-enable interrupts if necessary */
667 if (flag)
668 enable_interrupts();
669
670 /* wait at least 80us - let's wait 1 ms */
671 udelay (1000);
672
673 #if 0
674 /*
675 * We wait for the last triggered sector
676 */
677 if (l_sect < 0)
678 goto DONE;
679 wait_for_DQ7(info, l_sect);
680
681 DONE:
682 #endif
683 /* reset to read mode */
684 addr = (FLASH_WORD_SIZE *)info->start[0];
685 addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
686
687 printf (" done\n");
688 return 0;
689 }
690
691 void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
692 {
693 int i;
694 volatile FLASH_WORD_SIZE *addr2;
695 long c;
696 c= (long)cnt;
697 for(i=info->sector_count-1;i>0;i--)
698 {
699 if(addr>=info->start[i])
700 break;
701 }
702 do {
703 addr2 = (FLASH_WORD_SIZE *)(info->start[i]);
704 addr2[0] = (FLASH_WORD_SIZE)0x00600060; /* unlock sector setup */
705 addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* unlock sector */
706 intel_wait_for_DQ7(info, i);
707 i++;
708 c-=(info->start[i]-info->start[i-1]);
709 }while(c>0);
710
711
712 }
713
714
715 /*-----------------------------------------------------------------------
716 * Copy memory to flash, returns:
717 * 0 - OK
718 * 1 - write timeout
719 * 2 - Flash not erased
720 */
721
722 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
723 {
724 ulong cp, wp, data;
725 int i, l, rc;
726
727 if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
728 unlock_intel_sectors(info,addr,cnt);
729 }
730 wp = (addr & ~3); /* get lower word aligned address */
731 /*
732 * handle unaligned start bytes
733 */
734 if ((l = addr - wp) != 0) {
735 data = 0;
736 for (i=0, cp=wp; i<l; ++i, ++cp) {
737 data = (data << 8) | (*(uchar *)cp);
738 }
739 for (; i<4 && cnt>0; ++i) {
740 data = (data << 8) | *src++;
741 --cnt;
742 ++cp;
743 }
744 for (; cnt==0 && i<4; ++i, ++cp) {
745 data = (data << 8) | (*(uchar *)cp);
746 }
747
748 if ((rc = write_word(info, wp, data)) != 0) {
749 return (rc);
750 }
751 wp += 4;
752 }
753
754 /*
755 * handle word aligned part
756 */
757 while (cnt >= 4) {
758 data = 0;
759 for (i=0; i<4; ++i) {
760 data = (data << 8) | *src++;
761 }
762 if ((rc = write_word(info, wp, data)) != 0) {
763 return (rc);
764 }
765 wp += 4;
766 if((wp % 0x10000)==0)
767 printf("."); /* show Progress */
768 cnt -= 4;
769 }
770
771 if (cnt == 0) {
772 return (0);
773 }
774
775 /*
776 * handle unaligned tail bytes
777 */
778 data = 0;
779 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
780 data = (data << 8) | *src++;
781 --cnt;
782 }
783 for (; i<4; ++i, ++cp) {
784 data = (data << 8) | (*(uchar *)cp);
785 }
786 rc=write_word(info, wp, data);
787 return rc;
788 }
789
790 /*-----------------------------------------------------------------------
791 * Write a word to Flash, returns:
792 * 0 - OK
793 * 1 - write timeout
794 * 2 - Flash not erased
795 */
796 static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000;
797
798 static int write_word (flash_info_t *info, ulong dest, ulong data)
799 {
800 volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]);
801 volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
802 volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
803 ulong start;
804 int flag;
805 int i;
806
807 /* Check if Flash is (sufficiently) erased */
808 if ((*((volatile FLASH_WORD_SIZE *)dest) &
809 (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
810 return (2);
811 }
812 /* Disable interrupts which might cause a timeout here */
813 flag = disable_interrupts();
814 for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
815 {
816 if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
817 /* intel style writting */
818 dest2[i] = (FLASH_WORD_SIZE)0x00500050;
819 dest2[i] = (FLASH_WORD_SIZE)0x00400040;
820 *read_val++ = data2[i];
821 dest2[i] = data2[i];
822 if (flag)
823 enable_interrupts();
824 /* data polling for D7 */
825 start = get_timer (0);
826 udelay(10);
827 while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080)
828 {
829 if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
830 return (1);
831 }
832 dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
833 udelay(10);
834 dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
835 if(dest2[i]!=data2[i])
836 printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]);
837 }
838 else {
839 addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
840 addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
841 addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;
842 dest2[i] = data2[i];
843 /* re-enable interrupts if necessary */
844 if (flag)
845 enable_interrupts();
846 /* data polling for D7 */
847 start = get_timer (0);
848 while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
849 (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
850 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
851 return (1);
852 }
853 }
854 }
855 }
856 return (0);
857 }
858
859 /*-----------------------------------------------------------------------
860 */