]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/snmc/qs860t/flash.c
Merge git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / board / snmc / qs860t / flash.c
1 /*
2  * (C) Copyright 2003
3  * MuLogic B.V.
4  *
5  * (C) Copyright 2001
6  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <asm/ppc4xx.h>
13 #include <asm/u-boot.h>
14 #include <asm/processor.h>
15
16 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
17
18
19 #ifdef CONFIG_SYS_FLASH_16BIT
20 #define FLASH_WORD_SIZE unsigned short
21 #define FLASH_ID_MASK   0xFFFF
22 #else
23 #define FLASH_WORD_SIZE unsigned long
24 #define FLASH_ID_MASK   0xFFFFFFFF
25 #endif
26
27 /*-----------------------------------------------------------------------
28  * Functions
29  */
30 /* stolen from esteem192e/flash.c */
31 ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info);
32
33 #ifndef CONFIG_SYS_FLASH_16BIT
34 static int write_word (flash_info_t *info, ulong dest, ulong data);
35 #else
36 static int write_short (flash_info_t *info, ulong dest, ushort data);
37 #endif
38 static void flash_get_offsets (ulong base, flash_info_t *info);
39
40
41 /*-----------------------------------------------------------------------
42  */
43
44 unsigned long flash_init (void)
45 {
46         unsigned long size_b0, size_b1;
47         int i;
48         uint pbcr;
49         unsigned long base_b0, base_b1;
50
51         /* Init: no FLASHes known */
52         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
53                 flash_info[i].flash_id = FLASH_UNKNOWN;
54         }
55
56         /* Static FLASH Bank configuration here - FIXME XXX */
57
58         size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)FLASH_BASE1_PRELIM, &flash_info[0]);
59
60         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
61                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
62                         size_b0, size_b0<<20);
63         }
64
65         /* Only one bank */
66         if (CONFIG_SYS_MAX_FLASH_BANKS == 1) {
67                 /* Setup offsets */
68                 flash_get_offsets (FLASH_BASE1_PRELIM, &flash_info[0]);
69
70                 /* Monitor protection ON by default */
71 #if 0   /* sand: */
72                 (void)flash_protect(FLAG_PROTECT_SET,
73                         FLASH_BASE1_PRELIM-CONFIG_SYS_MONITOR_LEN+size_b0,
74                         FLASH_BASE1_PRELIM-1+size_b0,
75                         &flash_info[0]);
76 #else
77                 (void)flash_protect(FLAG_PROTECT_SET,
78                         CONFIG_SYS_MONITOR_BASE,
79                         CONFIG_SYS_MONITOR_BASE+CONFIG_SYS_MONITOR_LEN-1,
80                         &flash_info[0]);
81 #endif
82                 size_b1 = 0 ;
83                 flash_info[0].size = size_b0;
84         } else {        /* 2 banks */
85                 size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)FLASH_BASE1_PRELIM, &flash_info[1]);
86
87                 /* Re-do sizing to get full correct info */
88                 if (size_b1) {
89                         mtdcr(EBC0_CFGADDR, PB0CR);
90                         pbcr = mfdcr(EBC0_CFGDATA);
91                         mtdcr(EBC0_CFGADDR, PB0CR);
92                         base_b1 = -size_b1;
93                         pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
94                         mtdcr(EBC0_CFGDATA, pbcr);
95                 }
96
97                 if (size_b0) {
98                         mtdcr(EBC0_CFGADDR, PB1CR);
99                         pbcr = mfdcr(EBC0_CFGDATA);
100                         mtdcr(EBC0_CFGADDR, PB1CR);
101                         base_b0 = base_b1 - size_b0;
102                         pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
103                         mtdcr(EBC0_CFGDATA, pbcr);
104                 }
105
106                 size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b0, &flash_info[0]);
107
108                 flash_get_offsets (base_b0, &flash_info[0]);
109
110                 /* monitor protection ON by default */
111 #if 0   /* sand: */
112                 (void)flash_protect(FLAG_PROTECT_SET,
113                         FLASH_BASE1_PRELIM-CONFIG_SYS_MONITOR_LEN+size_b0,
114                         FLASH_BASE1_PRELIM-1+size_b0,
115                         &flash_info[0]);
116 #else
117                 (void)flash_protect(FLAG_PROTECT_SET,
118                         CONFIG_SYS_MONITOR_BASE,
119                         CONFIG_SYS_MONITOR_BASE+CONFIG_SYS_MONITOR_LEN-1,
120                         &flash_info[0]);
121 #endif
122
123                 if (size_b1) {
124                         /* Re-do sizing to get full correct info */
125                         size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b1, &flash_info[1]);
126
127                         flash_get_offsets (base_b1, &flash_info[1]);
128
129                         /* monitor protection ON by default */
130                         (void)flash_protect(FLAG_PROTECT_SET,
131                                 base_b1+size_b1-CONFIG_SYS_MONITOR_LEN,
132                                 base_b1+size_b1-1,
133                                 &flash_info[1]);
134                         /* monitor protection OFF by default (one is enough) */
135                         (void)flash_protect(FLAG_PROTECT_CLEAR,
136                                 base_b0+size_b0-CONFIG_SYS_MONITOR_LEN,
137                                 base_b0+size_b0-1,
138                                 &flash_info[0]);
139                 } else {
140                         flash_info[1].flash_id = FLASH_UNKNOWN;
141                         flash_info[1].sector_count = -1;
142                 }
143
144                 flash_info[0].size = size_b0;
145                 flash_info[1].size = size_b1;
146         }/* else 2 banks */
147         return (size_b0 + size_b1);
148 }
149
150
151 /*-----------------------------------------------------------------------
152  */
153
154 static void flash_get_offsets (ulong base, flash_info_t *info)
155 {
156         int i;
157
158         /* set up sector start adress table */
159         if ((info->flash_id & FLASH_TYPEMASK) == INTEL_ID_28F320J3A ||
160                 (info->flash_id & FLASH_TYPEMASK) == INTEL_ID_28F640J3A ||
161                 (info->flash_id & FLASH_TYPEMASK) == INTEL_ID_28F128J3A) {
162                 for (i = 0; i < info->sector_count; i++) {
163                         info->start[i] = base + (i * info->size/info->sector_count);
164                 }
165         }
166         else if (info->flash_id & FLASH_BTYPE) {
167                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
168
169 #ifndef CONFIG_SYS_FLASH_16BIT
170                         /* set sector offsets for bottom boot block type */
171                         info->start[0] = base + 0x00000000;
172                         info->start[1] = base + 0x00004000;
173                         info->start[2] = base + 0x00008000;
174                         info->start[3] = base + 0x0000C000;
175                         info->start[4] = base + 0x00010000;
176                         info->start[5] = base + 0x00014000;
177                         info->start[6] = base + 0x00018000;
178                         info->start[7] = base + 0x0001C000;
179                         for (i = 8; i < info->sector_count; i++) {
180                                 info->start[i] = base + (i * 0x00020000) - 0x000E0000;
181                         }
182                 } else {
183                         /* set sector offsets for bottom boot block type */
184                         info->start[0] = base + 0x00000000;
185                         info->start[1] = base + 0x00008000;
186                         info->start[2] = base + 0x0000C000;
187                         info->start[3] = base + 0x00010000;
188                         for (i = 4; i < info->sector_count; i++) {
189                                 info->start[i] = base + (i * 0x00020000) - 0x00060000;
190                         }
191                 }
192 #else
193                         /* set sector offsets for bottom boot block type */
194                         info->start[0] = base + 0x00000000;
195                         info->start[1] = base + 0x00002000;
196                         info->start[2] = base + 0x00004000;
197                         info->start[3] = base + 0x00006000;
198                         info->start[4] = base + 0x00008000;
199                         info->start[5] = base + 0x0000A000;
200                         info->start[6] = base + 0x0000C000;
201                         info->start[7] = base + 0x0000E000;
202                         for (i = 8; i < info->sector_count; i++) {
203                                 info->start[i] = base + (i * 0x00010000) - 0x00070000;
204                         }
205                 } else {
206                         /* set sector offsets for bottom boot block type */
207                         info->start[0] = base + 0x00000000;
208                         info->start[1] = base + 0x00004000;
209                         info->start[2] = base + 0x00006000;
210                         info->start[3] = base + 0x00008000;
211                         for (i = 4; i < info->sector_count; i++) {
212                                 info->start[i] = base + (i * 0x00010000) - 0x00030000;
213                         }
214                 }
215 #endif
216         } else {
217                 /* set sector offsets for top boot block type */
218                 i = info->sector_count - 1;
219                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
220
221 #ifndef CONFIG_SYS_FLASH_16BIT
222                         info->start[i--] = base + info->size - 0x00004000;
223                         info->start[i--] = base + info->size - 0x00008000;
224                         info->start[i--] = base + info->size - 0x0000C000;
225                         info->start[i--] = base + info->size - 0x00010000;
226                         info->start[i--] = base + info->size - 0x00014000;
227                         info->start[i--] = base + info->size - 0x00018000;
228                         info->start[i--] = base + info->size - 0x0001C000;
229                         for (; i >= 0; i--) {
230                                 info->start[i] = base + i * 0x00020000;
231                         }
232                 } else {
233
234                         info->start[i--] = base + info->size - 0x00008000;
235                         info->start[i--] = base + info->size - 0x0000C000;
236                         info->start[i--] = base + info->size - 0x00010000;
237                         for (; i >= 0; i--) {
238                                 info->start[i] = base + i * 0x00020000;
239                         }
240                 }
241 #else
242                         info->start[i--] = base + info->size - 0x00002000;
243                         info->start[i--] = base + info->size - 0x00004000;
244                         info->start[i--] = base + info->size - 0x00006000;
245                         info->start[i--] = base + info->size - 0x00008000;
246                         info->start[i--] = base + info->size - 0x0000A000;
247                         info->start[i--] = base + info->size - 0x0000C000;
248                         info->start[i--] = base + info->size - 0x0000E000;
249                         for (; i >= 0; i--) {
250                                 info->start[i] = base + i * 0x00010000;
251                         }
252                 } else {
253                         info->start[i--] = base + info->size - 0x00004000;
254                         info->start[i--] = base + info->size - 0x00006000;
255                         info->start[i--] = base + info->size - 0x00008000;
256                         for (; i >= 0; i--) {
257                                 info->start[i] = base + i * 0x00010000;
258                         }
259                 }
260 #endif
261         }
262 }
263
264 /*-----------------------------------------------------------------------
265  */
266
267 void flash_print_info  (flash_info_t *info)
268 {
269         int i;
270         uchar *boottype;
271         uchar botboot[]=", bottom boot sect)\n";
272         uchar topboot[]=", top boot sector)\n";
273
274         if (info->flash_id == FLASH_UNKNOWN) {
275                 printf ("missing or unknown FLASH type\n");
276                 return;
277         }
278
279         switch (info->flash_id & FLASH_VENDMASK) {
280         case FLASH_MAN_AMD:     printf ("AMD ");                break;
281         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
282         case FLASH_MAN_SST:     printf ("SST ");                break;
283         case FLASH_MAN_STM:     printf ("STM ");                break;
284         case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
285         default:                printf ("Unknown Vendor ");     break;
286         }
287
288         if (info->flash_id & 0x0001 ) {
289                 boottype = botboot;
290         } else {
291                 boottype = topboot;
292         }
293
294         switch (info->flash_id & FLASH_TYPEMASK) {
295         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit%s",boottype);
296                                 break;
297         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit%s",boottype);
298                                 break;
299         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit%s",boottype);
300                                 break;
301         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit%s",boottype);
302                                 break;
303         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit%s",boottype);
304                                 break;
305         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit%s",boottype);
306                                 break;
307         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit%s",boottype);
308                                 break;
309         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit%s",boottype);
310                                 break;
311         case FLASH_INTEL800B:   printf ("INTEL28F800B (8 Mbit%s",boottype);
312                                 break;
313         case FLASH_INTEL800T:   printf ("INTEL28F800T (8 Mbit%s",boottype);
314                                 break;
315         case FLASH_INTEL160B:   printf ("INTEL28F160B (16 Mbit%s",boottype);
316                                 break;
317         case FLASH_INTEL160T:   printf ("INTEL28F160T (16 Mbit%s",boottype);
318                                 break;
319         case FLASH_INTEL320B:   printf ("INTEL28F320B (32 Mbit%s",boottype);
320                                 break;
321         case FLASH_INTEL320T:   printf ("INTEL28F320T (32 Mbit%s",boottype);
322                                 break;
323         case FLASH_AMDL322T:    printf ("AM29DL322T (32 Mbit%s",boottype);
324                                 break;
325
326 #if 0 /* enable when devices are available */
327
328         case FLASH_INTEL640B:   printf ("INTEL28F640B (64 Mbit%s",boottype);
329                                 break;
330         case FLASH_INTEL640T:   printf ("INTEL28F640T (64 Mbit%s",boottype);
331                                 break;
332 #endif
333         case INTEL_ID_28F320J3A:        printf ("INTEL28F320JA3 (32 Mbit%s",boottype);
334                                 break;
335         case INTEL_ID_28F640J3A:        printf ("INTEL28F640JA3 (64 Mbit%s",boottype);
336                                 break;
337         case INTEL_ID_28F128J3A:        printf ("INTEL28F128JA3 (128 Mbit%s",boottype);
338                                 break;
339
340         default:                printf ("Unknown Chip Type\n");
341                                 break;
342         }
343
344         printf ("  Size: %ld MB in %d Sectors\n",
345                 info->size >> 20, info->sector_count);
346
347         printf ("  Sector Start Addresses:");
348         for (i=0; i<info->sector_count; ++i) {
349                 if ((i % 5) == 0)
350                         printf ("\n   ");
351                 printf (" %08lX%s",
352                         info->start[i],
353                         info->protect[i] ? " (RO)" : "     "
354                 );
355         }
356         printf ("\n");
357         return;
358 }
359
360
361 /*-----------------------------------------------------------------------
362  */
363
364
365 /*-----------------------------------------------------------------------
366  */
367
368 /*
369  * The following code cannot be run from FLASH!
370  */
371 ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
372 {
373         short i;
374         ulong base = (ulong)addr;
375         FLASH_WORD_SIZE value;
376
377         /* Write auto select command: read Manufacturer ID */
378
379
380 #ifndef CONFIG_SYS_FLASH_16BIT
381
382         /*
383          * Note: if it is an AMD flash and the word at addr[0000]
384          * is 0x00890089 this routine will think it is an Intel
385          * flash device and may(most likely) cause trouble.
386          */
387
388         addr[0x0000] = 0x00900090;
389         if(addr[0x0000] != 0x00890089){
390                 addr[0x0555] = 0x00AA00AA;
391                 addr[0x02AA] = 0x00550055;
392                 addr[0x0555] = 0x00900090;
393 #else
394
395         /*
396          * Note: if it is an AMD flash and the word at addr[0000]
397          * is 0x0089 this routine will think it is an Intel
398          * flash device and may(most likely) cause trouble.
399          */
400
401         addr[0x0000] = 0x0090;
402
403         if(addr[0x0000] != 0x0089){
404                 addr[0x0555] = 0x00AA;
405                 addr[0x02AA] = 0x0055;
406                 addr[0x0555] = 0x0090;
407 #endif
408         }
409         value = addr[0];
410
411         switch (value) {
412         case (AMD_MANUFACT & FLASH_ID_MASK):
413                 info->flash_id = FLASH_MAN_AMD;
414                 break;
415         case (FUJ_MANUFACT & FLASH_ID_MASK):
416                 info->flash_id = FLASH_MAN_FUJ;
417                 break;
418         case (STM_MANUFACT & FLASH_ID_MASK):
419                 info->flash_id = FLASH_MAN_STM;
420                 break;
421         case (SST_MANUFACT & FLASH_ID_MASK):
422                 info->flash_id = FLASH_MAN_SST;
423                 break;
424         case (INTEL_MANUFACT & FLASH_ID_MASK):
425                 info->flash_id = FLASH_MAN_INTEL;
426                 break;
427         default:
428                 info->flash_id = FLASH_UNKNOWN;
429                 info->sector_count = 0;
430                 info->size = 0;
431                 return (0); /* no or unknown flash */
432
433         }
434
435         value = addr[1];                        /* device ID            */
436
437         switch (value) {
438
439         case (AMD_ID_LV400T & FLASH_ID_MASK):
440                 info->flash_id += FLASH_AM400T;
441                 info->sector_count = 11;
442                 info->size = 0x00100000;
443                 break;                          /* => 1 MB              */
444
445         case (AMD_ID_LV400B & FLASH_ID_MASK):
446                 info->flash_id += FLASH_AM400B;
447                 info->sector_count = 11;
448                 info->size = 0x00100000;
449                 break;                          /* => 1 MB              */
450
451         case (AMD_ID_LV800T & FLASH_ID_MASK):
452                 info->flash_id += FLASH_AM800T;
453                 info->sector_count = 19;
454                 info->size = 0x00200000;
455                 break;                          /* => 2 MB              */
456
457         case (AMD_ID_LV800B & FLASH_ID_MASK):
458                 info->flash_id += FLASH_AM800B;
459                 info->sector_count = 19;
460                 info->size = 0x00200000;
461                 break;                          /* => 2 MB              */
462
463         case (AMD_ID_LV160T & FLASH_ID_MASK):
464                 info->flash_id += FLASH_AM160T;
465                 info->sector_count = 35;
466                 info->size = 0x00400000;
467                 break;                          /* => 4 MB              */
468
469         case (AMD_ID_LV160B & FLASH_ID_MASK):
470                 info->flash_id += FLASH_AM160B;
471                 info->sector_count = 35;
472                 info->size = 0x00400000;
473                 break;                          /* => 4 MB              */
474 #if 0   /* enable when device IDs are available */
475         case (AMD_ID_LV320T & FLASH_ID_MASK):
476                 info->flash_id += FLASH_AM320T;
477                 info->sector_count = 67;
478                 info->size = 0x00800000;
479                 break;                          /* => 8 MB              */
480
481         case (AMD_ID_LV320B & FLASH_ID_MASK):
482                 info->flash_id += FLASH_AM320B;
483                 info->sector_count = 67;
484                 info->size = 0x00800000;
485                 break;                          /* => 8 MB              */
486 #endif
487
488         case (AMD_ID_DL322T & FLASH_ID_MASK):
489                 info->flash_id += FLASH_AMDL322T;
490                 info->sector_count = 71;
491                 info->size = 0x00800000;
492                 break;                          /* => 8 MB              */
493
494         case (INTEL_ID_28F800B3T & FLASH_ID_MASK):
495                 info->flash_id += FLASH_INTEL800T;
496                 info->sector_count = 23;
497                 info->size = 0x00200000;
498                 break;                          /* => 2 MB              */
499
500         case (INTEL_ID_28F800B3B & FLASH_ID_MASK):
501                 info->flash_id += FLASH_INTEL800B;
502                 info->sector_count = 23;
503                 info->size = 0x00200000;
504                 break;                          /* => 2 MB              */
505
506         case (INTEL_ID_28F160B3T & FLASH_ID_MASK):
507                 info->flash_id += FLASH_INTEL160T;
508                 info->sector_count = 39;
509                 info->size = 0x00400000;
510                 break;                          /* => 4 MB              */
511
512         case (INTEL_ID_28F160B3B & FLASH_ID_MASK):
513                 info->flash_id += FLASH_INTEL160B;
514                 info->sector_count = 39;
515                 info->size = 0x00400000;
516                 break;                          /* => 4 MB              */
517
518         case (INTEL_ID_28F320B3T & FLASH_ID_MASK):
519                 info->flash_id += FLASH_INTEL320T;
520                 info->sector_count = 71;
521                 info->size = 0x00800000;
522                 break;                          /* => 8 MB              */
523
524         case (INTEL_ID_28F320B3B & FLASH_ID_MASK):
525                 info->flash_id += FLASH_AM320B;
526                 info->sector_count = 71;
527                 info->size = 0x00800000;
528                 break;                          /* => 8 MB              */
529
530 #if 0 /* enable when devices are available */
531         case (INTEL_ID_28F320B3T & FLASH_ID_MASK):
532                 info->flash_id += FLASH_INTEL320T;
533                 info->sector_count = 135;
534                 info->size = 0x01000000;
535                 break;                          /* => 16 MB             */
536
537         case (INTEL_ID_28F320B3B & FLASH_ID_MASK):
538                 info->flash_id += FLASH_AM320B;
539                 info->sector_count = 135;
540                 info->size = 0x01000000;
541                 break;                          /* => 16 MB             */
542 #endif
543         case (INTEL_ID_28F320J3A & FLASH_ID_MASK):
544                 info->flash_id += FLASH_28F320J3A;
545                 info->sector_count = 32;
546                 info->size = 0x00400000;
547                 break;                          /* => 32 MBit   */
548         case (INTEL_ID_28F640J3A & FLASH_ID_MASK):
549                 info->flash_id += FLASH_28F640J3A;
550                 info->sector_count = 64;
551                 info->size = 0x00800000;
552                 break;                          /* => 64 MBit   */
553         case (INTEL_ID_28F128J3A & FLASH_ID_MASK):
554                 info->flash_id += FLASH_28F128J3A;
555                 info->sector_count = 128;
556                 info->size = 0x01000000;
557                 break;                          /* => 128 MBit  */
558
559         default:
560                 /* FIXME*/
561                 info->flash_id = FLASH_UNKNOWN;
562                 return (0);                     /* => no or unknown flash */
563         }
564
565         flash_get_offsets(base, info);
566
567         /* check for protected sectors */
568         for (i = 0; i < info->sector_count; i++) {
569                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
570                 /* D0 = 1 if protected */
571                 addr = (volatile FLASH_WORD_SIZE *)(info->start[i]);
572                 info->protect[i] = addr[2] & 1;
573         }
574
575         /*
576          * Prevent writes to uninitialized FLASH.
577          */
578         if (info->flash_id != FLASH_UNKNOWN) {
579                 addr = (volatile FLASH_WORD_SIZE *)info->start[0];
580                 if( (info->flash_id & 0xFF00) == FLASH_MAN_INTEL){
581                         *addr = (0x00F000F0 & FLASH_ID_MASK);   /* reset bank */
582                 } else {
583                         *addr = (0x00FF00FF & FLASH_ID_MASK);   /* reset bank */
584                 }
585         }
586
587         return (info->size);
588 }
589
590
591 /*-----------------------------------------------------------------------
592  */
593
594 int flash_erase (flash_info_t * info, int s_first, int s_last)
595 {
596
597         volatile FLASH_WORD_SIZE *addr =
598                 (volatile FLASH_WORD_SIZE *) (info->start[0]);
599         int flag, prot, sect, l_sect, barf;
600         ulong start, now, last;
601         int rcode = 0;
602
603         if ((s_first < 0) || (s_first > s_last)) {
604                 if (info->flash_id == FLASH_UNKNOWN) {
605                         printf ("- missing\n");
606                 } else {
607                         printf ("- no sectors to erase\n");
608                 }
609                 return 1;
610         }
611
612         if ((info->flash_id == FLASH_UNKNOWN) ||
613             ((info->flash_id > FLASH_AMD_COMP) &&
614              ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL))) {
615                 printf ("Can't erase unknown flash type - aborted\n");
616                 return 1;
617         }
618
619         prot = 0;
620         for (sect = s_first; sect <= s_last; ++sect) {
621                 if (info->protect[sect]) {
622                         prot++;
623                 }
624         }
625
626         if (prot) {
627                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
628         } else {
629                 printf ("\n");
630         }
631
632         l_sect = -1;
633
634         /* Disable interrupts which might cause a timeout here */
635         flag = disable_interrupts ();
636         if (info->flash_id < FLASH_AMD_COMP) {
637 #ifndef CONFIG_SYS_FLASH_16BIT
638                 addr[0x0555] = 0x00AA00AA;
639                 addr[0x02AA] = 0x00550055;
640                 addr[0x0555] = 0x00800080;
641                 addr[0x0555] = 0x00AA00AA;
642                 addr[0x02AA] = 0x00550055;
643 #else
644                 addr[0x0555] = 0x00AA;
645                 addr[0x02AA] = 0x0055;
646                 addr[0x0555] = 0x0080;
647                 addr[0x0555] = 0x00AA;
648                 addr[0x02AA] = 0x0055;
649 #endif
650                 /* Start erase on unprotected sectors */
651                 for (sect = s_first; sect <= s_last; sect++) {
652                         if (info->protect[sect] == 0) { /* not protected */
653                                 addr = (volatile FLASH_WORD_SIZE *) (info->start[sect]);
654                                 addr[0] = (0x00300030 & FLASH_ID_MASK);
655                                 l_sect = sect;
656                         }
657                 }
658
659                 /* re-enable interrupts if necessary */
660                 if (flag)
661                         enable_interrupts ();
662
663                 /* wait at least 80us - let's wait 1 ms */
664                 udelay (1000);
665
666                 /*
667                  * We wait for the last triggered sector
668                  */
669                 if (l_sect < 0)
670                         goto DONE;
671
672                 start = get_timer (0);
673                 last = start;
674                 addr = (volatile FLASH_WORD_SIZE *) (info->start[l_sect]);
675                 while ((addr[0] & (0x00800080 & FLASH_ID_MASK)) !=
676                        (0x00800080 & FLASH_ID_MASK)) {
677                         if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
678                                 printf ("Timeout\n");
679                                 return 1;
680                         }
681                         /* show that we're waiting */
682                         if ((now - last) > 1000) {      /* every second */
683                                 serial_putc ('.');
684                                 last = now;
685                         }
686                 }
687
688               DONE:
689                 /* reset to read mode */
690                 addr = (volatile FLASH_WORD_SIZE *) info->start[0];
691                 addr[0] = (0x00F000F0 & FLASH_ID_MASK); /* reset bank */
692         } else {
693
694
695                 for (sect = s_first; sect <= s_last; sect++) {
696                         if (info->protect[sect] == 0) { /* not protected */
697                                 barf = 0;
698 #ifndef CONFIG_SYS_FLASH_16BIT
699                                 addr = (vu_long *) (info->start[sect]);
700                                 addr[0] = 0x00200020;
701                                 addr[0] = 0x00D000D0;
702                                 while (!(addr[0] & 0x00800080));        /* wait for error or finish */
703                                 if (addr[0] & 0x003A003A) {     /* check for error */
704                                         barf = addr[0] & 0x003A0000;
705                                         if (barf) {
706                                                 barf >>= 16;
707                                         } else {
708                                                 barf = addr[0] & 0x0000003A;
709                                         }
710                                 }
711 #else
712                                 addr = (vu_short *) (info->start[sect]);
713                                 addr[0] = 0x0020;
714                                 addr[0] = 0x00D0;
715                                 while (!(addr[0] & 0x0080));    /* wait for error or finish */
716                                 if (addr[0] & 0x003A)   /* check for error */
717                                         barf = addr[0] & 0x003A;
718 #endif
719                                 if (barf) {
720                                         printf ("\nFlash error in sector at %lx\n",
721                                                 (unsigned long) addr);
722                                         if (barf & 0x0002)
723                                                 printf ("Block locked, not erased.\n");
724                                         if ((barf & 0x0030) == 0x0030)
725                                                 printf ("Command Sequence error.\n");
726                                         if ((barf & 0x0030) == 0x0020)
727                                                 printf ("Block Erase error.\n");
728                                         if (barf & 0x0008)
729                                                 printf ("Vpp Low error.\n");
730                                         rcode = 1;
731                                 } else
732                                         printf (".");
733                                 l_sect = sect;
734                         }
735                         addr = (volatile FLASH_WORD_SIZE *) info->start[0];
736                         addr[0] = (0x00FF00FF & FLASH_ID_MASK); /* reset bank */
737
738                 }
739
740         }
741         printf (" done\n");
742         return rcode;
743 }
744
745 /*-----------------------------------------------------------------------
746  */
747
748 /*flash_info_t *addr2info (ulong addr)
749 {
750         flash_info_t *info;
751         int i;
752
753         for (i=0, info=&flash_info[0]; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
754                 if ((addr >= info->start[0]) &&
755                     (addr < (info->start[0] + info->size)) ) {
756                         return (info);
757                 }
758         }
759
760         return (NULL);
761 }
762 */
763 /*-----------------------------------------------------------------------
764  * Copy memory to flash.
765  * Make sure all target addresses are within Flash bounds,
766  * and no protected sectors are hit.
767  * Returns:
768  * 0 - OK
769  * 1 - write timeout
770  * 2 - Flash not erased
771  * 4 - target range includes protected sectors
772  * 8 - target address not in Flash memory
773  */
774
775 /*int flash_write (uchar *src, ulong addr, ulong cnt)
776 {
777         int i;
778         ulong         end        = addr + cnt - 1;
779         flash_info_t *info_first = addr2info (addr);
780         flash_info_t *info_last  = addr2info (end );
781         flash_info_t *info;
782
783         if (cnt == 0) {
784                 return (0);
785         }
786
787         if (!info_first || !info_last) {
788                 return (8);
789         }
790
791         for (info = info_first; info <= info_last; ++info) {
792                 ulong b_end = info->start[0] + info->size;*/    /* bank end addr */
793 /*              short s_end = info->sector_count - 1;
794                 for (i=0; i<info->sector_count; ++i) {
795                         ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
796
797                         if ((end >= info->start[i]) && (addr < e_addr) &&
798                             (info->protect[i] != 0) ) {
799                                 return (4);
800                         }
801                 }
802         }
803
804 */      /* finally write data to flash */
805 /*      for (info = info_first; info <= info_last && cnt>0; ++info) {
806                 ulong len;
807
808                 len = info->start[0] + info->size - addr;
809                 if (len > cnt)
810                         len = cnt;
811                 if ((i = write_buff(info, src, addr, len)) != 0) {
812                         return (i);
813                 }
814                 cnt  -= len;
815                 addr += len;
816                 src  += len;
817         }
818         return (0);
819 }
820 */
821 /*-----------------------------------------------------------------------
822  * Copy memory to flash, returns:
823  * 0 - OK
824  * 1 - write timeout
825  * 2 - Flash not erased
826  */
827
828 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
829 {
830 #ifndef CONFIG_SYS_FLASH_16BIT
831         ulong cp, wp, data;
832         int l;
833 #else
834         ulong cp, wp;
835         ushort data;
836 #endif
837         int i, rc;
838
839 #ifndef CONFIG_SYS_FLASH_16BIT
840
841
842         wp = (addr & ~3);       /* get lower word aligned address */
843
844         /*
845          * handle unaligned start bytes
846          */
847         if ((l = addr - wp) != 0) {
848                 data = 0;
849                 for (i=0, cp=wp; i<l; ++i, ++cp) {
850                         data = (data << 8) | (*(uchar *)cp);
851                 }
852                 for (; i<4 && cnt>0; ++i) {
853                         data = (data << 8) | *src++;
854                         --cnt;
855                         ++cp;
856                 }
857                 for (; cnt==0 && i<4; ++i, ++cp) {
858                         data = (data << 8) | (*(uchar *)cp);
859                 }
860
861                 if ((rc = write_word(info, wp, data)) != 0) {
862                         return (rc);
863                 }
864                 wp += 4;
865         }
866
867         /*
868          * handle word aligned part
869          */
870         while (cnt >= 4) {
871                 data = 0;
872                 for (i=0; i<4; ++i) {
873                         data = (data << 8) | *src++;
874                 }
875                 if ((rc = write_word(info, wp, data)) != 0) {
876                         return (rc);
877                 }
878                 wp  += 4;
879                 cnt -= 4;
880         }
881
882         if (cnt == 0) {
883                 return (0);
884         }
885
886         /*
887          * handle unaligned tail bytes
888          */
889         data = 0;
890         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
891                 data = (data << 8) | *src++;
892                 --cnt;
893         }
894         for (; i<4; ++i, ++cp) {
895                 data = (data << 8) | (*(uchar *)cp);
896         }
897
898         return (write_word(info, wp, data));
899
900 #else
901         wp = (addr & ~1);       /* get lower word aligned address */
902
903         /*
904          * handle unaligned start byte
905          */
906         if (addr - wp) {
907                 data = 0;
908                 data = (data << 8) | *src++;
909                 --cnt;
910                 if ((rc = write_short(info, wp, data)) != 0) {
911                         return (rc);
912                 }
913                 wp += 2;
914         }
915
916         /*
917          * handle word aligned part
918          */
919 /*      l = 0; used for debuging  */
920         while (cnt >= 2) {
921                 data = 0;
922                 for (i=0; i<2; ++i) {
923                         data = (data << 8) | *src++;
924                 }
925
926 /*              if(!l){
927                         printf("%x",data);
928                         l = 1;
929                 }  used for debuging */
930
931                 if ((rc = write_short(info, wp, data)) != 0) {
932                         return (rc);
933                 }
934                 wp  += 2;
935                 cnt -= 2;
936         }
937
938         if (cnt == 0) {
939                 return (0);
940         }
941
942         /*
943          * handle unaligned tail bytes
944          */
945         data = 0;
946         for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
947                 data = (data << 8) | *src++;
948                 --cnt;
949         }
950         for (; i<2; ++i, ++cp) {
951                 data = (data << 8) | (*(uchar *)cp);
952         }
953
954         return (write_short(info, wp, data));
955
956
957 #endif
958 }
959
960 /*-----------------------------------------------------------------------
961  * Write a word to Flash, returns:
962  * 0 - OK
963  * 1 - write timeout
964  * 2 - Flash not erased
965  */
966 #ifndef CONFIG_SYS_FLASH_16BIT
967 static int write_word (flash_info_t *info, ulong dest, ulong data)
968 {
969         vu_long *addr = (vu_long*)(info->start[0]);
970         ulong start,barf;
971         int flag;
972
973
974         /* Check if Flash is (sufficiently) erased */
975         if ((*((vu_long *)dest) & data) != data) {
976                 return (2);
977         }
978
979         /* Disable interrupts which might cause a timeout here */
980         flag = disable_interrupts();
981
982         if(info->flash_id > FLASH_AMD_COMP) {
983                 /* AMD stuff */
984                 addr[0x0555] = 0x00AA00AA;
985                 addr[0x02AA] = 0x00550055;
986                 addr[0x0555] = 0x00A000A0;
987         } else {
988                 /* intel stuff */
989                 *addr = 0x00400040;
990         }
991         *((vu_long *)dest) = data;
992
993         /* re-enable interrupts if necessary */
994         if (flag)
995                 enable_interrupts();
996
997         /* data polling for D7 */
998         start = get_timer (0);
999
1000         if(info->flash_id > FLASH_AMD_COMP) {
1001                 while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
1002                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
1003                                 return (1);
1004                         }
1005                 }
1006         } else {
1007                 while(!(addr[0] & 0x00800080)) {        /* wait for error or finish */
1008                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
1009                                 return (1);
1010                         }
1011
1012                 if( addr[0] & 0x003A003A) {     /* check for error */
1013                         barf = addr[0] & 0x003A0000;
1014                         if( barf ) {
1015                                 barf >>=16;
1016                         } else {
1017                                 barf = addr[0] & 0x0000003A;
1018                         }
1019                         printf("\nFlash write error at address %lx\n",(unsigned long)dest);
1020                         if(barf & 0x0002) printf("Block locked, not erased.\n");
1021                         if(barf & 0x0010) printf("Programming error.\n");
1022                         if(barf & 0x0008) printf("Vpp Low error.\n");
1023                         return(2);
1024                 }
1025         }
1026
1027         return (0);
1028 }
1029
1030 #else
1031
1032 static int write_short (flash_info_t *info, ulong dest, ushort data)
1033 {
1034         vu_short *addr = (vu_short*)(info->start[0]);
1035         ulong start,barf;
1036         int flag;
1037
1038         /* Check if Flash is (sufficiently) erased */
1039         if ((*((vu_short *)dest) & data) != data) {
1040                 return (2);
1041         }
1042
1043         /* Disable interrupts which might cause a timeout here */
1044         flag = disable_interrupts();
1045
1046         if(info->flash_id < FLASH_AMD_COMP) {
1047                 /* AMD stuff */
1048                 addr[0x0555] = 0x00AA;
1049                 addr[0x02AA] = 0x0055;
1050                 addr[0x0555] = 0x00A0;
1051         } else {
1052                 /* intel stuff */
1053                 *addr = 0x00D0;
1054                 *addr = 0x0040;
1055         }
1056         *((vu_short *)dest) = data;
1057
1058         /* re-enable interrupts if necessary */
1059         if (flag)
1060                 enable_interrupts();
1061
1062         /* data polling for D7 */
1063         start = get_timer (0);
1064
1065         if(info->flash_id < FLASH_AMD_COMP) {
1066                 /* AMD stuff */
1067                 while ((*((vu_short *)dest) & 0x0080) != (data & 0x0080)) {
1068                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
1069                                 return (1);
1070                         }
1071                 }
1072
1073         } else {
1074                 /* intel stuff */
1075                 while(!(addr[0] & 0x0080)){     /* wait for error or finish */
1076                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) return (1);
1077                 }
1078
1079                 if( addr[0] & 0x003A) { /* check for error */
1080                         barf = addr[0] & 0x003A;
1081                         printf("\nFlash write error at address %lx\n",(unsigned long)dest);
1082                         if(barf & 0x0002) printf("Block locked, not erased.\n");
1083                         if(barf & 0x0010) printf("Programming error.\n");
1084                         if(barf & 0x0008) printf("Vpp Low error.\n");
1085                         return(2);
1086                 }
1087                 *addr = 0x00B0;
1088                 *addr = 0x0070;
1089                 while(!(addr[0] & 0x0080)){     /* wait for error or finish */
1090                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) return (1);
1091                 }
1092                 *addr = 0x00FF;
1093         }
1094         return (0);
1095 }
1096
1097 #endif
1098
1099 /*-----------------------------------------------------------------------*/