]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/evb64260/flash.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.git] / board / evb64260 / flash.c
1 /*
2  * (C) Copyright 2001
3  * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
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  * flash.c - flash support for the 512k, 8bit boot flash on the GEVB
26  *           most of this file was based on the existing U-Boot
27  *           flash drivers.
28  */
29
30 #include <common.h>
31 #include <mpc8xx.h>
32 #include <galileo/gt64260R.h>
33 #include <galileo/memory.h>
34 #include "intel_flash.h"
35
36 #define FLASH_ROM       0xFFFD       /* unknown flash type                   */
37 #define FLASH_RAM       0xFFFE       /* unknown flash type                   */
38 #define FLASH_MAN_UNKNOWN 0xFFFF0000
39
40 /* #define DEBUG */
41 /* #define FLASH_ID_OVERRIDE */ /* Hack to set type to 040B if ROM emulator is installed.
42                                  * Can be used to program a ROM in circuit if a programmer
43                                  * is not available by swapping the rom out. */
44
45 /* Intel flash commands */
46 int flash_erase_intel(flash_info_t *info, int s_first, int s_last);
47 int write_word_intel(bank_addr_t addr, bank_word_t value);
48
49 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
50
51 /*-----------------------------------------------------------------------
52  * Functions
53  */
54 static ulong flash_get_size (int portwidth, vu_long *addr, flash_info_t *info);
55 static int write_word (flash_info_t *info, ulong dest, ulong data);
56 static void flash_get_offsets (ulong base, flash_info_t *info);
57 static flash_info_t *flash_get_info(ulong base);
58
59 /*-----------------------------------------------------------------------
60  */
61
62 unsigned long
63 flash_init (void)
64 {
65         unsigned int i;
66         unsigned long size_b0 = 0, size_b1 = 0;
67         unsigned long base, flash_size;
68
69         /* Init: no FLASHes known */
70         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
71                 flash_info[i].flash_id = FLASH_UNKNOWN;
72         }
73
74         /* the boot flash */
75         base = CONFIG_SYS_FLASH_BASE;
76 #ifndef CONFIG_SYS_BOOT_FLASH_WIDTH
77 #define CONFIG_SYS_BOOT_FLASH_WIDTH     1
78 #endif
79         size_b0 = flash_get_size(CONFIG_SYS_BOOT_FLASH_WIDTH, (vu_long *)base,
80                                  &flash_info[0]);
81
82 #ifndef CONFIG_P3G4
83         printf("[");
84         print_size (size_b0, "");
85         printf("@%08lX] ", base);
86 #endif
87
88         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
89                 printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
90                         base, size_b0, size_b0<<20);
91         }
92
93         base = memoryGetDeviceBaseAddress(CONFIG_SYS_EXTRA_FLASH_DEVICE);
94         for(i=1;i<CONFIG_SYS_MAX_FLASH_BANKS;i++) {
95             unsigned long size = flash_get_size(CONFIG_SYS_EXTRA_FLASH_WIDTH, (vu_long *)base, &flash_info[i]);
96
97 #ifndef CONFIG_P3G4
98             printf("[");
99             print_size (size, "");
100             printf("@%08lX] ", base);
101 #endif
102
103             if (flash_info[i].flash_id == FLASH_UNKNOWN) {
104                 if(i==1) {
105                     printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
106                             base, size_b1, size_b1<<20);
107                 }
108                 break;
109             }
110             size_b1+=size;
111             base+=size;
112         }
113
114 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
115         /* monitor protection ON by default */
116         flash_protect(FLAG_PROTECT_SET,
117                       CONFIG_SYS_MONITOR_BASE,
118                       CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
119                       flash_get_info(CONFIG_SYS_MONITOR_BASE));
120 #endif
121
122 #ifdef  CONFIG_ENV_IS_IN_FLASH
123         /* ENV protection ON by default */
124         flash_protect(FLAG_PROTECT_SET,
125                       CONFIG_ENV_ADDR,
126                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
127                       flash_get_info(CONFIG_ENV_ADDR));
128 #endif
129
130         flash_size = size_b0 + size_b1;
131         return flash_size;
132 }
133
134 /*-----------------------------------------------------------------------
135  */
136 static void
137 flash_get_offsets (ulong base, flash_info_t *info)
138 {
139         int i;
140         int sector_size;
141
142         if(!info->sector_count) return;
143
144         /* set up sector start address table */
145         switch(info->flash_id & FLASH_TYPEMASK) {
146             case FLASH_AM040:
147             case FLASH_28F128J3A:
148             case FLASH_28F640J3A:
149             case FLASH_RAM:
150                 /* this chip has uniformly spaced sectors */
151                 sector_size=info->size/info->sector_count;
152                 for (i = 0; i < info->sector_count; i++)
153                         info->start[i] = base + (i * sector_size);
154                 break;
155             default:
156                 if (info->flash_id & FLASH_BTYPE) {
157                     /* set sector offsets for bottom boot block type    */
158                     info->start[0] = base + 0x00000000;
159                     info->start[1] = base + 0x00008000;
160                     info->start[2] = base + 0x0000C000;
161                     info->start[3] = base + 0x00010000;
162                     for (i = 4; i < info->sector_count; i++) {
163                             info->start[i] = base + (i * 0x00020000) - 0x00060000;
164                     }
165                 } else {
166                     /* set sector offsets for top boot block type               */
167                     i = info->sector_count - 1;
168                     info->start[i--] = base + info->size - 0x00008000;
169                     info->start[i--] = base + info->size - 0x0000C000;
170                     info->start[i--] = base + info->size - 0x00010000;
171                     for (; i >= 0; i--) {
172                             info->start[i] = base + i * 0x00020000;
173                     }
174                 }
175         }
176 }
177
178 /*-----------------------------------------------------------------------
179  */
180
181 static flash_info_t *flash_get_info(ulong base)
182 {
183         int i;
184         flash_info_t * info;
185
186         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
187                 info = & flash_info[i];
188                 if (info->start[0] <= base && base <= info->start[0] + info->size - 1)
189                         break;
190         }
191
192         return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
193 }
194
195 /*-----------------------------------------------------------------------
196  */
197 void
198 flash_print_info  (flash_info_t *info)
199 {
200         int i;
201
202         if (info->flash_id == FLASH_UNKNOWN) {
203                 printf ("missing or unknown FLASH type\n");
204                 return;
205         }
206
207         switch (info->flash_id & FLASH_VENDMASK) {
208         case FLASH_MAN_AMD:     printf ("AMD ");                break;
209         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
210         case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
211         default:                printf ("Unknown Vendor ");     break;
212         }
213
214         switch (info->flash_id & FLASH_TYPEMASK) {
215         case FLASH_AM040:
216                 printf ("AM29LV040B (4 Mbit, bottom boot sect)\n");
217                 break;
218         case FLASH_AM400B:
219                 printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
220                 break;
221         case FLASH_AM400T:
222                 printf ("AM29LV400T (4 Mbit, top boot sector)\n");
223                 break;
224         case FLASH_AM800B:
225                 printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
226                 break;
227         case FLASH_AM800T:
228                 printf ("AM29LV800T (8 Mbit, top boot sector)\n");
229                 break;
230         case FLASH_AM160B:
231                 printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
232                 break;
233         case FLASH_AM160T:
234                 printf ("AM29LV160T (16 Mbit, top boot sector)\n");
235                 break;
236         case FLASH_AM320B:
237                 printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
238                 break;
239         case FLASH_AM320T:
240                 printf ("AM29LV320T (32 Mbit, top boot sector)\n");
241                 break;
242         case FLASH_28F640J3A:
243                 printf ("28F640J3A (64 Mbit)\n");
244                 break;
245         case FLASH_28F128J3A:
246                 printf ("28F128J3A (128 Mbit)\n");
247                 break;
248         case FLASH_ROM:
249                 printf ("ROM\n");
250                 break;
251         case FLASH_RAM:
252                 printf ("RAM\n");
253                 break;
254         default:
255                 printf ("Unknown Chip Type\n");
256                 break;
257         }
258
259         puts ("  Size: ");
260         print_size (info->size, "");
261         printf (" in %d Sectors\n", info->sector_count);
262
263         printf ("  Sector Start Addresses:");
264         for (i=0; i<info->sector_count; ++i) {
265                 if ((i % 5) == 0)
266                         printf ("\n   ");
267                 printf (" %08lX%s",
268                         info->start[i],
269                         info->protect[i] ? " (RO)" : "     "
270                 );
271         }
272         printf ("\n");
273         return;
274 }
275
276 /*-----------------------------------------------------------------------
277  */
278
279
280 /*-----------------------------------------------------------------------
281  */
282
283 /*
284  * The following code cannot be run from FLASH!
285  */
286
287 static inline void flash_cmd(int width, volatile unsigned char *addr, int offset, unsigned char cmd)
288 {
289         /* supports 1x8, 1x16, and 2x16 */
290         /* 2x8 and 4x8 are not supported */
291         if(width==4) {
292             /* assuming chips are in 16 bit mode */
293             /* 2x16 */
294             unsigned long cmd32=(cmd<<16)|cmd;
295             *(volatile unsigned long *)(addr+offset*2)=cmd32;
296         } else if (width == 2) {
297             /* 1x16 */
298             *(volatile unsigned short *)((unsigned short*)addr+offset)=cmd;
299         } else {
300             /* 1x8 */
301             *(volatile unsigned char *)(addr+offset)=cmd;
302         }
303 }
304
305 static ulong
306 flash_get_size (int portwidth, vu_long *addr, flash_info_t *info)
307 {
308         short i;
309         volatile unsigned char *caddr = (unsigned char *)addr;
310         volatile unsigned short *saddr = (unsigned short *)addr;
311         volatile unsigned long *laddr = (unsigned long *)addr;
312         char old[2], save;
313         ulong id, manu, base = (ulong)addr;
314
315         info->portwidth=portwidth;
316
317         save = *caddr;
318
319         flash_cmd(portwidth,caddr,0,0xf0);
320         flash_cmd(portwidth,caddr,0,0xf0);
321
322         udelay(10);
323
324         old[0] = caddr[0];
325         old[1] = caddr[1];
326
327
328         if(old[0]!=0xf0) {
329             flash_cmd(portwidth,caddr,0,0xf0);
330             flash_cmd(portwidth,caddr,0,0xf0);
331
332             udelay(10);
333
334             if(*caddr==0xf0) {
335                 /* this area is ROM */
336                 *caddr=save;
337 #ifndef FLASH_ID_OVERRIDE
338                 info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
339                 info->sector_count = 8;
340                 info->size = 0x80000;
341 #else
342                 info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
343                 info->sector_count = 8;
344                 info->size = 0x80000;
345                 info->chipwidth=1;
346 #endif
347                 flash_get_offsets(base, info);
348                 return info->size;
349             }
350         } else {
351             *caddr=0;
352
353             udelay(10);
354
355             if(*caddr==0) {
356                 /* this area is RAM */
357                 *caddr=save;
358                 info->flash_id = FLASH_RAM + FLASH_MAN_UNKNOWN;
359                 info->sector_count = 8;
360                 info->size = 0x80000;
361                 flash_get_offsets(base, info);
362                 return info->size;
363             }
364             flash_cmd(portwidth,caddr,0,0xf0);
365
366             udelay(10);
367         }
368
369         /* Write auto select command: read Manufacturer ID */
370         flash_cmd(portwidth,caddr,0x555,0xAA);
371         flash_cmd(portwidth,caddr,0x2AA,0x55);
372         flash_cmd(portwidth,caddr,0x555,0x90);
373
374         udelay(10);
375
376         if ((caddr[0] == old[0]) &&
377             (caddr[1] == old[1])) {
378
379             /* this area is ROM */
380 #ifndef FLASH_ID_OVERRIDE
381             info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
382             info->sector_count = 8;
383             info->size = 0x80000;
384 #else
385                 info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
386                 info->sector_count = 8;
387                 info->size = 0x80000;
388                 info->chipwidth=1;
389 #endif
390             flash_get_offsets(base, info);
391             return info->size;
392 #ifdef DEBUG
393         } else {
394             printf("%px%d: %02x:%02x -> %02x:%02x\n",
395                     caddr, portwidth, old[0], old[1],
396                     caddr[0], caddr[1]);
397 #endif
398         }
399
400         switch(portwidth) {
401             case 1:
402                 manu = caddr[0];
403                 manu |= manu<<16;
404                 id = caddr[1];
405                 break;
406             case 2:
407                 manu = saddr[0];
408                 manu |= manu<<16;
409                 id = saddr[1];
410                 id |= id<<16;
411                 break;
412             case 4:
413                 manu = laddr[0];
414                 id = laddr[1];
415                 break;
416         default:
417                 id = manu = -1;
418                 break;
419         }
420
421 #ifdef DEBUG
422         printf("\n%08lx:%08lx:%08lx\n", base, manu, id);
423         printf("%08lx %08lx %08lx %08lx\n",
424                 laddr[0],laddr[1],laddr[2],laddr[3]);
425 #endif
426
427         switch (manu) {
428             case AMD_MANUFACT:
429                     info->flash_id = FLASH_MAN_AMD;
430                     break;
431             case FUJ_MANUFACT:
432                     info->flash_id = FLASH_MAN_FUJ;
433                     break;
434             case INTEL_MANUFACT:
435                     info->flash_id = FLASH_MAN_INTEL;
436                     break;
437             default:
438                     printf("Unknown Mfr [%08lx]:%08lx\n", manu, id);
439                     info->flash_id = FLASH_UNKNOWN;
440                     info->sector_count = 0;
441                     info->size = 0;
442                     return (0);                 /* no or unknown flash  */
443         }
444
445         switch (id) {
446             case AMD_ID_LV400T:
447                     info->flash_id += FLASH_AM400T;
448                     info->sector_count = 11;
449                     info->size = 0x00100000;
450                     info->chipwidth=1;
451                     break;                              /* => 1 MB      */
452
453             case AMD_ID_LV400B:
454                     info->flash_id += FLASH_AM400B;
455                     info->sector_count = 11;
456                     info->size = 0x00100000;
457                     info->chipwidth=1;
458                     break;                              /* => 1 MB      */
459
460             case AMD_ID_LV800T:
461                     info->flash_id += FLASH_AM800T;
462                     info->sector_count = 19;
463                     info->size = 0x00200000;
464                     info->chipwidth=1;
465                     break;                              /* => 2 MB      */
466
467             case AMD_ID_LV800B:
468                     info->flash_id += FLASH_AM800B;
469                     info->sector_count = 19;
470                     info->size = 0x00200000;
471                     info->chipwidth=1;
472                     break;                              /* => 2 MB      */
473
474             case AMD_ID_LV160T:
475                     info->flash_id += FLASH_AM160T;
476                     info->sector_count = 35;
477                     info->size = 0x00400000;
478                     info->chipwidth=1;
479                     break;                              /* => 4 MB      */
480
481             case AMD_ID_LV160B:
482                     info->flash_id += FLASH_AM160B;
483                     info->sector_count = 35;
484                     info->size = 0x00400000;
485                     info->chipwidth=1;
486                     break;                              /* => 4 MB      */
487 #if 0   /* enable when device IDs are available */
488             case AMD_ID_LV320T:
489                     info->flash_id += FLASH_AM320T;
490                     info->sector_count = 67;
491                     info->size = 0x00800000;
492                     break;                              /* => 8 MB      */
493
494             case AMD_ID_LV320B:
495                     info->flash_id += FLASH_AM320B;
496                     info->sector_count = 67;
497                     info->size = 0x00800000;
498                     break;                              /* => 8 MB      */
499 #endif
500             case AMD_ID_LV040B:
501                     info->flash_id += FLASH_AM040;
502                     info->sector_count = 8;
503                     info->size = 0x80000;
504                     info->chipwidth=1;
505                     break;
506
507             case INTEL_ID_28F640J3A:
508                     info->flash_id += FLASH_28F640J3A;
509                     info->sector_count = 64;
510                     info->size = 128*1024 * 64; /* 128kbytes x 64 blocks */
511                     info->chipwidth=2;
512                     if(portwidth==4) info->size*=2;     /* 2x16 */
513                     break;
514
515             case INTEL_ID_28F128J3A:
516                     info->flash_id += FLASH_28F128J3A;
517                     info->sector_count = 128;
518                     info->size = 128*1024 * 128; /* 128kbytes x 128 blocks */
519                     info->chipwidth=2;
520                     if(portwidth==4) info->size*=2;     /* 2x16 */
521                     break;
522
523             default:
524                     printf("Unknown id %lx:[%lx]\n", manu, id);
525                     info->flash_id = FLASH_UNKNOWN;
526                     info->chipwidth=1;
527                     return (0);                 /* => no or unknown flash */
528
529         }
530
531         flash_get_offsets(base, info);
532
533 #if 0
534         /* set up sector start address table */
535         if (info->flash_id & FLASH_AM040) {
536                 /* this chip has uniformly spaced sectors */
537                 for (i = 0; i < info->sector_count; i++)
538                         info->start[i] = base + (i * 0x00010000);
539
540         } else if (info->flash_id & FLASH_BTYPE) {
541                 /* set sector offsets for bottom boot block type        */
542                 info->start[0] = base + 0x00000000;
543                 info->start[1] = base + 0x00008000;
544                 info->start[2] = base + 0x0000C000;
545                 info->start[3] = base + 0x00010000;
546                 for (i = 4; i < info->sector_count; i++) {
547                         info->start[i] = base + (i * 0x00020000) - 0x00060000;
548                 }
549         } else {
550                 /* set sector offsets for top boot block type           */
551                 i = info->sector_count - 1;
552                 info->start[i--] = base + info->size - 0x00008000;
553                 info->start[i--] = base + info->size - 0x0000C000;
554                 info->start[i--] = base + info->size - 0x00010000;
555                 for (; i >= 0; i--) {
556                         info->start[i] = base + i * 0x00020000;
557                 }
558         }
559 #endif
560
561         /* check for protected sectors */
562         for (i = 0; i < info->sector_count; i++) {
563                 /* read sector protection at sector address, (A7 .. A0)=0x02 */
564                 /* D0 = 1 if protected */
565                 caddr = (volatile unsigned char *)(info->start[i]);
566                 saddr = (volatile unsigned short *)(info->start[i]);
567                 laddr = (volatile unsigned long *)(info->start[i]);
568                 if(portwidth==1)
569                     info->protect[i] = caddr[2] & 1;
570                 else if(portwidth==2)
571                     info->protect[i] = saddr[2] & 1;
572                 else
573                     info->protect[i] = laddr[2] & 1;
574         }
575
576         /*
577          * Prevent writes to uninitialized FLASH.
578          */
579         if (info->flash_id != FLASH_UNKNOWN) {
580                 caddr = (volatile unsigned char *)info->start[0];
581
582                 flash_cmd(portwidth,caddr,0,0xF0);      /* reset bank */
583         }
584
585         return (info->size);
586 }
587
588 /* TODO: 2x16 unsupported */
589 int
590 flash_erase (flash_info_t *info, int s_first, int s_last)
591 {
592         volatile unsigned char *addr = (uchar *)(info->start[0]);
593         int flag, prot, sect, l_sect;
594         ulong start, now, last;
595
596         /* TODO: 2x16 unsupported */
597         if(info->portwidth==4) return 1;
598
599         if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
600         if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
601             for (sect = s_first; sect<=s_last; sect++) {
602                 int sector_size=info->size/info->sector_count;
603                 addr = (uchar *)(info->start[sect]);
604                 memset((void *)addr, 0, sector_size);
605             }
606             return 0;
607         }
608
609         if ((s_first < 0) || (s_first > s_last)) {
610                 if (info->flash_id == FLASH_UNKNOWN) {
611                         printf ("- missing\n");
612                 } else {
613                         printf ("- no sectors to erase\n");
614                 }
615                 return 1;
616         }
617
618         if ((info->flash_id&FLASH_VENDMASK) == FLASH_MAN_INTEL)  {
619                 return flash_erase_intel(info,
620                                 (unsigned short)s_first,
621                                 (unsigned short)s_last);
622         }
623
624 #if 0
625         if ((info->flash_id == FLASH_UNKNOWN) ||
626             (info->flash_id > FLASH_AMD_COMP)) {
627                 printf ("Can't erase unknown flash type %08lx - aborted\n",
628                         info->flash_id);
629                 return 1;
630         }
631 #endif
632
633         prot = 0;
634         for (sect=s_first; sect<=s_last; ++sect) {
635                 if (info->protect[sect]) {
636                         prot++;
637                 }
638         }
639
640         if (prot) {
641                 printf ("- Warning: %d protected sectors will not be erased!\n",
642                         prot);
643         } else {
644                 printf ("\n");
645         }
646
647         l_sect = -1;
648
649         /* Disable interrupts which might cause a timeout here */
650         flag = disable_interrupts();
651
652         flash_cmd(info->portwidth,addr,0x555,0xAA);
653         flash_cmd(info->portwidth,addr,0x2AA,0x55);
654         flash_cmd(info->portwidth,addr,0x555,0x80);
655         flash_cmd(info->portwidth,addr,0x555,0xAA);
656         flash_cmd(info->portwidth,addr,0x2AA,0x55);
657
658         /* Start erase on unprotected sectors */
659         for (sect = s_first; sect<=s_last; sect++) {
660                 if (info->protect[sect] == 0) { /* not protected */
661                         addr = (uchar *)(info->start[sect]);
662                         flash_cmd(info->portwidth,addr,0,0x30);
663                         l_sect = sect;
664                 }
665         }
666
667         /* re-enable interrupts if necessary */
668         if (flag)
669                 enable_interrupts();
670
671         /* wait at least 80us - let's wait 1 ms */
672         udelay (1000);
673
674         /*
675          * We wait for the last triggered sector
676          */
677         if (l_sect < 0)
678                 goto DONE;
679
680         start = get_timer (0);
681         last  = start;
682         addr = (volatile unsigned char *)(info->start[l_sect]);
683         /* broken for 2x16: TODO */
684         while ((addr[0] & 0x80) != 0x80) {
685                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
686                         printf ("Timeout\n");
687                         return 1;
688                 }
689                 /* show that we're waiting */
690                 if ((now - last) > 1000) {      /* every second */
691                         putc ('.');
692                         last = now;
693                 }
694         }
695
696 DONE:
697         /* reset to read mode */
698         addr = (volatile unsigned char *)info->start[0];
699         flash_cmd(info->portwidth,addr,0,0xf0);
700         flash_cmd(info->portwidth,addr,0,0xf0);
701
702         printf (" done\n");
703         return 0;
704 }
705
706 /*-----------------------------------------------------------------------
707  * Copy memory to flash, returns:
708  * 0 - OK
709  * 1 - write timeout
710  * 2 - Flash not erased
711  */
712
713 /* broken for 2x16: TODO */
714 int
715 write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
716 {
717         ulong cp, wp, data;
718         int i, l, rc;
719
720         if(info->portwidth==4) return 1;
721
722         if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 0;
723         if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
724             memcpy((void *)addr, src, cnt);
725             return 0;
726         }
727
728         wp = (addr & ~3);       /* get lower word aligned address */
729
730         /*
731          * handle unaligned start bytes
732          */
733         if ((l = addr - wp) != 0) {
734                 data = 0;
735                 for (i=0, cp=wp; i<l; ++i, ++cp) {
736                         data = (data << 8) | (*(uchar *)cp);
737                 }
738                 for (; i<4 && cnt>0; ++i) {
739                         data = (data << 8) | *src++;
740                         --cnt;
741                         ++cp;
742                 }
743                 for (; cnt==0 && i<4; ++i, ++cp) {
744                         data = (data << 8) | (*(uchar *)cp);
745                 }
746
747                 if ((rc = write_word(info, wp, data)) != 0) {
748                         return (rc);
749                 }
750                 wp += 4;
751         }
752
753         /*
754          * handle word aligned part
755          */
756         while (cnt >= 4) {
757                 data = 0;
758                 for (i=0; i<4; ++i) {
759                         data = (data << 8) | *src++;
760                 }
761                 if ((rc = write_word(info, wp, data)) != 0) {
762                         return (rc);
763                 }
764                 wp  += 4;
765                 cnt -= 4;
766         }
767
768         if (cnt == 0) {
769                 return (0);
770         }
771
772         /*
773          * handle unaligned tail bytes
774          */
775         data = 0;
776         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
777                 data = (data << 8) | *src++;
778                 --cnt;
779         }
780         for (; i<4; ++i, ++cp) {
781                 data = (data << 8) | (*(uchar *)cp);
782         }
783
784         return (write_word(info, wp, data));
785 }
786
787 /*-----------------------------------------------------------------------
788  * Write a word to Flash, returns:
789  * 0 - OK
790  * 1 - write timeout
791  * 2 - Flash not erased
792  */
793 /* broken for 2x16: TODO */
794 static int
795 write_word (flash_info_t *info, ulong dest, ulong data)
796 {
797         volatile unsigned char *addr = (uchar *)(info->start[0]);
798         ulong start;
799         int flag, i;
800
801         if(info->portwidth==4) return 1;
802
803         if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
804         if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
805             *(unsigned long *)dest=data;
806             return 0;
807         }
808         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)  {
809                 unsigned short low = data & 0xffff;
810                 unsigned short hi  = (data >> 16) & 0xffff;
811                 int ret = write_word_intel((bank_addr_t)dest, hi);
812
813                 if (!ret) ret = write_word_intel((bank_addr_t)(dest+2), low);
814
815                 return ret;
816         }
817
818         /* Check if Flash is (sufficiently) erased */
819         if ((*((vu_long *)dest) & data) != data) {
820                 return (2);
821         }
822         /* Disable interrupts which might cause a timeout here */
823         flag = disable_interrupts();
824
825         /* first, perform an unlock bypass command to speed up flash writes */
826         addr[0x555] = 0xAA;
827         addr[0x2AA] = 0x55;
828         addr[0x555] = 0x20;
829
830         /* write each byte out */
831         for (i = 0; i < 4; i++) {
832                 char *data_ch = (char *)&data;
833                 addr[0] = 0xA0;
834                 *(((char *)dest)+i) = data_ch[i];
835                 udelay(10); /* XXX */
836         }
837
838         /* we're done, now do an unlock bypass reset */
839         addr[0] = 0x90;
840         addr[0] = 0x00;
841
842         /* re-enable interrupts if necessary */
843         if (flag)
844                 enable_interrupts();
845
846         /* data polling for D7 */
847         start = get_timer (0);
848         while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
849                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
850                         return (1);
851                 }
852         }
853         return (0);
854 }