]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mpl/common/flash.c
Initial revision
[karo-tx-uboot.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  */