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