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