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