]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mpl/common/flash.c
board/mpl/common/flash.c: Fix GCC 4.6 build warning
[karo-tx-uboot.git] / board / mpl / common / flash.c
1 /*
2  * (C) Copyright 2000, 2001
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
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 /*
25  * Modified 4/5/2001
26  * Wait for completion of each sector erase command issued
27  * 4/5/2001
28  * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
29  */
30
31 /*
32  * Modified 3/7/2001
33  * - adapted for pip405, Denis Peter, MPL AG Switzerland
34  * TODO:
35  * clean-up
36  */
37
38 #include <common.h>
39
40 #if !defined(CONFIG_PATI)
41 #include <asm/ppc4xx.h>
42 #include <asm/processor.h>
43 #include "common_util.h"
44 #if defined(CONFIG_MIP405)
45 #include "../mip405/mip405.h"
46 #endif
47 #if defined(CONFIG_PIP405)
48 #include "../pip405/pip405.h"
49 #endif
50 #include <asm/4xx_pci.h>
51 #else /* defined(CONFIG_PATI) */
52 #include <mpc5xx.h>
53 #endif
54
55 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
56 /*-----------------------------------------------------------------------
57  * Functions
58  */
59 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
60 static int write_word (flash_info_t *info, ulong dest, ulong data);
61
62 void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt);
63
64 #define ADDR0           0x5555
65 #define ADDR1           0x2aaa
66 #define FLASH_WORD_SIZE unsigned short
67
68 #define FALSE           0
69 #define TRUE            1
70
71 #if !defined(CONFIG_PATI)
72
73 /*-----------------------------------------------------------------------
74  * Some CS switching routines:
75  *
76  * On PIP/MIP405 we have 3 (4) possible boot mode
77  *
78  * - Boot from Flash (Flash CS = CS0, MPS CS = CS1)
79  * - Boot from MPS   (Flash CS = CS1, MPS CS = CS0)
80  * - Boot from PCI with Flash map (Flash CS = CS0, MPS CS = CS1)
81  * - Boot from PCI with MPS map   (Flash CS = CS1, MPS CS = CS0)
82  * The flash init is the first board specific routine which is called
83  * after code relocation (running from SDRAM)
84  * The first thing we do is to map the Flash CS to the Flash area and
85  * the MPS CS to the MPS area. Since the flash size is unknown at this
86  * point, we use the max flash size and the lowest flash address as base.
87  *
88  * After flash detection we adjust the size of the CS area accordingly.
89  * The board_init_r will fill in wrong values in the board init structure,
90  * but this will be fixed in the misc_init_r routine:
91  * bd->bi_flashstart=0-flash_info[0].size
92  * bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN
93  * bd->bi_flashoffset=0
94  *
95  */
96 int get_boot_mode(void)
97 {
98         unsigned long pbcr;
99         int res = 0;
100         pbcr = mfdcr (CPC0_PSR);
101         if ((pbcr & PSR_ROM_WIDTH_MASK) == 0)
102                 /* boot via MPS or MPS mapping */
103                 res = BOOT_MPS;
104         if(pbcr & PSR_ROM_LOC)
105                 /* boot via PCI.. */
106                 res |= BOOT_PCI;
107          return res;
108 }
109
110 /* Map the flash high (in boot area)
111    This code can only be executed from SDRAM (after relocation).
112 */
113 void setup_cs_reloc(void)
114 {
115         int mode;
116         /* Since we are relocated, we can set-up the CS finaly
117          * but first of all, switch off PCI mapping (in case it was a PCI boot) */
118         out32r(PMM0MA,0L);
119         icache_enable (); /* we are relocated */
120         /* get boot mode */
121         mode=get_boot_mode();
122         /* we map the flash high in every case */
123         /* first findout on which cs the flash is */
124         if(mode & BOOT_MPS) {
125                 /* map flash high on CS1 and MPS on CS0 */
126                 mtdcr (EBC0_CFGADDR, PB0AP);
127                 mtdcr (EBC0_CFGDATA, MPS_AP);
128                 mtdcr (EBC0_CFGADDR, PB0CR);
129                 mtdcr (EBC0_CFGDATA, MPS_CR);
130                 /* we use the default values (max values) for the flash
131                  * because its real size is not yet known */
132                 mtdcr (EBC0_CFGADDR, PB1AP);
133                 mtdcr (EBC0_CFGDATA, FLASH_AP);
134                 mtdcr (EBC0_CFGADDR, PB1CR);
135                 mtdcr (EBC0_CFGDATA, FLASH_CR_B);
136         }
137         else {
138                 /* map flash high on CS0 and MPS on CS1 */
139                 mtdcr (EBC0_CFGADDR, PB1AP);
140                 mtdcr (EBC0_CFGDATA, MPS_AP);
141                 mtdcr (EBC0_CFGADDR, PB1CR);
142                 mtdcr (EBC0_CFGDATA, MPS_CR);
143                 /* we use the default values (max values) for the flash
144                  * because its real size is not yet known */
145                 mtdcr (EBC0_CFGADDR, PB0AP);
146                 mtdcr (EBC0_CFGDATA, FLASH_AP);
147                 mtdcr (EBC0_CFGADDR, PB0CR);
148                 mtdcr (EBC0_CFGDATA, FLASH_CR_B);
149         }
150 }
151
152 #endif /* #if !defined(CONFIG_PATI) */
153
154 unsigned long flash_init (void)
155 {
156         unsigned long size_b0;
157         int i;
158
159 #if !defined(CONFIG_PATI)
160         unsigned long flashcr,size_reg;
161         int mode;
162         extern char version_string;
163         char *p = &version_string;
164
165         /* Since we are relocated, we can set-up the CS finally */
166         setup_cs_reloc();
167         /* get and display boot mode */
168         mode=get_boot_mode();
169         if(mode & BOOT_PCI)
170                 printf("(PCI Boot %s Map) ",(mode & BOOT_MPS) ?
171                         "MPS" : "Flash");
172         else
173                 printf("(%s Boot) ",(mode & BOOT_MPS) ?
174                         "MPS" : "Flash");
175 #endif /* #if !defined(CONFIG_PATI) */
176         /* Init: no FLASHes known */
177         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
178                 flash_info[i].flash_id = FLASH_UNKNOWN;
179         }
180
181         /* Static FLASH Bank configuration here - FIXME XXX */
182
183         size_b0 = flash_get_size((vu_long *)CONFIG_SYS_MONITOR_BASE, &flash_info[0]);
184
185         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
186                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
187                         size_b0, size_b0<<20);
188         }
189         /* protect the bootloader */
190         /* Monitor protection ON by default */
191 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
192         flash_protect(FLAG_PROTECT_SET,
193                         CONFIG_SYS_MONITOR_BASE,
194                         CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
195                         &flash_info[0]);
196 #endif
197 #if !defined(CONFIG_PATI)
198         /* protect reset vector */
199         flash_info[0].protect[flash_info[0].sector_count-1] = 1;
200         flash_info[0].size = size_b0;
201         /* set up flash cs according to the size */
202         size_reg=(flash_info[0].size >>20);
203         switch (size_reg) {
204                 case 0:
205                 case 1: i=0; break; /* <= 1MB */
206                 case 2: i=1; break; /* = 2MB */
207                 case 4: i=2; break; /* = 4MB */
208                 case 8: i=3; break; /* = 8MB */
209                 case 16: i=4; break; /* = 16MB */
210                 case 32: i=5; break; /* = 32MB */
211                 case 64: i=6; break; /* = 64MB */
212                 case 128: i=7; break; /*= 128MB */
213                 default:
214                         printf("\n #### ERROR, wrong size %ld MByte reset board #####\n",size_reg);
215                         while(1);
216         }
217         if(mode & BOOT_MPS) {
218                 /* flash is on CS1 */
219                 mtdcr(EBC0_CFGADDR, PB1CR);
220                 flashcr = mfdcr (EBC0_CFGDATA);
221                 /* we map the flash high in every case */
222                 flashcr&=0x0001FFFF; /* mask out address bits */
223                 flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */
224                 flashcr|= (i << 17); /* size addr */
225                 mtdcr(EBC0_CFGADDR, PB1CR);
226                 mtdcr(EBC0_CFGDATA, flashcr);
227         }
228         else {
229                 /* flash is on CS0 */
230                 mtdcr(EBC0_CFGADDR, PB0CR);
231                 flashcr = mfdcr (EBC0_CFGDATA);
232                 /* we map the flash high in every case */
233                 flashcr&=0x0001FFFF; /* mask out address bits */
234                 flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */
235                 flashcr|= (i << 17); /* size addr */
236                 mtdcr(EBC0_CFGADDR, PB0CR);
237                 mtdcr(EBC0_CFGDATA, flashcr);
238         }
239 #if 0
240         /* enable this (PIP405/MIP405 only) if you want to test if
241            the relocation has be done ok.
242            This will disable both Chipselects */
243         mtdcr (EBC0_CFGADDR, PB0CR);
244         mtdcr (EBC0_CFGDATA, 0L);
245         mtdcr (EBC0_CFGADDR, PB1CR);
246         mtdcr (EBC0_CFGDATA, 0L);
247         printf("CS0 & CS1 switched off for test\n");
248 #endif
249         /* patch version_string */
250         for(i=0;i<0x100;i++) {
251                 if(*p=='\n') {
252                         *p=0;
253                         break;
254                 }
255                 p++;
256         }
257 #else /* #if !defined(CONFIG_PATI) */
258 #ifdef  CONFIG_ENV_IS_IN_FLASH
259         /* ENV protection ON by default */
260         flash_protect(FLAG_PROTECT_SET,
261                       CONFIG_ENV_ADDR,
262                       CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
263                       &flash_info[0]);
264 #endif
265 #endif /* #if !defined(CONFIG_PATI) */
266         return (size_b0);
267 }
268
269
270 /*-----------------------------------------------------------------------
271  */
272 void flash_print_info  (flash_info_t *info)
273 {
274         int i;
275         int k;
276         int size;
277         int erased;
278         volatile unsigned long *flash;
279
280         if (info->flash_id == FLASH_UNKNOWN) {
281                 printf ("missing or unknown FLASH type\n");
282                 return;
283         }
284
285         switch (info->flash_id & FLASH_VENDMASK) {
286         case FLASH_MAN_AMD:     printf ("AMD ");                break;
287         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
288         case FLASH_MAN_SST:     printf ("SST ");                break;
289         case FLASH_MAN_INTEL:   printf ("Intel ");              break;
290         default:                printf ("Unknown Vendor ");     break;
291         }
292
293         switch (info->flash_id & FLASH_TYPEMASK) {
294         case FLASH_AM040:       printf ("AM29F040 (512 Kbit, uniform sector size)\n");
295                                 break;
296         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
297                                 break;
298         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
299                                 break;
300         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
301                                 break;
302         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
303                                 break;
304         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
305                                 break;
306         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
307                                 break;
308         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
309                                 break;
310         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
311                                 break;
312         case FLASH_SST800A:     printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
313                                 break;
314         case FLASH_SST160A:     printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
315                                 break;
316         case FLASH_INTEL320T:   printf ("TE28F320C3 (32 Mbit, top sector size)\n");
317                                 break;
318         case FLASH_AM640U:      printf ("AM29LV640U (64 Mbit, uniform sector size)\n");
319                                 break;
320         default:                printf ("Unknown Chip Type\n");
321                                 break;
322         }
323
324         printf ("  Size: %ld KB in %d Sectors\n",
325                 info->size >> 10, info->sector_count);
326
327         printf ("  Sector Start Addresses:");
328         for (i=0; i<info->sector_count; ++i) {
329                 /*
330                  * Check if whole sector is erased
331                 */
332                 if (i != (info->sector_count-1))
333                         size = info->start[i+1] - info->start[i];
334                 else
335                         size = info->start[0] + info->size - info->start[i];
336                 erased = 1;
337                 flash = (volatile unsigned long *)info->start[i];
338                 size = size >> 2;        /* divide by 4 for longword access */
339                 for (k=0; k<size; k++) {
340                         if (*flash++ != 0xffffffff) {
341                                 erased = 0;
342                                 break;
343                         }
344                 }
345                 if ((i % 5) == 0)
346                         printf ("\n   ");
347                 printf (" %08lX%s%s",
348                         info->start[i],
349                         erased ? " E" : "  ",
350                         info->protect[i] ? "RO " : "   ");
351         }
352         printf ("\n");
353 }
354
355 /*-----------------------------------------------------------------------
356  */
357
358
359 /*-----------------------------------------------------------------------
360
361 */
362
363 /*
364  * The following code cannot be run from FLASH!
365  */
366 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
367 {
368         short i;
369         FLASH_WORD_SIZE value;
370         ulong base;
371         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
372
373         /* Write auto select command: read Manufacturer ID */
374         addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
375         addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
376         addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;
377
378         value = addr2[0];
379         /*      printf("flash_get_size value: %x\n",value); */
380         switch (value) {
381         case (FLASH_WORD_SIZE)AMD_MANUFACT:
382                 info->flash_id = FLASH_MAN_AMD;
383                 break;
384         case (FLASH_WORD_SIZE)FUJ_MANUFACT:
385                 info->flash_id = FLASH_MAN_FUJ;
386                 break;
387         case (FLASH_WORD_SIZE)INTEL_MANUFACT:
388                 info->flash_id = FLASH_MAN_INTEL;
389                 break;
390         case (FLASH_WORD_SIZE)SST_MANUFACT:
391                 info->flash_id = FLASH_MAN_SST;
392                 break;
393         default:
394                 info->flash_id = FLASH_UNKNOWN;
395                 info->sector_count = 0;
396                 info->size = 0;
397                 return (0);                     /* no or unknown flash  */
398         }
399         value = addr2[1];                       /* device ID            */
400         /*      printf("Device value %x\n",value);                  */
401         switch (value) {
402         case (FLASH_WORD_SIZE)AMD_ID_F040B:
403                 info->flash_id += FLASH_AM040;
404                 info->sector_count = 8;
405                 info->size = 0x0080000; /* => 512 ko */
406                 break;
407         case (FLASH_WORD_SIZE)AMD_ID_LV400T:
408                 info->flash_id += FLASH_AM400T;
409                 info->sector_count = 11;
410                 info->size = 0x00080000;
411                 break;                          /* => 0.5 MB            */
412
413         case (FLASH_WORD_SIZE)AMD_ID_LV400B:
414                 info->flash_id += FLASH_AM400B;
415                 info->sector_count = 11;
416                 info->size = 0x00080000;
417                 break;                          /* => 0.5 MB            */
418
419         case (FLASH_WORD_SIZE)AMD_ID_LV800T:
420                 info->flash_id += FLASH_AM800T;
421                 info->sector_count = 19;
422                 info->size = 0x00100000;
423                 break;                          /* => 1 MB              */
424
425         case (FLASH_WORD_SIZE)AMD_ID_LV800B:
426                 info->flash_id += FLASH_AM800B;
427                 info->sector_count = 19;
428                 info->size = 0x00100000;
429                 break;                          /* => 1 MB              */
430
431         case (FLASH_WORD_SIZE)AMD_ID_LV160T:
432                 info->flash_id += FLASH_AM160T;
433                 info->sector_count = 35;
434                 info->size = 0x00200000;
435                 break;                          /* => 2 MB              */
436
437         case (FLASH_WORD_SIZE)AMD_ID_LV160B:
438                 info->flash_id += FLASH_AM160B;
439                 info->sector_count = 35;
440                 info->size = 0x00200000;
441                 break;                          /* => 2 MB              */
442         case (FLASH_WORD_SIZE)AMD_ID_LV320T:
443                 info->flash_id += FLASH_AM320T;
444                 info->sector_count = 67;
445                 info->size = 0x00400000;
446                 break;                          /* => 4 MB              */
447         case (FLASH_WORD_SIZE)AMD_ID_LV640U:
448                 info->flash_id += FLASH_AM640U;
449                 info->sector_count = 128;
450                 info->size = 0x00800000;
451                 break;                          /* => 8 MB              */
452 #if 0   /* enable when device IDs are available */
453
454         case (FLASH_WORD_SIZE)AMD_ID_LV320B:
455                 info->flash_id += FLASH_AM320B;
456                 info->sector_count = 67;
457                 info->size = 0x00400000;
458                 break;                          /* => 4 MB              */
459 #endif
460         case (FLASH_WORD_SIZE)SST_ID_xF800A:
461                 info->flash_id += FLASH_SST800A;
462                 info->sector_count = 16;
463                 info->size = 0x00100000;
464                 break;                          /* => 1 MB              */
465         case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T:
466                 info->flash_id += FLASH_INTEL320T;
467                 info->sector_count = 71;
468                 info->size = 0x00400000;
469                 break;                          /* => 4 MB              */
470
471
472         case (FLASH_WORD_SIZE)SST_ID_xF160A:
473                 info->flash_id += FLASH_SST160A;
474                 info->sector_count = 32;
475                 info->size = 0x00200000;
476                 break;                          /* => 2 MB              */
477
478         default:
479                 info->flash_id = FLASH_UNKNOWN;
480                 return (0);                     /* => no or unknown flash */
481
482         }
483         /* base address calculation */
484         base=0-info->size;
485         /* set up sector start address table */
486         if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
487              (info->flash_id  == FLASH_AM040) ||
488              (info->flash_id  == FLASH_AM640U)){
489                 for (i = 0; i < info->sector_count; i++)
490                         info->start[i] = base + (i * 0x00010000);
491         }
492         else {
493                 if (info->flash_id & FLASH_BTYPE) {
494                         /* set sector offsets for bottom boot block type        */
495                         info->start[0] = base + 0x00000000;
496                         info->start[1] = base + 0x00004000;
497                         info->start[2] = base + 0x00006000;
498                         info->start[3] = base + 0x00008000;
499                         for (i = 4; i < info->sector_count; i++)
500                                 info->start[i] = base + (i * 0x00010000) - 0x00030000;
501                 }
502                 else {
503                         /* set sector offsets for top boot block type           */
504                         i = info->sector_count - 1;
505                         if(info->sector_count==71) {
506
507                                 info->start[i--] = base + info->size - 0x00002000;
508                                 info->start[i--] = base + info->size - 0x00004000;
509                                 info->start[i--] = base + info->size - 0x00006000;
510                                 info->start[i--] = base + info->size - 0x00008000;
511                                 info->start[i--] = base + info->size - 0x0000A000;
512                                 info->start[i--] = base + info->size - 0x0000C000;
513                                 info->start[i--] = base + info->size - 0x0000E000;
514                                 for (; i >= 0; i--)
515                                         info->start[i] = base + i * 0x000010000;
516                         }
517                         else {
518                                 info->start[i--] = base + info->size - 0x00004000;
519                                 info->start[i--] = base + info->size - 0x00006000;
520                                 info->start[i--] = base + info->size - 0x00008000;
521                                 for (; i >= 0; i--)
522                                         info->start[i] = base + i * 0x00010000;
523                         }
524                 }
525         }
526
527         /* check for protected sectors */
528         for (i = 0; i < info->sector_count; i++) {
529                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
530                 /* D0 = 1 if protected */
531                 addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
532                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
533                         info->protect[i] = 0;
534                 else
535                         info->protect[i] = addr2[2] & 1;
536         }
537
538         /*
539          * Prevent writes to uninitialized FLASH.
540          */
541         if (info->flash_id != FLASH_UNKNOWN) {
542                 addr2 = (FLASH_WORD_SIZE *)info->start[0];
543                 *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
544         }
545         return (info->size);
546 }
547
548
549 int wait_for_DQ7(flash_info_t *info, int sect)
550 {
551         ulong start, now, last;
552         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
553
554         start = get_timer (0);
555         last  = start;
556         while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
557                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
558                         printf ("Timeout\n");
559                         return ERR_TIMOUT;
560                 }
561                 /* show that we're waiting */
562                 if ((now - last) > 1000) {  /* every second */
563                         putc ('.');
564                         last = now;
565                 }
566         }
567         return ERR_OK;
568 }
569
570 int intel_wait_for_DQ7(flash_info_t *info, int sect)
571 {
572         ulong start, now, last, status;
573         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
574
575         start = get_timer (0);
576         last  = start;
577         while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
578                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
579                         printf ("Timeout\n");
580                         return ERR_TIMOUT;
581                 }
582                 /* show that we're waiting */
583                 if ((now - last) > 1000) {  /* every second */
584                         putc ('.');
585                         last = now;
586                 }
587         }
588         status = addr[0] & (FLASH_WORD_SIZE)0x00280028;
589         /* clear status register */
590         addr[0] = (FLASH_WORD_SIZE)0x00500050;
591         /* check status for block erase fail and VPP low */
592         return (status == 0 ? ERR_OK : ERR_NOT_ERASED);
593 }
594
595 /*-----------------------------------------------------------------------
596  */
597
598 int     flash_erase (flash_info_t *info, int s_first, int s_last)
599 {
600         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
601         volatile FLASH_WORD_SIZE *addr2;
602         int flag, prot, sect;
603         int i, rcode = 0;
604
605
606         if ((s_first < 0) || (s_first > s_last)) {
607                 if (info->flash_id == FLASH_UNKNOWN) {
608                         printf ("- missing\n");
609                 } else {
610                         printf ("- no sectors to erase\n");
611                 }
612                 return 1;
613         }
614
615         if (info->flash_id == FLASH_UNKNOWN) {
616                 printf ("Can't erase unknown flash type - aborted\n");
617                 return 1;
618         }
619
620         prot = 0;
621         for (sect=s_first; sect<=s_last; ++sect) {
622                 if (info->protect[sect]) {
623                         prot++;
624                 }
625         }
626
627         if (prot) {
628                 printf ("- Warning: %d protected sectors will not be erased!\n",
629                         prot);
630         } else {
631                 printf ("\n");
632         }
633
634         /* Disable interrupts which might cause a timeout here */
635         flag = disable_interrupts();
636
637         /* Start erase on unprotected sectors */
638         for (sect = s_first; sect<=s_last; sect++) {
639                 if (info->protect[sect] == 0) { /* not protected */
640                         addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
641                         /*  printf("Erasing sector %p\n", addr2); */ /* CLH */
642                         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
643                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
644                                 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
645                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
646                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
647                                 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
648                                 addr2[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
649                                 for (i=0; i<50; i++)
650                                         udelay(1000);  /* wait 1 ms */
651                                 rcode |= wait_for_DQ7(info, sect);
652                         }
653                         else {
654                                 if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
655                                         addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector */
656                                         addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
657                                         intel_wait_for_DQ7(info, sect);
658                                         addr2[0] = (FLASH_WORD_SIZE)0x00200020;  /* sector erase */
659                                         addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
660                                         rcode |= intel_wait_for_DQ7(info, sect);
661                                 }
662                                 else {
663                                         addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
664                                         addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
665                                         addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
666                                         addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
667                                         addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
668                                         addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
669                                         rcode |= wait_for_DQ7(info, sect);
670                                 }
671                         }
672                         /*
673                          * Wait for each sector to complete, it's more
674                          * reliable.  According to AMD Spec, you must
675                          * issue all erase commands within a specified
676                          * timeout.  This has been seen to fail, especially
677                          * if printf()s are included (for debug)!!
678                          */
679                         /*   wait_for_DQ7(info, sect); */
680                 }
681         }
682
683         /* re-enable interrupts if necessary */
684         if (flag)
685                 enable_interrupts();
686
687         /* wait at least 80us - let's wait 1 ms */
688         udelay (1000);
689
690         /* reset to read mode */
691         addr = (FLASH_WORD_SIZE *)info->start[0];
692         addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
693
694         if (!rcode)
695             printf (" done\n");
696
697         return rcode;
698 }
699
700
701 void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
702 {
703         int i;
704         volatile FLASH_WORD_SIZE *addr2;
705         long c;
706         c= (long)cnt;
707         for(i=info->sector_count-1;i>0;i--)
708         {
709                 if(addr>=info->start[i])
710                         break;
711         }
712         do {
713                 addr2 = (FLASH_WORD_SIZE *)(info->start[i]);
714                 addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector setup */
715                 addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* unlock sector */
716                 intel_wait_for_DQ7(info, i);
717                 i++;
718                 c-=(info->start[i]-info->start[i-1]);
719         }while(c>0);
720 }
721
722
723 /*-----------------------------------------------------------------------
724  * Copy memory to flash, returns:
725  * 0 - OK
726  * 1 - write timeout
727  * 2 - Flash not erased
728  */
729
730 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
731 {
732         ulong cp, wp, data;
733         int i, l, rc;
734
735         if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
736                 unlock_intel_sectors(info,addr,cnt);
737         }
738         wp = (addr & ~3);       /* get lower word aligned address */
739         /*
740          * handle unaligned start bytes
741          */
742         if ((l = addr - wp) != 0) {
743                 data = 0;
744                 for (i=0, cp=wp; i<l; ++i, ++cp) {
745                         data = (data << 8) | (*(uchar *)cp);
746                 }
747                 for (; i<4 && cnt>0; ++i) {
748                         data = (data << 8) | *src++;
749                         --cnt;
750                         ++cp;
751                 }
752                 for (; cnt==0 && i<4; ++i, ++cp) {
753                         data = (data << 8) | (*(uchar *)cp);
754                 }
755
756                 if ((rc = write_word(info, wp, data)) != 0) {
757                         return (rc);
758                 }
759                 wp += 4;
760         }
761
762         /*
763          * handle word aligned part
764          */
765         while (cnt >= 4) {
766                 data = 0;
767                 for (i=0; i<4; ++i) {
768                         data = (data << 8) | *src++;
769                 }
770                 if ((rc = write_word(info, wp, data)) != 0) {
771                         return (rc);
772                 }
773                 wp  += 4;
774                 if((wp % 0x10000)==0)
775                         printf("."); /* show Progress */
776                 cnt -= 4;
777         }
778
779         if (cnt == 0) {
780                 return (0);
781         }
782
783         /*
784          * handle unaligned tail bytes
785          */
786         data = 0;
787         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
788                 data = (data << 8) | *src++;
789                 --cnt;
790         }
791         for (; i<4; ++i, ++cp) {
792                 data = (data << 8) | (*(uchar *)cp);
793         }
794         rc=write_word(info, wp, data);
795         return rc;
796 }
797
798 /*-----------------------------------------------------------------------
799  * Write a word to Flash, returns:
800  * 0 - OK
801  * 1 - write timeout
802  * 2 - Flash not erased
803  */
804 static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000;
805
806 static int write_word (flash_info_t *info, ulong dest, ulong data)
807 {
808         volatile FLASH_WORD_SIZE *addr2 = (volatile FLASH_WORD_SIZE *)(info->start[0]);
809         volatile FLASH_WORD_SIZE *dest2 = (volatile FLASH_WORD_SIZE *)dest;
810         volatile FLASH_WORD_SIZE *data2;
811         ulong start;
812         ulong *data_p;
813         int flag;
814         int i;
815
816         data_p = &data;
817         data2 = (volatile FLASH_WORD_SIZE *)data_p;
818
819         /* Check if Flash is (sufficiently) erased */
820         if ((*((volatile FLASH_WORD_SIZE *)dest) &
821                 (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
822                 return (2);
823         }
824         /* Disable interrupts which might cause a timeout here */
825         flag = disable_interrupts();
826         for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
827         {
828                 if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
829                         /* intel style writting */
830                         dest2[i] = (FLASH_WORD_SIZE)0x00500050;
831                         dest2[i] = (FLASH_WORD_SIZE)0x00400040;
832                         *read_val++ = data2[i];
833                         dest2[i] = data2[i];
834                         if (flag)
835                                 enable_interrupts();
836                         /* data polling for D7 */
837                         start = get_timer (0);
838                         udelay(10);
839                         while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080)
840                         {
841                                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
842                                         return (1);
843                         }
844                         dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
845                         udelay(10);
846                         dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
847                         if(dest2[i]!=data2[i])
848                                 printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]);
849                 }
850                 else {
851                         addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
852                         addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
853                         addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;
854                         dest2[i] = data2[i];
855                         /* re-enable interrupts if necessary */
856                         if (flag)
857                                 enable_interrupts();
858                         /* data polling for D7 */
859                         start = get_timer (0);
860                         while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
861                                 (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
862                                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
863                                         return (1);
864                                 }
865                         }
866                 }
867         }
868         return (0);
869 }
870
871 /*-----------------------------------------------------------------------
872  */