]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/w7o/flash.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.git] / board / w7o / flash.c
1 /*
2  * (C) Copyright 2001
3  * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
4  *  Based on code by:
5  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 #include <common.h>
27 #include <ppc4xx.h>
28 #include <asm/processor.h>
29
30 #include <watchdog.h>
31
32 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips    */
33
34 /*-----------------------------------------------------------------------
35  * Functions
36  */
37 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
38 static int write_word8(flash_info_t *info, ulong dest, ulong data);
39 static int write_word32 (flash_info_t *info, ulong dest, ulong data);
40 static void flash_get_offsets (ulong base, flash_info_t *info);
41
42 /*-----------------------------------------------------------------------
43  */
44
45 unsigned long flash_init (void)
46 {
47     int i;
48     unsigned long size_b0, base_b0;
49     unsigned long size_b1, base_b1;
50
51     /* Init: no FLASHes known */
52     for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
53         flash_info[i].flash_id = FLASH_UNKNOWN;
54     }
55
56     /* Get Size of Boot and Main Flashes */
57     size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
58     if (flash_info[0].flash_id == FLASH_UNKNOWN) {
59         printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
60             size_b0, size_b0<<20);
61         return 0;
62     }
63     size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
64     if (flash_info[1].flash_id == FLASH_UNKNOWN) {
65         printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
66             size_b1, size_b1<<20);
67         return 0;
68     }
69
70     /* Calculate base addresses */
71     base_b0 = -size_b0;
72     base_b1 = -size_b1;
73
74     /* Setup offsets for Boot Flash */
75     flash_get_offsets (base_b0, &flash_info[0]);
76
77     /* Protect board level data */
78     (void)flash_protect(FLAG_PROTECT_SET,
79                         base_b0,
80                         flash_info[0].start[1] - 1,
81                         &flash_info[0]);
82
83
84     /* Monitor protection ON by default */
85     (void)flash_protect(FLAG_PROTECT_SET,
86                         base_b0 + size_b0 - monitor_flash_len,
87                         base_b0 + size_b0 - 1,
88                         &flash_info[0]);
89
90     /* Protect the FPGA image */
91     (void)flash_protect(FLAG_PROTECT_SET,
92                         FLASH_BASE1_PRELIM,
93                         FLASH_BASE1_PRELIM + CONFIG_SYS_FPGA_IMAGE_LEN - 1,
94                         &flash_info[1]);
95
96     /* Protect the default boot image */
97     (void)flash_protect(FLAG_PROTECT_SET,
98                         FLASH_BASE1_PRELIM + CONFIG_SYS_FPGA_IMAGE_LEN,
99                         FLASH_BASE1_PRELIM + CONFIG_SYS_FPGA_IMAGE_LEN + 0x600000 - 1,
100                         &flash_info[1]);
101
102     /* Setup offsets for Main Flash */
103     flash_get_offsets (FLASH_BASE1_PRELIM, &flash_info[1]);
104
105     return (size_b0 + size_b1);
106 } /* end flash_init() */
107
108 /*-----------------------------------------------------------------------
109  */
110 static void flash_get_offsets (ulong base, flash_info_t *info)
111 {
112     int i;
113
114     /* set up sector start address table - FOR BOOT ROM ONLY!!! */
115     if ((info->flash_id & FLASH_TYPEMASK)  == FLASH_AM040) {
116         for (i = 0; i < info->sector_count; i++)
117             info->start[i] = base + (i * 0x00010000);
118     }
119 } /* end flash_get_offsets() */
120
121 /*-----------------------------------------------------------------------
122  */
123 void flash_print_info  (flash_info_t *info)
124 {
125     int i;
126     int k;
127     int size;
128     int erased;
129     volatile unsigned long *flash;
130
131     if (info->flash_id == FLASH_UNKNOWN) {
132         printf ("missing or unknown FLASH type\n");
133         return;
134     }
135
136     switch (info->flash_id & FLASH_VENDMASK) {
137         case FLASH_MAN_AMD:     printf ("1 x AMD ");    break;
138         case FLASH_MAN_STM:     printf ("1 x STM ");    break;
139         case FLASH_MAN_INTEL:   printf ("2 x Intel ");  break;
140         default:                printf ("Unknown Vendor ");
141     }
142
143     switch (info->flash_id & FLASH_TYPEMASK) {
144         case FLASH_AM040:
145             if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
146                 printf ("AM29LV040 (4096 Kbit, uniform sector size)\n");
147             else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM)
148                 printf ("M29W040B (4096 Kbit, uniform block size)\n");
149             else
150                 printf ("UNKNOWN 29x040x (4096 Kbit, uniform sector size)\n");
151             break;
152         case FLASH_28F320J3A:
153             printf ("28F320J3A (32 Mbit = 128K x 32)\n");
154             break;
155         case FLASH_28F640J3A:
156             printf ("28F640J3A (64 Mbit = 128K x 64)\n");
157             break;
158         case FLASH_28F128J3A:
159             printf ("28F128J3A (128 Mbit = 128K x 128)\n");
160             break;
161         default:
162             printf ("Unknown Chip Type\n");
163     }
164
165     if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) {
166         printf ("  Size: %ld KB in %d Blocks\n",
167                 info->size >> 10, info->sector_count);
168     } else {
169         printf ("  Size: %ld KB in %d Sectors\n",
170                 info->size >> 10, info->sector_count);
171     }
172
173     printf ("  Sector Start Addresses:");
174     for (i=0; i<info->sector_count; ++i) {
175         /*
176          * Check if whole sector is erased
177          */
178         if (i != (info->sector_count-1))
179             size = info->start[i+1] - info->start[i];
180         else
181             size = info->start[0] + info->size - info->start[i];
182         erased = 1;
183         flash = (volatile unsigned long *)info->start[i];
184         size = size >> 2;        /* divide by 4 for longword access */
185         for (k=0; k<size; k++)
186         {
187             if (*flash++ != 0xffffffff)
188             {
189                 erased = 0;
190                 break;
191             }
192         }
193
194         if ((i % 5) == 0)
195             printf ("\n   ");
196         printf (" %08lX%s%s",
197             info->start[i],
198             erased ? " E" : "  ",
199             info->protect[i] ? "RO " : "   "
200         );
201     }
202     printf ("\n");
203 } /* end flash_print_info() */
204
205 /*
206  * The following code cannot be run from FLASH!
207  */
208 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
209 {
210     short i;
211     ulong base = (ulong)addr;
212
213     /* Setup default type */
214     info->flash_id = FLASH_UNKNOWN;
215     info->sector_count =0;
216     info->size = 0;
217
218     /* Test for Boot Flash */
219     if (base == FLASH_BASE0_PRELIM) {
220         unsigned char value;
221         volatile unsigned char * addr2 = (unsigned char *)addr;
222
223         /* Write auto select command: read Manufacturer ID */
224         *(addr2 + 0x555) = 0xaa;
225         *(addr2 + 0x2aa) = 0x55;
226         *(addr2 + 0x555) = 0x90;
227
228         /* Manufacture ID */
229         value = *addr2;
230         switch (value) {
231             case (unsigned char)AMD_MANUFACT:
232                 info->flash_id = FLASH_MAN_AMD;
233                 break;
234             case (unsigned char)STM_MANUFACT:
235                 info->flash_id = FLASH_MAN_STM;
236                 break;
237             default:
238                 *addr2 = 0xf0;              /* no or unknown flash  */
239                 return 0;
240         }
241
242         /* Device ID */
243         value = *(addr2 + 1);
244         switch (value) {
245             case (unsigned char)AMD_ID_LV040B:
246             case (unsigned char)STM_ID_29W040B:
247                 info->flash_id += FLASH_AM040;
248                 info->sector_count = 8;
249                 info->size = 0x00080000;
250                 break;                       /* => 512Kb */
251             default:
252                 *addr2 = 0xf0;               /* => no or unknown flash */
253                 return 0;
254         }
255     }
256     else { /* MAIN Flash */
257         unsigned long value;
258         volatile unsigned long * addr2 = (unsigned long *)addr;
259
260         /* Write auto select command: read Manufacturer ID */
261         *addr2 = 0x90909090;
262
263         /* Manufacture ID */
264         value = *addr2;
265         switch (value) {
266             case (unsigned long)INTEL_MANUFACT:
267                 info->flash_id = FLASH_MAN_INTEL;
268                 break;
269             default:
270                 *addr2 = 0xff;              /* no or unknown flash  */
271                 return 0;
272         }
273
274         /* Device ID - This shit is interleaved... */
275         value = *(addr2 + 1);
276         switch (value) {
277             case (unsigned long)INTEL_ID_28F320J3A:
278                 info->flash_id += FLASH_28F320J3A;
279                 info->sector_count = 32;
280                 info->size = 0x00400000 * 2;
281                 break;                       /* => 2 X 4 MB */
282             case (unsigned long)INTEL_ID_28F640J3A:
283                 info->flash_id += FLASH_28F640J3A;
284                 info->sector_count = 64;
285                 info->size = 0x00800000 * 2;
286                 break;                       /* => 2 X 8 MB */
287             case (unsigned long)INTEL_ID_28F128J3A:
288                 info->flash_id += FLASH_28F128J3A;
289                 info->sector_count = 128;
290                 info->size = 0x01000000 * 2;
291                 break;                       /* => 2 X 16 MB */
292             default:
293                 *addr2 = 0xff;               /* => no or unknown flash */
294         }
295     }
296
297     /* Make sure we don't exceed CONFIG_SYS_MAX_FLASH_SECT */
298     if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
299         printf ("** ERROR: sector count %d > max (%d) **\n",
300                 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
301         info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
302     }
303
304     /* set up sector start address table */
305     switch (info->flash_id & FLASH_TYPEMASK) {
306         case FLASH_AM040:
307             for (i = 0; i < info->sector_count; i++)
308                 info->start[i] = base + (i * 0x00010000);
309             break;
310         case FLASH_28F320J3A:
311         case FLASH_28F640J3A:
312         case FLASH_28F128J3A:
313             for (i = 0; i < info->sector_count; i++)
314                 info->start[i] = base + (i * 0x00020000 * 2); /* 2 Banks */
315             break;
316     }
317
318     /* Test for Boot Flash */
319     if (base == FLASH_BASE0_PRELIM) {
320         volatile unsigned char *addr2;
321         /* check for protected sectors */
322         for (i = 0; i < info->sector_count; i++) {
323             /* read sector protection at sector address, (AX .. A0) = 0x02 */
324             /* D0 = 1 if protected */
325             addr2 = (volatile unsigned char *)(info->start[i]);
326             info->protect[i] = *(addr2 + 2) & 1;
327         }
328
329         /* Restore read mode */
330         *(unsigned char *)base = 0xF0;       /* Reset NORMAL Flash */
331     }
332     else { /* Main Flash */
333         volatile unsigned long *addr2;
334         /* check for protected sectors */
335         for (i = 0; i < info->sector_count; i++) {
336             /* read sector protection at sector address, (AX .. A0) = 0x02 */
337             /* D0 = 1 if protected */
338             addr2 = (volatile unsigned long *)(info->start[i]);
339             info->protect[i] = *(addr2 + 2) & 0x1;
340         }
341
342         /* Restore read mode */
343         *(unsigned long *)base = 0xFFFFFFFF; /* Reset  Flash */
344     }
345
346     return (info->size);
347 } /* end flash_get_size() */
348
349 /*-----------------------------------------------------------------------
350  */
351
352 static int wait_for_DQ7(ulong addr, uchar cmp_val, ulong tout)
353 {
354     int i;
355
356     volatile uchar *vaddr =  (uchar *)addr;
357
358     /* Loop X times */
359     for (i = 1; i <= (100 * tout); i++) {    /* Wait up to tout ms */
360         udelay(10);
361         /* Pause 10 us */
362
363         /* Check for completion */
364         if ((vaddr[0] & 0x80) == (cmp_val & 0x80)) {
365             return 0;
366         }
367
368         /* KEEP THE LUSER HAPPY - Print a dot every 1.1 seconds */
369         if (!(i % 110000))
370             putc('.');
371
372         /* Kick the dog if needed */
373         WATCHDOG_RESET();
374     }
375
376     return 1;
377 } /* wait_for_DQ7() */
378
379 /*-----------------------------------------------------------------------
380  */
381
382 static int flash_erase8(flash_info_t *info, int s_first, int s_last)
383 {
384     int tcode, rcode = 0;
385     volatile uchar *addr = (uchar *)(info->start[0]);
386     volatile uchar *sector_addr;
387     int flag, prot, sect;
388
389     /* Validate arguments */
390     if ((s_first < 0) || (s_first > s_last)) {
391         if (info->flash_id == FLASH_UNKNOWN)
392             printf ("- missing\n");
393         else
394             printf ("- no sectors to erase\n");
395         return 1;
396     }
397
398     /* Check for KNOWN flash type */
399     if (info->flash_id == FLASH_UNKNOWN) {
400         printf ("Can't erase unknown flash type - aborted\n");
401         return 1;
402     }
403
404     /* Check for protected sectors */
405     prot = 0;
406     for (sect = s_first; sect <= s_last; ++sect) {
407         if (info->protect[sect])
408             prot++;
409     }
410     if (prot)
411         printf ("- Warning: %d protected sectors will not be erased!\n", prot);
412     else
413         printf ("\n");
414
415     /* Start erase on unprotected sectors */
416     for (sect = s_first; sect <= s_last; sect++) {
417         if (info->protect[sect] == 0) {      /* not protected */
418             sector_addr = (uchar *)(info->start[sect]);
419
420                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM)
421                     printf("Erasing block %p\n", sector_addr);
422                 else
423                     printf("Erasing sector %p\n", sector_addr);
424
425             /* Disable interrupts which might cause Flash to timeout */
426             flag = disable_interrupts();
427
428             *(addr + 0x555) = (uchar)0xAA;
429             *(addr + 0x2aa) = (uchar)0x55;
430             *(addr + 0x555) = (uchar)0x80;
431             *(addr + 0x555) = (uchar)0xAA;
432             *(addr + 0x2aa) = (uchar)0x55;
433             *sector_addr = (uchar)0x30;      /* sector erase */
434
435             /*
436              * Wait for each sector to complete, it's more
437              * reliable.  According to AMD Spec, you must
438              * issue all erase commands within a specified
439              * timeout.  This has been seen to fail, especially
440              * if printf()s are included (for debug)!!
441              * Takes up to 6 seconds.
442              */
443             tcode  = wait_for_DQ7((ulong)sector_addr, 0x80, 6000);
444
445             /* re-enable interrupts if necessary */
446             if (flag)
447                 enable_interrupts();
448
449             /* Make sure we didn't timeout */
450             if (tcode) {
451                 printf ("Timeout\n");
452                 rcode = 1;
453             }
454         }
455     }
456
457     /* wait at least 80us - let's wait 1 ms */
458     udelay (1000);
459
460     /* reset to read mode */
461     addr = (uchar *)info->start[0];
462     *addr = (uchar)0xF0;                     /* reset bank */
463
464     printf (" done\n");
465     return rcode;
466 } /* end flash_erase8() */
467
468 static int flash_erase32(flash_info_t *info, int s_first, int s_last)
469 {
470     int flag, sect;
471     ulong start, now, last;
472     int prot = 0;
473
474     /* Validate arguments */
475     if ((s_first < 0) || (s_first > s_last)) {
476         if (info->flash_id == FLASH_UNKNOWN)
477             printf ("- missing\n");
478         else
479             printf ("- no sectors to erase\n");
480         return 1;
481     }
482
483     /* Check for KNOWN flash type */
484     if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
485         printf ("Can erase only Intel flash types - aborted\n");
486         return 1;
487     }
488
489     /* Check for protected sectors */
490     for (sect = s_first; sect <= s_last; ++sect) {
491         if (info->protect[sect])
492             prot++;
493     }
494     if (prot)
495         printf ("- Warning: %d protected sectors will not be erased!\n", prot);
496     else
497         printf ("\n");
498
499     start = get_timer (0);
500     last  = start;
501     /* Start erase on unprotected sectors */
502     for (sect = s_first; sect <= s_last; sect++) {
503         WATCHDOG_RESET();
504         if (info->protect[sect] == 0) {      /* not protected */
505             vu_long *addr = (vu_long *)(info->start[sect]);
506             unsigned long status;
507
508             /* Disable interrupts which might cause a timeout here */
509             flag = disable_interrupts();
510
511             *addr = 0x00500050;              /* clear status register */
512             *addr = 0x00200020;              /* erase setup */
513             *addr = 0x00D000D0;              /* erase confirm */
514
515             /* re-enable interrupts if necessary */
516             if (flag)
517                 enable_interrupts();
518
519             /* Wait at least 80us - let's wait 1 ms */
520             udelay (1000);
521
522             while (((status = *addr) & 0x00800080) != 0x00800080) {
523                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
524                     printf ("Timeout\n");
525                     *addr = 0x00B000B0;      /* suspend erase      */
526                     *addr = 0x00FF00FF;      /* reset to read mode */
527                     return 1;
528                 }
529
530                 /* show that we're waiting */
531                 if ((now - last) > 990) {   /* every second */
532                     putc ('.');
533                     last = now;
534                 }
535             }
536             *addr = 0x00FF00FF;              /* reset to read mode */
537         }
538     }
539     printf (" done\n");
540     return 0;
541 } /* end flash_erase32() */
542
543 int flash_erase(flash_info_t *info, int s_first, int s_last)
544 {
545     if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
546         return flash_erase8(info, s_first, s_last);
547     else
548         return flash_erase32(info, s_first, s_last);
549 } /* end flash_erase() */
550
551 /*-----------------------------------------------------------------------
552  * Copy memory to flash, returns:
553  * 0 - OK
554  * 1 - write timeout
555  * 2 - Flash not erased
556  */
557 static int write_buff8(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
558 {
559     ulong cp, wp, data;
560     ulong start;
561     int i, l, rc;
562
563     start = get_timer (0);
564
565     wp = (addr & ~3);                        /* get lower word
566                                                 aligned address */
567
568     /*
569      * handle unaligned start bytes
570      */
571     if ((l = addr - wp) != 0) {
572         data = 0;
573         for (i=0, cp=wp; i<l; ++i, ++cp) {
574             data = (data << 8) | (*(uchar *)cp);
575         }
576         for (; i<4 && cnt>0; ++i) {
577             data = (data << 8) | *src++;
578             --cnt;
579             ++cp;
580         }
581         for (; cnt==0 && i<4; ++i, ++cp) {
582             data = (data << 8) | (*(uchar *)cp);
583         }
584
585         if ((rc = write_word8(info, wp, data)) != 0) {
586             return (rc);
587         }
588         wp += 4;
589     }
590
591     /*
592      * handle word aligned part
593      */
594     while (cnt >= 4) {
595         data = 0;
596         for (i=0; i<4; ++i) {
597             data = (data << 8) | *src++;
598         }
599         if ((rc = write_word8(info, wp, data)) != 0) {
600             return (rc);
601         }
602         wp  += 4;
603         cnt -= 4;
604         if (get_timer(start) > 1000) {   /* every second */
605            WATCHDOG_RESET();
606            putc ('.');
607            start = get_timer(0);
608         }
609     }
610
611     if (cnt == 0) {
612         return (0);
613     }
614
615     /*
616      * handle unaligned tail bytes
617      */
618     data = 0;
619     for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
620         data = (data << 8) | *src++;
621         --cnt;
622     }
623     for (; i<4; ++i, ++cp) {
624         data = (data << 8) | (*(uchar *)cp);
625     }
626
627     return (write_word8(info, wp, data));
628 } /* end write_buff8() */
629
630 #define FLASH_WIDTH     4       /* flash bus width in bytes */
631 static int write_buff32 (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
632 {
633         ulong cp, wp, data;
634         int i, l, rc;
635         ulong start;
636
637         start = get_timer (0);
638
639         if (info->flash_id == FLASH_UNKNOWN) {
640                 return 4;
641         }
642
643         wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH aligned address */
644
645         /*
646          * handle unaligned start bytes
647          */
648         if ((l = addr - wp) != 0) {
649                 data = 0;
650                 for (i=0, cp=wp; i<l; ++i, ++cp) {
651                         data = (data << 8) | (*(uchar *)cp);
652                 }
653                 for (; i<FLASH_WIDTH && cnt>0; ++i) {
654                         data = (data << 8) | *src++;
655                         --cnt;
656                         ++cp;
657                 }
658                 for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
659                         data = (data << 8) | (*(uchar *)cp);
660                 }
661
662                 if ((rc = write_word32(info, wp, data)) != 0) {
663                         return (rc);
664                 }
665                 wp += FLASH_WIDTH;
666         }
667
668         /*
669          * handle FLASH_WIDTH aligned part
670          */
671         while (cnt >= FLASH_WIDTH) {
672                 data = 0;
673                 for (i=0; i<FLASH_WIDTH; ++i) {
674                         data = (data << 8) | *src++;
675                 }
676                 if ((rc = write_word32(info, wp, data)) != 0) {
677                         return (rc);
678                 }
679                 wp  += FLASH_WIDTH;
680                 cnt -= FLASH_WIDTH;
681           if (get_timer(start) > 990) {   /* every second */
682                         putc ('.');
683                         start = get_timer(0);
684                 }
685         }
686
687         if (cnt == 0) {
688                 return (0);
689         }
690
691         /*
692          * handle unaligned tail bytes
693          */
694         data = 0;
695         for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
696                 data = (data << 8) | *src++;
697                 --cnt;
698         }
699         for (; i<FLASH_WIDTH; ++i, ++cp) {
700                 data = (data << 8) | (*(uchar *)cp);
701         }
702
703         return (write_word32(info, wp, data));
704 } /* write_buff32() */
705
706 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
707 {
708     int retval;
709
710     if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
711         retval = write_buff8(info, src, addr, cnt);
712     else
713         retval = write_buff32(info, src, addr, cnt);
714
715     return retval;
716 } /* end write_buff() */
717
718 /*-----------------------------------------------------------------------
719  * Write a word to Flash, returns:
720  * 0 - OK
721  * 1 - write timeout
722  * 2 - Flash not erased
723  */
724
725 static int write_word8(flash_info_t *info, ulong dest, ulong data)
726 {
727     volatile uchar *addr2 = (uchar *)(info->start[0]);
728     volatile uchar *dest2 = (uchar *)dest;
729     volatile uchar *data2 = (uchar *)&data;
730     int flag;
731     int i, tcode, rcode = 0;
732
733     /* Check if Flash is (sufficently) erased */
734     if ((*((volatile uchar *)dest) &
735         (uchar)data) != (uchar)data) {
736         return (2);
737     }
738
739     for (i=0; i < (4 / sizeof(uchar)); i++) {
740         /* Disable interrupts which might cause a timeout here */
741         flag = disable_interrupts();
742
743         *(addr2 + 0x555) = (uchar)0xAA;
744         *(addr2 + 0x2aa) = (uchar)0x55;
745         *(addr2 + 0x555) = (uchar)0xA0;
746
747         dest2[i] = data2[i];
748
749         /* Wait for write to complete, up to 1ms */
750         tcode = wait_for_DQ7((ulong)&dest2[i], data2[i], 1);
751
752         /* re-enable interrupts if necessary */
753         if (flag)
754             enable_interrupts();
755
756         /* Make sure we didn't timeout */
757         if (tcode) {
758             rcode = 1;
759         }
760     }
761
762     return rcode;
763 } /* end write_word8() */
764
765 static int write_word32(flash_info_t *info, ulong dest, ulong data)
766 {
767     vu_long *addr = (vu_long *)dest;
768     ulong status;
769     ulong start;
770     int flag;
771
772     /* Check if Flash is (sufficiently) erased */
773     if ((*addr & data) != data) {
774         return (2);
775     }
776     /* Disable interrupts which might cause a timeout here */
777     flag = disable_interrupts();
778
779     *addr = 0x00400040;                      /* write setup */
780     *addr = data;
781
782     /* re-enable interrupts if necessary */
783     if (flag)
784         enable_interrupts();
785
786     start = get_timer (0);
787
788     while (((status = *addr) & 0x00800080) != 0x00800080) {
789         WATCHDOG_RESET();
790         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
791             *addr = 0x00FF00FF;              /* restore read mode */
792             return (1);
793         }
794     }
795
796     *addr = 0x00FF00FF;                      /* restore read mode */
797
798     return (0);
799 } /* end write_word32() */
800
801
802 static int _flash_protect(flash_info_t *info, long sector)
803 {
804     int i;
805     int flag;
806     ulong status;
807     int rcode = 0;
808     volatile long *addr = (long *)sector;
809
810     switch(info->flash_id & FLASH_TYPEMASK) {
811         case FLASH_28F320J3A:
812         case FLASH_28F640J3A:
813         case FLASH_28F128J3A:
814             /* Disable interrupts which might cause Flash to timeout */
815             flag = disable_interrupts();
816
817             /* Issue command */
818             *addr = 0x00500050L;             /* Clear the status register */
819             *addr = 0x00600060L;             /* Set lock bit setup */
820             *addr = 0x00010001L;             /* Set lock bit confirm */
821
822             /* Wait for command completion */
823             for (i = 0; i < 10; i++) {       /* 75us timeout, wait 100us */
824                 udelay(10);
825                 if ((*addr & 0x00800080L) == 0x00800080L)
826                     break;
827             }
828
829             /* Not successful? */
830             status = *addr;
831             if (status != 0x00800080L) {
832                 printf("Protect %x sector failed: %x\n",
833                        (uint)sector, (uint)status);
834                 rcode = 1;
835             }
836
837             /* Restore read mode */
838             *addr = 0x00ff00ffL;
839
840             /* re-enable interrupts if necessary */
841             if (flag)
842                 enable_interrupts();
843
844             break;
845         case FLASH_AM040:                    /* No soft sector protection */
846             break;
847     }
848
849     /* Turn protection on for this sector */
850     for (i = 0; i < info->sector_count; i++) {
851         if (info->start[i] == sector) {
852             info->protect[i] = 1;
853             break;
854         }
855     }
856
857     return rcode;
858 } /* end _flash_protect() */
859
860 static int _flash_unprotect(flash_info_t *info, long sector)
861 {
862     int i;
863     int flag;
864     ulong status;
865     int rcode = 0;
866     volatile long *addr = (long *)sector;
867
868     switch(info->flash_id & FLASH_TYPEMASK) {
869         case FLASH_28F320J3A:
870         case FLASH_28F640J3A:
871         case FLASH_28F128J3A:
872             /* Disable interrupts which might cause Flash to timeout */
873             flag = disable_interrupts();
874
875             *addr = 0x00500050L;             /* Clear the status register */
876             *addr = 0x00600060L;             /* Clear lock bit setup */
877             *addr = 0x00D000D0L;             /* Clear lock bit confirm */
878
879             /* Wait for command completion */
880             for (i = 0; i < 80 ; i++) {      /* 700ms timeout, wait 800 */
881                 udelay(10000);               /* Delay 10ms */
882                 if ((*addr & 0x00800080L) == 0x00800080L)
883                     break;
884             }
885
886             /* Not successful? */
887             status = *addr;
888             if (status != 0x00800080L) {
889                 printf("Un-protect %x sector failed: %x\n",
890                        (uint)sector, (uint)status);
891                 *addr = 0x00ff00ffL;
892                 rcode = 1;
893             }
894
895             /* restore read mode */
896             *addr = 0x00ff00ffL;
897
898             /* re-enable interrupts if necessary */
899             if (flag)
900                 enable_interrupts();
901
902             break;
903         case FLASH_AM040:                    /* No soft sector protection */
904             break;
905     }
906
907     /*
908      * Fix Intel's little red wagon.  Reprotect
909      * sectors that were protected before we undid
910      * protection on a specific sector.
911      */
912     for (i = 0; i < info->sector_count; i++) {
913         if (info->start[i] != sector) {
914             if (info->protect[i]) {
915                 if (_flash_protect(info, info->start[i]))
916                     rcode = 1;
917             }
918         }
919         else /* Turn protection off for this sector */
920             info->protect[i] = 0;
921     }
922
923     return rcode;
924 } /* end _flash_unprotect() */
925
926
927 int flash_real_protect(flash_info_t *info, long sector, int prot)
928 {
929     int rcode;
930
931     if (prot)
932         rcode = _flash_protect(info, info->start[sector]);
933     else
934         rcode = _flash_unprotect(info, info->start[sector]);
935
936     return rcode;
937 } /* end flash_real_protect() */
938
939 /*-----------------------------------------------------------------------
940  */