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