]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/logodl/flash.c
0240c72362f82126f35a49e5b37096cba287dbe7
[karo-tx-uboot.git] / board / logodl / flash.c
1 /*
2  * (C) 2000 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
3  * (C) 2003 August Hoeraendl, Logotronic GmbH
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #undef CONFIG_FLASH_16BIT
25
26 #include <common.h>
27
28 #define FLASH_BANK_SIZE 0x1000000
29 #define MAIN_SECT_SIZE  0x20000 /* 2x64k = 128k per sector */
30
31 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips    */
32
33 /* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
34  *        has nothing to do with the flash chip being 8-bit or 16-bit.
35  */
36 #ifdef CONFIG_FLASH_16BIT
37 typedef unsigned short FLASH_PORT_WIDTH;
38 typedef volatile unsigned short FLASH_PORT_WIDTHV;
39
40 #define FLASH_ID_MASK   0xFFFF
41 #else
42 typedef unsigned long FLASH_PORT_WIDTH;
43 typedef volatile unsigned long FLASH_PORT_WIDTHV;
44
45 #define FLASH_ID_MASK   0xFFFFFFFF
46 #endif
47
48 #define FPW     FLASH_PORT_WIDTH
49 #define FPWV    FLASH_PORT_WIDTHV
50
51 #define ORMASK(size) ((-size) & OR_AM_MSK)
52
53 /*-----------------------------------------------------------------------
54  * Functions
55  */
56 static ulong flash_get_size (FPWV * addr, flash_info_t * info);
57 static void flash_reset (flash_info_t * info);
58 static int write_word_intel (flash_info_t * info, FPWV * dest, FPW data);
59 static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data);
60
61 #define write_word(in, de, da)   write_word_amd(in, de, da)
62 static void flash_get_offsets (ulong base, flash_info_t * info);
63
64 #ifdef CFG_FLASH_PROTECTION
65 static void flash_sync_real_protect (flash_info_t * info);
66 #endif
67
68 /*-----------------------------------------------------------------------
69  * flash_init()
70  *
71  * sets up flash_info and returns size of FLASH (bytes)
72  */
73 ulong flash_init (void)
74 {
75         int i, j;
76         ulong size = 0;
77
78         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
79                 ulong flashbase = 0;
80
81                 flash_info[i].flash_id =
82                                 (FLASH_MAN_AMD & FLASH_VENDMASK) |
83                                 (FLASH_AM640U & FLASH_TYPEMASK);
84                 flash_info[i].size = FLASH_BANK_SIZE;
85                 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
86                 memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
87                 switch (i) {
88                 case 0:
89                         flashbase = PHYS_FLASH_1;
90                         break;
91                 case 1:
92                         flashbase = PHYS_FLASH_2;
93                         break;
94                 default:
95                         panic ("configured to many flash banks!\n");
96                         break;
97                 }
98                 for (j = 0; j < flash_info[i].sector_count; j++) {
99                         flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
100                 }
101                 size += flash_info[i].size;
102         }
103
104         /* Protect monitor and environment sectors
105          */
106         flash_protect (FLAG_PROTECT_SET,
107                         CFG_FLASH_BASE,
108                         CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
109                         &flash_info[0]);
110
111         flash_protect (FLAG_PROTECT_SET,
112                         CFG_ENV_ADDR,
113                         CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
114
115         return size;
116 }
117
118 /*-----------------------------------------------------------------------
119  */
120 static void flash_reset (flash_info_t * info)
121 {
122         FPWV *base = (FPWV *) (info->start[0]);
123
124         /* Put FLASH back in read mode */
125         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
126                 *base = (FPW) 0x00FF00FF;       /* Intel Read Mode */
127         else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
128                 *base = (FPW) 0x00F000F0;       /* AMD Read Mode */
129 }
130
131 /*-----------------------------------------------------------------------
132  */
133 static void flash_get_offsets (ulong base, flash_info_t * info)
134 {
135         int i;
136
137         /* set up sector start address table */
138         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
139                 && (info->flash_id & FLASH_BTYPE)) {
140                 int bootsect_size;      /* number of bytes/boot sector  */
141                 int sect_size;          /* number of bytes/regular sector */
142
143                 bootsect_size = 0x00002000 * (sizeof (FPW) / 2);
144                 sect_size = 0x00010000 * (sizeof (FPW) / 2);
145
146                 /* set sector offsets for bottom boot block type    */
147                 for (i = 0; i < 8; ++i) {
148                         info->start[i] = base + (i * bootsect_size);
149                 }
150                 for (i = 8; i < info->sector_count; i++) {
151                         info->start[i] = base + ((i - 7) * sect_size);
152                 }
153         } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
154                            && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
155
156                 int sect_size;          /* number of bytes/sector */
157
158                 sect_size = 0x00010000 * (sizeof (FPW) / 2);
159
160                 /* set up sector start address table (uniform sector type) */
161                 for (i = 0; i < info->sector_count; i++)
162                         info->start[i] = base + (i * sect_size);
163         }
164 }
165
166 /*-----------------------------------------------------------------------
167  */
168
169 void flash_print_info (flash_info_t * info)
170 {
171         int i;
172         uchar *boottype;
173         uchar *bootletter;
174         uchar *fmt;
175         uchar botbootletter[] = "B";
176         uchar topbootletter[] = "T";
177         uchar botboottype[] = "bottom boot sector";
178         uchar topboottype[] = "top boot sector";
179
180         if (info->flash_id == FLASH_UNKNOWN) {
181                 printf ("missing or unknown FLASH type\n");
182                 return;
183         }
184
185         switch (info->flash_id & FLASH_VENDMASK) {
186         case FLASH_MAN_AMD:
187                 printf ("AMD ");
188                 break;
189         case FLASH_MAN_BM:
190                 printf ("BRIGHT MICRO ");
191                 break;
192         case FLASH_MAN_FUJ:
193                 printf ("FUJITSU ");
194                 break;
195         case FLASH_MAN_SST:
196                 printf ("SST ");
197                 break;
198         case FLASH_MAN_STM:
199                 printf ("STM ");
200                 break;
201         case FLASH_MAN_INTEL:
202                 printf ("INTEL ");
203                 break;
204         default:
205                 printf ("Unknown Vendor ");
206                 break;
207         }
208
209         /* check for top or bottom boot, if it applies */
210         if (info->flash_id & FLASH_BTYPE) {
211                 boottype = botboottype;
212                 bootletter = botbootletter;
213         } else {
214                 boottype = topboottype;
215                 bootletter = topbootletter;
216         }
217
218         switch (info->flash_id & FLASH_TYPEMASK) {
219         case FLASH_AM640U:
220                 fmt = "29LV641D (64 Mbit, uniform sectors)\n";
221                 break;
222         case FLASH_28F800C3B:
223         case FLASH_28F800C3T:
224                 fmt = "28F800C3%s (8 Mbit, %s)\n";
225                 break;
226         case FLASH_INTEL800B:
227         case FLASH_INTEL800T:
228                 fmt = "28F800B3%s (8 Mbit, %s)\n";
229                 break;
230         case FLASH_28F160C3B:
231         case FLASH_28F160C3T:
232                 fmt = "28F160C3%s (16 Mbit, %s)\n";
233                 break;
234         case FLASH_INTEL160B:
235         case FLASH_INTEL160T:
236                 fmt = "28F160B3%s (16 Mbit, %s)\n";
237                 break;
238         case FLASH_28F320C3B:
239         case FLASH_28F320C3T:
240                 fmt = "28F320C3%s (32 Mbit, %s)\n";
241                 break;
242         case FLASH_INTEL320B:
243         case FLASH_INTEL320T:
244                 fmt = "28F320B3%s (32 Mbit, %s)\n";
245                 break;
246         case FLASH_28F640C3B:
247         case FLASH_28F640C3T:
248                 fmt = "28F640C3%s (64 Mbit, %s)\n";
249                 break;
250         case FLASH_INTEL640B:
251         case FLASH_INTEL640T:
252                 fmt = "28F640B3%s (64 Mbit, %s)\n";
253                 break;
254         default:
255                 fmt = "Unknown Chip Type\n";
256                 break;
257         }
258
259         printf (fmt, bootletter, boottype);
260
261         printf ("  Size: %ld MB in %d Sectors\n",
262                 info->size >> 20, info->sector_count);
263
264         printf ("  Sector Start Addresses:");
265
266         for (i = 0; i < info->sector_count; ++i) {
267                 if ((i % 5) == 0) {
268                         printf ("\n   ");
269                 }
270
271                 printf (" %08lX%s", info->start[i],
272                         info->protect[i] ? " (RO)" : "     ");
273         }
274
275         printf ("\n");
276 }
277
278 /*-----------------------------------------------------------------------
279  */
280
281 /*
282  * The following code cannot be run from FLASH!
283  */
284
285 ulong flash_get_size (FPWV * addr, flash_info_t * info)
286 {
287         /* Write auto select command: read Manufacturer ID */
288
289         /* Write auto select command sequence and test FLASH answer */
290         addr[0x0555] = (FPW) 0x00AA00AA;        /* for AMD, Intel ignores this */
291         addr[0x02AA] = (FPW) 0x00550055;        /* for AMD, Intel ignores this */
292         addr[0x0555] = (FPW) 0x00900090;        /* selects Intel or AMD */
293
294         /* The manufacturer codes are only 1 byte, so just use 1 byte.
295          * This works for any bus width and any FLASH device width.
296          */
297         switch (addr[0] & 0xff) {
298
299         case (uchar) AMD_MANUFACT:
300                 info->flash_id = FLASH_MAN_AMD;
301                 break;
302
303         case (uchar) INTEL_MANUFACT:
304                 info->flash_id = FLASH_MAN_INTEL;
305                 break;
306
307         default:
308                 info->flash_id = FLASH_UNKNOWN;
309                 info->sector_count = 0;
310                 info->size = 0;
311                 break;
312         }
313
314         /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
315         if (info->flash_id != FLASH_UNKNOWN)
316                 switch (addr[1]) {
317
318                 case (FPW) AMD_ID_LV640U:       /* 29LV640 and 29LV641 have same ID */
319                         info->flash_id += FLASH_AM640U;
320                         info->sector_count = 128;
321                         info->size = 0x00800000 * (sizeof (FPW) / 2);
322                         break;                  /* => 8 or 16 MB    */
323
324                 case (FPW) INTEL_ID_28F800C3B:
325                         info->flash_id += FLASH_28F800C3B;
326                         info->sector_count = 23;
327                         info->size = 0x00100000 * (sizeof (FPW) / 2);
328                         break;                  /* => 1 or 2 MB     */
329
330                 case (FPW) INTEL_ID_28F800B3B:
331                         info->flash_id += FLASH_INTEL800B;
332                         info->sector_count = 23;
333                         info->size = 0x00100000 * (sizeof (FPW) / 2);
334                         break;                  /* => 1 or 2 MB     */
335
336                 case (FPW) INTEL_ID_28F160C3B:
337                         info->flash_id += FLASH_28F160C3B;
338                         info->sector_count = 39;
339                         info->size = 0x00200000 * (sizeof (FPW) / 2);
340                         break;                  /* => 2 or 4 MB     */
341
342                 case (FPW) INTEL_ID_28F160B3B:
343                         info->flash_id += FLASH_INTEL160B;
344                         info->sector_count = 39;
345                         info->size = 0x00200000 * (sizeof (FPW) / 2);
346                         break;                  /* => 2 or 4 MB     */
347
348                 case (FPW) INTEL_ID_28F320C3B:
349                         info->flash_id += FLASH_28F320C3B;
350                         info->sector_count = 71;
351                         info->size = 0x00400000 * (sizeof (FPW) / 2);
352                         break;                  /* => 4 or 8 MB     */
353
354                 case (FPW) INTEL_ID_28F320B3B:
355                         info->flash_id += FLASH_INTEL320B;
356                         info->sector_count = 71;
357                         info->size = 0x00400000 * (sizeof (FPW) / 2);
358                         break;                  /* => 4 or 8 MB     */
359
360                 case (FPW) INTEL_ID_28F640C3B:
361                         info->flash_id += FLASH_28F640C3B;
362                         info->sector_count = 135;
363                         info->size = 0x00800000 * (sizeof (FPW) / 2);
364                         break;                  /* => 8 or 16 MB    */
365
366                 case (FPW) INTEL_ID_28F640B3B:
367                         info->flash_id += FLASH_INTEL640B;
368                         info->sector_count = 135;
369                         info->size = 0x00800000 * (sizeof (FPW) / 2);
370                         break;                  /* => 8 or 16 MB    */
371
372                 default:
373                         info->flash_id = FLASH_UNKNOWN;
374                         info->sector_count = 0;
375                         info->size = 0;
376                         return (0);             /* => no or unknown flash */
377                 }
378
379         flash_get_offsets ((ulong) addr, info);
380
381         /* Put FLASH back in read mode */
382         flash_reset (info);
383
384         return (info->size);
385 }
386
387 #ifdef CFG_FLASH_PROTECTION
388 /*-----------------------------------------------------------------------
389  */
390
391 static void flash_sync_real_protect (flash_info_t * info)
392 {
393         FPWV *addr = (FPWV *) (info->start[0]);
394         FPWV *sect;
395         int i;
396
397         switch (info->flash_id & FLASH_TYPEMASK) {
398         case FLASH_28F800C3B:
399         case FLASH_28F800C3T:
400         case FLASH_28F160C3B:
401         case FLASH_28F160C3T:
402         case FLASH_28F320C3B:
403         case FLASH_28F320C3T:
404         case FLASH_28F640C3B:
405         case FLASH_28F640C3T:
406                 /* check for protected sectors */
407                 *addr = (FPW) 0x00900090;
408                 for (i = 0; i < info->sector_count; i++) {
409                         /* read sector protection at sector address, (A7 .. A0) = 0x02.
410                          * D0 = 1 for each device if protected.
411                          * If at least one device is protected the sector is marked
412                          * protected, but mixed protected and  unprotected devices
413                          * within a sector should never happen.
414                          */
415                         sect = (FPWV *) (info->start[i]);
416                         info->protect[i] = (sect[2] & (FPW) (0x00010001)) ? 1 : 0;
417                 }
418
419                 /* Put FLASH back in read mode */
420                 flash_reset (info);
421                 break;
422
423         case FLASH_AM640U:
424         default:
425                 /* no hardware protect that we support */
426                 break;
427         }
428 }
429 #endif
430
431 /*-----------------------------------------------------------------------
432  */
433
434 int flash_erase (flash_info_t * info, int s_first, int s_last)
435 {
436         FPWV *addr;
437         int flag, prot, sect;
438         int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
439         ulong start, now, last;
440         int rcode = 0;
441
442         if ((s_first < 0) || (s_first > s_last)) {
443                 if (info->flash_id == FLASH_UNKNOWN) {
444                         printf ("- missing\n");
445                 } else {
446                         printf ("- no sectors to erase\n");
447                 }
448                 return 1;
449         }
450
451         switch (info->flash_id & FLASH_TYPEMASK) {
452         case FLASH_INTEL800B:
453         case FLASH_INTEL160B:
454         case FLASH_INTEL320B:
455         case FLASH_INTEL640B:
456         case FLASH_28F800C3B:
457         case FLASH_28F160C3B:
458         case FLASH_28F320C3B:
459         case FLASH_28F640C3B:
460         case FLASH_AM640U:
461                 break;
462         case FLASH_UNKNOWN:
463         default:
464                 printf ("Can't erase unknown flash type %08lx - aborted\n",
465                         info->flash_id);
466                 return 1;
467         }
468
469         prot = 0;
470         for (sect = s_first; sect <= s_last; ++sect) {
471                 if (info->protect[sect]) {
472                         prot++;
473                 }
474         }
475
476         if (prot) {
477                 printf ("- Warning: %d protected sectors will not be erased!\n",
478                                 prot);
479         } else {
480                 printf ("\n");
481         }
482
483         start = get_timer (0);
484         last = start;
485
486         /* Start erase on unprotected sectors */
487         for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
488
489                 if (info->protect[sect] != 0)   /* protected, skip it */
490                         continue;
491
492                 /* Disable interrupts which might cause a timeout here */
493                 flag = disable_interrupts ();
494
495                 addr = (FPWV *) (info->start[sect]);
496                 if (intel) {
497                         *addr = (FPW) 0x00500050;       /* clear status register */
498                         *addr = (FPW) 0x00200020;       /* erase setup */
499                         *addr = (FPW) 0x00D000D0;       /* erase confirm */
500                 } else {
501                         /* must be AMD style if not Intel */
502                         FPWV *base;                     /* first address in bank */
503
504                         base = (FPWV *) (info->start[0]);
505                         base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
506                         base[0x02AA] = (FPW) 0x00550055;        /* unlock */
507                         base[0x0555] = (FPW) 0x00800080;        /* erase mode */
508                         base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
509                         base[0x02AA] = (FPW) 0x00550055;        /* unlock */
510                         *addr = (FPW) 0x00300030;       /* erase sector */
511                 }
512
513                 /* re-enable interrupts if necessary */
514                 if (flag)
515                         enable_interrupts ();
516
517                 /* wait at least 50us for AMD, 80us for Intel.
518                  * Let's wait 1 ms.
519                  */
520                 udelay (1000);
521
522                 while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
523                         if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
524                                 printf ("Timeout\n");
525
526                                 if (intel) {
527                                         /* suspend erase    */
528                                         *addr = (FPW) 0x00B000B0;
529                                 }
530
531                                 flash_reset (info);     /* reset to read mode */
532                                 rcode = 1;              /* failed */
533                                 break;
534                         }
535
536                         /* show that we're waiting */
537                         if ((now - last) > 1000) {      /* every second */
538                                 putc ('.');
539                                 last = now;
540                         }
541                 }
542
543                 flash_reset (info);             /* reset to read mode   */
544         }
545
546         printf (" done\n");
547         return rcode;
548 }
549
550 /*-----------------------------------------------------------------------
551  * Copy memory to flash, returns:
552  * 0 - OK
553  * 1 - write timeout
554  * 2 - Flash not erased
555  */
556 int bad_write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
557 {
558         FPW data = 0;   /* 16 or 32 bit word, matches flash bus width */
559         int bytes;      /* number of bytes to program in current word */
560         int left;       /* number of bytes left to program            */
561         int i, res;
562
563         /*    printf("write_buff: src: %8p addr %08lx count: %ld\n", src, addr, cnt); */
564
565         for (left = cnt, res = 0;
566                  left > 0 && res == 0;
567                  addr += sizeof (data), left -= sizeof (data) - bytes) {
568
569                 bytes = addr & (sizeof (data) - 1);
570                 addr &= ~(sizeof (data) - 1);
571
572                 /* combine source and destination data so can program
573                  * an entire word of 16 or 32 bits
574                  */
575                 for (i = 0; i < sizeof (data); i++) {
576                         data <<= 8;
577                         if (i < bytes || i - bytes >= left)
578                                 data += *((uchar *) addr + i);
579                         else
580                                 data += *src++;
581                 }
582
583                 /* write one word to the flash */
584                 switch (info->flash_id & FLASH_VENDMASK) {
585                 case FLASH_MAN_AMD:
586                         res = write_word_amd (info, (FPWV *) addr, data);
587                         break;
588                 case FLASH_MAN_INTEL:
589                         res = write_word_intel (info, (FPWV *) addr, data);
590                         break;
591                 default:
592                         /* unknown flash type, error! */
593                         printf ("missing or unknown FLASH type\n");
594                         res = 1;        /* not really a timeout, but gives error */
595                         break;
596                 }
597         }
598
599         return (res);
600 }
601
602 /**
603  * write_buf: - Copy memory to flash.
604  *
605  * @param info:
606  * @param src:  source of copy transaction
607  * @param addr: where to copy to
608  * @param cnt:  number of bytes to copy
609  *
610  * @return      error code
611  */
612
613 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
614 {
615         ulong cp, wp;
616         FPW data;
617         int l;
618         int i, rc;
619
620         wp = (addr & ~1);       /* get lower word aligned address */
621
622         /*
623          * handle unaligned start bytes
624          */
625         if ((l = addr - wp) != 0) {
626                 data = 0;
627                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
628                         data = (data >> 8) | (*(uchar *) cp << 8);
629                 }
630                 for (; i < 2 && cnt > 0; ++i) {
631                         data = (data >> 8) | (*src++ << 8);
632                         --cnt;
633                         ++cp;
634                 }
635                 for (; cnt == 0 && i < 2; ++i, ++cp) {
636                         data = (data >> 8) | (*(uchar *) cp << 8);
637                 }
638
639                 if ((rc = write_word (info, wp, data)) != 0) {
640                         return (rc);
641                 }
642                 wp += 2;
643         }
644
645         /*
646          * handle word aligned part
647          */
648         while (cnt >= 2) {
649                 /* data = *((vushort*)src); */
650                 data = *((FPW *) src);
651                 if ((rc = write_word (info, wp, data)) != 0) {
652                         return (rc);
653                 }
654                 src += sizeof (FPW);
655                 wp += sizeof (FPW);
656                 cnt -= sizeof (FPW);
657         }
658
659         if (cnt == 0)
660                 return ERR_OK;
661
662         /*
663          * handle unaligned tail bytes
664          */
665         data = 0;
666         for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
667                 data = (data >> 8) | (*src++ << 8);
668                 --cnt;
669         }
670         for (; i < 2; ++i, ++cp) {
671                 data = (data >> 8) | (*(uchar *) cp << 8);
672         }
673
674         return write_word (info, wp, data);
675 }
676
677
678
679 /*-----------------------------------------------------------------------
680  * Write a word to Flash for AMD FLASH
681  * A word is 16 or 32 bits, whichever the bus width of the flash bank
682  * (not an individual chip) is.
683  *
684  * returns:
685  * 0 - OK
686  * 1 - write timeout
687  * 2 - Flash not erased
688  */
689 static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data)
690 {
691         ulong start;
692         int flag;
693         int res = 0;            /* result, assume success   */
694         FPWV *base;             /* first address in flash bank  */
695
696         /* Check if Flash is (sufficiently) erased */
697         if ((*dest & data) != data) {
698                 return (2);
699         }
700
701
702         base = (FPWV *) (info->start[0]);
703         /* Disable interrupts which might cause a timeout here */
704         flag = disable_interrupts ();
705
706         base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
707         base[0x02AA] = (FPW) 0x00550055;        /* unlock */
708         base[0x0555] = (FPW) 0x00A000A0;        /* selects program mode */
709
710         *dest = data;                           /* start programming the data   */
711
712         /* re-enable interrupts if necessary */
713         if (flag)
714                 enable_interrupts ();
715
716         start = get_timer (0);
717
718         /* data polling for D7 */
719         while (res == 0
720                    && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
721                 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
722                         *dest = (FPW) 0x00F000F0;       /* reset bank */
723                         res = 1;
724                 }
725         }
726
727         return (res);
728 }
729
730 /*-----------------------------------------------------------------------
731  * Write a word to Flash for Intel FLASH
732  * A word is 16 or 32 bits, whichever the bus width of the flash bank
733  * (not an individual chip) is.
734  *
735  * returns:
736  * 0 - OK
737  * 1 - write timeout
738  * 2 - Flash not erased
739  */
740 static int write_word_intel (flash_info_t * info, FPWV * dest, FPW data)
741 {
742         ulong start;
743         int flag;
744         int res = 0;                    /* result, assume success   */
745
746         /* Check if Flash is (sufficiently) erased */
747         if ((*dest & data) != data) {
748                 return (2);
749         }
750
751         /* Disable interrupts which might cause a timeout here */
752         flag = disable_interrupts ();
753
754         *dest = (FPW) 0x00500050;       /* clear status register    */
755         *dest = (FPW) 0x00FF00FF;       /* make sure in read mode   */
756         *dest = (FPW) 0x00400040;       /* program setup        */
757
758         *dest = data;                   /* start programming the data   */
759
760         /* re-enable interrupts if necessary */
761         if (flag)
762                 enable_interrupts ();
763
764         start = get_timer (0);
765
766         while (res == 0 && (*dest & (FPW) 0x00800080) != (FPW) 0x00800080) {
767                 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
768                         *dest = (FPW) 0x00B000B0;       /* Suspend program  */
769                         res = 1;
770                 }
771         }
772
773         if (res == 0 && (*dest & (FPW) 0x00100010))
774                 res = 1;        /* write failed, time out error is close enough */
775
776         *dest = (FPW) 0x00500050;       /* clear status register    */
777         *dest = (FPW) 0x00FF00FF;       /* make sure in read mode   */
778
779         return (res);
780 }
781
782 #ifdef CFG_FLASH_PROTECTION
783 /*-----------------------------------------------------------------------
784  */
785 int flash_real_protect (flash_info_t * info, long sector, int prot)
786 {
787         int rcode = 0;                          /* assume success */
788         FPWV *addr;                             /* address of sector */
789         FPW value;
790
791         addr = (FPWV *) (info->start[sector]);
792
793         switch (info->flash_id & FLASH_TYPEMASK) {
794         case FLASH_28F800C3B:
795         case FLASH_28F800C3T:
796         case FLASH_28F160C3B:
797         case FLASH_28F160C3T:
798         case FLASH_28F320C3B:
799         case FLASH_28F320C3T:
800         case FLASH_28F640C3B:
801         case FLASH_28F640C3T:
802                 flash_reset (info);             /* make sure in read mode */
803                 *addr = (FPW) 0x00600060L;      /* lock command setup */
804                 if (prot)
805                         *addr = (FPW) 0x00010001L;      /* lock sector */
806                 else
807                         *addr = (FPW) 0x00D000D0L;      /* unlock sector */
808                 flash_reset (info);             /* reset to read mode */
809
810                 /* now see if it really is locked/unlocked as requested */
811                 *addr = (FPW) 0x00900090;
812                 /* read sector protection at sector address, (A7 .. A0) = 0x02.
813                  * D0 = 1 for each device if protected.
814                  * If at least one device is protected the sector is marked
815                  * protected, but return failure. Mixed protected and
816                  * unprotected devices within a sector should never happen.
817                  */
818                 value = addr[2] & (FPW) 0x00010001;
819                 if (value == 0)
820                         info->protect[sector] = 0;
821                 else if (value == (FPW) 0x00010001)
822                         info->protect[sector] = 1;
823                 else {
824                         /* error, mixed protected and unprotected */
825                         rcode = 1;
826                         info->protect[sector] = 1;
827                 }
828                 if (info->protect[sector] != prot)
829                         rcode = 1;                      /* failed to protect/unprotect as requested */
830
831                 /* reload all protection bits from hardware for now */
832                 flash_sync_real_protect (info);
833                 break;
834
835         case FLASH_AM640U:
836         default:
837                 /* no hardware protect that we support */
838                 info->protect[sector] = prot;
839                 break;
840         }
841
842         return rcode;
843 }
844 #endif