CCM board: fix build errors.
[platform/kernel/u-boot.git] / board / alaska / flash.c
1 /*
2  * (C) Copyright 2001
3  * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
4  *
5  * (C) Copyright 2001-2004
6  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <linux/byteorder/swab.h>
29
30
31 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips    */
32
33 /* Board support for 1 or 2 flash devices */
34 #define FLASH_PORT_WIDTH8
35
36 typedef unsigned char FLASH_PORT_WIDTH;
37 typedef volatile unsigned char FLASH_PORT_WIDTHV;
38
39 #define SWAP(x)         (x)
40
41 /* Intel-compatible flash ID */
42 #define INTEL_COMPAT    0x89
43 #define INTEL_ALT       0xB0
44
45 /* Intel-compatible flash commands */
46 #define INTEL_PROGRAM   0x10
47 #define INTEL_ERASE     0x20
48 #define INTEL_CLEAR     0x50
49 #define INTEL_LOCKBIT   0x60
50 #define INTEL_PROTECT   0x01
51 #define INTEL_STATUS    0x70
52 #define INTEL_READID    0x90
53 #define INTEL_CONFIRM   0xD0
54 #define INTEL_RESET     0xFF
55
56 /* Intel-compatible flash status bits */
57 #define INTEL_FINISHED  0x80
58 #define INTEL_OK        0x80
59
60 #define FPW             FLASH_PORT_WIDTH
61 #define FPWV            FLASH_PORT_WIDTHV
62
63 #define FLASH_CYCLE1    0x0555
64 #define FLASH_CYCLE2    0x02aa
65
66 #define WR_BLOCK        0x20
67 /*-----------------------------------------------------------------------
68  * Functions
69  */
70 static ulong flash_get_size (FPW * addr, flash_info_t * info);
71 static int write_data (flash_info_t * info, ulong dest, FPW data);
72 static int write_data_block (flash_info_t * info, ulong src, ulong dest);
73 static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data);
74 static void flash_get_offsets (ulong base, flash_info_t * info);
75 void inline spin_wheel (void);
76 static void flash_sync_real_protect (flash_info_t * info);
77 static unsigned char intel_sector_protected (flash_info_t *info, ushort sector);
78 static unsigned char same_chip_banks (int bank1, int bank2);
79
80 /*-----------------------------------------------------------------------
81  */
82
83 unsigned long flash_init (void)
84 {
85         int i;
86         ulong size = 0;
87         ulong fsize = 0;
88
89         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
90                 memset (&flash_info[i], 0, sizeof (flash_info_t));
91
92                 switch (i) {
93                 case 0:
94                         flash_get_size ((FPW *) CFG_FLASH1_BASE,
95                                         &flash_info[i]);
96                         flash_get_offsets (CFG_FLASH1_BASE, &flash_info[i]);
97                         break;
98                 case 1:
99                         flash_get_size ((FPW *) CFG_FLASH1_BASE,
100                                         &flash_info[i]);
101                         fsize = CFG_FLASH1_BASE + flash_info[i - 1].size;
102                         flash_get_offsets (fsize, &flash_info[i]);
103                         break;
104                 case 2:
105                         flash_get_size ((FPW *) CFG_FLASH0_BASE,
106                                         &flash_info[i]);
107                         flash_get_offsets (CFG_FLASH0_BASE, &flash_info[i]);
108                         break;
109                 case 3:
110                         flash_get_size ((FPW *) CFG_FLASH0_BASE,
111                                         &flash_info[i]);
112                         fsize = CFG_FLASH0_BASE + flash_info[i - 1].size;
113                         flash_get_offsets (fsize, &flash_info[i]);
114                         break;
115                 default:
116                         panic ("configured to many flash banks!\n");
117                         break;
118                 }
119                 size += flash_info[i].size;
120
121                 /* get the h/w and s/w protection status in sync */
122                 flash_sync_real_protect(&flash_info[i]);
123         }
124
125         /* Protect monitor and environment sectors
126          */
127 #if defined (CFG_AMD_BOOT)
128         flash_protect (FLAG_PROTECT_SET,
129                        CFG_MONITOR_BASE,
130                        CFG_MONITOR_BASE + monitor_flash_len - 1,
131                        &flash_info[2]);
132         flash_protect (FLAG_PROTECT_SET,
133                        CFG_INTEL_BASE,
134                        CFG_INTEL_BASE + monitor_flash_len - 1,
135                        &flash_info[1]);
136 #else
137         flash_protect (FLAG_PROTECT_SET,
138                        CFG_MONITOR_BASE,
139                        CFG_MONITOR_BASE + monitor_flash_len - 1,
140                        &flash_info[3]);
141         flash_protect (FLAG_PROTECT_SET,
142                        CFG_AMD_BASE,
143                        CFG_AMD_BASE + monitor_flash_len - 1, &flash_info[0]);
144 #endif
145
146         flash_protect (FLAG_PROTECT_SET,
147                        CFG_ENV1_ADDR,
148                        CFG_ENV1_ADDR + CFG_ENV1_SIZE - 1, &flash_info[1]);
149         flash_protect (FLAG_PROTECT_SET,
150                        CFG_ENV_ADDR,
151                        CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[3]);
152
153         return size;
154 }
155
156 /*-----------------------------------------------------------------------
157  */
158 static void flash_get_offsets (ulong base, flash_info_t * info)
159 {
160         int i;
161
162         if (info->flash_id == FLASH_UNKNOWN)
163                 return;
164
165         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) {
166                 for (i = 0; i < info->sector_count; i++) {
167                         info->start[i] = base + (i * PHYS_AMD_SECT_SIZE);
168                         info->protect[i] = 0;
169                 }
170         }
171
172         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
173                 for (i = 0; i < info->sector_count; i++) {
174                         info->start[i] = base + (i * PHYS_INTEL_SECT_SIZE);
175                 }
176         }
177 }
178
179 /*-----------------------------------------------------------------------
180  */
181 void flash_print_info (flash_info_t * info)
182 {
183         int i;
184
185         if (info->flash_id == FLASH_UNKNOWN) {
186                 printf ("missing or unknown FLASH type\n");
187                 return;
188         }
189
190         switch (info->flash_id & FLASH_VENDMASK) {
191         case FLASH_MAN_INTEL:
192                 printf ("INTEL ");
193                 break;
194         case FLASH_MAN_AMD:
195                 printf ("AMD ");
196                 break;
197         default:
198                 printf ("Unknown Vendor ");
199                 break;
200         }
201
202         switch (info->flash_id & FLASH_TYPEMASK) {
203         case FLASH_28F128J3A:
204                 printf ("28F128J3A\n");
205                 break;
206
207         case FLASH_AM040:
208                 printf ("AMD29F040B\n");
209                 break;
210
211         default:
212                 printf ("Unknown Chip Type\n");
213                 break;
214         }
215
216         printf ("  Size: %ld MB in %d Sectors\n",
217                 info->size >> 20, info->sector_count);
218
219         printf ("  Sector Start Addresses:");
220         for (i = 0; i < info->sector_count; ++i) {
221                 if ((i % 5) == 0)
222                         printf ("\n   ");
223                 printf (" %08lX%s",
224                         info->start[i], info->protect[i] ? " (RO)" : "     ");
225         }
226         printf ("\n");
227         return;
228 }
229
230 /*
231  * The following code cannot be run from FLASH!
232  */
233 static ulong flash_get_size (FPW * addr, flash_info_t * info)
234 {
235         FPWV value;
236         static int amd = 0;
237
238         /* Write auto select command: read Manufacturer ID */
239         /* Write auto select command sequence and test FLASH answer */
240         addr[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* for AMD, Intel ignores this */
241         __asm__ ("sync");
242         addr[FLASH_CYCLE2] = (FPW) 0x00550055;  /* for AMD, Intel ignores this */
243         __asm__ ("sync");
244         addr[FLASH_CYCLE1] = (FPW) 0x00900090;  /* selects Intel or AMD */
245         __asm__ ("sync");
246
247         udelay (100);
248
249         switch (addr[0] & 0xff) {
250
251         case (uchar) AMD_MANUFACT:
252                 info->flash_id = FLASH_MAN_AMD;
253                 value = addr[1];
254                 break;
255
256         case (uchar) INTEL_MANUFACT:
257                 info->flash_id = FLASH_MAN_INTEL;
258                 value = addr[2];
259                 break;
260
261         default:
262                 printf ("unknown\n");
263                 info->flash_id = FLASH_UNKNOWN;
264                 info->sector_count = 0;
265                 info->size = 0;
266                 addr[0] = (FPW) 0x00FF00FF;     /* restore read mode */
267                 return (0);     /* no or unknown flash  */
268         }
269
270         switch (value) {
271
272         case (FPW) INTEL_ID_28F128J3A:
273                 info->flash_id += FLASH_28F128J3A;
274                 info->sector_count = 64;
275                 info->size = 0x00800000;        /* => 16 MB     */
276                 break;
277
278         case (FPW) AMD_ID_LV040B:
279                 info->flash_id += FLASH_AM040;
280                 if (amd == 0) {
281                         info->sector_count = 7;
282                         info->size = 0x00070000;        /* => 448 KB     */
283                         amd = 1;
284                 } else {
285                         /* for Environment settings */
286                         info->sector_count = 1;
287                         info->size = PHYS_AMD_SECT_SIZE;        /* => 64 KB     */
288                         amd = 0;
289                 }
290                 break;
291
292         default:
293                 info->flash_id = FLASH_UNKNOWN;
294                 break;
295         }
296
297         if (info->sector_count > CFG_MAX_FLASH_SECT) {
298                 printf ("** ERROR: sector count %d > max (%d) **\n",
299                         info->sector_count, CFG_MAX_FLASH_SECT);
300                 info->sector_count = CFG_MAX_FLASH_SECT;
301         }
302
303         if (value == (FPW) INTEL_ID_28F128J3A)
304                 addr[0] = (FPW) 0x00FF00FF;     /* restore read mode */
305         else
306                 addr[0] = (FPW) 0x00F000F0;     /* restore read mode */
307
308         return (info->size);
309 }
310
311
312 /*
313  * This function gets the u-boot flash sector protection status
314  * (flash_info_t.protect[]) in sync with the sector protection
315  * status stored in hardware.
316  */
317 static void flash_sync_real_protect (flash_info_t * info)
318 {
319         int i;
320
321         switch (info->flash_id & FLASH_TYPEMASK) {
322         case FLASH_28F128J3A:
323                 for (i = 0; i < info->sector_count; ++i) {
324                         info->protect[i] = intel_sector_protected(info, i);
325                 }
326                 break;
327         case FLASH_AM040:
328         default:
329                 /* no h/w protect support */
330                 break;
331         }
332 }
333
334
335 /*
336  * checks if "sector" in bank "info" is protected. Should work on intel
337  * strata flash chips 28FxxxJ3x in 8-bit mode.
338  * Returns 1 if sector is protected (or timed-out while trying to read
339  * protection status), 0 if it is not.
340  */
341 static unsigned char intel_sector_protected (flash_info_t *info, ushort sector)
342 {
343         FPWV *addr;
344         FPWV *lock_conf_addr;
345         ulong start;
346         unsigned char ret;
347
348         /*
349          * first, wait for the WSM to be finished. The rationale for
350          * waiting for the WSM to become idle for at most
351          * CFG_FLASH_ERASE_TOUT is as follows. The WSM can be busy
352          * because of: (1) erase, (2) program or (3) lock bit
353          * configuration. So we just wait for the longest timeout of
354          * the (1)-(3), i.e. the erase timeout.
355          */
356
357         /* wait at least 35ns (W12) before issuing Read Status Register */
358         udelay(1);
359         addr = (FPWV *) info->start[sector];
360         *addr = (FPW) INTEL_STATUS;
361
362         start = get_timer (0);
363         while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) {
364                 if (get_timer (start) > CFG_FLASH_ERASE_TOUT) {
365                         *addr = (FPW) INTEL_RESET; /* restore read mode */
366                         printf("WSM busy too long, can't get prot status\n");
367                         return 1;
368                 }
369         }
370
371         /* issue the Read Identifier Codes command */
372         *addr = (FPW) INTEL_READID;
373
374         /* wait at least 35ns (W12) before reading */
375         udelay(1);
376
377         /* Intel example code uses offset of 4 for 8-bit flash */
378         lock_conf_addr = (FPWV *) info->start[sector] + 4;
379         ret = (*lock_conf_addr & (FPW) INTEL_PROTECT) ? 1 : 0;
380
381         /* put flash back in read mode */
382         *addr = (FPW) INTEL_RESET;
383
384         return ret;
385 }
386
387
388 /*
389  * Checks if "bank1" and "bank2" are on the same chip.  Returns 1 if they
390  * are and 0 otherwise.
391  */
392 static unsigned char same_chip_banks (int bank1, int bank2)
393 {
394         unsigned char same_chip[CFG_MAX_FLASH_BANKS][CFG_MAX_FLASH_BANKS] = {
395                 {1, 1, 0, 0},
396                 {1, 1, 0, 0},
397                 {0, 0, 1, 1},
398                 {0, 0, 1, 1}
399         };
400         return same_chip[bank1][bank2];
401 }
402
403
404 /*-----------------------------------------------------------------------
405  */
406 int flash_erase (flash_info_t * info, int s_first, int s_last)
407 {
408         int flag, prot, sect;
409         ulong type, start, last;
410         int rcode = 0, intel = 0;
411
412         if ((s_first < 0) || (s_first > s_last)) {
413                 if (info->flash_id == FLASH_UNKNOWN)
414                         printf ("- missing\n");
415                 else
416                         printf ("- no sectors to erase\n");
417                 return 1;
418         }
419
420         type = (info->flash_id & FLASH_VENDMASK);
421         if ((type != FLASH_MAN_INTEL)) {
422                 type = (info->flash_id & FLASH_VENDMASK);
423                 if ((type != FLASH_MAN_AMD)) {
424                         printf ("Can't erase unknown flash type %08lx - aborted\n",
425                                 info->flash_id);
426                         return 1;
427                 }
428         }
429
430         if (type == FLASH_MAN_INTEL)
431                 intel = 1;
432
433         prot = 0;
434         for (sect = s_first; sect <= s_last; ++sect) {
435                 if (info->protect[sect]) {
436                         prot++;
437                 }
438         }
439
440         if (prot) {
441                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
442         } else {
443                 printf ("\n");
444         }
445
446         start = get_timer (0);
447         last = start;
448
449         /* Disable interrupts which might cause a timeout here */
450         flag = disable_interrupts ();
451
452         /* Start erase on unprotected sectors */
453         for (sect = s_first; sect <= s_last; sect++) {
454                 if (info->protect[sect] == 0) { /* not protected */
455                         FPWV *addr = (FPWV *) (info->start[sect]);
456                         FPW status;
457
458                         printf ("Erasing sector %2d ... ", sect);
459
460                         /* arm simple, non interrupt dependent timer */
461                         start = get_timer (0);
462
463                         if (intel) {
464                                 *addr = (FPW) 0x00500050;       /* clear status register */
465                                 *addr = (FPW) 0x00200020;       /* erase setup */
466                                 *addr = (FPW) 0x00D000D0;       /* erase confirm */
467                         } else {
468                                 FPWV *base;     /* first address in bank */
469
470                                 base = (FPWV *) (CFG_AMD_BASE);
471                                 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* unlock */
472                                 base[FLASH_CYCLE2] = (FPW) 0x00550055;  /* unlock */
473                                 base[FLASH_CYCLE1] = (FPW) 0x00800080;  /* erase mode */
474                                 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* unlock */
475                                 base[FLASH_CYCLE2] = (FPW) 0x00550055;  /* unlock */
476                                 *addr = (FPW) 0x00300030;       /* erase sector */
477                         }
478
479                         while (((status =
480                                  *addr) & (FPW) 0x00800080) !=
481                                (FPW) 0x00800080) {
482                                 if (get_timer (start) > CFG_FLASH_ERASE_TOUT) {
483                                         printf ("Timeout\n");
484                                         if (intel) {
485                                                 *addr = (FPW) 0x00B000B0;       /* suspend erase     */
486                                                 *addr = (FPW) 0x00FF00FF;       /* reset to read mode */
487                                         } else
488                                                 *addr = (FPW) 0x00F000F0;       /* reset to read mode */
489
490                                         rcode = 1;
491                                         break;
492                                 }
493                         }
494
495                         if (intel) {
496                                 *addr = (FPW) 0x00500050;       /* clear status register cmd.   */
497                                 *addr = (FPW) 0x00FF00FF;       /* resest to read mode          */
498                         } else
499                                 *addr = (FPW) 0x00F000F0;       /* reset to read mode */
500
501                         printf (" done\n");
502                 }
503         }
504         return rcode;
505 }
506
507 /*-----------------------------------------------------------------------
508  * Copy memory to flash, returns:
509  * 0 - OK
510  * 1 - write timeout
511  * 2 - Flash not erased
512  * 4 - Flash not identified
513  */
514
515 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
516 {
517         if (info->flash_id == FLASH_UNKNOWN) {
518                 return 4;
519         }
520
521         switch (info->flash_id & FLASH_VENDMASK) {
522         case FLASH_MAN_AMD:
523             {
524                 FPW data = 0;   /* 16 or 32 bit word, matches flash bus width */
525                 int bytes;      /* number of bytes to program in current word */
526                 int left;       /* number of bytes left to program */
527                 int i, res;
528
529                 for (left = cnt, res = 0;
530                      left > 0 && res == 0;
531                      addr += sizeof (data), left -=
532                      sizeof (data) - bytes) {
533
534                         bytes = addr & (sizeof (data) - 1);
535                         addr &= ~(sizeof (data) - 1);
536
537                         /* combine source and destination data so can program
538                          * an entire word of 16 or 32 bits
539                          */
540                         for (i = 0; i < sizeof (data); i++) {
541                                 data <<= 8;
542                                 if (i < bytes || i - bytes >= left)
543                                         data += *((uchar *) addr + i);
544                                 else
545                                         data += *src++;
546                         }
547
548                         res = write_word_amd (info, (FPWV *) addr,
549                                               data);
550                 }
551                 return res;
552             }           /* case FLASH_MAN_AMD */
553
554         case FLASH_MAN_INTEL:
555             {
556                 ulong cp, wp;
557                 FPW data;
558                 int count, i, l, rc, port_width;
559
560                 /* get lower word aligned address */
561                 wp = addr;
562                 port_width = 1;
563
564                 /*
565                  * handle unaligned start bytes
566                  */
567                 if ((l = addr - wp) != 0) {
568                         data = 0;
569                         for (i = 0, cp = wp; i < l; ++i, ++cp) {
570                                 data = (data << 8) | (*(uchar *) cp);
571                         }
572
573                         for (; i < port_width && cnt > 0; ++i) {
574                                 data = (data << 8) | *src++;
575                                 --cnt;
576                                 ++cp;
577                         }
578
579                         for (; cnt == 0 && i < port_width; ++i, ++cp)
580                                 data = (data << 8) | (*(uchar *) cp);
581
582                         if ((rc =
583                              write_data (info, wp, SWAP (data))) != 0)
584                                 return (rc);
585                         wp += port_width;
586                 }
587
588                 if (cnt > WR_BLOCK) {
589                         /*
590                          * handle word aligned part
591                          */
592                         count = 0;
593                         while (cnt >= WR_BLOCK) {
594
595                                 if ((rc =
596                                      write_data_block (info,
597                                                        (ulong) src,
598                                                        wp)) != 0)
599                                         return (rc);
600
601                                 wp += WR_BLOCK;
602                                 src += WR_BLOCK;
603                                 cnt -= WR_BLOCK;
604
605                                 if (count++ > 0x800) {
606                                         spin_wheel ();
607                                         count = 0;
608                                 }
609                         }
610                 }
611
612                 if (cnt < WR_BLOCK) {
613                         /*
614                          * handle word aligned part
615                          */
616                         count = 0;
617                         while (cnt >= port_width) {
618                                 data = 0;
619                                 for (i = 0; i < port_width; ++i)
620                                         data = (data << 8) | *src++;
621
622                                 if ((rc =
623                                      write_data (info, wp,
624                                                  SWAP (data))) != 0)
625                                         return (rc);
626
627                                 wp += port_width;
628                                 cnt -= port_width;
629                                 if (count++ > 0x800) {
630                                         spin_wheel ();
631                                         count = 0;
632                                 }
633                         }
634                 }
635
636                 if (cnt == 0)
637                         return (0);
638
639                 /*
640                  * handle unaligned tail bytes
641                  */
642                 data = 0;
643                 for (i = 0, cp = wp; i < port_width && cnt > 0;
644                      ++i, ++cp) {
645                         data = (data << 8) | *src++;
646                         --cnt;
647                 }
648
649                 for (; i < port_width; ++i, ++cp)
650                         data = (data << 8) | (*(uchar *) cp);
651
652                 return (write_data (info, wp, SWAP (data)));
653             }           /* case FLASH_MAN_INTEL */
654
655         }                       /* switch */
656         return (0);
657 }
658
659 /*-----------------------------------------------------------------------
660  * Write a word or halfword to Flash, returns:
661  * 0 - OK
662  * 1 - write timeout
663  * 2 - Flash not erased
664  */
665 static int write_data (flash_info_t * info, ulong dest, FPW data)
666 {
667         FPWV *addr = (FPWV *) dest;
668         ulong start;
669         int flag;
670
671         /* Check if Flash is (sufficiently) erased */
672         if ((*addr & data) != data) {
673                 printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
674                 return (2);
675         }
676         /* Disable interrupts which might cause a timeout here */
677         flag = disable_interrupts ();
678
679         *addr = (FPW) 0x00400040;       /* write setup */
680         *addr = data;
681
682         /* arm simple, non interrupt dependent timer */
683         start = get_timer (0);
684
685         /* wait while polling the status register */
686         while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
687                 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
688                         *addr = (FPW) 0x00FF00FF;       /* restore read mode */
689                         return (1);
690                 }
691         }
692
693         *addr = (FPW) 0x00FF00FF;       /* restore read mode */
694
695         return (0);
696 }
697
698 /*-----------------------------------------------------------------------
699  * Write a word or halfword to Flash, returns:
700  * 0 - OK
701  * 1 - write timeout
702  * 2 - Flash not erased
703  */
704 static int write_data_block (flash_info_t * info, ulong src, ulong dest)
705 {
706         FPWV *srcaddr = (FPWV *) src;
707         FPWV *dstaddr = (FPWV *) dest;
708         ulong start;
709         int flag, i;
710
711         /* Check if Flash is (sufficiently) erased */
712         for (i = 0; i < WR_BLOCK; i++)
713                 if ((*dstaddr++ & 0xff) != 0xff) {
714                         printf ("not erased at %08lx (%lx)\n",
715                                 (ulong) dstaddr, *dstaddr);
716                         return (2);
717                 }
718
719         dstaddr = (FPWV *) dest;
720
721         /* Disable interrupts which might cause a timeout here */
722         flag = disable_interrupts ();
723
724         *dstaddr = (FPW) 0x00e800e8;    /* write block setup */
725
726         /* arm simple, non interrupt dependent timer */
727         start = get_timer (0);
728
729         /* wait while polling the status register */
730         while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) {
731                 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
732                         *dstaddr = (FPW) 0x00FF00FF;    /* restore read mode */
733                         return (1);
734                 }
735         }
736
737         *dstaddr = (FPW) 0x001f001f;    /* write 32 to buffer */
738         for (i = 0; i < WR_BLOCK; i++)
739                 *dstaddr++ = *srcaddr++;
740
741         dstaddr -= 1;
742         *dstaddr = (FPW) 0x00d000d0;    /* write 32 to buffer */
743
744         /* arm simple, non interrupt dependent timer */
745         start = get_timer (0);
746
747         /* wait while polling the status register */
748         while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) {
749                 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
750                         *dstaddr = (FPW) 0x00FF00FF;    /* restore read mode */
751                         return (1);
752                 }
753         }
754
755         *dstaddr = (FPW) 0x00FF00FF;    /* restore read mode */
756
757         return (0);
758 }
759
760 /*-----------------------------------------------------------------------
761  * Write a word to Flash for AMD FLASH
762  * A word is 16 or 32 bits, whichever the bus width of the flash bank
763  * (not an individual chip) is.
764  *
765  * returns:
766  * 0 - OK
767  * 1 - write timeout
768  * 2 - Flash not erased
769  */
770 static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data)
771 {
772         ulong start;
773         int flag;
774         int res = 0;            /* result, assume success */
775         FPWV *base;             /* first address in flash bank */
776
777         /* Check if Flash is (sufficiently) erased */
778         if ((*dest & data) != data) {
779                 return (2);
780         }
781
782         base = (FPWV *) (CFG_AMD_BASE);
783
784         /* Disable interrupts which might cause a timeout here */
785         flag = disable_interrupts ();
786
787         base[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* unlock */
788         base[FLASH_CYCLE2] = (FPW) 0x00550055;  /* unlock */
789         base[FLASH_CYCLE1] = (FPW) 0x00A000A0;  /* selects program mode */
790
791         *dest = data;           /* start programming the data */
792
793         /* re-enable interrupts if necessary */
794         if (flag)
795                 enable_interrupts ();
796
797         start = get_timer (0);
798
799         /* data polling for D7 */
800         while (res == 0
801                && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
802                 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
803                         *dest = (FPW) 0x00F000F0;       /* reset bank */
804                         res = 1;
805                 }
806         }
807
808         return (res);
809 }
810
811 void inline spin_wheel (void)
812 {
813         static int p = 0;
814         static char w[] = "\\/-";
815
816         printf ("\010%c", w[p]);
817         (++p == 3) ? (p = 0) : 0;
818 }
819
820 /*-----------------------------------------------------------------------
821  * Set/Clear sector's lock bit, returns:
822  * 0 - OK
823  * 1 - Error (timeout, voltage problems, etc.)
824  */
825 int flash_real_protect (flash_info_t * info, long sector, int prot)
826 {
827         ulong start;
828         int i, j;
829         int curr_bank;
830         int bank;
831         int rc = 0;
832         FPWV *addr = (FPWV *) (info->start[sector]);
833         int flag = disable_interrupts ();
834
835         /*
836          * 29F040B AMD flash does not support software protection/unprotection,
837          * the only way to protect the AMD flash is marked it as prot bit.
838          * This flash only support hardware protection, by supply or not supply
839          * 12vpp to the flash
840          */
841         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) {
842                 info->protect[sector] = prot;
843
844                 return 0;
845         }
846
847         *addr = INTEL_CLEAR;    /* Clear status register    */
848         if (prot) {             /* Set sector lock bit      */
849                 *addr = INTEL_LOCKBIT;  /* Sector lock bit          */
850                 *addr = INTEL_PROTECT;  /* set                      */
851         } else {                /* Clear sector lock bit    */
852                 *addr = INTEL_LOCKBIT;  /* All sectors lock bits    */
853                 *addr = INTEL_CONFIRM;  /* clear                    */
854         }
855
856         start = get_timer (0);
857
858         while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) {
859                 if (get_timer (start) > CFG_FLASH_UNLOCK_TOUT) {
860                         printf ("Flash lock bit operation timed out\n");
861                         rc = 1;
862                         break;
863                 }
864         }
865
866         if (*addr != INTEL_OK) {
867                 printf ("Flash lock bit operation failed at %08X, CSR=%08X\n",
868                         (uint) addr, (uint) * addr);
869                 rc = 1;
870         }
871
872         if (!rc)
873                 info->protect[sector] = prot;
874
875         /*
876          * Clear lock bit command clears all sectors lock bits, so
877          * we have to restore lock bits of protected sectors.
878          */
879         if (!prot) {
880                 /*
881                  * re-locking must be done for all banks that belong on one
882                  * FLASH chip, as all the sectors on the chip were unlocked
883                  * by INTEL_LOCKBIT/INTEL_CONFIRM commands. (let's hope
884                  * that banks never span chips, in particular chips which
885                  * support h/w protection differently).
886                  */
887
888                 /* find the current bank number */
889                 curr_bank = CFG_MAX_FLASH_BANKS + 1;
890                 for (j = 0; j < CFG_MAX_FLASH_BANKS; ++j) {
891                         if (&flash_info[j] == info) {
892                                 curr_bank = j;
893                         }
894                 }
895                 if (curr_bank == CFG_MAX_FLASH_BANKS + 1) {
896                         printf("Error: can't determine bank number!\n");
897                 }
898
899                 for (bank = 0; bank < CFG_MAX_FLASH_BANKS; ++bank) {
900                         if (!same_chip_banks(curr_bank, bank)) {
901                                 continue;
902                         }
903                         info = &flash_info[bank];
904                         for (i = 0; i < info->sector_count; i++) {
905                                 if (info->protect[i]) {
906                                         start = get_timer (0);
907                                         addr = (FPWV *) (info->start[i]);
908                                         *addr = INTEL_LOCKBIT;  /* Sector lock bit  */
909                                         *addr = INTEL_PROTECT;  /* set              */
910                                         while ((*addr & INTEL_FINISHED) !=
911                                                INTEL_FINISHED) {
912                                                 if (get_timer (start) >
913                                                     CFG_FLASH_UNLOCK_TOUT) {
914                                                         printf ("Flash lock bit operation timed out\n");
915                                                         rc = 1;
916                                                         break;
917                                                 }
918                                         }
919                                 }
920                         }
921                 }
922
923                 /*
924                  * get the s/w sector protection status in sync with the h/w,
925                  * in case something went wrong during the re-locking.
926                  */
927                 flash_sync_real_protect(info); /* resets flash to read  mode */
928         }
929
930         if (flag)
931                 enable_interrupts ();
932
933         *addr = INTEL_RESET;    /* Reset to read array mode */
934
935         return rc;
936 }